33. Events and input — Homework solutions
Problem 1 — Key reporter
Problem. Print which key is currently held to the
terminal each frame; print "no key" when nothing is
held.
How to think about it. Check
pygame.key.get_pressed() for each key you care about. Use a
flag variable to know whether any key matched. Checking every possible
key is impractical, so check the ones that matter — arrow keys,
spacebar, escape.
Worked solution.
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Key Reporter")
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
held = []
if keys[pygame.K_LEFT]:
held.append("left")
if keys[pygame.K_RIGHT]:
held.append("right")
if keys[pygame.K_UP]:
held.append("up")
if keys[pygame.K_DOWN]:
held.append("down")
if keys[pygame.K_SPACE]:
held.append("space")
if keys[pygame.K_ESCAPE]:
running = False
if held:
print(", ".join(held))
else:
print("no key")
screen.fill((30, 30, 30))
pygame.display.flip()
clock.tick(10) # slow tick so terminal output is readable
pygame.quit()clock.tick(10) slows to 10 fps so the terminal does not
flood with 60 prints per second.
Common mistakes.
- Using
pygame.KEYDOWNevent instead ofget_pressed.KEYDOWNfires only once per press;get_pressedreturns the current held state every frame.
Problem 2 — Click counter
Problem. Count left-clicks and print the count each time it goes up.
How to think about it. A counter variable starts at
0. On MOUSEBUTTONDOWN with event.button == 1,
increment and print.
Worked solution.
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Click Counter")
clock = pygame.time.Clock()
clicks = 0
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
clicks += 1
print(f"clicks: {clicks}")
screen.fill((30, 30, 30))
pygame.display.flip()
clock.tick(60)
pygame.quit()Common mistakes.
- Checking
event.button == 1insideMOUSEBUTTONDOWNis important because button3(right-click) would also triggerMOUSEBUTTONDOWN.
Problem 3 — Arrow mover
Problem. A circle that moves with arrow keys; Escape
quits; print "moved" each frame the circle is moving.
How to think about it. Use get_pressed
for movement. Track whether any movement key is held to decide whether
to print.
Worked solution.
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Arrow Mover")
clock = pygame.time.Clock()
cx, cy = 400, 300
speed = 4
running = True
while running:
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
keys = pygame.key.get_pressed()
moving = False
if keys[pygame.K_LEFT]:
cx -= speed
moving = True
if keys[pygame.K_RIGHT]:
cx += speed
moving = True
if keys[pygame.K_UP]:
cy -= speed
moving = True
if keys[pygame.K_DOWN]:
cy += speed
moving = True
if moving:
print("moved")
screen.fill((30, 30, 30))
pygame.draw.circle(screen, (255, 100, 100), (cx, cy), 30)
pygame.display.flip()
clock.tick(60)
pygame.quit()Common mistakes.
- Putting the Escape check inside
get_pressed. Escape as an exit key is a one-shot action — put it inKEYDOWN, notget_pressed. Both work technically, butKEYDOWNis the correct pattern for exit.
Challenge — Mouse follower
Problem. Draw a circle that follows the mouse. Change its colour while the left button is held.
How to think about it. Track a boolean
button_held. Set it to True on
MOUSEBUTTONDOWN and back to False on
MOUSEBUTTONUP. Use it to choose the draw colour.
Worked solution.
import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Mouse Follower")
clock = pygame.time.Clock()
button_held = False
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
button_held = True
if event.type == pygame.MOUSEBUTTONUP:
if event.button == 1:
button_held = False
mx, my = pygame.mouse.get_pos()
color = (255, 255, 0) if button_held else (200, 200, 200)
screen.fill((30, 30, 30))
pygame.draw.circle(screen, color, (mx, my), 15)
pygame.display.flip()
clock.tick(60)
pygame.quit()pygame.mouse.get_pos() returns the current cursor
position, updated every frame. The circle stays centred on the
cursor.
Common mistakes.
- Using
pygame.mouse.get_pressed()[0]directly instead of trackingMOUSEBUTTONDOWN/MOUSEBUTTONUP. Both approaches work. The event approach is shown here because it follows the pattern used in the chapter.
Done?
Chapter 34 uses positions and velocities to make objects move inside the game loop.