By the end of this guide, you’ll have a real, playable game running on your Raspberry Pi — a moving player square that collects targets, tracks your score, and responds to keyboard input. Pygame is a Python library built for exactly this kind of project, and it runs surprisingly well on Pi hardware. This walkthrough covers everything from installation to a finished game, with every code block explained so you can modify it confidently.
What You’ll Build
- Project: Pygame collector game on Raspberry Pi
- Tools Needed: Raspberry Pi 3B+ or newer, Raspberry Pi OS, Python 3, Pygame 2.x
- Difficulty: Beginner
- Time Required: 45–60 minutes
What You’ll Need Before You Start
Getting your hardware and software lined up before writing a single line of code saves a lot of frustration. Pygame works best on a Pi connected directly to a display — headless setups (running the Pi without a monitor via SSH) require extra display configuration that’s outside the scope of this walkthrough.
Required Hardware
- Raspberry Pi 3B+, Pi 4, or Pi 5 (Pi 3B+ is the minimum for smooth Pygame performance at 60fps)
- MicroSD card with Raspberry Pi OS Bookworm installed (32-bit or 64-bit both work)
- Monitor connected via HDMI
- USB keyboard and mouse
Required Software
- Python 3 — pre-installed on Raspberry Pi OS, confirm with
python3 --version - pip3 — the Python package manager, also pre-installed
- A terminal window open on the Pi’s desktop
You can write your code in Thonny IDE, which comes pre-installed on Raspberry Pi OS and offers syntax highlighting and a built-in file runner. Open it from the Programming menu on your desktop.
Installing Pygame on Raspberry Pi
How do you install Pygame on a Raspberry Pi? The process takes about five minutes, but skipping the system update step first causes dependency errors that trip up many first-timers. Run these commands in order from your terminal.
Step-by-Step Installation
- Open the terminal on your Raspberry Pi desktop.
- Update your system packages:
sudo apt update && sudo apt upgrade -y - Install Pygame using pip3:
pip3 install pygame - Verify the install worked:
python3 -c 'import pygame; print(pygame.ver)'
You should see a version number printed — something like 2.5.2. If the install fails on an older Pi OS version, fall back to a tested stable release: pip3 install pygame==2.1.2. This version handles SDL (Simple DirectMedia Layer, the graphics library Pygame sits on top of) dependencies cleanly on older Raspberry Pi OS builds.
Confirm everything works by running the built-in aliens demo: python3 -m pygame.examples.aliens. A retro shooter should launch. If it does, your Pygame setup is solid.
Understanding the Pygame Game Loop
The game loop is the engine behind every Pygame project. Your Pi runs it dozens of times per second, and each pass does exactly three things: read player input, update the game state, and draw everything to the screen. Miss any one of those phases and your game either freezes, ignores controls, or flickers.
The Three Core Phases
- Event handling: Check what the player is doing — pressing keys, clicking, or closing the window.
- Update logic: Move the player, check for collisions, update the score.
- Draw/render: Clear the screen, draw every object in its new position, push the frame to the display.
The pygame.time.Clock object controls how fast this loop runs. Call clock.tick(60) to cap the loop at 60 frames per second. Without it, the loop runs as fast as your Pi’s CPU allows — which sounds good until your game runs at different speeds on different hardware, and your Pi’s processor hits 100% for no reason.
Here’s the minimal skeleton every Pygame script starts with:
import pygame
import sys
pygame.init() # Start all Pygame modules
screen = pygame.display.set_mode((800, 600)) # Create the game window
clock = pygame.time.Clock() # Create the frame rate controller
running = True
while running: # Main game loop starts here
for event in pygame.event.get(): # Check for events
if event.type == pygame.QUIT: # Player closed the window
running = False
screen.fill((0, 0, 0)) # Clear screen with black
pygame.display.flip() # Push frame to display
clock.tick(60) # Cap at 60fps
pygame.quit()
sys.exit()
This block creates the game window, runs the loop, and exits cleanly. Run it and you’ll see a black 800×600 window. That’s your canvas.
Drawing a Player and Handling Keyboard Input
This is where it gets interesting. You’ll draw a rectangle as your player and move it with the arrow keys. The key method here is pygame.key.get_pressed(), which returns the state of every key on every frame — perfect for smooth, held-down movement.
Player Movement Code
Add these variables before your game loop, then add the movement block inside the loop after event handling:
player_x = 375 # Starting X position
player_y = 275 # Starting Y position
player_speed = 4 # Pixels moved per frame
BLUE = (50, 120, 220) # Player color as RGB tuple
# Inside the game loop, after event handling:
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and player_x > 0:
player_x -= player_speed
if keys[pygame.K_RIGHT] and player_x < 760:
player_x += player_speed
if keys[pygame.K_UP] and player_y > 0:
player_y -= player_speed
if keys[pygame.K_DOWN] and player_y < 560:
player_y += player_speed
# In the draw section:
pygame.draw.rect(screen, BLUE, (player_x, player_y, 40, 40))
The boundary checks (player_x > 0 and player_x < 760) clamp the player to the screen edges. The 760 limit accounts for the 40-pixel width of the rectangle inside an 800-pixel window. Pygame uses RGB tuples — three numbers from 0 to 255 representing red, green, and blue — for every color you define.
Use pygame.key.get_pressed() for held movement. Use event-based pygame.KEYDOWN inside your event loop for single-press actions like pausing or firing.
Adding a Target and Collision Detection
A moving square alone isn't a game. Add a target the player collects, track the score, and display it on screen. This section introduces pygame.Rect — a rectangle object that handles collision detection with a single method call.
Target and Score Setup
Add these imports and variables at the top of your script:
import random
RED = (220, 60, 60)
score = 0
target_x = random.randint(0, 760)
target_y = random.randint(0, 560)
font = pygame.font.SysFont("monospace", 28)
Collision Detection with pygame.Rect
Inside your game loop, after updating player position, add this collision block:
player_rect = pygame.Rect(player_x, player_y, 40, 40)
target_rect = pygame.Rect(target_x, target_y, 30, 30)
if player_rect.colliderect(target_rect):
score += 1
target_x = random.randint(0, 760)
target_y = random.randint(0, 560)
# In the draw section:
pygame.draw.rect(screen, RED, (target_x, target_y, 30, 30))
score_text = font.render(f"Score: {score}", True, (255, 255, 255))
screen.blit(score_text, (10, 10))
colliderect() returns True when two pygame.Rect objects overlap. On collision, the target jumps to a new random position and your score goes up by one. The screen.blit() call draws the rendered text surface onto the screen at coordinates (10, 10) — top-left corner.
Running Your Game and Fixing Common Issues
Save your script as collector_game.py and run it from the terminal: python3 collector_game.py. A window should open immediately with your player and target visible.
Common Errors and Fixes
pygame.error: No available video device — This appears when you run the script from an SSH session without a display. Pygame needs a screen to draw to. Run your script from the terminal on the Pi's desktop instead, or set the display variable first: export DISPLAY=:0 before running.
ModuleNotFoundError: No module named 'pygame' — pip installed Pygame for a different Python version. Try python3 -m pip install pygame to make sure you're installing to the right interpreter.
Slow or choppy performance on Pi Zero or Pi 2 — Reduce the window size to 480x320 and lower your clock tick to 30fps. These older models handle smaller render areas much better. The Pi 3B+ and Pi 4 run 800x600 at 60fps without issues.
Where to Take Your Pygame Project Next
You've built a working game. The structure you understand now — init, game loop, event handling, draw, clock — applies to every Pygame project you'll ever build. So what comes next?
- Add a countdown timer: Use
pygame.time.get_ticks()to track elapsed time and introduce a "game over" state when the timer hits zero. This teaches you game state management. - Replace rectangles with sprites: Load a PNG image with
pygame.image.load('player.png')and draw it instead of a plain rectangle. Suddenly your game looks like a real game. - Add sound effects:
pygame.mixer.Sound('collect.wav').play()fires a sound on collision. Pygame's mixer module handles audio with just a few lines. - Build a two-player version: Map WASD keys to a second player rectangle. Two players, one keyboard, one screen — a natural fit for Pi game nights.
Ready to go further? Check out our related guide on beginner Python projects for Raspberry Pi, or explore building a retro game console with RetroPie to run your Pygame creations on a dedicated arcade setup. Every project you finish is the starting point for the next one.
Frequently Asked Questions
Can Pygame actually run on a Raspberry Pi without lag?
Yes — on a Raspberry Pi 3B+ or newer, Pygame runs smoothly at 60fps for 2D games at standard resolutions like 800x600. The Pi Zero and Pi 2 can handle Pygame at lower resolutions and 30fps. Stick to 2D rendering and avoid loading large uncompressed images for best performance.
What version of Pygame works with Raspberry Pi OS Bookworm?
Pygame 2.x installs cleanly on Raspberry Pi OS Bookworm using pip3 install pygame. If you're on an older OS version and hit dependency errors, install pygame==2.1.2 as a stable fallback.
Why is Pygame running slowly on my Raspberry Pi?
The most common cause is a missing clock.tick() call, which lets the game loop run uncapped and pins your CPU. Add clock.tick(60) at the end of your loop. Also reduce your window size if you're on a Pi Zero or Pi 2.
How do I stop my Pygame game from freezing?
A frozen game almost always means your event loop isn't processing events. Make sure pygame.event.get() runs on every iteration of your main loop. Skipping this call causes the OS to think your window has stopped responding.
What games can I make with Pygame on Raspberry Pi?
Pygame handles any 2D game well — platformers, top-down shooters, puzzle games, and collectors like the one in this guide. It's also a solid base for educational simulations and interactive art projects. The library's built-in support for sprites, sound, and fonts covers most beginner and intermediate game types.

Simon Gregory, a seasoned Raspberry Pi enthusiast and IoT innovator, brings a wealth of knowledge to Pi Beginners. With a background in computer science and a passion for teaching, Simon simplifies complex concepts, making Raspberry Pi accessible to all. His articles not only guide but inspire readers to explore the limitless possibilities of Raspberry Pi in the IoT realm.
