Keyboard Control
Keyboard input lets players control characters, navigate menus, and trigger actions. PyGame offers two approaches: event-based (single press/release) and state-based (continuous hold).
Learning Objectives
- 12.5.3.4 Code keyboard control to move objects
Conceptual Anchor
Two Listening Modes
Event-based = a doorbell: you hear it ring once per press. Perfect for shooting, jumping, pausing. State-based = checking if a light switch is on: you check every frame. Perfect for smooth walking/running.
Rules & Theory
Method 1: Event-Based (Single Action)
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
print("Space pressed!")
if event.type == pygame.KEYUP:
if event.key == pygame.K_SPACE:
print("Space released!")Method 2: State-Based (Continuous Movement)
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
player_x -= speed
if keys[pygame.K_RIGHT]:
player_x += speed
if keys[pygame.K_UP]:
player_y -= speed
if keys[pygame.K_DOWN]:
player_y += speedCommon Key Constants
| Constant | Key | Constant | Key |
|---|---|---|---|
K_LEFT |
← | K_a |
A |
K_RIGHT |
→ | K_d |
D |
K_UP |
↑ | K_w |
W |
K_DOWN |
↓ | K_s |
S |
K_SPACE |
Space | K_RETURN |
Enter |
K_ESCAPE |
Esc | K_TAB |
Tab |
Worked Examples
1 Player Movement (Arrow Keys)
import pygame, sys
pygame.init()
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Arrow Key Movement")
clock = pygame.time.Clock()
# Player
player = pygame.Rect(375, 275, 50, 50)
speed = 5
RED = (255, 50, 50)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Continuous key checking
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
player.x -= speed
if keys[pygame.K_RIGHT]:
player.x += speed
if keys[pygame.K_UP]:
player.y -= speed
if keys[pygame.K_DOWN]:
player.y += speed
# Keep player on screen
player.clamp_ip(screen.get_rect())
# Render
screen.fill((30, 30, 30))
pygame.draw.rect(screen, RED, player)
pygame.display.flip()
clock.tick(60)
pygame.quit()
sys.exit()2 WASD + Arrow Keys (Dual Control)
keys = pygame.key.get_pressed()
# Move left with A or LEFT arrow
if keys[pygame.K_a] or keys[pygame.K_LEFT]:
player.x -= speed
# Move right with D or RIGHT arrow
if keys[pygame.K_d] or keys[pygame.K_RIGHT]:
player.x += speed
# Move up with W or UP arrow
if keys[pygame.K_w] or keys[pygame.K_UP]:
player.y -= speed
# Move down with S or DOWN arrow
if keys[pygame.K_s] or keys[pygame.K_DOWN]:
player.y += speed3 Single-Press Actions (Shoot Bullet)
bullets = []
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
# Create bullet at player position
bullet = pygame.Rect(player.centerx - 3,
player.top, 6, 12)
bullets.append(bullet)
# Move all bullets upward
for bullet in bullets[:]:
bullet.y -= 8
if bullet.bottom < 0:
bullets.remove(bullet)Common Pitfalls
Using KEYDOWN for Movement
KEYDOWN fires once per press. For smooth movement, use
get_pressed() which checks key state every frame.
Diagonal Speed Boost
Moving diagonally (right+up) moves √2 ≈ 1.41× faster! Fix with vector normalization or just limit speed separately.
Tasks
Create a player square that moves with WASD keys and stays within the window boundaries.
Add sprint: when holding Shift, player moves at 2× speed.
Create a 2-player game: Player 1 uses WASD, Player 2 uses arrow keys. Both move independently.
Self-Check Quiz
Q1: What's the difference between KEYDOWN and get_pressed()?
KEYDOWN fires once
per press (event). get_pressed() returns current state of all keys every frame
(continuous).Q2: How do you keep a player inside the window?
player.clamp_ip(screen.get_rect()) — clamps the player rect inside the screen rect
in place.Q3: When should you use event-based vs state-based keyboard input?