Issue with Multiple condition if statement Python - python

I'm writing a program that moves my mouse (using pyautogui lib) if it has not been moved in x amount of seconds. I take the X,Y coordinates twice once at the start and then again after the time delay, then compare both X and Y values against the previous one. I've having issues with my if statement which in theory should do the above but after testing it out it doesn't work as expected. Can anyone suggest any edits I can a make to fix this simple issue.
Here's my code:
#!/usr/bin/env python3
import pyautogui
import time
currentMouseX, currentMouseY = pyautogui.position() #Grabs X,Y mouse position
print("position X1 is", currentMouseX)
print("position Y1 is", currentMouseY)
X1 = currentMouseX
Y1 = currentMouseY
time.sleep(3)
currentMouseX2, currentMouseY2 = pyautogui.position() #Grabs second X,Y position after 3 seconds
X2 = currentMouseX
Y2 = currentMouseY
print("position X2 is", currentMouseX2)
print("position Y2 is", currentMouseY2)
**if ((X1 == X2) and (Y1 == Y2)):
print ("!!! MOVE MOUSE !!!")
else:
print("Mouse does not need to be moved")**
FYI: I've left the if statement very simple as I'd like it working before I continue with the program. Any help is very much appreciated.

Note: Saying that your code does not work as expected makes no sense unless you explain what it is supposed to do ALONG WITH WHAT IT IS ACTUALLY DOING.
Having said that, looking at your code I assume your problem is that you always get the result "!!! MOVE MOUSE !!!", even if you did move your mouse.
If you look at your code carfully you will notice that X1 and X2 will always be the same, and Y1 and Y2 also, because you assign them using:
X1 = currentMouseX
Y1 = currentMouseY
and
X2 = currentMouseX
Y2 = currentMouseY
without overwriting currentMouseY. Instead, you load the second coordinates into currentMouseX2 and currentMouseY2.
In short your code uses way to many unnessecary assignments. Instead, do the following:
#!/usr/bin/env python3
import pyautogui
import time
prev = pyautogui.position() #Grabs X,Y mouse position
print("position X1 is", prev[0])
print("position Y1 is", prev[1])
time.sleep(3)
after = pyautogui.position() #Grabs second X,Y position after 3 seconds
print("position X2 is", after[0])
print("position Y2 is", after[1])
if (prev == after):
print ("!!! MOVE MOUSE !!!")
else:
print("Mouse does not need to be moved")

Rather than testing for equality, it might be better to test whether the difference is below some threshold value:
moveThresh = 4 # (or suitable small number)
XMove = X2 - X1
YMove = Y2 - Y1
if abs(XMove) < moveThresh and abs(YMove) < moveThresh:
# treat tiny moves as no move
print("The mouse is effectively stationary & the cat is bored")
else:
print("The mouse is moving & the cat is interested")
etc.
Unless you're hooking up some interesting hardware, I doubt you'll be moving the mouse - only the mouse pointer.

Related

Why is the math of my stacking game not working?

This is my first pygame project, and it's a stacking game. I made the game with the idea of any piece not touching the base is chopped off, and it goes on until your piece gets too small or if you reach the top of the screen. The problem with my game here, is that it works if you only stack pieces to the right. However, it falls apart if you start stacking to the left. I checked the math many times already, but it doesn't work still. It calculates the part that is chopped off by taking the base x position of the piece on the bottom, and then subtracting or adding the x position of the piece on top.
import pygame
import time
pygame.init()
win=pygame.display.set_mode((800,800))
pygame.display.set_caption("Stacking Game")
length=200 #The length of you CURRENT piece, the one that is moving
base=0 #X pos of the PREVIOUS stacked piece
x=0 #X pos of current piece
y=750 #y pos of current piece
blocks=0 #How many blocks have been stacked
difference=0
speed=5
direction=1
running=1
lengthbase=0 #Length of the PREVIOUS stacked piece
while (running==1):
pygame.time.delay(10)
for event in pygame.event.get():
if event.type==pygame.QUIT:
pygame.quit()
if direction==1:
if x>800-length:
direction=0
else:
x+=speed
else:
if direction==0:
if x<0:
direction=1
else:
x-=speed
pygame.draw.rect(win,(0),(0,0,800,y+50)) #Blacks out the screen from the current piece to the top, leaving previously stacked pieces
pygame.draw.rect(win,(255,0,0),(x,y,length,50))
if blocks==16: #16 is the maximum number of blocks on the screen
pygame.quit()
print("You win!")
if event.type==pygame.KEYDOWN and event.key==pygame.K_SPACE:
if blocks==0: #Since the math is all based off the previous piece's length and position, this inserts the information of the first piece. We now know the position and length of the first stacked piece
base=x
lengthbase=200
else:
if x>base and x<(base+lengthbase): #The current piece should always be the same size and the previous piece, so it can either be stacked perfectly, to the right, or to the left. This calulates data when it is stacked to the right.
difference=(x+length)-(base+lengthbase)
length=length-difference
pygame.draw.rect(win,(0),(0,0,800,y+50))
pygame.draw.rect(win,(255,0,0),(x,y,length,50)) #Draws the new piece at the same position as the current piece, but with the new length
else:
if (x+length)>base and (x+length)<(base+lengthbase): #Calculates if the piece is stacked to the left.
difference=base-x
length=length-difference
pygame.draw.rect(win,(0),(0,0,800,y+50))
pygame.draw.rect(win,(255,0,0),(x+difference,y,length,50)) #If it was drawn on x, the stacked piece and the one below it would not be aligned. It has to move a distance of difference
else:
pygame.quit()
print("You lost.")
base=x #The stacked piece then becomes the bases for the next piece
lengthbase=length
speed+=1
blocks+=1
y-=50
time.sleep(0.5)
pygame.display.update()
You have to evaluate if the ranges [x1, x1+w1] and [x2, x2+w2] are overlapping.
Not overlapping:
x1 x1+w1
+----+
+----+
x2 x2+w2
x1 x1+w1
+----+
+----+
x2 x2+w2
Overlapping
x1 x1+w1
+--------------+
+----+
x2 x2+w2
x1 x1+w1
+----+
+---------------+
x2 x2+w2
x1 x1+w1
+---------+
+----------+
x2 x2+w2
x1 x1+w1
+----------+
+----------+
x2 x2+w2
This mean, that the ranges are overlapping if
x1 < x2+w2 and x2 < x1+w1
You don't need 2 separate cases for left and right. Just evaluate whether the areas overlap. Calculate the beginning and the end of the common area with min and max:
if x < base + lengthbase and base < x + length:
start = max(x, base)
end = min(x+length, base+lengthbase)
x = start
length = end - start
pygame.draw.rect(win,(0),(0,0,800,y+50))
pygame.draw.rect(win,(255,0,0),(x,y,length,50))
else:
pygame.quit()
print("You lost.")
This can be further simplified:
start = max(x, base)
end = min(x+length, base+lengthbase)
if start < end:
x, length = start, end - start
pygame.draw.rect(win,(0),(0,0,800,y+50))
pygame.draw.rect(win,(255,0,0),(x,y,length,50))
else:
# [...]
Side note: You've to handle the events in the event loop, rather than after the event loop:
while running==1:
pygame.time.delay(10)
for event in pygame.event.get():
if event.type==pygame.QUIT:
pygame.quit()
if event.type==pygame.KEYDOWN and event.key==pygame.K_SPACE:
if blocks==0:
base=x
lengthbase=200
else:
start = max(x, base)
end = min(x+length, base+lengthbase)
if start < end:
x, length = start, end - start
pygame.draw.rect(win,(0),(0,0,800,y+50))
pygame.draw.rect(win,(255,0,0),(x,y,length,50))
else:
pygame.quit()
print("You lost.")
base, lengthbase = x, length
speed += 1
blocks += 1
y -= 50
time.sleep(0.5)

First python project: Boggle

I'm working on adding directionality to boggle so that the user can trace their path on the board game. I found some code that would help in laying down diagonal functioning to the program but I'm not exactly sure what the code means. It would help a lot if someone could explain the function posted below.
def valid_direction(x1, y1, x2, y2):
dy = y2 - y1
dx = x2 - x1
if dx == 0:
return dy != 0
elif dy == 0:
return dx != 0
else:
return abs(dx) == abs(dy)
I also want to allow the user to input coordinates pertaining to a letter from a 16 letter square board. looks like this in the shell:
|w||e||b||e|
|r||t||o||l|
|e||t||a||e|
|i||p||a||a|
Enter coordinate:
The inputted coordinates get stored in path = [] which I already wrote a function for. My goal is to actually get the function to work so that the user is prompted multiple times until they've finished entering an actual word. Here's the function
def validate_path(path):
word = word_from_path(path, board)
if valid_word(word):
# is it value = value from while loop and the rest?
value = word_value(word)
print("Value of {} is {}".format(word, value))
score += value
else:
print("Invalid word")
return validate_path(path)
And part of the loop for the game
while game:
curr_input = input("Enter coordinate: ")
if curr_input == "quit":
print("Your total score is:", score)
game = False
elif curr_input == "done":
validate_path(path)
Thanks so much to whoever spends the time reading all of this !
The function valid_direction stores delta-y (change in y-coordinate) in dy and delta-x in dx. Then, the ensuing if statements have the following logic:
If the y-coordinate hasn't changed (dy == 0), then if dx == 0 return 0 because the coordinates are the same and it's an invalid move, otherwise return 1.
If the x-coordinate hasn't changed (dx == 0), do the same as in 1. except with y and x reversed.
If both x and y coordinates have changed (dy != 0 and dx != 0) then check if they've both changed by the same absolute amount. If so, then it's a diagonal move by that absolute amount and it returns 1, otherwise it returns 0.
I'm not sure if this is what you want for Boggle though, since I think you want strictly adjacent moves (or a move to a directly diagonal space), so to check a valid move between two points would be:
def valid_direction(x1, y1, x2, y2):
dy = y2 - y1
dx = x2 - x1
if dx == 0:
return abs(dy) == 1
elif dy == 0:
return abs(dx) == 1
else:
return abs(dx) == abs(dy) == 1
Which checks if subsequent moves' coordinates differ by exactly one. Or, more concisely put:
def valid_direction(x1, y1, x2, y2):
dy = y2 - y1
dx = x2 - x1
if not dy and not dx:
return 0
return abs(dx) <= 1 and abs(dy) <= 1

drawing a jagged mountain curve using turtle-graphics and recursion

I am trying to create a function for a homework assignment which draws a jagged mountain curve using turtles and recursion. The function is called jaggedMountain(x,y,c,t) where x x,y are end coordinates, c is a complexity constant, and t is the turtle object. I am trying to create an image like this:
def jaggedCurve(x,y,c,t):
t.pendown()
x1 = t.xcor() + x / 2
y1 = t.ycor() + y / 2
y1 = y + (random.uniform(0,c)-0.5) * (t.xcor() - x)
if (x1,y1) == (x,y):
return None
else:
jaggedCurve(x1,y1,c,t)
This crashes quickly as the base case never executes, the function is called 993 times, and the recursion depth is exceeded. I have been scratching my head with this for quite some time, are there any suggestions?
Initially, I see two issues with your code. The first is:
if (x1,y1) == (x,y):
Turtles wander a floating point plane, the odds of these being exactly equal is small. You're likely better off doing something like:
def distance(x1, y1, x2, y2):
return ((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5
...
if distance(x1, y1, x, y) < 1.0:
The second issue is that jaggedCurve() draws nothing nor returns anything that can be used for drawing. Somewhere you need to actually move the turtle to cause something to be drawn.
Finally, though it's hard to be certain without a value for c, my guess is even with the above changes you won't get you what you want. Good luck.
Very interesting problem!
My solution is to make a recursive function that draws a mountain curve given two end points. Randomly pick a x coordinate value that lies in between two end points and compute the range of possible y coordinate given the maximum possible slope and randomly pick a y value in between this range and do this recursively. When to end points are close enough, just draw the line between them. Here is the code:
MAX_SLOPE = 45
MIN_SLOPE = -45
MIN_HEIGHT = 0
def dist_squared(P1,P2):
return (P1[0]-P2[0])**2 + (P1[1]-P2[1])**2
def mountain(P1,P2):
if dist_squared(P1,P2) < 1:
turtle.goto(P2)
return
x1,y1 = P1
x2,y2 = P2
x3 = random.uniform(x1,x2)
y3_max = min((x3-x1)*math.tan(math.radians(MAX_SLOPE)) + y1, (x2-x3)*math.tan(-math.radians(MIN_SLOPE)) + y2)
y3_min = max((x3-x1)*math.tan(math.radians(MIN_SLOPE)) + y1, (x2-x3)*math.tan(-math.radians(MAX_SLOPE)) + y2)
y3_min = max(y3_min, MIN_HEIGHT)
y3 = random.uniform(y3_min,y3_max)
P3 = (x3, y3)
mountain(P1,P3)
mountain(P3,P2)
return
turtle.up()
turtle.goto(-400,0)
turtle.down()
mountain((-400,0),(400,0))
I know this was posted like 3 months ago, but hopefully this is helpful to someone that was also assigned this terrible problem 5 days before finals! Ha!
The struggle I had with this problem was not realizing that you only need to pass in one point. To get the point the turtle is starting at, you just use .xcor() and .ycor() that are included in the turtle library.
import turtle
import random
def mountain (x, y, complexity, turtleName):
if complexity == 0:
turtleName.setposition(x, y)
else:
x1 = (turtleName.xcor() + x)/2
y1 = (turtleName.ycor() + y)/2
y1 = y1 + (random.uniform(0, complexity) - 0.5) * (turtleName.xcor() - x)
complexity = complexity - 1
mountain(x1, y1, complexity, turtleName)
mountain(x, y, complexity, turtleName)
def main ():
#Gets input for first coordinate pair, splits, and assigns to variables
coordinate = str(input("Enter the coordinate pair, separated by a comma: "))
x, y = coordinate.split(',')
x = int(x)
y = int(y)
complexity = int(input("Enter the complexity: "))
while complexity < 0:
complexity = int(input("Input must be positive. Enter the complexity: "))
Bob = turtle.Turtle()
mountain(x, y, complexity, Bob)
main ()

Why is My Python Turtle Screen not responding

I am trying to create a collision detection system between a turtle and another turtle's line. The problem is that whenever i run the program, the turtle screen does not respond.I am using Pycharm and Python. Please Help!
import turtle
Screen = turtle.Screen()
P1 = turtle.Turtle()
P2 = turtle.Turtle()
Screen.screensize(100, 100)
x1 = []
x2 = []
y1 = []
y2 = []
P1.penup()
P1.setheading(180)
P2.setheading(90)
P1.goto(100, 50)
P2.penup()
P2.goto(50, 0)
P2.pendown()
P1.pendown()
n = 0
Num = 0
XC = P2.position()[0]
YC = P2.position()[1]
x1.append(XC)
y1.append(YC)
while Num == 0:
XC = P2.position()[0]
YC = P2.position()[1]
x1[n] = XC
y1[n] = YC
if P1.heading() is 180:
XC = P2.position()[0]
YC = P2.position()[1]
x2[n] = XC
y2[n] = YC
P1.position()
XC1 = P1.position()[0]
YC1 = P1.position()[1]
for x in range(0, n):
for z in range(x1.index(x), x2.index(x)):
if abs(z-YC1)<10:
print("Found")
P2.forward(1)
P1.forward(0.5)
There are a few problems with that code. A major one is this line:
if P1.heading() is 180:
The is operator tests identity, i.e., it's True if two expressions evaluate to the same object. You should not use it to test if two expressions have the same value. In this case, P1.heading() returns the float object with a value of 180.0, so there's no way it could be the same object as the integer object with value 180. Thus your if block is never entered. And since the main commands that move the turtles are at the end of the if block, the turtles don't move once you enter the while loop.
Also, you are using n to index into your lists, but you never update n from zero, so all of the coordinates that you want to save are getting written into the first items of the lists.
However, if you did update n you'd run into another problem: you'd be attempting to index list items that don't exist, since x1 and y1 are of length one, and x2 and y2 are of length zero.
Anyway, here's a simplified version of your code that does update the lists correctly, and does simple collision detection. It only detects exact collision, not approximate collision, but it should get you going in the right direction.
import turtle
Screen = turtle.Screen()
Screen.screensize(100, 100)
P1 = turtle.Turtle()
P2 = turtle.Turtle()
x1 = []
x2 = []
y1 = []
y2 = []
P1.penup()
P1.setheading(180)
P2.setheading(90)
P1.goto(100, 50)
P2.penup()
P2.goto(50, 0)
P2.pendown()
P1.pendown()
while True:
print(P1.heading() is 180)
XC = P2.position()[0]
YC = P2.position()[1]
x2.append(XC)
y2.append(YC)
XC = P1.position()[0]
YC = P1.position()[1]
x1.append(XC)
y1.append(YC)
if XC in x2 and YC in y2:
print("Found")
P2.forward(1)
P1.forward(0.5)
turtle.done()
There are many errors in your code.
First,
if P1.heading() is 180:
should be
if P1.heading() == 180:
In your loop you don't change your Num var.
You are trying to access an index that was not defined
x2[n] = XC
y2[n] = YC
Your logic doesn't make much sense in that for loop either.
Here, I made some corrections and I included a timer so you can see how your turtles are moving. This should help you to visualize what you are doing
import time
import turtle
Screen = turtle.Screen()
P1 = turtle.Turtle()
P2 = turtle.Turtle()
Screen.screensize(100, 100)
P1.penup()
P1.setheading(180)
P2.setheading(90)
P1.goto(100, 50)
P2.penup()
P2.goto(50, 0)
P2.pendown()
P1.pendown()
time.sleep(1)
n = 100
if P1.heading() == 180:
for x in range(0, n):
print(P1.position())
print(P2.position())
if abs(P1.position()[1] - P2.position()[1]) > 10:
time.sleep(.3)
P2.forward(1)
P1.forward(.5)
else:
print('Found')
break

How do I make a translation animation in python?

I'm trying to animate smooth motion between two points on the screen. At the moment, I am using the following python generator function to determine the point at which to draw the image:
#indexes (just for readability)
X=0
Y=1
def followLine(pointA, pointB, speed):
x1, y1 = pointA
x2, y2 = pointB
movement=[0, 0]
pos=list(pointA)
diffY=y2-y1
diffX=x2-x1
if abs(diffY) > abs(diffX):
#Y distance is greater than x distace
movement[Y]=speed
numFrames=abs(diffY)//speed
if numFrames==0:
movement[X]=0
else:
movement[X]=abs(diffX)//numFrames
elif abs(diffY) < abs(diffX):
#Y distance is less than x distace
movement[X]=speed
numFrames=abs(diffX)//speed
if numFrames==0:
movement[Y]=0
else:
movement[Y]=abs(diffY)//numFrames
else: #Equal
movement=[speed]*2
if diffY < 0:
#is negative
movement[Y] *= -1
if diffX < 0:
movement[X] *= -1
yield pointA
while (abs(pos[X]-x2) > speed)or(abs(pos[Y]-y2) > speed):
pos[X] += movement[X]
pos[Y] += movement[Y]
yield pos
yield pointB
However, this has 2 problems:
First, my main concern is that if pointA and pointB are very far apart, or if the speed is too low, the animation will pass right by pointB, and will keep going for infinity;
The other problem is that, at the end of the animation, there is a sort of jolt as the image snaps into place. This jolt is usually fairly imperceptible, but I'd like to try and make the animation smoother.
How can I do this? I've been looking into the use of trig functions and that seems promising, but I'm not much of a math person, so I'm having trouble understanding exactly how I might implement it using trig.
Also, for what it's worth I'm using Python 3.2.
There's missing information, I think. Seems like you need to either substitute a numFrames arg for speed, or add a time arg in addition to speed. Assuming the former, how about this. Note this generates numFrames+1 points so that pointA and pointB are always the first and last point, respectively, but that's trivial to change if that's not the behavior you want:
def followLine(pointA, pointB, numFrames):
x1, y1 = pointA
x2, y2 = pointB
diffY = float(y2 - y1) / numFrames
diffX = float(x2 - x1) / numFrames
yield(pointA)
for f in range(1,numFrames):
point = (x1 + f * diffX, y1 + f * diffY)
yield(point)
yield(pointB)
points = followLine((0,0), (1,1), 10)
# then iterate over the points and do whatever
for p in points:
print str(p)

Categories

Resources