Pygame records everything the player does as an event: a key going down, the mouse moving, the window's close button. The events wait in a queue, and pygame.event.get() hands you all of them once per frame:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
Each event has a type and, depending on the type, some attributes. This program prints every key, click and wheel turn it receives:
Press Play, click the game, then press keys and click. The Console shows each event.
Common event types
| Type | When | Attributes |
|---|---|---|
QUIT | The window's close button | none |
KEYDOWN | A key goes down | key, unicode, mod, scancode |
KEYUP | A key comes up | key, mod, scancode |
MOUSEBUTTONDOWN | A mouse button goes down | pos, button |
MOUSEBUTTONUP | A mouse button comes up | pos, button |
MOUSEMOTION | The mouse moves | pos, rel, buttons |
MOUSEWHEEL | The wheel turns | x, y |
TEXTINPUT | Text is typed (respects the keyboard layout) | text |
WINDOWFOCUSLOST, WINDOWFOCUSGAINED | The window loses or gains focus | |
USEREVENT and custom types | Your own events | Anything you attach |
Key events are covered on keyboard input and mouse events on mouse input.
Events or state?
Events tell you that something changed: a key went down once. For things that last, such as holding an arrow key to walk, ask for the current state instead: pygame.key.get_pressed() and pygame.mouse.get_pressed(). A rule of thumb:
- One action per press (jump, shoot, pause, menu choice): use the
KEYDOWNevent. - Continuous action while held (walk, aim, accelerate): use
get_pressed().
Read the queue once per frame
pygame.event.get() empties the queue. A second call in the same frame gets nothing that the first one took, so a game that calls it in two places loses key presses at random. Read events in one loop and pass what you need along.
The queue also needs reading for the window to stay alive: if your loop never calls pygame.event.get(), the system reports the window as not responding.
Custom events
Your own events go through the same queue. pygame.event.custom_type() returns a fresh event type number, and pygame.event.post() puts an event in the queue:
Any keyword you pass to pygame.event.Event (here points) becomes an attribute of the event. Custom events are a clean way for one part of a game to tell another that something happened. To post one on a timer, see pygame timers.
Other event functions
| Function | Does |
|---|---|
pygame.event.get() | Returns and removes all events |
pygame.event.get(pygame.KEYDOWN) | Returns and removes only events of that type |
pygame.event.poll() | Returns one event, or NOEVENT if the queue is empty |
pygame.event.wait() | Waits until an event arrives (for programs that only react to input) |
pygame.event.clear() | Throws the queued events away |
pygame.event.set_blocked(type) | Stops a type from being queued |
Frequently Asked Questions
What does pygame.event.get() do?
It returns a list of every event that happened since the last call (key presses, mouse clicks, the window closing) and empties the queue. Call it once per frame and loop over the list.
How do I check which key was pressed in an event?
Look for event.type == pygame.KEYDOWN, then compare event.key with a key constant such as pygame.K_SPACE. event.unicode holds the character typed, such as "a".
Should I call pygame.event.get() more than once per frame?
No. Each call empties the queue, so a second call misses the events the first one took. Read the events once and handle them all in the same loop.
How do I make a custom event?
Get a new type with MY_EVENT = pygame.event.custom_type(), then post it with pygame.event.post(pygame.event.Event(MY_EVENT)), or have pygame post it on a timer with pygame.time.set_timer(MY_EVENT, 1000).