Level 6: Bouw Je Eigen Spel!
Kies een starter
Dit level heeft 3 starter kits. Elke starter leert je iets nieuws. Kies er een, of combineer ideeën uit meerdere starters!
Het doel
Bouw je eigen tactisch zombie spel! Gebruik alles wat je geleerd hebt in de vorige levels en voeg nieuwe dingen toe.
De starters
Starter A: Game States
Bekijk de code
# =============================================================================
# ZOMBIE APOCALYPSE - Level 6 - Starter A: Game States
# =============================================================================
# Start met: pgzrun zombie.py
#
# Deze starter laat zien hoe je een Enum gebruikt voor game states.
# In Level 5 gebruikten we strings zoals "spel" en "game_over".
# Met een Enum kan dat niet meer fout gaan!
#
# Nieuw in deze starter:
# - Enum: een vaste lijst van mogelijke waarden
# - Duidelijkere code door Toestand.SPEL i.p.v. "spel"
# =============================================================================
import random
from enum import Enum
from pgzero.builtins import clock
from pgzero.screen import Screen
screen: Screen
WIDTH = 800
HEIGHT = 600
TITLE = "Brainstorm"
# =============================================================================
# ENUM VOOR GAME STATES
# =============================================================================
# Een Enum (enumeration) is een klasse met vaste waarden.
# Voordeel t.o.v. strings:
# - Je kan geen typfout maken (Toestand.SPEL vs "speel")
# - Je editor helpt je met automatisch aanvullen
# - Je ziet meteen welke toestanden er zijn
#
# class Seizoen(Enum):
# LENTE = "lente"
# ZOMER = "zomer"
# HERFST = "herfst"
# WINTER = "winter"
# =============================================================================
class Toestand(Enum):
SPEL = "spel"
RESULTAAT = "resultaat"
GAME_OVER = "game_over"
toestand = Toestand.SPEL
levens = 3
resultaat_tekst = ""
def draw():
if toestand == Toestand.SPEL:
screen.blit("achtergrond", (0, 0))
for i in range(levens):
screen.blit("hart", (20 + i * 50, 20))
screen.draw.text("Klik om te vechten!", center=(400, 300), fontsize=48, color="white")
elif toestand == Toestand.RESULTAAT:
screen.blit("achtergrond", (0, 0))
screen.draw.text(resultaat_tekst, center=(400, 300), fontsize=48, color="white")
elif toestand == Toestand.GAME_OVER:
screen.blit("game_over", (0, 0))
screen.draw.text("GAME OVER", center=(400, 250), fontsize=60, color="red")
screen.draw.text("Klik om opnieuw te spelen", center=(400, 350), fontsize=24, color="gray")
def update(dt):
"""Wordt elk frame aangeroepen. Handig voor animaties!"""
pass
def on_mouse_down(pos):
global toestand, levens, resultaat_tekst
if toestand == Toestand.SPEL:
if random.randint(1, 2) == 1:
resultaat_tekst = "Je verslaat de zombie!"
else:
resultaat_tekst = "De zombie bijt je..."
levens -= 1
toestand = Toestand.RESULTAAT
clock.schedule(ga_naar_volgende, 2.0)
elif toestand == Toestand.GAME_OVER:
toestand = Toestand.SPEL
levens = 3
def ga_naar_volgende():
global toestand
if levens <= 0:
toestand = Toestand.GAME_OVER
else:
toestand = Toestand.SPEL
Een Enum is een klasse met vaste waarden. In Level 5 gebruikten we
strings zoals "spel" en "game_over". Met een Enum kan je geen typfouten
meer maken!
from enum import Enum
class Toestand(Enum):
SPEL = "spel"
RESULTAAT = "resultaat"
GAME_OVER = "game_over"
In plaats van:
Gebruik je nu:
Je editor helpt je zelfs met automatisch aanvullen.
Starter B: Locaties
Bekijk de code
# =============================================================================
# ZOMBIE APOCALYPSE - Level 6 - Starter B: Locaties
# =============================================================================
# Start met: pgzrun zombie.py
#
# Deze starter laat zien hoe je met pijltjestoetsen tussen
# locaties kan navigeren. Elke locatie heeft een eigen achtergrond.
#
# Nieuw in deze starter:
# - Keyboard input met on_key_down()
# - Navigatie tussen verschillende schermen
# =============================================================================
from pgzero.screen import Screen
screen: Screen
WIDTH = 800
HEIGHT = 600
TITLE = "Brainstorm"
# =============================================================================
# LOCATIES
# =============================================================================
# Een lijst van tuples: (naam, afbeelding)
#
# Een tuple lijkt op een lijst maar kan niet veranderd worden.
# Perfect voor vaste data!
# locaties[0] -> ("Kelder", "loc_basement")
# locaties[0][0] -> "Kelder"
# locaties[0][1] -> "loc_basement"
# =============================================================================
locaties = [
("Kelder", "loc_basement"),
("Supermarkt", "loc_supermarket"),
("Park", "loc_park"),
("Dak", "loc_rooftop"),
]
huidige_locatie = 0
def draw():
naam, afbeelding = locaties[huidige_locatie]
screen.blit(afbeelding, (0, 0))
screen.draw.text(naam.upper(), center=(400, 50), fontsize=48, color="white",
shadow=(2, 2), scolor="black")
teken_navigatie()
# =============================================================================
# KEYBOARD INPUT
# =============================================================================
# on_key_down(key) wordt aangeroepen als je een toets indrukt.
# key is een constante zoals keys.LEFT, keys.SPACE, etc.
# =============================================================================
def on_key_down(key):
if key == keys.UP:
ga_naar(-1)
elif key == keys.DOWN:
ga_naar(1)
def on_mouse_down(pos):
x, y = pos
# Klik op de pijltjes onderaan
if 350 < x < 450:
if y > 545:
ga_naar(1)
elif y > 510:
ga_naar(-1)
def update(dt):
"""Wordt elk frame aangeroepen. Handig voor animaties!"""
pass
# =============================================================================
# HELPER FUNCTIES
# =============================================================================
def ga_naar(richting):
"""Verander van locatie. richting is 1 (vooruit) of -1 (terug)."""
global huidige_locatie
nieuwe_locatie = huidige_locatie + richting
if 0 <= nieuwe_locatie < len(locaties):
huidige_locatie = nieuwe_locatie
def teken_navigatie():
"""Teken pijltjes onderaan om te navigeren (klikbaar!)."""
if huidige_locatie > 0:
screen.draw.text("^", center=(400, 530), fontsize=60, color="white",
shadow=(2, 2), scolor="black")
if huidige_locatie < len(locaties) - 1:
screen.draw.text("v", center=(400, 560), fontsize=60, color="white",
shadow=(2, 2), scolor="black")
Navigeer met de pijltjestoetsen (of klik) tussen verschillende locaties. Elke locatie heeft een eigen achtergrond.
Nieuw: Keyboard input!
Dit is anders dan on_mouse_down(pos) uit Level 5. Andere toetsen
die je kan gebruiken: keys.LEFT, keys.RIGHT, keys.SPACE, keys.ESCAPE.
Nieuw: Tuples!
locaties = [
("Kelder", "loc_basement"),
("Supermarkt", "loc_supermarket"),
("Park", "loc_park"),
("Dak", "loc_rooftop"),
]
Een tuple lijkt op een lijst maar kan niet veranderd worden. Perfect voor vaste data! Je kan de waarden uitpakken:
Starter C: JSON Data
Bekijk de code
# =============================================================================
# ZOMBIE APOCALYPSE - Level 6 - Starter C: JSON Data
# =============================================================================
# Start met: pgzrun zombie.py
#
# Deze starter laat zien hoe je game data uit een JSON bestand laadt.
# Zo kan je zombies, items en locaties aanpassen zonder code te wijzigen!
#
# Nieuw in deze starter:
# - JSON bestanden laden met json.load()
# - Data-driven design: speldata staat los van de code
# - Afbeeldingen laden op basis van namen uit data
# =============================================================================
import json
import random
import pygame
from pgzero.builtins import Rect, images
from pgzero.screen import Screen
screen: Screen
WIDTH = 800
HEIGHT = 600
TITLE = "Brainstorm"
# =============================================================================
# JSON LADEN
# =============================================================================
# JSON (JavaScript Object Notation) is een standaard formaat
# om data op te slaan. Het lijkt heel erg op Python dictionaries!
#
# json.load(bestand) leest een JSON bestand en geeft een
# Python dictionary of lijst terug.
#
# Voordeel: je kan de data aanpassen in data.json zonder
# de Python code te veranderen!
# =============================================================================
with open("data.json") as bestand:
data = json.load(bestand)
zombies = data["zombies"]
# Willekeurige zombie uit de JSON data
huidige_zombie = random.choice(zombies)
def draw():
screen.fill((30, 30, 40))
teken_tekst("Zombie Dex", center=(400, 40), fontsize=44)
teken_zombie(huidige_zombie)
teken_tekst("Klik voor een andere zombie",
center=(400, HEIGHT - 40), fontsize=20, kleur="gray")
def teken_zombie(zombie):
"""Teken een zombie met afbeelding en stats."""
# ==========================================================================
# AFBEELDING OP BASIS VAN DATA
# ==========================================================================
# In data.json staat: "afbeelding": "zombie_chef"
# Dit is dezelfde naam als het bestand in images/: zombie_chef.png
#
# getattr(images, naam) laadt het plaatje met die naam
# transform.scale past de grootte van het plaatje aan
# ==========================================================================
img = getattr(images, zombie["afbeelding"])
geschaald = pygame.transform.scale(img, (210, 140))
screen.surface.blit(geschaald, (295, 100))
# Zombie naam
teken_tekst(zombie["naam"], center=(400, 310), fontsize=36)
# ==========================================================================
# STATS TEKENEN
# ==========================================================================
# We tekenen een simpele balk voor elke stat
# De breedte van de balk is gebaseerd op de waarde (1-5)
# ==========================================================================
stats = zombie["stats"]
stat_namen = {
"snelheid": "Snelheid",
"kracht": "Kracht",
"slimheid": "Slimheid",
}
y_start = 400
for i, (sleutel, label) in enumerate(stat_namen.items()):
y = y_start + i * 50
waarde = stats[sleutel]
# Label
teken_tekst(label, center=(250, y), fontsize=24)
# Achtergrond balk
balk_x = 340
balk_breedte = 200
screen.draw.filled_rect(Rect(balk_x, y - 10, balk_breedte, 20), (60, 60, 80))
# Gekleurde balk op basis van waarde (1-5)
gevuld = int(balk_breedte * waarde / 5)
kleur = (50 + waarde * 40, 200 - waarde * 30, 50)
screen.draw.filled_rect(Rect(balk_x, y - 10, gevuld, 20), kleur)
# Waarde als tekst
teken_tekst(str(waarde), center=(balk_x + balk_breedte + 30, y), fontsize=24)
def on_mouse_down(pos):
"""Klik voor een nieuwe willekeurige zombie."""
global huidige_zombie
huidige_zombie = random.choice(zombies)
def teken_tekst(tekst, center, fontsize, kleur="white"):
x, y = center
screen.draw.text(tekst, center=(x+2, y+2), fontsize=fontsize, color="black")
screen.draw.text(tekst, center=(x, y), fontsize=fontsize, color=kleur)
Laad zombie data uit een JSON bestand. Zo staat je speldata los van de code!
Nieuw: JSON laden!
JSON lijkt heel erg op Python dictionaries. Open data.json om te zien
hoe de data eruitziet. Je kan makkelijk zombies toevoegen of aanpassen
zonder de Python code te veranderen.
En nu?
Website
De Brainstorm, Zombiepedia en Pygame Recepten staan op de website: laoujin.github.io/CoderDojo-Zombies
Extra plaatjes
Elke starter heeft alleen de plaatjes die hij nodig heeft.
Wil je meer? In levels/level-5/images/ vind je 70+ plaatjes:
achtergronden, knoppen, items, zombies en locaties.
In levels/level-5/images/sprites/ vind je losse zombie sprites
met transparante achtergrond — perfect om als Actor te gebruiken!
Kopieer wat je nodig hebt naar de images/ map van jouw starter.
Kies een starter en bouw je eigen spel! Hier zijn een paar ideeën om je op weg te helpen:
Tactisch gevecht met zombie stats
Begin met Starter C (JSON Data). De zombies hebben al stats (snelheid, slimheid, kracht). Gebruik die stats om te bepalen welke actie werkt:
- Snelle zombie? → Rennen werkt niet!
- Slimme zombie? → Verstoppen werkt niet!
- Sterke zombie? → Vechten zonder wapen werkt niet!
Bekijk de Brainstorm voor voorbeeldcode die laat zien hoe je kansen berekent op basis van stats.
Meerdere locaties ontdekken
Begin met Starter B (Locaties). Voeg zombie-ontmoetingen toe op elke locatie. Misschien heeft het ziekenhuis andere zombies dan het park?
Bekijk de Zombiepedia om te kiezen welke zombies waar verschijnen.
Combineer alles
Wil je het ultieme spel? Combineer de ideeën!
- Gebruik Starter A (Enums) voor nette code
- Voeg locaties toe uit Starter B
- Laad zombie data uit een JSON bestand zoals in Starter C
- Gebruik de Brainstorm voor tactisch gevecht
- Kies je zombies uit de Zombiepedia
Hulp nodig?
- Brainstorm — de uitdaging, spelregels en voorbeeldcode
- Zombiepedia — alle zombies met stats en zwaktes
- Pygame Recepten — handige patronen voor animaties, meerdere sprites en meer