<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Dojo Defender: Session 4 :: CoderDojo Python &amp; Pygame</title><link>https://python.coderdojohasselt.be/en/dojo-defender/session-4/index.html</link><description>Today Dojo Defender becomes a real game with a menu. No more black start — you get a title screen, a game-over screen, and three different enemy types that each move in their own way.
What you’ll learn today State machines: your game has states (MENU, PLAYING, GAME OVER) Enemy AI: every enemy moves differently (straight, zigzag, charger) Wave system: increasingly hard waves with a mix of enemies A reset function: putting everything back neatly without restarting Step 0: Download the starter The starter is the solution of session 3 — Dojo Defender in raw pygame with sound.</description><generator>Hugo</generator><language>en</language><atom:link href="https://python.coderdojohasselt.be/en/dojo-defender/session-4/index.xml" rel="self" type="application/rss+xml"/><item><title>Dojo Defender Session 4: Cheatsheet</title><link>https://python.coderdojohasselt.be/en/dojo-defender/session-4/cheatsheet/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://python.coderdojohasselt.be/en/dojo-defender/session-4/cheatsheet/index.html</guid><description>State machine state = "MENU" # "MENU", "PLAYING", "GAME_OVER" # In the event loop: if event.key == pygame.K_SPACE: if state == "MENU": reset_game() state = "PLAYING" elif state == "GAME_OVER": reset_game() state = "PLAYING" elif state == "PLAYING" and not game_over: # shoot # In the drawing loop: if state == "MENU": # title screen elif state == "PLAYING": # normal game elif state == "GAME_OVER": # game over screen Reset function def reset_game(): global ship, asteroids, bullets, enemies, lives, score global game_over, timer, explosion_active, explosion_frame global explosion_timer, invincible, invincible_timer global shoot_cooldown, wave, wave_display_timer global enemies_destroyed, spawn_counter, spawn_interval ship.rect.center = (WIDTH / 2, HEIGHT - 50) ship.visible = True asteroids.clear() bullets.clear() enemies.clear() lives = 3 score = 0 game_over = False timer = 0 explosion_active = False explosion_frame = 0 explosion_timer = 0 invincible = False invincible_timer = 0 shoot_cooldown = 0 wave = 1 wave_display_timer = 0 enemies_destroyed = 0 spawn_counter = 0 spawn_interval = 120 Spawning three enemy types def spawn_enemy_drone(): enemy = GameObject('enemy_drone.png', random.randint(30, WIDTH - 30), -30) enemy.type = 'drone' enemy.speed = random.uniform(1, 3) enemies.append(enemy) def spawn_enemy_zigzag(): enemy = GameObject('enemy_zigzag.png', random.randint(30, WIDTH - 30), -30) enemy.type = 'zigzag' enemy.speed = random.uniform(2, 4) enemy.dx = random.choice([-2, 2]) enemies.append(enemy) def spawn_enemy_charger(): enemy = GameObject('enemy_charger.png', random.randint(30, WIDTH - 30), -30) enemy.type = 'charger' enemy.speed = random.uniform(3, 5) enemies.append(enemy) Movement per type for enemy in enemies[:]: if enemy.type == 'drone': enemy.rect.y += enemy.speed elif enemy.type == 'zigzag': enemy.rect.x += enemy.dx enemy.rect.y += enemy.speed if enemy.rect.left &lt;= 0 or enemy.rect.right >= WIDTH: enemy.dx = -enemy.dx elif enemy.type == 'charger': dx = ship.rect.centerx - enemy.rect.centerx if dx > 0: enemy.rect.centerx += min(enemy.speed, abs(dx)) elif dx &lt; 0: enemy.rect.centerx -= min(enemy.speed, abs(dx)) enemy.rect.y += enemy.speed * 0.8 Wave selection def spawn_enemy(): if wave == 1: spawn_enemy_drone() elif wave &lt;= 3: if random.random() &lt; 0.5: spawn_enemy_drone() else: spawn_enemy_zigzag() else: r = random.random() if r &lt; 0.3: spawn_enemy_drone() elif r &lt; 0.65: spawn_enemy_zigzag() else: spawn_enemy_charger()</description></item><item><title>Dojo Defender Session 4: Coach notes</title><link>https://python.coderdojohasselt.be/en/dojo-defender/session-4/mentor-notes/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://python.coderdojohasselt.be/en/dojo-defender/session-4/mentor-notes/index.html</guid><description>Goal of this session After this session a ninja can:
Apply a state machine (MENU → PLAYING → GAME_OVER) Write a reset function that puts all the global variables back Implement different enemy AI (drone, zigzag, charger) Build a wave system that raises the difficulty Preparation (30 min before the session) Starter ZIPs ready on USB and on the site: dojo-defender-s5-starter.en.zip and dojo-defender-s5-solution.en.zip. Run the starter once on the dojo room laptop. Check whether enemy_zigzag.png and enemy_charger.png are in the images/ folder of the starter. Explain the state machine on the board: draw three blocks (MENU, PLAYING, GAME_OVER) with arrows between them. Schedule (3 hours) This session is an integral part of the normal session 5 (Breakout). Use the time like this:</description></item><item><title>Dojo Defender Session 4: Demo</title><link>https://python.coderdojohasselt.be/en/dojo-defender/session-4/demo/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://python.coderdojohasselt.be/en/dojo-defender/session-4/demo/index.html</guid><description>How to demo the solution Open a terminal in the project folder. Run: uv run python3 code/sessions/05-breakout/dojo-defender-solution/main.py Show:
The game starts in the MENU with the “DOJO DEFENDER” title and “Press SPACE to start” SPACE starts the game and resets all the values Three enemy types: Drone (blue, square) — moves straight down Zigzag (red, triangular) — moves diagonally, bounces off the edges Charger (yellow, pointed) — follows the ship horizontally Wave system: Wave 1 only drones, Wave 2-3 drones + zigzag, Wave 4+ chargers too Game over: shows “GAME OVER” with the score and “Press SPACE to restart” State transitions: MENU → PLAYING → GAME_OVER → PLAYING Code highlights to show:</description></item></channel></rss>