Subsecties van Dojo Defender
Dojo Defender: Sessie 1
Je ruimteschip is geland in de donkere ruimte. Tijd om het tot leven te brengen. In deze sessie voeg je een bestuurbaar schip toe en laat je asteroïden naar beneden vallen. Ontwijk ze of verlies een leven. Hoe lang overleef jij?
Wat je vandaag leert
- Lijsten gebruiken om meerdere asteroïden bij te houden
- Objecten spawnen en verwijderen
- Botsingen detecteren met
colliderect - Levens bijhouden en een explosie-effect tonen
- Game-over afdwingen als je levens op zijn
Stap 0: Installeren
- Open Thonny.
- Download de Dojo Defender starter, pak de ZIP uit en open
main.py. - Klik op Run. Je ziet een donkerblauw scherm met je ruimteschip onderaan. Je kan het al bewegen met de pijltjestoetsen.
- Problemen? Kijk bij Thonny instellen.
Stap 1: Laat asteroïden spawnen
Een game zonder gevaar is saai. Voeg een lijst toe waarin je alle asteroïden bijhoudt, en een functie die nieuwe asteroïden aanmaakt:
# bovenaan, na WIDTH en HEIGHT:
asteroids = []
def spawn_asteroid():
rock = Actor('asteroid_big')
rock.x = random.randint(30, WIDTH - 30)
rock.y = -30
rock.speed = random.uniform(3, 5)
asteroids.append(rock)
Je hebt ook import random nodig bovenaan het bestand. Voeg die regel toe.
Roep de functie aan in update() met een teller zodat niet élke frame een asteroïde verschijnt:
# bovenaan, buiten de functies:
timer = 0
def update():
global timer
timer += 1
if timer % 60 == 0: # elke seconde (60 frames)
spawn_asteroid()
Zet dit vóór de bewegingscode van het schip.
Stap 2: ✅ Basic: asteroïden laten vallen en tekenen
Asteroïden moeten naar beneden vallen en verdwijnen als ze het scherm uit zijn:
def update():
global timer
timer += 1
if timer % 60 == 0:
spawn_asteroid()
for rock in asteroids[:]: # [:] = kopie zodat je veilig kunt verwijderen
rock.y += rock.speed
if rock.y > HEIGHT + 30:
asteroids.remove(rock)
Vergeet niet om de asteroïden te tekenen in draw():
def draw():
screen.fill((10, 10, 30))
for rock in asteroids:
rock.draw()
ship.draw()
Stap 3: ⭐ Stretch: botsing + levens
Als een asteroïde je schip raakt, verlies je een leven. Voeg lives en game_over toe bovenaan:
lives = 3
game_over = False
Voeg in de for-loop collision-detectie toe:
for rock in asteroids[:]:
rock.y += rock.speed
if rock.y > HEIGHT + 30:
asteroids.remove(rock)
elif rock.colliderect(ship):
asteroids.remove(rock)
global lives, game_over
lives -= 1
if lives <= 0:
game_over = True
Toon de levens en score in draw():
screen.draw.text(f"Score: {score}", (10, 10), color="white", fontsize=24)
screen.draw.text(f"Lives: {lives}", (10, 40), color="red", fontsize=24)
Stop het spel als game_over True is:
def update():
if game_over:
return
...
Toon een game-over scherm in draw():
if game_over:
screen.draw.text(
"GAME OVER",
center=(WIDTH / 2, HEIGHT / 2),
color="red",
fontsize=60,
)
screen.draw.text(
f"Final Score: {score}",
center=(WIDTH / 2, HEIGHT / 2 + 60),
color="white",
fontsize=30,
)
Stap 4: 🔥 Expert: explosies + onzichtbaarheid
Als een asteroïde je raakt, wil je een explosie zien in plaats van dat het schip zomaar verdwijnt. Gebruik de vier explosie-frames (explosion_1 t/m explosion_4):
explosion = Actor('explosion_1')
explosion_active = False
explosion_frame = 0
explosion_timer = 0
Bij een botsing: verberg het schip, start de explosie:
elif rock.colliderect(ship):
asteroids.remove(rock)
global lives, game_over, explosion_active, explosion_frame, explosion_timer
lives -= 1
explosion.pos = (ship.x, ship.y)
explosion.image = 'explosion_1'
explosion_frame = 1
explosion_timer = 5
explosion_active = True
ship.visible = False
if lives <= 0:
game_over = True
Laat de explosie afspelen in update():
if explosion_active:
explosion_timer -= 1
if explosion_timer <= 0:
explosion_frame += 1
if explosion_frame > 4:
explosion_active = False
ship.visible = True
ship.pos = (WIDTH / 2, HEIGHT - 50)
else:
explosion.image = f'explosion_{explosion_frame}'
explosion_timer = 5
Voeg daarna een onzichtbaarheidsperiode toe zodat je niet meteen opnieuw geraakt wordt:
invincible = False
invincible_timer = 0
In update():
if invincible:
invincible_timer -= 1
if invincible_timer <= 0:
invincible = False
ship.visible = True
Pas de collision-check aan:
elif rock.colliderect(ship) and not invincible and ship.visible:
Teken de explosie in draw():
if explosion_active:
explosion.draw()
Showcase
Laat je Dojo Defender zien aan een coach en een buddy. Hoe lang overleef jij? Heb je explosies? Ziet het er vet uit?
Tot de volgende keer!
“Volgende keer: je ruimteschip SCHIET TERUG. Vijanden in formatie, en jij blast ze weg met lasers. Dit wordt episch.”
Neem mee naar huis
Probeer thuis één van deze uitbreidingen:
- Geluid — Voeg
sounds/explosion.wav toe als een asteroïde ontploft (sounds.explosion.play()). - Moeilijker — Laat asteroïden sneller vallen naarmate de score stijgt:
rock.speed = random.uniform(3 + score // 10, 5 + score // 10). - Power-up — Voeg een zeldzame groene power-up toe die een extra leven geeft.
- Kleiner — Gebruik
asteroid_med of asteroid_small voor variatie in grootte en snelheid.
Download Dojo Defender
Dojo Defender: Sessie 2
Je schip heeft nu een wapen. Vijanden komen eraan. Schiet ze neer voordat ze de bodem bereiken. Elke 10 vijanden betekent een nieuwe wave — en het wordt steeds moeilijker.
Wat je vandaag leert
- Schieten met de spatiebalk en een cooldown
- Lijsten voor kogels en vijanden
- Collision tussen kogels en vijanden
- Golven (waves) die steeds moeilijker worden
- Vijanden die sinus-bewegingen maken
Stap 0: Open de starter
- Open Thonny.
- Download de Dojo Defender starter voor vandaag, pak de ZIP uit en open
main.py. - Was je er vorige keer niet bij? Download de oplossing van sessie 1 en begin daarmee.
- Klik op Run. Je ziet hetzelfde spel als vorige keer: schip, asteroïden, explosies.
- Problemen? Kijk bij Thonny instellen.
Stap 1: Schieten met SPATIE
Je schip heeft een laserkanon. Voeg een lijst voor kogels toe bovenaan:
Gebruik on_key_down — die wordt maar één keer aangeroepen als je een toets indrukt (in tegenstelling tot update die blijft herhalen):
def on_key_down(key):
if key == keys.SPACE:
bullet = Actor('bullet')
bullet.x = ship.x
bullet.y = ship.y - 20
bullets.append(bullet)
Laat de kogels omhoog bewegen in update() en verwijder ze als ze uit beeld zijn:
for bullet in bullets[:]:
bullet.y -= 8
if bullet.y < -10:
bullets.remove(bullet)
Vergeet niet de kogels te tekenen in draw():
for bullet in bullets:
bullet.draw()
Stap 2: ✅ Basic: schiet-cooldown
Zonder cooldown vuur je tientallen kogels per seconde. Voeg een timer toe:
In update():
if shoot_cooldown > 0:
shoot_cooldown -= 1
Pas on_key_down aan zodat je alleen kunt schieten als de cooldown 0 is:
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
Stap 3: ⭐ Stretch: vijanden toevoegen
Vijanden spawnen bovenaan en vallen naar beneden. Voeg een lijst toe:
Een spawn-functie:
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)
Roep spawn_enemy() aan in update() met een spawn-interval:
# bovenaan:
spawn_counter = 0
spawn_interval = 120
# in update():
spawn_counter += 1
if spawn_counter >= spawn_interval:
spawn_counter = 0
spawn_enemy()
Teken vijanden in draw():
for enemy in enemies:
enemy.draw()
Stap 4: 🔥 Expert: collision + waves
Kogel raakt vijand: verwijder beide, +10 punten:
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
Vijand raakt bodem of schip: verlies een leven (zelfde als asteroïde).
Waves: elke 10 vijanden een nieuwe wave. Vijanden spawnen sneller:
# bovenaan:
wave = 1
enemies_destroyed = 0
# bij destroy:
enemies_destroyed += 1
if enemies_destroyed % 10 == 0:
wave += 1
spawn_interval = max(60, spawn_interval - 10)
Toon de huidige wave in draw():
screen.draw.text(f"Wave: {wave}", (10, 70), color="yellow", fontsize=24)
Toon “WAVE N!” in het groot bij een nieuwe wave (gebruik een timer).
Sinus-beweging: laat vijanden links-rechts zwenken:
import math # bovenaan
enemy.x = enemy.start_x + math.sin(timer * 0.03 + enemy.strafe_offset) * 50
Showcase
Laat je Dojo Defender zien aan een coach. Hoeveel waves haal jij? Heb je de sinus-beweging werkend? Vergelijk scores met een buddy.
Tot de volgende keer!
“Volgende keer: POWER-UPS. Schilden, speed-boosts en spread-shots. Je schip wordt steeds sterker naarmate je langer overleeft.”
Neem mee naar huis
Probeer thuis één van deze uitbreidingen:
- Vijandvariatie — Gebruik
enemy_charger.png voor een snellere vijand die geen sinus maakt, maar recht op je af komt. - Geluid — Voeg
sounds/laser.wav en sounds/explosion.wav toe. - Harde modus — Vijanden spawnen steeds sneller, tot maximaal elke 30 frames.
- Score multiplier — Hoe hoger de wave, hoe meer punten per kill:
score += 10 * wave.
Download Dojo Defender
Dojo Defender: Sessie 3
Vandaag verhuist Dojo Defender van pgzero naar echte pygame. Geen pgzrun.go() meer — jij schrijft de game loop zelf. Het spel blijft hetzelfde, maar de motor eronder is anders. En aan het einde voeg je GELUID toe.
Wat je vandaag leert
- Het verschil tussen pgzero en raw pygame
- De game loop zelf programmeren:
while running: clock.tick(60) - Actors omzetten naar
Surface + Rect - Geluid laden en afspelen met
pygame.mixer - Achtergrondmuziek laten loepen
Stap 0: Download de starter
De starter voor vandaag is een volledige port van Dojo Defender Sessie 2 naar raw pygame. Geen pgzero meer, maar het speelt hetzelfde.
- Download de Dojo Defender starter voor vandaag, pak uit en open
main.py. - Was je er vorige keer niet bij? Download de oplossing van sessie 2 en probeer die te porten.
- Klik op Run. Het spel werkt zoals je gewend bent: schip, asteroïden, kogels, vijanden, waves, explosies.
Wat is er veranderd?
In pgzero schreef je draw() en update() en pgzrun deed de rest. In raw pygame doe je alles zelf:
pgzero (vroeger):
import pgzrun
def draw():
screen.fill((10, 10, 30))
ship.draw()
def update():
if keyboard.left:
ship.x -= 5
pgzrun.go()
raw pygame (nu):
import pygame, sys
pygame.init()
screen = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()
running = True
while running:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit(); sys.exit()
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
ship.rect.centerx -= 5
screen.fill((10, 10, 30))
ship.draw(screen)
pygame.display.flip()
De belangrijkste verschillen:
| pgzero | raw pygame |
|---|
Actor('plaatje') | GameObject('plaatje.png', x, y) |
keyboard.left | keys[pygame.K_LEFT] |
on_key_down(key) | event.type == pygame.KEYDOWN |
screen.draw.text(...) | font.render() + screen.blit() |
rock.colliderect(ship) | rock.rect.colliderect(ship.rect) |
pgzrun.go() | while running: ... clock.tick(60) |
Stap 1: Verken de code
Open main.py en vergelijk met de oude pgzero-code van sessie 2. Zoek deze onderdelen:
- Game loop — Zoek de
while running:-lus. Zie je clock.tick(60), pygame.display.flip()? - GameObject — Zoek de
class GameObject. Hoe wordt een afbeelding geladen? Wat is rect? - Input — Zoek
pygame.key.get_pressed() en pygame.KEYDOWN. Hoe werkt de spatiebalk?
Verander de WIDTH naar 1024. Wat gebeurt er? (Alles wordt breder — de game werkt nog steeds.)
Stap 2: ✅ Basic — Voeg restart toe met de R-toets
In de pgzero-versie kon je niet herstarten na game over. Voeg dat nu toe:
# in de event loop, bij KEYDOWN:
if event.key == pygame.K_r and game_over:
# reset alles
ship.rect.center = (WIDTH / 2, HEIGHT - 50)
ship.visible = True
asteroids.clear()
bullets.clear()
enemies.clear()
lives = 3
score = 0
wave = 1
enemies_destroyed = 0
spawn_counter = 0
spawn_interval = 120
wave_display_timer = 0
game_over = False
invincible = False
ship.visible = True
Toon ook een hint op het game-over scherm: druk op R om opnieuw te spelen.
Stap 3: ⭐ Stretch — Voeg geluid toe
De starter heeft nog geen geluid. Voeg sounds toe!
Maak een sounds/ map naast images/ en kopieer de geluidsbestanden uit dojo-defender-assets/sounds/ (vraag de coach). Of download de oplossing die ze al bevat.
Voeg bovenaan toe:
pygame.mixer.init() # na pygame.init()
shoot_sound = pygame.mixer.Sound('sounds/shoot.wav')
explode_sound = pygame.mixer.Sound('sounds/explode.wav')
hit_sound = pygame.mixer.Sound('sounds/hit.wav')
pygame.mixer.music.load('sounds/bg_music.wav')
pygame.mixer.music.play(-1) # -1 = blijven herhalen
Let op: het pad moet kloppen. Gebruik os.path.join(_DIR, 'sounds/shoot.wav') zoals de starter ook met afbeeldingen doet.
Speel de geluiden af op de juiste momenten:
shoot_sound.play() — als je schietexplode_sound.play() — als een vijand of asteroïde ontplofthit_sound.play() — als je schip geraakt wordt
Stap 4: 🔥 Expert — Mute-knop en volume
Voeg een M-toets toe die het geluid aan/uit zet:
muted = False
# in KEYDOWN:
if event.key == pygame.K_m:
muted = not muted
pygame.mixer.music.set_volume(0 if muted else 1)
Elk geluid moet dan gecheckt worden:
if not muted:
shoot_sound.play()
Volume per geluid: Laat het schietgeluid zachter dan de explosie:
shoot_sound.set_volume(0.3)
explode_sound.set_volume(0.7)
Showcase
Laat aan een coach zien dat:
- Je spel werkt in echte pygame zonder pgzero
- Je geluid hebt toegevoegd (shoot, explode, hit, bg music)
- Bonus: restart met R of mute met M
Tot de volgende keer!
“Volgende keer: POWER-UPS. Schilden, speed-boosts en spread-shots. En je schip wordt sterker naarmate je langer overleeft.”
Neem mee naar huis
Probeer thuis één van deze uitbreidingen:
- Health bar — Vervang de tekst “Lives: 3” door een visuele balk: teken drie rechthoekjes bovenaan.
- Pauze — Voeg een P-toets toe die het spel pauzeert. Zet
running = False is niet genoeg — gebruik een aparte paused variabele. - Particle-effect — Laat kleine witte stipjes rondspatten bij een explosie (gebruik een lijst met deeltjes die steeds kleiner worden).
- Eigen skin — Vervang
player_ship.png door een eigen ontwerp.
Download Dojo Defender
Dojo Defender: Sessie 4
Vandaag wordt Dojo Defender een echt spel met een menu. Geen zwarte start meer — je krijgt een titelscherm, een game-over scherm, en drie verschillende vijandtypes die elk hun eigen beweging hebben.
Wat je vandaag leert
- State machines: je spel heeft toestanden (MENU, PLAYING, GAME OVER)
- Vijand-AI: elke vijand beweegt anders (recht, zigzag, charger)
- Wave-systeem: steeds moeilijkere golven met mixen van vijanden
- Een reset-functie: alles netjes terugzetten zonder herstart
Stap 0: Download de starter
De starter is de oplossing van sessie 3 — Dojo Defender in raw pygame met geluid.
- Download de starter voor vandaag, pak uit en open
main.py. - Was je er niet bij? Download de oplossing van sessie 3.
- Klik op Run. Het spel werkt zoals voorheen: schip, asteroïden, kogels, drones, geluid.
Stap 1: Voeg een state machine toe
Een state machine houdt bij in welke “toestand” het spel zich bevindt:
state = "MENU" # kan "MENU", "PLAYING", "GAME_OVER" zijn
Plaats deze variabele bovenaan, bij de andere globale variabelen.
Menu-scherm tekenen: Vervang de screen.fill en al het tekenen door een check op state:
if state == "MENU":
# Teken titel en instructies
screen.fill((10, 10, 30))
titel = title_font.render("DOJO DEFENDER", True, (0, 200, 255))
screen.blit(titel, (WIDTH // 2 - titel.get_width() // 2, HEIGHT // 2 - 60))
sub = big_font.render("Press SPACE to start", True, (200, 200, 200))
screen.blit(sub, (WIDTH // 2 - sub.get_width() // 2, HEIGHT // 2))
elif state == "PLAYING":
# = al jouw bestaande game code hier
elif state == "GAME_OVER":
# Teken "GAME OVER" + score
Maak title_font en big_font bovenaan:
title_font = pygame.font.SysFont(None, 80)
big_font = pygame.font.SysFont(None, 60)
Nu moet SPACE het volgende doen:
- Als
state == "MENU": reset het spel en ga naar PLAYING - Als
state == "GAME_OVER": reset het spel en ga naar PLAYING - Als
state == "PLAYING" en game_over == False: schiet zoals normaal
Pas de KEYDOWN-logic aan:
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 shoot_cooldown == 0 and not game_over:
# schiet (bestaande code)
Stap 2: ✅ Basic — Schrijf de reset-functie
Maak een functie die alles terugzet naar de beginwaarden:
def reset_game():
global ship, asteroids, bullets, enemies
global lives, score, game_over, timer
global explosion_active, explosion_frame, explosion_timer
global invincible, invincible_timer, shoot_cooldown
global wave, wave_display_timer, enemies_destroyed
global 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
Zet state = "GAME_OVER" als de speler 0 levens heeft (bij lives <= 0):
if lives <= 0:
game_over = True
state = "GAME_OVER"
Check: Het spel start nu met een blauw titelscherm. SPACE start het spel. Bij game over zie je GAME OVER en kun je met SPACE herstarten.
Stap 3: ⭐ Stretch — Drie vijandtypes
Vervang de ene spawn_enemy() door drie functies:
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)
Beweging per type
In de game loop, waar je enemy.rect.y += enemy.speed deed, moet je nu per type andere beweging toevoegen:
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 <= 0 or enemy.rect.right >= WIDTH:
enemy.dx = -enemy.dx
elif enemy.type == 'charger':
# Stuur naar de x-positie van de speler
dx = ship.rect.centerx - enemy.rect.centerx
if dx > 0:
enemy.rect.centerx += min(enemy.speed, abs(dx))
elif dx < 0:
enemy.rect.centerx -= min(enemy.speed, abs(dx))
enemy.rect.y += enemy.speed * 0.8
# Daarna: off-screen check, collision met schip etc.
Belangrijk: De charger moet langzamer dalen (* 0.8) zodat de speler tijd heeft om te reageren.
Stap 4: 🔥 Expert — Enhanced waves
Maak een spawn_enemy() die beslist welk type er spawnt op basis van de huidige wave:
def spawn_enemy():
if wave == 1:
spawn_enemy_drone()
elif wave <= 3:
if random.random() < 0.5:
spawn_enemy_drone()
else:
spawn_enemy_zigzag()
else:
r = random.random()
if r < 0.3:
spawn_enemy_drone()
elif r < 0.65:
spawn_enemy_zigzag()
else:
spawn_enemy_charger()
Zo wordt het steeds moeilijker:
- Wave 1: alleen drones (warmlopen)
- Wave 2-3: drones + zigzag (50/50)
- Wave 4+: alle drie, met meer chargers (30% drone, 35% zigzag, 35% charger)
Showcase
Laat aan een coach zien dat:
- Je een menu-scherm hebt met titel en “Press SPACE to start”
- Je drie vijandtypes hebt: drone (↓), zigzag (↘↗), charger (→ jouw schip)
- De waves steeds moeilijker worden (meer zigzags, dan chargers)
- Game over werkt met scoreweergave en restart
Tot de volgende keer!
“Volgende keer: POWER-UPS. Schilden, speed-boosts, spread-shots. En een échte eindbaas.”
Neem mee naar huis
Probeer thuis één van deze uitbreidingen:
- High score — Bewaar de hoogste score in een bestand en toon hem op het menu.
- Moeilijkheidsgraad — Laat de speler kiezen tussen “Makkelijk” en “Moeilijk” op het menu.
- Boss wave — Elke 5 waves verschijnt een grote baas met veel hits.
- Charger Warning — Teken een rode lijn onder een charger voordat hij verschijnt.
Download Dojo Defender
Dojo Defender: Sessie 5
Vandaag geef je Dojo Defender een diepte-effect met een parallax sterrenachtergrond en explosie-deeltjes. Asteroïden worden ook vernietigbaar: grote asteroïden splitsen in kleinere.
Wat je vandaag leert
- Parallax rekenen: meerdere lagen sterren met eigen snelheid
- Deeltjeslijsten: een lijst van dictionaries voor particles
- Positie-gebaseerde effecten: particles spawnen op de juiste plek
- Recursief splitsen: grote asteroïde → 2 medium → 2 klein → weg
Stap 0: Download de starter
De starter is de oplossing van sessie 4 — Dojo Defender met menu, drie vijandtypes en waves.
- Download de starter voor vandaag, pak uit en open
main.py. - Was je er niet bij? Download de oplossing van sessie 4.
- Klik op Run. Het spel werkt zoals voorheen: schip, asteroïden, kogels, drones, zigzags, chargers.
Stap 1: 🌟 Parallax sterrenachtergrond
Een parallax achtergrond heeft meerdere lagen die met verschillende snelheden bewegen. Ver weg = langzaam, dichtbij = snel. Dat geeft diepte.
Voeg een lijst stars = [] toe bovenaan het bestand, bij de andere globale variabelen:
Maak een init_stars() functie die drie lagen sterren aanmaakt:
def init_stars():
global stars
stars = []
layers = [
(40, 0.3, 2, 120), # ver weg: 40 sterren, speed 0.3, grootte 2, donkerder
(40, 0.7, 3, 180), # middel: 40 sterren, speed 0.7, grootte 3
(30, 1.5, 4, 255), # dichtbij: 30 sterren, speed 1.5, grootte 4, fel
]
for count, speed, size, brightness in layers:
for _ in range(count):
stars.append({
'x': random.randint(0, WIDTH),
'y': random.randint(0, HEIGHT),
'speed': speed,
'size': size,
'brightness': brightness,
})
Wiskunde erachter: elke ster krijgt een y-snelheid. Verre sterren (0.3 px/frame) bewegen bijna niet, nabije sterren (1.5 px/frame) bewegen sneller. Je brein interpreteert dat als diepte, precies zoals in een auto: bomen naast de weg vliegen voorbij, bergen ver weg blijven stil.
Voeg ook de update-functie toe. Die laat sterren zakken en zet ze terug naar boven als ze onder het scherm zijn:
def update_stars():
for star in stars:
star['y'] += star['speed']
if star['y'] > HEIGHT + star['size']:
star['y'] = -star['size']
star['x'] = random.randint(0, WIDTH)
En een teken-functie. Kleine sterren teken je met pygame.draw.rect (2×2), grotere met pygame.draw.circle:
def draw_stars(surface):
for star in stars:
c = (star['brightness'], star['brightness'], star['brightness'])
if star['size'] <= 2:
pygame.draw.rect(surface, c, (star['x'], star['y'], star['size'], star['size']))
else:
pygame.draw.circle(surface, c, (int(star['x']), int(star['y'])), star['size'] // 2)
Aanroepen: Roep init_stars() één keer aan (bij het opstarten, ná alle functies), update_stars() elke frame (zelfs in het menu!), en draw_stars(screen) na screen.fill() in ALLE states.
Check
Zie je drie lagen sterren naar beneden scrollen, ook in het menu? De verre sterren zijn kleiner en bewegen langzamer.
Stap 2: ✅ Basic — Particle systeem
Een particle is een klein deeltje dat beweegt, vervaagt en verdwijnt. We gebruiken een lijst van dictionaries:
particles = [] # {x, y, vx, vy, life, max_life, color, size}
Maak een functie om particles te spawnen:
def spawn_particles(x, y, count, colors, speed_range, size_range, life_range):
for _ in range(count):
angle = random.uniform(0, 2 * math.pi)
speed = random.uniform(speed_range[0], speed_range[1])
particles.append({
'x': x,
'y': y,
'vx': math.cos(angle) * speed,
'vy': math.sin(angle) * speed,
'life': random.randint(life_range[0], life_range[1]),
'max_life': life_range[1],
'color': random.choice(colors),
'size': random.uniform(size_range[0], size_range[1]),
})
Wat gebeurt er? Elke particle krijgt:
- Een positie (
x, y) - Een snelheid in x en y (
vx, vy), berekend uit een hoek en snelheid - Een levensduur (
life wordt elke frame met 1 verlaagd) - Een kleur en grootte
Update-functie (elke frame elke particle 1 stap verplaatsen en de levensduur verkorten):
def update_particles():
for p in particles[:]:
p['x'] += p['vx']
p['y'] += p['vy']
p['life'] -= 1
if p['life'] <= 0:
particles.remove(p)
Waarom [:]? We passen de lijst aan tijdens het loopen (we verwijderen particles). Zonder [:] krijg je een runtime error. De slice [:] maakt een kopie van de lijst om veilig over te loopen.
Teken-functie met vervaging (alpha-fade): hoe minder levensduur, hoe kleiner en donkerder:
def draw_particles(surface):
for p in particles:
ratio = p['life'] / p['max_life']
color = tuple(int(c * ratio) for c in p['color'])
pygame.draw.circle(surface, color, (int(p['x']), int(p['y'])), int(p['size'] * ratio))
De ratio is een getal tussen 1 (net geboren) en 0 (bijna dood). We vermenigvuldigen de kleur en grootte ermee, zodat de particle langzaam verdwijnt.
Particle-lijst wissen in reset
Voeg particles.clear() toe aan de reset_game() functie, anders blijven dode particles na een restart zweven.
Roep update_particles() aan in de PLAYING state en draw_particles(screen) na draw_stars(screen) in alle states.
Check
Start het spel en druk op SPACE. Er gebeurt nog niets zichtbaars — maar het systeem staat klaar voor de volgende stappen.
Stap 3: ⭐ Stretch — Positie-gebaseerde effecten
Nu gaan we particles spawnen op de juiste momenten en posities.
Uitlaatgassen
Als het schip beweegt, spawn kleine rode/oranje particles onder het schip. Voeg dit toe in de if not game_over sectie, waar je de pijltjestoetsen checked:
keys = pygame.key.get_pressed()
moving = False
if keys[pygame.K_LEFT] and ship.rect.centerx > 30:
ship.rect.centerx -= 5
moving = True
if keys[pygame.K_RIGHT] and ship.rect.centerx < WIDTH - 30:
ship.rect.centerx += 5
moving = True
if moving and ship.visible:
spawn_particles(
ship.rect.centerx, ship.rect.bottom,
1, # of random.randint(1, 2)
[(255, 100, 0), (255, 60, 0), (200, 50, 0)],
(0.5, 1.5), (2, 4), (10, 20),
)
De particles spawnen onder het schip (ship.rect.bottom) en krijgen een kleine snelheid omhoog (negatieve vy door de hoek).
Explosie puin
Als een vijand wordt geraakt door een kogel, spawn 8-12 deeltjes in alle richtingen. Voeg dit toe waar je een enemy uit de lijst haalt na een bullet-collision:
spawn_particles(
enemy.rect.centerx, enemy.rect.centery,
random.randint(8, 12),
[(255, 140, 0), (255, 0, 0), (255, 255, 0), (255, 255, 255)],
(1, 4), (2, 5), (20, 40),
)
Vijand-sterfsparkels
Als een vijand de onderkant van het scherm bereikt, spawn 3-5 witte vonkjes:
spawn_particles(
enemy.rect.centerx, HEIGHT - 30,
random.randint(3, 5),
[(255, 255, 255), (200, 200, 255)],
(1, 3), (1, 3), (15, 30),
)
Check
Beweeg het schip — zie je oranje uitlaatgassen? Schiet een vijand — zie je 8-12 rondvliegende deeltjes? Laat een vijand ontsnappen — zie je witte vonkjes?
Stap 4: 🔥 Expert — Vernietigbare asteroïden
Asteroïden zijn nu recursief splitsbaar:
asteroid_big.png → wordt geraakt → 2× asteroid_med.pngasteroid_med.png → wordt geraakt → 2× asteroid_small.pngasteroid_small.png → wordt geraakt → weg + particles
Pas spawn_asteroid() aan zodat elke asteroïde een asteroid_size krijgt:
def spawn_asteroid(size='big'):
rock = GameObject(f'asteroid_{size}.png', random.randint(30, WIDTH - 30), -30)
rock.speed = random.uniform(3, 5)
rock.asteroid_size = size
asteroids.append(rock)
return rock
Maak een split_asteroid() functie die een asteroïde in twee kleinere splitst:
def split_asteroid(rock):
# Eerst: exploderende particles
spawn_particles(
rock.rect.centerx, rock.rect.centery,
random.randint(8, 12),
[(255, 140, 0), (255, 0, 0), (255, 255, 0), (255, 255, 255)],
(1, 4), (2, 5), (20, 40),
)
if rock.asteroid_size == 'big':
for _ in range(2):
r = spawn_asteroid('med')
r.rect.center = rock.rect.center
r.rect.x += random.randint(-20, 20)
r.speed = random.uniform(2, 4)
elif rock.asteroid_size == 'med':
for _ in range(2):
r = spawn_asteroid('small')
r.rect.center = rock.rect.center
r.rect.x += random.randint(-15, 15)
r.speed = random.uniform(1, 3)
asteroids.remove(rock)
Wat gebeurt hier?
- We spawnen explosie-particles op de positie van de asteroïde
- We checken de grootte: ‘big’ → 2 ‘med’, ‘med’ → 2 ‘small’, ‘small’ → geen verdere splitsing
- Nieuwe asteroïden spawnen vlakbij de oude positie met een lichte offset
- De kleinere asteroïden zijn langzamer dan de grotere
Pas de collision-logic aan: waar je astersoids.remove(rock) deed bij een kogelraak, roep nu split_asteroid(rock) aan:
for rock in asteroids[:]:
if bullet.rect.colliderect(rock.rect):
bullets.remove(bullet)
explode_sound.play()
split_asteroid(rock)
score += 5
break
Belangrijk: Het geluid (explode_sound.play()) speel je af vóór split_asteroid() zodat het niet per ongeluk twee keer afspeelt.
Check
Schiet een grote asteroïde. Zie je hem splitsen in twee medium asteroïden? Schiet die — ze splitsen in twee kleine. Schiet de kleine — die verdwijnen met een mooie particle-explosie.
Showcase
Laat aan een coach zien dat:
- Parallax sterrenachtergrond met drie snelheden
- Particle systeem met vervaging (alpha-fade)
- Uitlaatgassen onder het bewegende schip
- Explosie-puin bij vernietigde vijanden en asteroïden
- Asteroïden splitsen: big → med → small → weg
Tot de volgende keer!
“Volgende keer: POWER-UPS. Schilden, speed-boosts, spread-shots. En een échte eindbaas.”
Neem mee naar huis
Probeer thuis één van deze uitbreidingen:
- Makkelijk: verander de kleur van de sterren per laag (bijv. verre sterren blauwachtig, nabije geel).
- Middel: voeg een vierde laag sterren toe, nog sneller (speed 3.0), met grote heldere sterren.
- Lastig: laat particle-kleur veranderen tijdens de levensduur (van geel naar rood naar grijs).
- Erg lastig: voeg een “comet” particle type toe dat een klein staartje heeft.
Download Dojo Defender
Dojo Defender: Sessie 6
Vandaag voeg je een eindbaas (boss) toe aan Dojo Defender. De boss verschijnt om de 5 waves en heeft 3 fases met eigen gedrag. Je leert werken met een eigen state machine, HP-balken en schermeffecten.
Wat je vandaag leert
- State machine voor een baas: PHASE_1, PHASE_2, PHASE_3 en EXPLODING
- HP-balk tekenen met kleurverloop (groen → geel → rood)
- Doelzoekende kogels: een kogel die naar de speler beweegt
- Screen shake: willekeurige offset op teken-coördinaten
- Fase-overgangen met visuele effecten
Stap 0: Download de starter
De starter is de oplossing van sessie 5 — Dojo Defender met parallax sterren, particles en splitsende asteroïden.
- Download de starter voor vandaag, pak uit en open
main.py. - Was je er niet bij? Download de oplossing van sessie 5.
- Klik op Run. Het spel werkt zoals voorheen. Dood 10 vijanden om wave 5 te halen — dan verschijnt de boss!
Stap 1: ✅ Basic — Boss-variabelen
Een boss heeft eigen variabelen. Voeg deze toe bij de andere globale variabelen:
boss = None
boss_active = False
boss_hp = 0
boss_hp_max = 50
boss_phase = "PHASE_1"
boss_timer = 0
boss_phase_transition_timer = 0
boss_defeated_timer = 0
boss_shoot_timer = 0
boss_minion_spawn_timer = 0
boss_bullets = []
boss_minions = []
screen_shake_x = 0
screen_shake_y = 0
boss_direction = 1
Voeg ook leegmaken van boss_bullets en boss_minions toe in reset_game().
Waarom zoveel variabelen? Een baas is complexer dan gewone vijanden. Hij moet bewegen, schieten, minions spawnen, fases hebben en een dood-animatie. Elke variabele is één aspect van dat gedrag.
Check
Start het spel. Er verandert nog niets — maar de variabelen staan klaar.
Stap 2: ⭐ Stretch — Boss spawnen en tekenen
Spawn-functie
Schrijf een functie die de boss activeert:
def start_boss():
global boss_active, boss, boss_hp, boss_phase, boss_timer
global boss_bullets, boss_minions, boss_shoot_timer
global boss_minion_spawn_timer, boss_direction, screen_shake_x, screen_shake_y
boss_active = True
boss = GameObject('boss.png', WIDTH / 2, -80)
boss_hp = boss_hp_max
boss_phase = "PHASE_1"
boss_timer = 0
boss_shoot_timer = 0
boss_minion_spawn_timer = 0
boss_direction = 1
screen_shake_x = 0
screen_shake_y = 0
boss_bullets.clear()
boss_minions.clear()
roar_path = os.path.join(_DIR, 'sounds/boss_roar.wav')
if os.path.exists(roar_path):
pygame.mixer.Sound(roar_path).play()
Boss-wave detectie
Elke 5e wave (vanaf wave 5) verschijnt een boss. Voeg dit toe waar de wave omhoog gaat:
def check_boss_wave():
if wave >= 5 and wave % 5 == 0 and not boss_active:
start_boss()
Roep check_boss_wave() aan na wave += 1.
Vijanden stoppen tijdens boss
Zorg dat gewone vijanden niet spawnen tijdens een boss fight. Omcirkel de spawn-logic:
if not boss_active:
spawn_counter += 1
if spawn_counter >= spawn_interval:
spawn_counter = 0
spawn_enemy()
Boss tekenen
Teken de boss als hij actief is, en teken ook de HP-balk bovenaan het scherm:
if boss_active and boss is not None:
boss.draw(screen)
# HP-balk
bar_width = 300
bar_height = 20
bar_x = (WIDTH - bar_width) // 2
bar_y = 10
bar_bg = pygame.Rect(bar_x, bar_y, bar_width, bar_height)
pygame.draw.rect(screen, (100, 20, 20), bar_bg)
hp_ratio = max(0, boss_hp / boss_hp_max)
fill_width = int(bar_width * hp_ratio)
if hp_ratio > 0.5:
color = (0, 255, 0)
elif hp_ratio > 0.25:
color = (255, 255, 0)
else:
color = (255, 0, 0)
fill_rect = pygame.Rect(bar_x, bar_y, fill_width, bar_height)
pygame.draw.rect(screen, color, fill_rect)
pygame.draw.rect(screen, (255, 255, 255), bar_bg, 2)
label = font.render(f"BOSS {boss_hp}/{boss_hp_max}", True, (255, 255, 255))
screen.blit(label, (bar_x + bar_width // 2 - label.get_width() // 2, bar_y - 5))
Check
Speel tot wave 5. Zie je de boss binnenkomen met een HP-balk? Gewone vijanden spawnen niet meer.
Stap 3: 🔥 Expert — Boss AI (3 fases)
De boss heeft een state machine met 3 fases. Elke fase is anders gedrag.
Fase 1 (HP 34-50, 100-66%)
De boss drijft langzaam naar links en rechts en vuurt af en toe een doelzoekende kogel.
def fire_boss_bullet():
dx = ship.rect.centerx - boss.rect.centerx
dy = ship.rect.centery - boss.rect.centery
dist = math.sqrt(dx * dx + dy * dy)
if dist == 0:
dist = 1
speed = 3
bullet = {
'x': boss.rect.centerx,
'y': boss.rect.centery + 30,
'vx': dx / dist * speed,
'vy': dy / dist * speed,
}
boss_bullets.append(bullet)
Wiskunde: Door dx en dy te delen door de afstand (dist) krijg je een eenheidsvector — een richting met lengte 1. Vermenigvuldig met speed voor de gewenste snelheid. Dit werkt in élke richting, niet alleen horizontaal/verticaal.
Voeg de AI-update toe in de game loop (if boss_active and boss is not None):
if boss.rect.centery < 80:
boss.rect.centery += 2 # komt binnen
else:
if boss_phase == "PHASE_1":
boss.rect.centerx += boss_direction * 1.5
if boss.rect.centerx > WIDTH - 60:
boss_direction = -1
if boss.rect.centerx < 60:
boss_direction = 1
boss_shoot_timer += 1
if boss_shoot_timer >= 60:
boss_shoot_timer = 0
fire_boss_bullet()
Fase-overgang (HP ≤ 66%)
Check of de baas van fase moet wisselen. Roep dit aan na de boss update:
hp_ratio = boss_hp / boss_hp_max
if hp_ratio <= 0.66 and boss_phase == "PHASE_1":
boss_phase = "PHASE_2"
boss_phase_transition_timer = 20
Tijdens een fase-overgang laat je de boss knipperen:
if boss_phase_transition_timer > 0 and boss_phase_transition_timer % 4 < 2:
flash_surf = pygame.Surface(boss.image.get_size(), pygame.SRCALPHA)
flash_surf.fill((255, 255, 255, 180))
screen.blit(flash_surf, (boss.rect.x, boss.rect.y))
Fase 2 (HP 17-33, 66-33%)
De boss beweegt sneller, vuurt vaker en spawnt minions:
elif boss_phase == "PHASE_2":
boss.rect.centerx += boss_direction * 3
...
boss_shoot_timer += 1
if boss_shoot_timer >= 40:
boss_shoot_timer = 0
fire_boss_bullet()
boss_minion_spawn_timer += 1
if boss_minion_spawn_timer >= 180:
boss_minion_spawn_timer = 0
spawn_boss_minion()
Een minion spawnen:
def spawn_boss_minion():
minion = GameObject('boss_minion.png', random.randint(30, WIDTH - 30), -30)
minion.speed = random.uniform(1, 2)
boss_minions.append(minion)
Fase 3 (HP 0-16, 33-0%)
De boss is enraged (woedend): vuurt twee kogels tegelijk, spawn sneller minions, en het scherm schudt:
elif boss_phase == "PHASE_3":
boss.rect.centerx += boss_direction * 4
...
boss_shoot_timer += 1
if boss_shoot_timer >= 20:
boss_shoot_timer = 0
fire_boss_bullet()
if boss_hp < boss_hp_max * 0.15:
fire_boss_bullet()
...
Screen shake: voeg een willekeurige offset toe aan ALLE teken-coördinaten:
if boss_phase == "PHASE_3":
screen_shake_x = random.randint(-3, 3)
screen_shake_y = random.randint(-3, 3)
else:
screen_shake_x = 0
screen_shake_y = 0
Pas alle draw functies aan om offset_x en offset_y parameters te accepteren. Bijvoorbeeld draw_stars(screen, screen_shake_x, screen_shake_y).
Check
Speel tot wave 5. Zie je de boss door 3 fases gaan? Fase 1: langzaam, af en toe een kogel. Fase 2: sneller + minions. Fase 3: scherm schudt, regen van kogels.
Stap 4: 💀 Expert — Boss verslaan
Als de boss 0 HP bereikt, start de exploding sequence:
if boss_hp <= 0:
boss_phase = "EXPLODING"
boss_defeated_timer = 90
boss_phase_transition_timer = 60
score += 500
explode_sound.play()
Tijdens EXPLODING spawn je elke 10 frames een particle-burst:
if boss_phase == "EXPLODING":
if boss_phase_transition_timer > 0 and boss_phase_transition_timer % 10 == 0:
spawn_particles(
boss.rect.centerx + random.randint(-40, 40),
boss.rect.centery + random.randint(-40, 40),
random.randint(10, 20),
[(255, 255, 0), (255, 100, 0), (255, 0, 0), (255, 255, 255)],
(2, 6), (3, 7), (20, 40),
)
Toon “BOSS DEFEATED!” bovenaan het scherm:
if boss_defeated_timer > 0:
defeat_msg = big_font.render("BOSS DEFEATED!", True, (255, 255, 0))
screen.blit(defeat_msg, (WIDTH // 2 - defeat_msg.get_width() // 2, HEIGHT // 2 - 100))
Let op: zet na de baas de gewone vijand-spawning weer aan. De wave gaat door naar de volgende.
Check
Versla de boss. Zie je de explosie-animatie, de “BOSS DEFEATED!” tekst en +500 score? Gaan de gewone waves daarna verder?
Showcase
Laat aan een coach zien dat:
- Boss verschijnt om de 5 waves met HP-balk
- 3 fases met eigen gedrag (langzaam → minions → enraged)
- Doelzoekende kogels die naar de speler vliegen
- Screen shake in fase 3
- Minions spawnen in fase 2 en 3
- Boss defeated: explosion sequence, “BOSS DEFEATED!”, +500 score
Tot de volgende keer!
“Volgende keer: de gepolijste versie. Geluid, menu-scherm, high scores — en jouw eigen draai aan de game.”
Neem mee naar huis
Probeer thuis één van deze uitbreidingen:
- Makkelijk: verander de boss-kleur of -grootte via de image.
- Middel: voeg een vierde fase toe (HP < 10%) waarin de boss teleporteert.
- Lastig: laat de boss delay-bullets schieten die een spoor achterlaten.
- Erg lastig: voeg een tweede boss-type toe die in een andere wave verschijnt.
Download Dojo Defender
Dojo Defender: Sessie 7
Vandaag bepaal jij wat er in Dojo Defender gebeurt. Geen stap-voor-stap instructies — kies een feature, plan hem, en bouw hem.
Je start van de complete Dojo Defender met alles erop en eraan: schip, asteroïden, 3 vijandtypes, waves, particles, parallax sterren, en een eindbaas met 3 fases.
Dit is jouw game. Maak er iets van.
Kies wat jij wil bouwen
Hieronder staan ideeën. Kies er één — of bedenk je eigen feature.
Makkelijk
- Power-ups: vijanden laten soms (20%) een power-up vallen. Rood = spread shot (3 kogels), groen = schild, geel = speed boost. Power-ups werken 5 seconden.
- Moeilijkheidsgraad: maak het spel makkelijker (meer levens, langzamere vijanden) of moeilijker (minder levens, snellere spawns).
- Geluid: voeg een power-up geluid toe (
powerup.wav), een game-over geluid, of achtergrondmuziek die versnelt bij hogere waves.
Gemiddeld
- High score: bewaar de hoogste score in een bestand (
highscore.txt). Toon hem op het menu en game-over scherm. Alleen overschrijven als de nieuwe score hoger is. - Moeilijkheidsschalen: maak het spel elke wave iets moeilijker — snellere vijanden, kleinere asteroïden, vaker spawnen.
- Gifte vijanden: een nieuwe vijandsoort die een spoor van giftige deeltjes achterlaat.
- Ship-animatie: het schip kan maar 3 kogels tegelijk schieten. Laad een “heat” indicator of maak een cooldown.
Moeilijk
- Tweede boss: maak een nieuwe boss die op een andere wave verschijnt (bijv. wave 7). Ander uiterlijk, ander gedrag.
- Power-up systeem uitbreiden: voeg een 4e power-up toe (bijv. “time freeze” — vijanden bevriezen voor 3 seconden).
- Combo-systeem: hoe sneller je vijanden doodt, hoe meer punten. Een “combo multiplier” die oploopt.
- Baas heeft eigen power-up drops: de baas laat een zeldzame power-up vallen als hij verslagen wordt.
Eigen idee
Heb je een eigen idee? Top. Bespreek het kort met een coach en begin met bouwen.
Tips voor het plannen van je feature
Voor je begint met code schrijven, beantwoord deze vragen:
- Wat moet de speler zien? (een nieuwe power-up, een tekst, een icoon?)
- Wanneer gebeurt het? (als je SPACE indrukt, als een vijand sterft, als wave 10 begint?)
- Hoe lang duurt het? (5 seconden? Permanent? Tot de volgende wave?)
- Wat moet er veranderen aan de code? (nieuwe variabelen? een nieuwe lijst? een timer?)
- Hoe weet ik dat het werkt? (wat is de “check” — wat moet ik zien om te weten dat het af is?)
Schrijf je antwoorden op papier of in commentaar bovenaan het bestand.
Cheatsheets van vorige sessies
Kun je iets niet meer herinneren? Gebruik de cheatsheets van vorige keren:
Coach-geleide planning
Dit deel vul je samen met een coach in voordat je begint met coderen.
Mijn feature: _________________________________________________
Ik kies: Makkelijk / Gemiddeld / Moeilijk / Eigen idee
Nieuwe variabelen die ik nodig heb:
- __________________________________
- __________________________________
- __________________________________
Nieuwe afbeeldingen of geluiden:
- __________________________________
- __________________________________
Check: hoe weet ik dat het werkt?
- __________________________________
Showcase
Aan het einde van de sessie laat je aan een coach en je buddy zien wat je hebt gebouwd. Vertel in 30 seconden:
- Wat je wilde maken
- Of het gelukt is
- Wat het moeilijkst was
Stappenplan (voor als je er zelf niet uitkomt)
- Open
main.py in Thonny en klik Run — werkt het nog? - Maak een kopie van de game-map voor het geval je vastloopt.
- Begin met de kleinste mogelijke verandering (bijv. een variabele toevoegen).
- Test. Werkt het? → Volgende stap. Werkt het niet? → Vraag een coach.
Tot de volgende keer!
“Volgende keer: een compleet nieuw spel. Wat wordt het?”
Voortgang per sessie
| DD Sessie | Na curriculum | Wat is er nieuw? | Snapshot |
|---|
| 1 | S2 | Ruimteschip + asteroïden + leven + explosies | (volgt) |
| 2 | S3 | Schieten + vijanden + score + waves | (volgt) |
| 3 | S4 (Pygame) | Herbouwd in Pygame met sprites + geluid | (volgt) |
| 4 | S5 | Menu + 3 vijandtypes | (volgt) |
| 5 | S6 | Parallax sterren + particles + splitsende asteroïden | (volgt) |
| 6 | S7 | Boss fight met 3 fases + HP-balk | (volgt) |
| 7 | S8 | Jouw eigen versie (power-ups, high score, …) | (volgt) |