We gaan Snake bouwen voor in de browser.
Introductie

Snake is een mobiele video game geïntroduceerd op een Nokia telefoon in 1998.
Spelregels
Het doel van het spel Snake is om zoveel mogelijk fruit te eten (dit is je score). Hoe meer je eet, hoe langer de slang wordt en ook beweegt de slang sneller. Als de slang tegen zichzelf botst of buiten het scherm gaat is het game over.
Dus om Snake te bouwen moet het spel het volgende doen:
- Beweeg de slang met de pijltjestoetsen
- Plaats op een willekeurige plek fruit
- De slang moet het fruit kunnen eten
- Als er fruit gegeten is moet de slang langer worden
- Als er fruit gegeten is krijg je een punt
- Als de slang tegen zichzelf botst, is het game over
- Ook als de slang buiten het scherm gaat is het game over
Nu we de spelregels duidelijk hebben en weten wat het spel moet gaan doen, is het tijd om Snake te gaan bouwen!
Wat heb je nodig?
Een text editor als Visual Studio Code en natuurlijk een browser zoals Chrome.
Instructie
Dit gaan we maken:

1. HTML
We beginnen met de basis. Maak een nieuw bestand aan met bijvoorbeeld de naam snake.html. Kopieer en plak daarin
onderstaande code. Als je het bestand opent in Chrome, zie je een groot vierkant. Dit is het speelveld van de game.
| |
2. Een appel
We gaan nu aan de slag met Javascript en beginnen met het tekenen van een appel:
Voeg toe op regel 17 in de vorige code:
| |
En tussen de <script> en </script> tags:
| |
Je ziet nu in de browser linksboven in het vierkant een rode cirkel: de appel.
We hebben best veel code nodig gehad, maar regels 1 t/m 8 zijn nodig ter voorbereiding van tekenen en de indeling van het vierkant in kleine vakjes van 25 bij 25 pixels.
function tekenAppel() tekent tenslotte de rode cirkel.
3. De kop van de slang
Voeg toe na regel const appel = { x: 0, y: 0 };:
| |
En dan vóór regel tekenAppel();:
| |
En na regel tekenAppel();:
| |
Variabele slang is een lijst van delen van de slang. Deze lijst wordt steeds grotere naarmate de slang meer appels
heeft gegeven. Voor ieder slangdeel bepalen de x en y de positie van dat deel op het speelveld.
Functie tekenSlang gaat langs ieder deel van de slang met een “for”-lus en tekent ieder deel op de juiste plaats
bepaald door slangDeel.x en slangDeel.y.

4. De slang besturen, deel 1
Om de slang te besturen, gaan we de pijltjestoetsen op je toetsenbord gebruiken.
Als eerste stap gaan het indrukken van de pijltjestoetsen vertalen naar een richting voor de slang: omhoog, omlaag,
link, rechts.
We moeten eerst bewaren welke richting de slang op moet bewegen. We voegen daarvoor de volgende regel toe na de regel
met daarin const slang = [{ x: 10, y: 10 }];. We beginnen met de richting naar rechts:
| |
En vervolgens voegen we code toe om het indrukken van de pijltjestoetsen om te zetten naar een richting:
| |
Als je dit hebt toegevoegd, dan zie de kop van de slang nog niet bewegen. Maar je kunt wel de richting als tekst wel
zijn de “developer console”. Om daar te komen druk je op toetscombinatie ctrl + shift + i. Je kunt dan zien wat er
aan de “achterkant” van de webpagina gebeurd. Kies tabje “console” en klik dan weer op de webpagina. Als je dan
op de pijltjestoetsen drukt, zie je richtingen getoond in die console.

4. De slang besturen, deel 2
We kunnen de slang alleen besturen als het ook beweegt. Dus we beginnen met het laten bewegen van de slang:
| |
Deze code maakt een nieuwe kop van de slang aan, voegt die toe aan de slang (slang.unshift(nieuweSlangenKop)) en verwijdert het
achterste deel van de slang (slang.pop()). Hiermee verplaatst de slang iedere keer 1 blokje verder.
Om de slang dus te laten bewegen, moeten we deze functie meerdere keren achter elkaar uitvoeren. Bij iedere keer dat de functie wordt uitgevoerd, zal de slang weer een blokje verder verplaatsen.
Om deze functie en die om de slang en appel te tekenen meerdere keren uit te voeren, hebben we de volgende code nodig:
| |
setInterval roept functie gameLoop 10 x per seconde aan. Hiermee wordt dus 10 x per seconde de slang verplaatst en
de slang en appel opnieuw getekend.
Als je dit test, zie je de slang bewegen, maar het einde van de slang wordt steeds langer. Dat is gek, want we hebben
code toegevoegd om het einde van de slang weer te verwijderen, toch?
Dit komt, doordat we het speelveld niet leeg maken voordat we de slang en de appel opnieuw tekenen. De vorige slang
blijft dus staan.
We maken een nieuwe functie maakSpeelveldLeeg() en voegen die toe aan functie gameLoop():
| |
We hebben nu al veel code geschreven. Als je niet zeker weet of je het allemaal goed hebt gedaan, kun je even in dit bestand kijken: tot-en-met-opdracht-4.html.
5. Appels eten
De slang eet appels als de kop van de slang een appel raakt. Dat zullen we dus moeten toevoegen aan onze code:
Vervang:
| |
Met:
| |
Als de nieuweSlangenKop nu op dezelfde plek komt als de appel, wordt functie nieuwePlaatsAppel() aangeroepen.
Maar ook wordt slang.pop() niet aangeroepen en dus wordt de slang 1 blokje langer.
We moeten nog wel functie nieuwePlaatsAppel() maken:
| |
Math.random() is een functie in Javascript om zomaar een getal tussen 0 en 1 te maken. Iedere keer weer een ander
getal. Door dit getal met het aantalVakjes op het speelveld te vermenigvuldigen en af te ronden (Math.floor()),
kunnen we nieuwe x en y posities van de appel bepalen.
6. Game over: als de slang tegen zichzelf botst
De meeste van de spelregels hebben we nu gemaakt in het spel. Maar één van de regels is dat het spel over is als de slang tegen zichzelf botst. Dus dat moeten we er nog even aan toe voegen.
Voeg aan het begin van de gameLoop() functie het volgende toe:
| |
Als isGameOver() waar is, dan eindigt gameLoop() en stop het spel.
Om dit te laten werken, moeten we functie isGameOver() maken:
| |
Het spel is over als slangHeeftZichzelfGeraakt() waar is. Deze functie ziet er als volgt uit:
| |
In deze functie wordt de positie van de slangenKop vergeleken met alle slangDeelen na de kop. Als een deel wordt
gevonden op dezelfde positie, dan is het resultaat van slangHeeftZichzelfGeraakt() waar (true).
Als er geen gevonden wordt, is het resultaat niet waar (false).
7. Game over: als de slang de randen heeft geraakt
We hebben de gameOver() functie al, maar moeten het aanpassen met de 2e voorwaarde:
| |
|| betekend hier “of”, dus als slangHeeftZichzelfGeraakt() of slangHeeftEenRandGeraakt() waar is, dan geeft
isGameOver() ook waar (true) terug.
Met nieuwe functie slangHeeftEenRandGeraakt():
| |
8. Game over: toon game over!
Als het game over is, stopt nu het spel. Maar verder zie je niet dat het spel afgelopen is. Het zou beter
zijn als we dat laten zien in het spel.
Als isGameOver() waar is, roepen we toonGameOver() aan:
| |
En voegen die toe aan het script:
| |

9. De score
We zouden het bijna vergeten, maar ook de score moet worden bijgehouden.
Voeg de volgende functie toe:
| |
En roep deze functie aan, aan het einde van de gameLoop():
| |
10. Een échte appel
Het rode cirkeltje wat de appel voorstelt, is een beetje saai. We kunnen het ook vervangen met een plaatje van een appel.
We voegen allereerst een plaatje toe aan de html, regels 3, 4 en 5:
| |
En dan vervangen we de inhoud van functie tekenAppel() met:
| |
En we vervangen:
| |
Met:
| |
Goed gedaan!
En dat is het, je hebt het spel Snake gebouwd! Hoe lang hou jij het vol en wat is de hoogste score die je kunt krijgen?
Heb je iets niet goed begrepen, vraag het dan aan één van de mentoren, we helpen je natuurlijk graag!
Je kunt ook altijd een kijkje nemen bij de andere kinderen, misschien kan jij hun helpen!
Hier kun je tenslotte nog het eindresultaat zien: resultaat.
Licentie
Deze instructies worden, net als alle andere instructies van CoderDojo Nijmegen, aangeboden onder een Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Licentie.
