Snake copy
0 Wat gaan we leren
We gaan nog een projectje maken met Thonny (uit de vorige les) en bij dit project gaan we gebruik maken van de standaard Python library:
pgzero
Weet je nog hoe je een pacakgepackage installeert in Thonny?
Yep, Tools - Manage Packages en dan pgzero zoeken en installeren.
1 Snake – Les 1: Teken de slangkop
In deze les gaan we beginnen met het maken van een eigen versie van Snake in Python met Pygame Zero.
We gaan eerst de kop van de slang tekenen op het scherm. Je ziet dan een vierkantje dat straks kan gaan bewegen.
Wat gaan we doen?
We maken een slangkop als vierkant met een bepaalde positie en grootte, en tekenen die in de draw()
-functie.
📦 Benodigdheden
- Een werkende Python-omgeving met Pygame Zero (zoals Thonny)
- Geen plaatjes nodig – we tekenen de slang met blokken
🔰 Startercode
# importeer library
import pgzrun
# Spelgrootte
WIDTH = 600
HEIGHT = 400
# Startpositie van de slangkop
snake_x = 100
snake_y = 100
tile_size = 20
def draw():
screen.clear()
screen.draw.filled_rect(Rect((snake_x, snake_y), (tile_size, tile_size)), "green")
#start programma
pgzrun.go()
ℹ️ Uitleg
WIDTH
enHEIGHT
: grootte van het spelvenstersnake_x
ensnake_y
: positie van de slangkoptile_size
: grootte van het blokjescreen.draw.filled_rect(...)
: tekent een gevuld vierkantje op het scherm
🛠️ Opdracht
- Pas de waarde van
snake_x
ensnake_y
aan – wat gebeurt er? - Maak het vierkant groter of kleiner door
tile_size
te wijzigen - Verander de kleur van het vierkant in bijvoorbeeld
"blue"
of"orange"
💡 Extra uitdaging
Teken een tweede blokje naast de slangkop alsof er al een stukje staart is. Gebruik nog een screen.draw.filled_rect()
.
📤 Inleveren
- Maak een screenshot van je 'slangkop' op het scherm waarbij je de 'slangkop'op een andere positie
hebhebt gezet.
2 Snake – Les 2: Beweeg de slang
In deze les gaan we de slangkop laten bewegen met de pijltjestoetsen.
We gebruiken daarvoor de update()
-functie van Pygame Zero en de toetsenbordinput.
Wat gaan we doen?
We maken een richting-variabele en passen de positie van de slang aan op basis van de pijltjes die je indrukt.
🔰 Code
Dit is een deel van de code, je moet jouw bestaande code aanpassen aan de hand van deze nieuwe code.
# Startpositie van de slangkop
snake_x = 200
snake_y = 200
tile_size = 10
step = 1
def draw():
screen.clear()
screen.draw.filled_rect(Rect((snake_x, snake_y), (tile_size, tile_size)), "green")
def update():
global snake_x, snake_y
if keyboard.left:
snake_x -= step
if keyboard.right:
snake_x += step
if keyboard.up:
snake_y -= step
if keyboard.down:
snake_y += step
ℹ️ Uitleg
update()
wordt automatisch meerdere keren per seconde uitgevoerdkeyboard.left
controleert of de linkerpijl is ingedrukt- Telkens als je een toets indrukt, verandert de positie van de slang
step
bepaalt hoe ver de slang per stap beweegt
🛠️ Opdracht
- Beweeg de slang door het scherm met de pijltjes
- Pas
step
aan naar een andere waarde – wat merk je? - Laat de slang sneller of langzamer bewegen door minder of meer pixels per keer te verplaatsen
💡 Extra uitdaging
Laat de slang automatisch blijven bewegen in de laatst gekozen richting:
- Gebruik een variabele
richting
die je bijwerkt meton_key_down()
- Laat de slang dan elke update in die richting verder bewegen
📤 Inleveren
- Leg uit wat de variable step doet.
- Welke waarde heb je gekozen, waarom?
(je kunt dit inleveren in het tekst veld of in een .txt. bestandje)
3 Snake – Les 3: Slang groeit
In deze les gaan we de slang laten groeien. De slang bestaat dan uit meerdere blokjes in plaats van alleen de kop.
Als de slang eten raakt, groeit zijn lichaam één blokje langer.
Wat gaan we doen?
We werken met een list waarin we alle segmenten van de slang opslaan. Bij elke stap schuift de slang een blokje op, en als hij iets eet voegen we er een nieuw blokje aan toe.
🔰 Startercode
import random
WIDTH = 600
HEIGHT = 400
tile_size = 20
# Startpositie en richting
snake = [(100, 100)]
richting = "rechts"
# Plaats van het eten
food_x = 300
food_y = 200
def draw():
screen.clear()
for segment in snake:
screen.draw.filled_rect(Rect(segment, (tile_size, tile_size)), "green")
screen.draw.filled_rect(Rect((food_x, food_y), (tile_size, tile_size)), "red")
def update():
global food_x, food_y
# Huidige koppositie
head_x, head_y = snake[0]
# Nieuwe positie bepalen
if keyboard.left:
new_head = (head_x - tile_size, head_y)
elif keyboard.right:
new_head = (head_x + tile_size, head_y)
elif keyboard.up:
new_head = (head_x, head_y - tile_size)
elif keyboard.down:
new_head = (head_x, head_y + tile_size)
else:
return # Geen toets ingedrukt
# Nieuwe kop toevoegen aan de slang
snake.insert(0, new_head)
# Controleren op eten
if new_head[0] == food_x and new_head[1] == food_y:
food_x = random.randint(0, (WIDTH // tile_size) - 1) * tile_size
food_y = random.randint(0, (HEIGHT // tile_size) - 1) * tile_size
# slang groeit: we verwijderen geen staart
else:
# Verwijder het laatste segment van de staart
snake.pop()
ℹ️ Uitleg
snakeis een lijst met alle blokjes van de slang (als coördinaten)Elke keer als je beweegt voeg je een nieuw blokje toe aan het beginAls je geen eten raakt, verwijder je het laatste blokjeAls je wél eten raakt, blijft het hele lichaam staan → de slang groeit!
🛠️ Opdracht
Speel het spel en probeer de slang langer te maken door eten op te pakkenBekijk hoe de slang groeit – hoeveel blokjes zie je na 3 stukjes eten?Verander de kleur van het eten of maak het iets groter
💡 Extra uitdaging
Laat het eten op een andere plek verschijnen als je de slang startMaak het eten een ander soort vorm, bijvoorbeeld met een `screen.draw.circle()`
📤 Inleveren
Maak een screenshot van je slang die gegroeid is (minimaal 4 segmenten lang).
Schrijf in 1 zin uit hoe het komt dat de slang groeit.
4 Snake – Les 4: Eten op random plek
In deze les gaan we ervoor zorgen dat het eten steeds op een andere plek verschijnt als de slang het opeet.
We zorgen er ook voor dat het eten netjes op de “grid” ligt, zodat het altijd op een blokje van de slang past.
Wat gaan we doen?
We gebruiken de functie random.randint() om een willekeurige x- en y-coördinaat te kiezen.
We leggen uit waarom we moeten vermenigvuldigen met tile_size.
🔰 Startercode
import random
WIDTH = 600
HEIGHT = 400
tile_size = 20
snake = [(100, 100)]
richting = "rechts"
# Eten verschijnt op een random plek
def nieuwe_eten_plek():
x = random.randint(0, (WIDTH // tile_size) - 1) * tile_size
y = random.randint(0, (HEIGHT // tile_size) - 1) * tile_size
return x, y
food_x, food_y = nieuwe_eten_plek()
def draw():
screen.clear()
for segment in snake:
screen.draw.filled_rect(Rect(segment, (tile_size, tile_size)), "green")
screen.draw.filled_rect(Rect((food_x, food_y), (tile_size, tile_size)), "red")
def update():
global food_x, food_y
head_x, head_y = snake[0]
if keyboard.left:
new_head = (head_x - tile_size, head_y)
elif keyboard.right:
new_head = (head_x + tile_size, head_y)
elif keyboard.up:
new_head = (head_x, head_y - tile_size)
elif keyboard.down:
new_head = (head_x, head_y + tile_size)
else:
return
snake.insert(0, new_head)
if new_head == (food_x, food_y):
food_x, food_y = nieuwe_eten_plek()
else:
snake.pop()
ℹ️ Uitleg
WIDTH // tile_sizeberekent hoeveel blokjes er in de breedte passenrandom.randint(...)kiest een willekeurig blokjeDoor daarna te vermenigvuldigen mettile_size, krijg je een echte pixelpositieWe zorgen dat het eten altijd op een logische plek verschijnt
🛠️ Opdracht
Test of het eten steeds op een andere plek verschijnt als je het paktWat gebeurt er als je het etennet nietraakt?Probeer ook een keer het spel opnieuw te starten en zie hoe het eten telkens ergens anders staat
💡 Extra uitdaging
Laat het eten een andere kleur krijgen elke keer dat het verspringtLaat meerdere stukken eten tegelijk op het scherm verschijnen
📤 Inleveren
Maak een screenshot van een moment waarop het eten net op een nieuwe plek is verschenen.
Beschrijf in 1 zin wat de functie nieuwe_eten_plek() doet.
5 Snake – Les 5: Game Over bij botsing
In deze les leren we hoe het spel stopt als de slang zichzelf raakt of tegen de rand van het scherm botst.
We voegen een “Game Over”-scherm toe zodat je ziet wanneer je verloren hebt.
Wat gaan we doen?
We controleren of de kop van de slang buiten het scherm komt of of hij in zijn eigen lichaam bijt.
Als dat gebeurt, zetten we de variabele game_over op True en stoppen we het spel.
🔰 Startercode
import random
WIDTH = 600
HEIGHT = 400
tile_size = 20
snake = [(100, 100)]
richting = "rechts"
game_over = False
def nieuwe_eten_plek():
x = random.randint(0, (WIDTH // tile_size) - 1) * tile_size
y = random.randint(0, (HEIGHT // tile_size) - 1) * tile_size
return x, y
food_x, food_y = nieuwe_eten_plek()
def draw():
screen.clear()
if game_over:
screen.draw.text("GAME OVER", center=(WIDTH // 2, HEIGHT // 2), fontsize=60, color="red")
return
for segment in snake:
screen.draw.filled_rect(Rect(segment, (tile_size, tile_size)), "green")
screen.draw.filled_rect(Rect((food_x, food_y), (tile_size, tile_size)), "red")
def update():
global food_x, food_y, game_over
if game_over:
return
head_x, head_y = snake[0]
if keyboard.left:
new_head = (head_x - tile_size, head_y)
elif keyboard.right:
new_head = (head_x + tile_size, head_y)
elif keyboard.up:
new_head = (head_x, head_y - tile_size)
elif keyboard.down:
new_head = (head_x, head_y + tile_size)
else:
return
# Check voor botsing met rand
if new_head[0] < 0 or new_head[0] >= WIDTH or new_head[1] < 0 or new_head[1] >= HEIGHT:
game_over = True
return
# Check voor botsing met eigen lichaam
if new_head in snake:
game_over = True
return
snake.insert(0, new_head)
if new_head == (food_x, food_y):
food_x, food_y = nieuwe_eten_plek()
else:
snake.pop()
ℹ️ Uitleg
game_overis een variabele die bepaalt of het spel nog bezig isAls de slang buiten het scherm gaat of zichzelf raakt, stopt de update-functieIndraw()tonen we dan een rode “GAME OVER”-tekst
🛠️ Opdracht
Speel het spel en probeer expres tegen jezelf of de rand te botsenControleer of “GAME OVER” verschijnt en het spel stoptVerander de tekst of kleur van de “Game Over”-melding
💡 Extra uitdaging
Laat de speler opnieuw beginnen met de R-toetsSpeel een geluid af als het spel voorbij is (bijv.sounds.crash.play())
📤 Inleveren
Maak een screenshot waarop de slang tegen zichzelf of de rand is gebotst en “GAME OVER” verschijnt.
Leg in een paar zinnen uit wat de code doet om te controleren of je verloren hebt.
6 Snake – Les 6: Score bijhouden
In deze les gaan we een score bijhouden. Elke keer dat de slang eten opeet, telt de score één punt op.
We tonen deze score linksboven op het scherm, zolang het spel bezig is.
Wat gaan we doen?
We maken een score-variabele en verhogen deze telkens als de slang het eten raakt. In draw() tekenen we de score op het scherm.
🔰 Startercode
import random
WIDTH = 600
HEIGHT = 400
tile_size = 20
snake = [(100, 100)]
richting = "rechts"
game_over = False
score = 0
def nieuwe_eten_plek():
x = random.randint(0, (WIDTH // tile_size) - 1) * tile_size
y = random.randint(0, (HEIGHT // tile_size) - 1) * tile_size
return x, y
food_x, food_y = nieuwe_eten_plek()
def draw():
screen.clear()
if game_over:
screen.draw.text("GAME OVER", center=(WIDTH // 2, HEIGHT // 2), fontsize=60, color="red")
screen.draw.text(f"Score: {score}", center=(WIDTH // 2, HEIGHT // 2 + 50), fontsize=40, color="black")
return
for segment in snake:
screen.draw.filled_rect(Rect(segment, (tile_size, tile_size)), "green")
screen.draw.filled_rect(Rect((food_x, food_y), (tile_size, tile_size)), "red")
screen.draw.text(f"Score: {score}", (10, 10), fontsize=40, color="black")
def update():
global food_x, food_y, game_over, score
if game_over:
return
head_x, head_y = snake[0]
if keyboard.left:
new_head = (head_x - tile_size, head_y)
elif keyboard.right:
new_head = (head_x + tile_size, head_y)
elif keyboard.up:
new_head = (head_x, head_y - tile_size)
elif keyboard.down:
new_head = (head_x, head_y + tile_size)
else:
return
# Check voor botsing met rand
if new_head[0] < 0 or new_head[0] >= WIDTH or new_head[1] < 0 or new_head[1] >= HEIGHT:
game_over = True
return
# Check voor botsing met eigen lichaam
if new_head in snake:
game_over = True
return
snake.insert(0, new_head)
if new_head == (food_x, food_y):
food_x, food_y = nieuwe_eten_plek()
score += 1
else:
snake.pop()
ℹ️ Uitleg
score = 0: we starten met een lege scoreBij een botsing met eten doen wescore += 1Metscreen.draw.text(...)tonen we de score op het schermBij Game Over tonen we ook de score onder de tekst
🛠️ Opdracht
Speel het spel en probeer een score van minimaal 5 te halenVerander de kleur of het lettertype van de scoreLaat de tekst op een andere plek op het scherm zien (bijvoorbeeld rechtsboven)
💡 Extra uitdaging
Laat de kleur van de score veranderen bij elke 5 puntenToon de hoogste score ooit behaald (highscore bijhouden)
📤 Inleveren
Maak een screenshot van je spel met een zichtbare score van minimaal 5 punten.
Leg in één zin uit wat de regel score += 1 doet in jouw spel.
7 Snake – Reflectie & Uitbreiding
In deze laatste les ga je terugkijken op wat je hebt geleerd en krijg je de kans om zelf iets toe te voegen aan jouw Snake-spel.
Je beslist zelf wat je wilt verbeteren, uitbreiden of mooier maken.
🧠 Reflectie
Beantwoord de volgende vragen in een apart document of als commentaar onderaan je code:
Wat vond je het leukste om te maken aan het Snake-spel?Wat vond je lastig? Hoe heb je dat opgelost?Wat heb je geleerd over Python en programmeren?Waar ben je trots op?
🎮 Eindopdracht: Uitbreiding
Kies één van de onderstaande uitbreidingen en voeg die toe aan je spel. Je mag ook je eigen idee uitvoeren!
🐍 Toon het volledige lichaam van de slang met een andere kleur voor de kop🧱 Voeg muren toe waar je niet doorheen mag (botsing = Game Over)🔁 Laat de slang automatisch blijven bewegen in de huidige richting🕹️ Laat het spel moeilijker worden (bv. door sneller te gaan naarmate je groeit)🎨 Maak je eigen kleuren of achtergrond📊 Laat een highscore zien die blijft staan zolang je speelt
💡 Eigen idee?
Bedenk zelf een uitbreiding en beschrijf wat je van plan bent. Probeer het daarna te maken!
📤 Inleveren
Lever een screenshot of filmpje in van jouw aangepaste versie van het spelVertel in 1 of 2 zinnen wat jij hebt toegevoegd of verbeterdLever je reflectie in met de antwoorden op de 4 vragen hierboven
###
# Docenten
🎓 Docentenhandleiding
📘 Overzicht
Doelgroep:Leerlingen van 13-16 jaar met basiskennis PythonDuur:6 lessen van ±45-60 minutenSoftware:Thonny + Pygame ZeroSpelconcept:Maak een klassieke Snake-game waarbij de slang groeit als hij voedsel eet
🎯 Leerdoelen
Werken met coördinaten en rastersGebruik vandraw()enupdate()voor game loopToetsenbordinput metkeyboard.left/right/up/downWerken met lijsten (snake = [(x, y), ...])Gebruik vanif-statements voor botsing en logicaGebruik van functies zoalsrandom.randint()Reflecteren en uitbreiden van bestaande code
📚 Lesoverzicht
| ||
| ||
| ||
| ||
| ||
|
⚠️ Valkuilen
Slang beweegt niet goed → positie niet geüpdatet met vaste stappenEten verschijnt buiten raster →tile_sizevergeten bij randomizingSlang groeit te veel of niet → vergetensnake.pop()uit te voerenGame Over werkt niet → koppositie niet correct gecheckt tegen eigen lichaam
🧠 Differentiatie
Voor snelle leerlingen
Voeg muren toe of maak levels met obstakelsVoeg een tweede speler toe (WASD)Maak het spel sneller bij hogere scoreLaat de slang automatisch bewegen in huidige richting
Voor langzamere leerlingen
Werk alleen met een kop zonder lichaamLaat beweging alleen per toetsdruk toe (geen auto-move)Gebruik visueel grid of help bij rasteruitlijning
📊 Beoordeling (optioneel)
💡 Lesaanpak & tips
Gebruik bij elke les een klassikale “test en speel”-faseLaat leerlingen fouten tonen op het bord (met uitleg!)Bespreek hoe je problemen oplost met print-debuggenGeef tijd voor zelfstandig uitbreiden in les 6Laat leerlingen elkaars spel testen in tweetallen
🧰 Benodigdheden
Thonny met Pygame Zero (pip install pgzero)Werkende computer met toetsenbordBasiskennis van Python:if,def, variabelen