Session 3: Space Blaster
Enemies stand in formation at the top of the screen. You’re at the bottom with a spaceship and one goal: knock them all out before they reach the bottom. Press SPACE to shoot, and don’t miss.
What you’ll learn today
- Keeping track of bullets in a list
- Creating a bullet when you press SPACE
- Collision between bullets and enemies
- Game over when an enemy reaches the bottom
Step 0: Setup
- Open Thonny.
- Download the starter via this link, unpack the ZIP and open
main.py. - Click Run. You see the ship at the bottom and 12 enemies in a grid, but nothing moves and you can’t shoot yet.
Step 1: Let the ship move
The ship already moves with the arrow keys. Check the code in update(). Make sure the ship doesn’t go off the screen:
if keyboard.left and ship.x > 30:
ship.x -= 5
if keyboard.right and ship.x < WIDTH - 30:
ship.x += 5Step 2: ✅ Basic: shooting with SPACE
Fill in the shoot() function. A bullet is an Actor that starts at the position of the ship:
def shoot():
kogel = Actor('bullet')
kogel.x = ship.x
kogel.y = ship.y - 20
bullets.append(kogel)Call shoot() when the space bar is pressed. Use on_key_down (Pgzero style):
def on_key_down(key):
if key == keys.SPACE:
shoot()Make the bullets move up in update() and remove them when they go off the screen:
for kogel in bullets[:]:
kogel.y -= 8
if kogel.y < -10:
bullets.remove(kogel)Step 3: ⭐ Stretch: hitting enemies
colliderect checks whether the rectangular hitbox of two actors overlaps. Move your mouse over the screen below to see when that happens:
Check in update() whether a bullet hits an enemy:
for kogel in bullets[:]:
kogel.y -= 8
if kogel.y < -10:
bullets.remove(kogel)
continue
for vijand in enemies[:]:
if kogel.colliderect(vijand):
bullets.remove(kogel)
enemies.remove(vijand)
global score
score += 10
breakWin condition: If enemies is empty, you’ve won:
if not enemies:
screen.draw.text("YOU WIN!", center=(WIDTH/2, HEIGHT/2), color="yellow", fontsize=60)Step 4: 🔥 Expert: enemies move and game over
Make the enemies come down slowly. Use a timer:
vijand_timer = 0
def update():
global vijand_timer
vijand_timer += 1
if vijand_timer % 90 == 0: # every 1.5 seconds
for vijand in enemies:
vijand.y += 20Game over when an enemy reaches the bottom:
for vijand in enemies:
if vijand.y > HEIGHT - 30:
global game_over
game_over = TrueFaster shooting rate: Build in a cooldown so the ninja can’t shoot endlessly fast:
shoot_cooldown = 0
def update():
global shoot_cooldown
if shoot_cooldown > 0:
shoot_cooldown -= 1
def on_key_down(key):
global shoot_cooldown
if key == keys.SPACE and shoot_cooldown == 0:
shoot()
shoot_cooldown = 15Showcase
Show your game to a coach. How fast do you clear all the enemies? Compare scores with a buddy.
See you next time!
“Next time: two players, one ball: PONG. And you learn real pygame without pgzrun.”
Take it home
- Easy: change the colour of the bullets or the enemies.
- Medium: make enemies move left and right (one direction per step, turn around at the edge).
- Hard: add a second wave: when all the enemies are gone, spawn a new row that comes down faster.
- Very hard: let enemies shoot back too: send a bullet down at random every N frames.
View the cheatsheet for this session
Dojo Defender
Download the Dojo Defender starter for today.
Were you not there last time? Download the solution from session 1 and start from there.
The complete worksheet: Dojo Defender Session 2.