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

  1. Open Thonny.
  2. Download the starter via this link, unpack the ZIP and open main.py.
  3. 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 += 5

Step 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
            break

Win 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 += 20

Game over when an enemy reaches the bottom:

        for vijand in enemies:
            if vijand.y > HEIGHT - 30:
                global game_over
                game_over = True

Faster 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 = 15

Showcase

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

  1. Easy: change the colour of the bullets or the enemies.
  2. Medium: make enemies move left and right (one direction per step, turn around at the edge).
  3. Hard: add a second wave: when all the enemies are gone, spawn a new row that comes down faster.
  4. 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.