Dojo Defender: Session 2

Your ship has a weapon now. Enemies are coming. Shoot them down before they reach the bottom. Every 10 enemies means a new wave — and it gets harder and harder.

What you’ll learn today

  • Shooting with the space bar and a cooldown
  • Lists for bullets and enemies
  • Collision between bullets and enemies
  • Waves that get harder and harder
  • Enemies that make sine movements

Step 0: Open the starter

  1. Open Thonny.
  2. Download the Dojo Defender starter for today, unpack the ZIP and open main.py.
  3. Were you not there last time? Download the solution from session 1 and start with that.
  4. Click Run. You see the same game as last time: ship, asteroids, explosions.
  5. Problems? Take a look at Installing Thonny.

Step 1: Shooting with SPACE

Your ship has a laser cannon. Add a list for bullets at the top:

bullets = []

Use on_key_down — it is called only once when you press a key (unlike update, which keeps repeating):

def on_key_down(key):
    if key == keys.SPACE:
        bullet = Actor('bullet')
        bullet.x = ship.x
        bullet.y = ship.y - 20
        bullets.append(bullet)

Make the bullets move up in update() and remove them when they are off screen:

for bullet in bullets[:]:
    bullet.y -= 8
    if bullet.y < -10:
        bullets.remove(bullet)

Don’t forget to draw the bullets in draw():

for bullet in bullets:
    bullet.draw()

Step 2: ✅ Basic: shooting cooldown

Without a cooldown you fire dozens of bullets per second. Add a timer:

shoot_cooldown = 0

In update():

if shoot_cooldown > 0:
    shoot_cooldown -= 1

Adjust on_key_down so that you can only shoot when the cooldown is 0:

def on_key_down(key):
    global shoot_cooldown
    if key == keys.SPACE and shoot_cooldown == 0:
        bullet = Actor('bullet')
        bullet.x = ship.x
        bullet.y = ship.y - 20
        bullets.append(bullet)
        shoot_cooldown = 15

Step 3: ⭐ Stretch: adding enemies

Enemies spawn at the top and fall down. Add a list:

enemies = []

A spawn function:

def spawn_enemy():
    enemy = Actor('enemy_drone')
    enemy.x = random.randint(30, WIDTH - 30)
    enemy.y = -30
    enemy.speed = random.uniform(1, 3)
    enemies.append(enemy)

Call spawn_enemy() in update() with a spawn interval:

# at the top:
spawn_counter = 0
spawn_interval = 120

# in update():
spawn_counter += 1
if spawn_counter >= spawn_interval:
    spawn_counter = 0
    spawn_enemy()

Draw enemies in draw():

for enemy in enemies:
    enemy.draw()

Step 4: 🔥 Expert: collision + waves

Bullet hits enemy: remove both, +10 points:

for bullet in bullets[:]:
    bullet.y -= 8
    if bullet.y < -10:
        bullets.remove(bullet)
        continue
    for enemy in enemies[:]:
        if bullet.colliderect(enemy):
            bullets.remove(bullet)
            enemies.remove(enemy)
            global score
            score += 10
            break

Enemy hits the bottom or the ship: lose a life (same as an asteroid).

Waves: a new wave every 10 enemies. Enemies spawn faster:

# at the top:
wave = 1
enemies_destroyed = 0

# on destroy:
enemies_destroyed += 1
if enemies_destroyed % 10 == 0:
    wave += 1
    spawn_interval = max(60, spawn_interval - 10)

Show the current wave in draw():

screen.draw.text(f"Wave: {wave}", (10, 70), color="yellow", fontsize=24)

Show “WAVE N!” in big letters on a new wave (use a timer).

Sine movement: let enemies veer left and right:

import math  # at the top

enemy.x = enemy.start_x + math.sin(timer * 0.03 + enemy.strafe_offset) * 50

Showcase

Show your Dojo Defender to a coach. How many waves do you reach? Do you have the sine movement working? Compare scores with a buddy.

See you next time!

“Next time: POWER-UPS. Shields, speed boosts and spread shots. Your ship gets stronger the longer you survive.”

Take it home

Try one of these extensions at home:

  1. Enemy variation — Use enemy_charger.png for a faster enemy that doesn’t do a sine, but comes straight at you.
  2. Sound — Add sounds/laser.wav and sounds/explosion.wav.
  3. Hard mode — Enemies spawn faster and faster, up to every 30 frames at most.
  4. Score multiplier — The higher the wave, the more points per kill: score += 10 * wave.

Download Dojo Defender