Code of the Day
BeginnerGame Concepts

Player input

Poll the event queue for discrete key presses and use pygame.key.get_pressed for held keys — then wire both to move a sprite.

Game DevBeginner10 min read
By the end of this lesson you will be able to:
  • Poll the event queue for QUIT and KEYDOWN events
  • Use pygame.key.get_pressed to detect continuously held keys
  • Explain the difference between event-driven and polled input
  • Move a player rectangle in four directions using arrow keys

Until now the rectangle moved on its own. This lesson wires the keyboard to the player's position, turning a demo into something interactive. There are two ways to read input in pygame, and knowing when to use each saves a lot of frustration.

Two input models

Event-driven input captures discrete moments: a key was pressed down, a key was released, the mouse was clicked. Pygame stores these events in a queue between frames. You drain the queue with pygame.event.get() and handle each event exactly once.

Use the event queue for one-shot actions: opening a menu, firing a bullet, or toggling pause. If you read movement from the event queue, the player will stutter — one step per keypress, not smooth motion.

Polled input asks "what is the keyboard state right now?" every frame. pygame.key.get_pressed() returns a list indexed by key code. If keys[K_RIGHT] is True, the right arrow is currently held. Check this every frame and you get smooth, continuous movement.

Use polled input for anything the player holds: movement, charging an attack, holding a shield.

Input-driven movement

Pyodide (the in-browser Python runner) does not support pygame's display system. Read through this code carefully, then run it locally: pip install pygame followed by python input.py.

import pygame
import sys

pygame.init()
screen = pygame.display.set_mode((640, 480))
pygame.display.set_caption("Player input")

clock = pygame.time.Clock()

# Player state
px, py = 300, 220   # starting position
SPEED = 4
SIZE = 40

running = True
while running:
    # --- Phase 1: process input ---

    # Event queue: handle one-shot events
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                running = False          # Escape also quits

    # Polled input: handle continuous movement
    keys = pygame.key.get_pressed()
    if keys[pygame.K_LEFT]:
        px -= SPEED
    if keys[pygame.K_RIGHT]:
        px += SPEED
    if keys[pygame.K_UP]:
        py -= SPEED
    if keys[pygame.K_DOWN]:
        py += SPEED

    # Clamp player inside the window
    px = max(0, min(640 - SIZE, px))
    py = max(0, min(480 - SIZE, py))

    # --- Phase 2: update state ---
    # (No other state to update for now)

    # --- Phase 3: render ---
    screen.fill((20, 20, 30))
    pygame.draw.rect(screen, (100, 210, 120), (px, py, SIZE, SIZE))
    pygame.display.flip()

    clock.tick(60)

pygame.quit()
sys.exit()

What each part does

pygame.event.get() drains the queue. Every frame you must drain it — even if you only care about QUIT — or the queue fills up and the window stops responding. Never skip the event loop.

event.type == pygame.KEYDOWN fires exactly once when a key transitions from up to down. event.key identifies which key. Use this for menu navigation, shooting, and any action that should happen once per press.

keys = pygame.key.get_pressed() gives you the live keyboard state. It is a sequence; index it with a key constant. Since you call this every frame inside the loop, movement is updated 60 times per second and feels smooth.

The clamp px = max(0, min(640 - SIZE, px)) prevents the player from moving outside the window boundaries. max(0, ...) stops negative x; min(640 - SIZE, ...) stops x from pushing the rectangle's right edge past the screen width.

Both input methods are independent. You can check polled keys and process the event queue in the same frame. In a real game you always do both: event queue for actions, polled keys for movement.

Where to go next

Next: lab — build a basic game — apply everything from this module to build a minimal complete game: a player that moves, a goal square to reach, and a win condition.

Finished reading? Mark it complete to track your progress.

On this page