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 package 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 hebt gezet.
2 Snake β Les 2: Beweeg de slang
In deze les gaan we de slangkop laten bewegen met de pijltjestoets die je indrukt.
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.
Je hoeft dus niet alles opnieuw te typen. Plaats deΒ update()
functieΒ en pas eventueel snake_x
, snake_y
, tile_size
en step
aan in jouw bestaande 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 Automatische beweging
In deze les gaan we de slang automatisch laten blijven bewegen in de richting van de laatste pijltjestoets die je hebt ingedrukt.
π Wat gaan we doen?
- We maken een nieuwe variabele
richting
. - Als je op een pijltjestoets drukt, verandert de waarde van
richting
. - In de
update()
functie verplaatst de slang zich elke keer opnieuw in de gekozen richting β ook als je de toets niet ingedrukt houdt!
π° Code
Gebruik deze versie als nieuwe code (je mag dit toevoegen aan of combineren met je bestaande code):
import pgzrun
WIDTH = 600
HEIGHT = 400
snake_x = 200
snake_y = 200
tile_size = 20
step = 10
richting = "right"
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 richting == "left":
snake_x -= step
elif richting == "right":
snake_x += step
elif richting == "up":
snake_y -= step
elif richting == "down":
snake_y += step
def on_key_down(key):
global richting
if key == keys.LEFT:
richting = "left"
elif key == keys.RIGHT:
richting = "right"
elif key == keys.UP:
richting = "up"
elif key == keys.DOWN:
richting = "down"
pgzrun.go()
βΉοΈ Uitleg
richting
: deze variabele onthoudt de laatst gekozen richtingon_key_down()
: dit is een functie die wordt uitgevoerd als je op een toets druktupdate()
: deze functie verplaatst de slang elke keer in de gekozen richting, ook als je geen toets indrukt
π οΈ Opdracht
- Test of je slang automatisch blijft bewegen nadat je een pijl indrukt
- Wat gebeurt er als je twee keer snel op een andere richting drukt?
- Probeer met
tile_size
enstep
te spelen voor een ander effect
π‘ Extra uitdaging
Voeg grenzen toe aan je spel: laat de slang stoppen of ergens anders naartoe gaan als hij de rand van het scherm raakt.
π€ Inleveren
- Leg in je eigen woorden uit wat de functie
on_key_down()
doet
(Lever dit in via het tekstvak of via een upload.)
4 Randbotsing en automatische richting
In deze les zorgen we ervoor dat de slang niet zomaar het scherm verlaat. Zodra hij een rand raakt, verandert hij automatisch van richting. Zo beweegt hij steeds binnen het scherm!
π Wat gaan we doen?
- We controleren of de slang de rand van het scherm raakt.
- Als dat zo is, passen we automatisch de richting aan.
π° Code (let op: onvolledig!)
Hieronder zie je de code. EΓ©n belangrijke regel ontbreekt β die moet jij toevoegen!
import pgzrun
WIDTH = 600
HEIGHT = 400
snake_x = 200
snake_y = 200
tile_size = 20
step = 5
richting = "right"
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, richting
if richting == "left":
snake_x -= step
elif richting == "right":
snake_x += step
elif richting == "...":
snake_y -= step
elif richting == "...":
snake_y += step
# π§ Hier controleren we of de slang de rand raakt
if snake_x < 0:
richting = "right"
elif snake_x + tile_size > WIDTH:
richting = "left"
elif snake_y < 0:
richting = "..."
elif snake_y + tile_size > HEIGHT:
richting = "..."
def on_key_down(key):
global richting
if key == keys.LEFT:
richting = "left"
elif key == keys.RIGHT:
richting = "right"
elif key == keys.UP:
richting = "up"
elif key == keys.DOWN:
richting = "down"
pgzrun.go()
Als je de linker- of rechterkant raakt, dan 'stuitert' je terug. Dat gebeurt niet als je de boven- of onderkant aanraakt. Pas de code aan zodat je ook terugstuiters als je de onder-of bovenkant aanraakt.
βΉοΈ Uitleg
snake_x + tile_size > WIDTH
: betekent dat de slang voorbij de rechterrand gaat- Als de slang een rand raakt, verander je de variabele
richting
- De ontbrekende waarde is wat de slang moet doen als hij links het scherm uit dreigt te gaan
π οΈ Opdracht
- Voeg de ontbrekende regel toe zodat de slang niet door de linkerkant verdwijnt
- Test of de slang de andere richtingen goed oppikt
- Verander eventueel de standaardrichting of startpositie om verschillende randen te testen
π‘ Extra uitdaging
Laat de slang bij elke randbotsing van kleur veranderen! (Tip: maak een variabele kleur
en gebruik bijvoorbeeld random.choice()
)
π€ Inleveren
- Leg uit wat je hebt aangepast en waarom dat werkt.
5 Geen omkeren toegestaan
In deze les zorgen we ervoor dat de slang niet meteen omkeert. In een echte Snake-game kun je namelijk niet ineens van rechts naar links bewegen β dan zou de slang zichzelf opeten!
π Wat gaan we doen?
- We voorkomen dat de slang direct de tegenovergestelde richting kiest.
- We vergelijken de huidige richting met de nieuwe richting voordat we die veranderen.
π° Code (let op: onvolledig!)
De volgende code voorkomt omkeren, maar jij moet één voorwaarde nog zelf aanvullen.
import pgzrun
WIDTH = 600
HEIGHT = 400
snake_x = 200
snake_y = 200
tile_size = 20
step = 1
richting = "right"
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 richting == "left":
snake_x -= step
elif richting == "right":
snake_x += step
elif richting == "up":
snake_y -= step
elif richting == "down":
snake_y += step
def on_key_down(key):
global richting
if key == keys.LEFT and richting != "right":
richting = "left"
elif key == keys.RIGHT and richting != "left":
richting = "right"
elif key == keys.UP and richting != "down":
richting = "up"
elif key == keys.DOWN and richting != "...":
richting = "down"
pgzrun.go()
Stuiteren tegen randen werkt niet meer
Het botsen tegen de randen wat in stap 4 is gedaan, zit niet in deze code. Dat is express gedaan. We proberen op deze manier een ding gelijktijdig uit te leggen en het voorkomt dat je op dit moment "door de bomen het bos niet meer ziet".
βΉοΈ Uitleg
- We gebruiken een
if
-voorwaarde om te voorkomen dat je teruggaat in de tegenovergestelde richting. - De ontbrekende regel is die voor
keys.DOWN
: welke richting is dan niet toegestaan?
π οΈ Opdracht
- Vul de ontbrekende voorwaarde aan zodat de slang niet van "up" naar "down" mag keren
- Test alle richtingen: kun je nog steeds normaal draaien? Keren lukt niet meer, toch?
π‘ Extra uitdaging
Laat de slang een geluidje maken als je op een toets drukt, maar de richting wordt niet veranderd (bijv. als je wΓ©l op links drukt, maar dat mag niet).
Met deze code kan je ene geluidje afspelen.
sounds.beep.play()
Om een sound af te kunnen spelen moet jouw project folder een mapje maken sounds en daarin moet een beep.wav komen.
mijn_project/
βββ main.py
βββ sounds/
βββ beep.wav
Geluidjes toevoegen
Je kunt zelf geluidjes toevoegen, stel je hebt een geluidjeΒ bel.wav dan plaats je dat in de sounds directory en dan gebruik je het commando
souds.bel.play()
π€ Inleveren
- Leg uit wat je hebt veranderd en hoe het werkt.Β
6 Snake β Les 6: Appel tekenen en raken
In deze les voegen we een appel toe aan het spel. De appel verschijnt op een willekeurige plek op het scherm. Als de slang de appel raakt, verschijnt er een bericht in de console.
π Wat gaan we doen?
- We gebruiken de
random
-module om een appel op een willekeurige positie te tekenen. - We tekenen de 'appel' met een geel cirkeltje of vierkantje.
- We detecteren of de slang de appel raakt.
π¦ Benodigdheden
- Je slangkop beweegt al automatisch over het scherm
- Je hebt al gewerkt met
tile_size
ensnake_x
/snake_y
π° Startercode (let op: onvolledig!)
Onderstaande code tekent een slangkop en een appel. De botsing werkt al, maar na een botsing blijft de appel op dezelfde plek staan. Vul zelf aan wat er moet gebeuren!
import pgzrun
import random
WIDTH = 600
HEIGHT = 400
tile_size = 20
snake_x = 100
snake_y = 100
richting = "right"
step = 1
# Appelpositie (willekeurig op het grid)
apple_x = random.randint(0, (WIDTH - tile_size) // tile_size) * tile_size
apple_y = random.randint(0, (HEIGHT - tile_size) // tile_size) * tile_size
def draw():
screen.clear()
screen.draw.filled_rect(Rect((snake_x, snake_y), (tile_size, tile_size)), "green")
screen.draw.filled_circle((apple_x + tile_size // 2, apple_y + tile_size // 2), tile_size // 2, "yellow")
def on_key_down(key):
global richting
if key == keys.LEFT and richting != "right":
richting = "left"
elif key == keys.RIGHT and richting != "left":
richting = "right"
elif key == keys.UP and richting != "down":
richting = "up"
elif key == keys.DOWN and richting != "up":
richting = "down"
def update():
global snake_x, snake_y, apple_x, apple_y
if richting == "left":
snake_x -= step
elif richting == "right":
snake_x += step
elif richting == "up":
snake_y -= step
elif richting == "down":
snake_y += step
# Botst de slang met de appel?
snake_rect = Rect((snake_x, snake_y), (tile_size, tile_size))
apple_rect = Rect((apple_x, apple_y), (tile_size, tile_size))
if snake_rect.colliderect(apple_rect):
print("π Appel geraakt!")
# π VUL HIER AAN: genereer een nieuwe positie voor de appel
# apple_x = ...
# apple_y = ...
pgzrun.go()
βΉοΈ Uitleg
random.randint()
: geeft een willekeurig geheel getal terug- De appelpositie wordt op het grid berekend, zodat deze altijd netjes uitlijnt
filled_circle()
: tekent een geel rondje (je kunt ookfilled_rect()
gebruiken)
π οΈ Opdracht
- Test of de appel op het scherm verschijnt
- Beweeg de slang naar de appel β zie je de console-uitvoer?
- Vul de ontbrekende regels in zodat de appel na een botsing op een nieuwe plek verschijnt
π‘ Extra uitdaging
Laat de appel niet precies op dezelfde plek als de slang verschijnen wanneer hij opnieuw wordt gegenereerd!
π€ Inleveren
- Lever de code in .py bestand.