I am trying to implement a game using mouse position to see if the user clicks a button. Somehow the mouse position does not update for a couple seconds, and changes to a new position for another couple seconds, and repeat. I moved and pressed the mouse at different location in the screen, but the mouse position did not change at all. (Working on python3.5.1 and pygame 1.9.2, using IDE PyCharm)Any idea?
Here is my code:
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if click[0]==1:
print(mouse)
pygame.display.update()
The call
mouse = pygame.mouse.get_pos()
doesn't update the position unless the event MouseMotion is executed.
If you are executing the program in a window on a MAC, the mouse must be pressed, held, and moved (if you were to press, hold, then move the mouse, pygame.mouse.get_pos() would return the current mouse position).
There is two ways of handling input events in pygame :
State Checking
Event Handling
For better understanding of how it works :
http://www.pygame.org/docs/tut/newbieguide.html#managing-the-event-subsystem
You use both in your code, state checking :
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
Event handling :
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
If you still want to use state checking to get the mouse position you can add:
clock=pygame.time.Clock()
clock.tick(60) # 60 frames per second
So the update of the position should be better.
If the button has a rect then you can use the rect.collidepoint() method with event checking like this:
mouse_pos = pygame.mouse.get_pos()
if event.type == pygame.MOUSEBUTTONDOWN and pygame.mouse.get_pressed()[0] and button.rect.collidepoint(mouse_pos):
This drove me crazy for hours. I had a similar problem.
Using pygame in:
Mac OSX 10.13 (High Sierra)
pygame 1.9.3
python 3.6
in a virtualenv
In this setup (specifically in the virtualenv), window focus is not properly tracked. Click and dragging will generate a MOUSEMOTION event, but simply moving the mouse around will not. If the MOUSEMOTION event is not generated, calling:
pos = pygame.mouse.get_pos()
will continue report the same value until another MOUSEMOTION event occurs.
Installing pygame outside of the virtualenv, all works as expected. Not really the answer I was hoping for, but at least it explains the behavior I was seeing.
Your
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
only get the states at the time of the call. As per the documentation http://www.pygame.org/docs/ref/mouse.html:
to get all of the mouse events it is better to use either
pygame.event.wait() or pygame.event.get() and check all of those events
That is you are missing the clicks because your program isn't storing them to process. You only see it when you get lucky and the program calls the function when the button is actually down.
This shows a basic pygame mouse getting program. Simply click anywhere in the window and the mouse coordinate are printed:
import pygame as py
py.init()
white = (255,255,255)
window = (400,400)
screen = py.display.set_mode(window)
clock = py.time.Clock()
done = False
while not done:
for event in py.event.get():
if event.type == py.QUIT:
done = True
elif event.type == py.MOUSEBUTTONDOWN:
print py.mouse.get_pos()
screen.fill(white)
py.display.flip()
clock.tick(30)
py.quit()
hope this helps :)
Related
I've read everything I could find about the mouse in pygame and yet I miss something.
The device has (and will not) have a mouse attached so I need to remove the cursor from the game surface, ideally even before it draws the first screen.
But no matter what I try I always have a big oppalin cursor in the middle of the screen.
My current function is this :
# initialize the pygame module
pygame.init()
# create a surface on screen that has the size of 240 x 180
screen = pygame.display.set_mode((160,80))
# define a variable to control the main loop
running = True
pygame.display.flip()
# main loop
while running:
screen.fill((0, 0, 0))
# hide cursor
pygame.mouse.set_pos((160,80)) # my screen is actually 160 x 80 px so this should hide it by pushing it over the edge
pygame.mouse.set_visible(False) # this should hide the mouse plain and simple
# Here I do other unrelated (but working) stuff, like displaying images and text
# event handling, gets all event from the event queue
for event in pygame.event.get():
# only do something if the event is of type QUIT
if event.type == pygame.QUIT:
# change the value to False, to exit the main loop
running = False
pygame.display.flip()
And the mouse is still on screen, sometimes after a while it disappears.
I tried other method like making the cursor transparent, but that crash the app.
Note that I'm running Pygame on an Alpine Linux with direct output to the framebuffer on a Raspberry Pi. There's no mouse attached to the device but if I connect one I can move the cursor around.
Pygame is Version 2.1.2 (compiled and installed by pip)
Python is 3.10.0
Any help or pointer would be greatly appreciated.
(sorry if it's a dumb question; I'm a total noob with python/pygame)
Just write the set_visible(False) outside the main loop, you don't need to call this every frame:
pygame.init()
screen = pygame.display.set_mode((160,80))
pygame.mouse.set_visible(False) # Hide cursor here
running = True
pygame.display.flip()
# main loop
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# unrelated with your question but I also suggest that you clear your background inside the loop, at the contrary you likely will need this at each frame
screen.fill((0, 0, 0))
# ... your code, blitting images etc
pygame.display.flip()
I'm learning Pygame to make games w/ Python. However, I'm encountering a problem. I'm trying to detect when the player is currently clicking the screen, but my code isn't working. Is my code actually screwed, or is it just the online Pygame compiler that I'm using?
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 800))
while True:
pygame.display.update()
mouse = pygame.mouse.get_pressed()
if mouse:
print("You are clicking")
else:
print("You released")
When I ran this code, the output console spammed the text "You are clicking", thousands of times in a second. Even when I'm not clicking the screen, it still says this. Even when my mouse isn't over the screen. Just the same text. Over, and over. Is Pygame executing my program correctly?
To learn Pygame, I am using the official Docs from the developers. https://www.pygame.org/docs/ Is this an outdated way to learn, is this why my code continues to run errors?
The coordinates which are returned by pygame.mouse.get_pressed() are evaluated when the events are handled. You need to handle the events by either pygame.event.pump() or pygame.event.get().
See pygame.event.get():
For each frame of your game, you will need to make some sort of call to the event queue. This ensures your program can internally interact with the rest of the operating system.
pygame.mouse.get_pressed() returns a sequence of booleans representing the state of all the mouse buttons. Hense you have to evaluate if any button is pressed (any(buttons)) or if a special button is pressed by subscription (e.g. buttons[0]).
For instance:
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 800))
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
buttons = pygame.mouse.get_pressed()
# if buttons[0]: # for the left mouse button
if any(buttons): # for any mouse button
print("You are clicking")
else:
print("You released")
pygame.display.update()
If you just want to detect when the mouse button is pressed respectively released, then you have to implement the MOUSEBUTTONDOWN and MOUSEBUTTONUP (see pygame.event module):
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 800))
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
print("You are clicking", event.button)
if event.type == pygame.MOUSEBUTTONUP:
print("You released", event.button)
pygame.display.update()
While pygame.mouse.get_pressed() returns the current state of the buttons, the MOUSEBUTTONDOWN and MOUSEBUTTONUP occurs only once a button is pressed.
The function pygame.mouse.get_pressed returns a list which contains true or false so for single click u should use-
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 800))
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.display.update()
mouse = pygame.mouse.get_pressed()
if mouse[0]:
print("You are clicking")
else:
print("You released")
I am trying to create a simple program in which a user can move a shape on the screen using his finger (on a touchscreen).
this is my code so far:
import pygame
def main():
pygame.init()
DISPLAY = pygame.display.set_mode((1000,500),0,32)
WHITE = (255,255,255)
blue = (0,0,255)
DISPLAY.fill(WHITE)
pygame.mouse.set_visible(False)
pygame.draw.rect(DISPLAY, blue,(480,200,50,250))
pygame.display.update()
pygame.mouse.set_pos(480, 200)
while True:
for event in pygame.event.get():
pos = pygame.mouse.get_pos()
pygame.draw.rect(DISPLAY, blue, (pos[0]-25,pos[1], 50, 250))
pygame.display. update()
DISPLAY.fill(WHITE)
main()
The problem is that when I touch the screen, nothing will happen until I move my finger. If I print the events I can see that there is no event listed until I start moving my finger, so that is probably the reason.
I want to be able to register the finger press (as an event I guess) on the screen even before it starts to move, is there anyway to do this using PyGame?
Thanks.
In case anyone is stumbling across this later, in pygame 2 there is much better touch support. You can install with
pip install pygame==2.0.0.dev6
(check the pygame github for the most recent version) And there are three new event types. pygame.FINGERDOWN, pygame.FINGERUP, and pygame.FINGERMOTION. The pygame.FINGERUP event registers the touch input right when the screen is touched instead of when the screen is released like pygame.MOUSEBUTTONDOWN
I have made a game that utilises a computer touch screen and manages the touch quite well by handling two types of events. One is pygame.MOUSEMOTION and the other one is pygame.MOUSEBUTTONDOWN. Both of them contain the attribute event.pos. Problem is, at least when it comes to my touch screen (Lenovo), that the initial touch is not registered by the event handler of pygame.
You can confirm this by printing all the events to the terminal while touching your screen. I get nothing until I release or move my finger but on release I get the event pygame.MOUSEBUTTONDOWN rapidly followed by pygame.MOUSEBUTTONUP.
I know that this doesn't really solve your problem, but it might perhaps help you in some way. Otherwise, check out Kivy. There might be a solution there.
import pygame
def main():
pygame.init()
DISPLAY = pygame.display.set_mode((1000,500),0,32)
WHITE = (255,255,255)
blue = (0,0,255)
DISPLAY.fill(WHITE)
pygame.mouse.set_visible(False)
pygame.draw.rect(DISPLAY, blue,(480,200,50,250))
pygame.display.update()
pygame.mouse.set_pos(480, 200)
while True:
for event in pygame.event.get():
if event.type == MOUSEBUTTONDOWN or event.type == MOUSEMOTION:
pos = event.pos
pygame.draw.rect(DISPLAY, blue, (pos[0]-25,pos[1], 50, 250))
pygame.display. update()
DISPLAY.fill(WHITE)
main()
My program does only two things :
1) It's printing word 'hello' every time i hover mouse on one of two images (anyone,in any order)
2) It's closing , when i close window by pressing ESC , or by mouse
import pygame,sys ,os,random,math
from pygame.locals import *
pygame.init()
white=(255,255,255)
black=(0,0,0)
WINDOWWIDTH = 1680
WINDOWHEIGHT =1050
mousex, mousey=0,0
screen=pygame.display.set_mode((WINDOWWIDTH,WINDOWHEIGHT))
ticket=pygame.image.load(os.path.join('imag','ticket.png'))
ticket2=pygame.image.load(os.path.join('imag','ticket2.png'))
def terminate():
pygame.quit()
sys.exit()
def checkForQuit():
for event in pygame.event.get(QUIT): # get all the QUIT events
terminate() # terminate if any QUIT events are present
for event in pygame.event.get(KEYUP): # get all the KEYUP events
if event.key == K_ESCAPE:
terminate() # terminate if the KEYUP event was for the ESc key
pygame.event.post(event)
tic1=ticket.get_rect(topleft=(50,770))
tic2=ticket2.get_rect(topleft=(220,770))
List_of_tickets=[tic1,tic2]
while 1:
screen.fill(white)
checkForQuit()
screen.blit(ticket,(50,770))
screen.blit(ticket2,(220,770))
for tic in List_of_tickets:
if tic.collidepoint(pygame.mouse.get_pos()):
print 'Hello !'
pygame.display.update()
The problem is that second part is not working !
So if i hover mouse on one ticket - everything fine . I got my 'Hello' word and i can close window if i need to .
But if i hover mouse on one ticket , and THEN on second ticket (so i got many more of my 'Hello' - and that's good) - i cannot quit program nor with ESC , nor with mouse.
It seems like quitting event ceased to be handled.
The questions are :
1) What i do not understand in handling of events in Pygame ?
2) What should i do to make my code quittin in any case ?
From the docs:
"If you are only taking specific events from the queue, be aware that the queue could eventually fill up with the events you are not interested."
Toss pygame.event.clear() in there and see what happens.
(If so, the reason it only fails if you go to both tickets is that all mouse movements add an event; moving to one ticket doesn't completely fill the queue, but moving to both does. Slightly wiggling the mouse would have the same effect.)
This question already has answers here:
Pygame window not responding after a few seconds
(3 answers)
Pygame unresponsive display
(1 answer)
Closed 1 year ago.
Basically I have a loop (tick, set_caption, screen_fill, event.get(), send_frame_event, flip, repeat)
When I drag the window around on windows 7, the loop stops looping, I ended up stuck in pygame.event.get(), I have tried to define certain events only for get e.g. get([pygame.QUIT]) to no avail.
Simply calling pygame.event.clear() has the same freeze effect when dragging/moving the window.
Is there a workaround?
Not full code, but should be enough:
def start(self):
self.running = True
Clock = pygame.time.Clock()
while self.running:
self.p += 25
tickFPS = Clock.tick(self.fps)
pygame.display.set_caption("Press Esc to quit. FPS: %.2f" % (Clock.get_fps()))
self.screen.fill([self.p&0xFF,(255-self.p)&0xFF,255])
self.handleEvents()
self.raiseEvent("updateFrame")
pygame.display.flip()
def handleEvents(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
self.running = False
full code at: http://pastie.org/private/wm5vqq3f7xe0xlffy1fq
Try placing a call to pygame.event.pump() inside your mainloop (or handleEvents function)
No idea if this will help or not:
I realize the problem is with moving the window window, not with re-sizing the window.
Perhaps there is some similarity between moving and re-sizing?
I found this in the documentation on re-sizing:
Then the display mode is set, several events are placed on the pygame event queue. pygame.QUIT is sent when the user has requested the program to shutdown. The window will receive pygame.ACTIVEEVENT events as the display gains and loses input focus. If the display is set with the pygame.RESIZABLE flag, pygame.VIDEORESIZE events will be sent when the user adjusts the window dimensions. Hardware displays that draw direct to the screen will get pygame.VIDEOEXPOSE events when portions of the window must be redrawn.
and:
Note that when the user resizes the game window, pygame does not automatically update its internal screen surface. You must call set_mode() every time VIDEORESIZE is sent. This really should be more clear in the documentation.
Perhaps when moving the game window, something similar happens?