psychopy event based on mouse position - python

I am setting up a Fitts' law experiment where I would like a participant to click on a start button, move the mouse in a straight line, and then click on a target. After clicking start, if the participant moves their mouse too far up or down in the vertical direction I would like to display a white screen for 30 seconds and accept no input, afterward moving to the next trial.
Currently, no matter what, the experiment is behaving as if I'm moving outside the acceptable range and always executes the if statement.
Here is the code for it that I have right now:
from psychopy import core
start = mouse.isPressedIn(polygon, buttons=[0])
if start==True:
thisExp.addData('starttime',core.getTime())
x, y = mouse.getPos()
mouse.x.append(x)
mouse.y.append(y)
if y>10 or y<-10: #this is the statement that isn't resulting in what I would expect
thisExp.addData('penalty',1)
finish = mouse.isPressedIn(polygon2, buttons=[0])
if finish==True:
thisExp.addData('stoptime',core.getTime())
continueRoutine=False
I haven't figured out everything I need under the nested if statement yet. Right now I am just trying to make sure it works correctly. It never evaluates the if statement as true and never adds the penalty, even though looking at the collected mouse.y list data in the csv file I can see that there were instances where y was outside of whatever range I set.
It appears that mouse position data is being collected as soon as the trial begins, not just after polygon is clicked. However, starttime and stoptime do appear to be based on when polygon and polygon2 are clicked. I'm really not sure what is going on.
UPDATE:
I didn't get notified about Jonas' response until a day later for some reason. I wish I had because it would have put me on the right track a few hours earlier. It's a builder code component.
My code was all running each frame. At the beginning of the routine I added:
checkstart = False
That with the following code each frame solves this particular problem:
start = mouse.isPressedIn(polygon, buttons=[0])
if start==True:
thisExp.addData('starttime',core.getTime())
x, y = mouse.getPos()
mouse.x.append(x)
mouse.y.append(y)
checkstart=True;
if checkstart==True:
if y>10 or y <-10:
thisExp.addData('penalty',1)
finish = mouse.isPressedIn(polygon2, buttons=[0])
if finish==True:
thisExp.addData('stoptime',core.getTime())
continueRoutine=False
I still don't know why mouse position is collected before polygon is clicked but it doesn't actually matter to me. I can match the data for the frame where the mouse was clicked to the position that corresponds to the start button to get the beginning of the mouse path trace.

My code was all running each frame. At the beginning of the routine I added:
checkstart = False
That with the following code each frame solves this particular problem:
start = mouse.isPressedIn(polygon, buttons=[0])
if start==True:
thisExp.addData('starttime',core.getTime())
x, y = mouse.getPos()
mouse.x.append(x)
mouse.y.append(y)
checkstart=True;
if checkstart==True:
if y>10 or y <-10:
thisExp.addData('penalty',1)
finish = mouse.isPressedIn(polygon2, buttons=[0])
if finish==True:
thisExp.addData('stoptime',core.getTime())
continueRoutine=False
I still don't know why mouse position is collected before polygon is clicked but it doesn't actually matter to me. I can match the data for the frame where the mouse was clicked to the position that corresponds to the start button to get the beginning of the mouse path trace.

Related

Object's location not recognized when solving maze

When I run my code, it opens up a random-generated maze for the user to solve by using the agent object, mover, to move around the maze. When my object reaches the end of the maze, in which it is at the top-left of the maze with the position (1,1), I want it to print "Done" in the terminal. The problem is that the program won't recognize the status of the object's position when it is at the end of the maze, resulting in the conditional statement (shown below) not working.
from pyamaze import maze,COLOR,agent,textLabel
m=maze(10, 10)
m.CreateMaze()
mover = agent(m, footprints=True, color = "red")
m.enableWASD(mover)
if(mover.position == (1,1)):
print("Done")
m.run()
However, when I place my object at the end of the maze then run the program, the conditional statement surprisingly works and it prints out the result. The problem is that I want my object to be controlled by the user when it starts off at the bottom of the maze and when the user reaches the end of the maze, I want the conditional statement to work and print out the result in the terminal.
mover.position = (1,1)
if(mover.position == (1,1)):
print("Done")
Can someone help me in solving this problem, so that my object's position can be recognized when the user reaches the end of the maze, making the conditional statement to work?

PyAutoGui While loop keep going when if statement remains true

I've just started learning python and started working on a project.
I'm moving my mouse cursor from one area to another. I just want it to stop when it reach a certain point/area/zone. I'm using the mouse position to tell me where it is, currently.
For some reason, when this loops starts, it keeps looping even when the IF statement is true.
But if I started when the IF statement is true, the loops kinda works as intended, so far it's only reading the 'X' values.
I couldn't find an answer to this, or any questions like it. If anyone has an idea or can point me to a similar post, I'll appreciate it.
import pyautogui, sys, time, autoit
#Search for a position on screen manually
try:
while True:
x, y = pyautogui.position()
print(pyautogui.position())
print('Stopping for 1 seconds, keep searching or CTRL + C to end')
time.sleep(1)
#Confirmed location on screen.
if pyautogui.position(x,y) >= pyautogui.position(710, 15):
pyautogui.leftClick()
print('The Eagle has landed')
print(pyautogui.position())
break
Update: I got it! Following mkrieger1 advice, I manage to get the 'x, y' values to update. Code was rewritten.

How to get window origin (position) in mate applet?

I try to get window origin in a mate panel applet.
To be more precise I want to know the position of my applet (x and y) on the screen because I have a button which show/hide a Gtk.window but I need to move that window next to my button (above, below, right, left depending on where the mate panel is)
The only way that I found is to call get_origin but there is a problem. It should return a tuple x,y but instead like the c function it require two integers and since python use pass by value of course it doesn't work.
This code is valid but useless:
window = self.get_window()
x = 0
y = 0
window.get_origin(x, y)
All other "way to use" get_origin (that you can found in any doc) does not work because it require 3 args (I don't know why)
So I'm looking for a way to get the position of my applet (even if it's not accurate) or to move my window next to my button.
I found an alternative get_root_coords
window = self.get_window()
x,y = window.get_root_coords(0, 0)
It works even with multiple screens and I'm able to move my Gtk.Window next to my button with it.

Python if statement not working as expected. Code 'apparently' called twice

I have this piece of code:
import bge
import GameLogic
import os
os.system("cls")
scene = GameLogic.getCurrentScene()
objects = scene.objects
objectCube = objects["Cube"]
visible = objectCube.visible
if visible == True:
objectCube.setVisible(False, True)
else:
objectCube.setVisible(True, True)
This code is supposed to toggle the visibility of an object but instead the object disappears and immediately reappears in a split second. It looks as if it just flickers. What am I doing wrong?
Also, don't worry about the other variables, they work fine. I have tested them using some Console outputs.
The problem: The mouse sensor sends two signals per click, one for mouse down and one for mouse up. Mouse down sends a positive signal while mouse up sends negative.
You can test this by holding the mouse button down, the cube will disappear and when you release the mouse it will return.
The solution: Use the sensor's positive property to determine if this is a mouse up or down event.
import bge
import GameLogic
import os
os.system("cls")
scene = GameLogic.getCurrentScene()
objects = scene.objects
objectCube = objects["Cube"]
visible = objectCube.visible
# get the mouse sensor
cont = bge.logic.getCurrentController()
sens = cont.sensors['Mouse']
if sens.positive: # positive means a down button event
if visible == True:
objectCube.setVisible(False, True)
else:
objectCube.setVisible(True, True)
The second parameter of setVisible set the game children objects visibility. You set it to True. In this case You hidden the main object and show the children objects.
Following to http://bgepython.tutorialsforblender3d.com/GameObject/setVisible recursive parameter does not mean recursive show/hide all children elements but set the visibility to children elements to True/False
Following to http://www.tutorialsforblender3d.com/BGE_Python/Sensors/Mouse/MouseSensor_LButton_getButtonStatus.html mouse event send two events mouse press and mouse release. Maybe You do not differentiate between press and release and call code twice?

Pygame: Sprite animation Theory - Need Feedback

After some tweaking of some code I got from someone to cause a characters images to move in regards to its direction and up down left right input I've put this together: (hope the code isn't too messy)
Character Move Code + IMG
The Sprite sheet only runs lengthwise, so basically each sprite section is a different action. Now would there be a way I could make a code that functions with the current one to cycle down from a set 'action' in order to make an animation?
For example:
'Run Left' is sprite 3. So then after we designate that column would it be possible to loop down how ever many frames of the run animation (lets say 4) in order to make an animation?
Example Picture:
http://animania1.ca/ShowFriends/dev/example.jpg
It should be easy.
If you record the frame number in a variable, you can modulo this with the number of frames you have to get an animation frame number to display.
frame_count = 0
animation_frames = 4
while quit == False:
# ...
# snip
# ...
area = pygame.Rect(
image_number * 100,
(frame_count % animation_frames) * 150,
100,
150
)
display.blit(sprite, sprite_pos, area)
pygame.display.flip()
frame_count += 1
If different actions have different numbers of frames, you'll have to update animation_frames when you update image_number.
Also, this assumes that it's ok to play the animation starting at any frame. If this is not the case, you'll need to record what the frame count was when the action started, and take this away from frame count before the modulo:
area = pygame.Rect(
image_number * 100,
((frame_count - action_start_frame) % animation_frames) * 150,
100,
150
)
A note about your event handling. If you hold down, say, left, and tap right but keep holding down left, the sprite stops moving because the last event you processed was a keyup event, despite the fact that I'm still holding left.
If this is not what you want, you can get around it by either keeping a record of the up/down states of the keys you are interested in, or by using the pygame.key.get_pressed interface.
On another note, you appear to be aiming for a fixed frame rate, and at the same time determining how far to move your sprite based on the time taken in the last frame. In my opinion, this probably isn't ideal.
2D action games generally need to work in a predictable manner. If some CPU heavy process starts in the background on your computer and causes your game to no longer be able to churn out 60 frames a second, it's probably preferable for it to slow down, rather then have your objects start skipping huge distances between frames. Imagine if this happened in a 2D action game like Metal Slug where you're having to jump around avoiding bullets?
This also makes any physics calculations much simpler. You'll have to make a judgement call based on what type of game it is.

Categories