Om het werken met classes te oefenen gaan we een spelletje maken op basis van het Sprite-voorbeeld (de ufo's) dat we aan het boek hebben toegevoegd.
In de repo vind je een html-file die een <div> en een <button> maakt.
Klikken op de button start het spel, dat plaats zal vinden in de div. De file gebruikt twee JS-bestanden:
SpriteEngine.js-- Dit is een library die gebaseerd is op de classes uit het boek, maar wat netter en krachtiger is. Er is nu ook een Sprite-subklasse die kan helpen met botsingen tussen sprites detecteren.ufoGame.js-- een applicatie-specifieke file om, op basis van de SpriteEngine, een spel te maken waarin Ufo's een rol spelen. [Deze files maken nog geen gebruik van een volwassen module-systeem. Moderne JS code zou niet meer op deze manier met modules werken, en in latere weken gaan wij dat ook niet meer doen in de cursus.]{aside}
1️⃣ Begin met het bekijken van de opzet vande HTML file. Die is vrij overzichtelijk.
2️⃣ Open ufoGame.js. De volgende dingen zijn de moeite van het bestuderen
waard:
- De code bevat een class die Ufo heet. Deze class bestond niet in de versie in het boek, maar is nu even handig omdat we dit keer alle ufo's een ander kleurtje willen geven. Daarnaast kun je nu, als dat handig is, checken of een sprite van het type "Ufo" is.
- En er is code om het spel op te starten. Er worden Ufo's gemaakt, en de start-knop krijgt een event-handler om het spel te starten.
- In
/* */-commentaar zie je alvast drie regels die gaan over classes die jij gaat maken: Een Bullit-klasse voor kogeltjes (dat is stap 3), en een player-klasse om een raket te kunnen besturen die kogels afschiet op de ufo's (stap 1). - Er wordt ook een event-handler geïnstalleerd die naar het toetsenbord luistert. Nu doet-ie nog niet zoveel. Ook dat is code die er staat om het makkelijk te maken daar zelf straks echte dingen te laten gebeuren.
- Op de één-na-laaste programmaregel zie je de aanroep
Sprite.startEngine(). Dat is een aanroep van een statische methode, vandaar dat er een klassenaam voor de punt staat.
{{exLong "constructor-parameters" "Ufo-game-vraag-1"
De constructor van de Ufo class heeft één parameter minder dan die van de
Sprite-class. Waarom is dat geen probleem?
exLong}}
3️⃣ Bestudeer de code van de file SpriteEngine.js. De code definieert drie
classes: Sprite, CollidingSprite en BouncingSprite.
Spriteis wat uitgebreider dan de versie in het boek. Maar de enige uitbreiding die wat ingewikkeld is, is dat deze klasse nu zelf bijhoudt welke Sprites er aangemaakt worden, zodat het al die instanties ook zelf kan animeren (door periodiek hunupdate()methode aan te roepen).- Lees de commentaren nauwkeurig.
- De klasse BouncingSprite is bevat niets nieuws.
- De klasse CollidingSprite wel. Bekijk ook daar de code en de commentaren nauwkeurig.
{{exShort "Vraag:" "Ufo-game-vraag-2"
Geef de regelnummers van alle regels van de klasse Sprite die iets doen (maken, gebruiken) met statische functies.
exShort}}
{{exShort "Vraag:" "Ufo-game-vraag-3" Er is ook een statisch variabele. Die wordt nogal anders aangemaakt dan de statische functies.
Geef de regelnummers van alle regels van de klasse Sprite die iets doen (maken, gebruiken) met de statische variabele.
exShort}}
Voor de speler hebben we maar één sprite nodig, maar daarvoor maken we wel eerst een klasse. De speler heeft namelijk eigen gedrag die andere Sprites niet hebben:
- De speler bevindt zich onderin het game-scherm,
- en beweegt alleen naar links of naar rechts.
- Als de speler voor het eerst in beeld komt, staat-ie stil, ergens links-onderin (b.v. 60px van de kant).
- De constructor heeft geen parameters nodig. Afbeelding, startlokatie, en snelheid liggen vast.
- Als de gebruiker een pijltjestoets (links/rechts) indrukt, dan gaat de speler bewegen in de richting van de toets.
- Maar de speler stopt niet met bewegen als de gebruiker de toets weer loslaat. Hij blijft bewegen.
- Als de speler tegen de linker- of rechterkant aankomt, dan stopt-ie wel met bewegen. Hij gaat niet door, en stuitert ook niet terug. Hij blijft dan stilstaan.
- De speler is niet geïnteresseerd in botsingen. Ufo's vliegen dwars door 'm heen.
👉 Maak deze klasse, en noem de klasse Player.
- Keyboard-interface maken we in de volgende stap. De klasse zelf luistert
niet naar keyboard-events. Het enige wat-ie moet doen is twee methodes
aanbieden:
moveLeft()zet de x-snelheid op -3. (y-snelheid blijft 0).moveRight()zet de x-snelheid op +3. That's it.
- Van welke klasse laat je Player erven?
Sprite?CollidingSprite? ofBouncingSprite? - Er is al een globale constante
rocketImageUrldie je kan gebruiken voor de afbeelding. - Twee regels die in
/* */-commentaar staan kunnen nu geactiveerd worden: de regel die een globaleplayervariabele declareert, en de regel die die variabele vult met een nieuwe instantie van dePlayerclass. Verwijder de commentaar-markers eromheen. - Zorg ervoor dat de klasse voldoet aan de eisen hierboven (behalve keyboardreactie).
In de code heb je al een event-handler gezien die naar het toetsenbord luistert. Nu bevat deze event-handler alleen het begin van een reactie op de spatiebalk. Gebruik dat als voorbeeld.
👉 Breid de event-handler voor het toetsenbord uit dat-ie ook kijkt
naar pijltje-naar-links (code: "ArrowLeft") en pijltje-naar-rechts (code:
"ArrowRight"). De event-handler hoeft (bijna) alleen maar de moveLeft() of
moveRight() methodes op de player aan te roepen.
👉 Test je code. Als het goed is moet je player nu reageren op de pijltjestoetsen, naar links of rechts schuiven, en stil blijven staan bij de rand.
We maken eerst de kogels, an pas later "koppelen" we die aan de player.
Een kogel is een soort Sprite die botsingen kan detecteren.
- Kogels gaan van beneden naar boven. 8 is een mooie y-speed.
- Kogels checken of ze botsen met Ufo's. Niet met de speler. Ufo's hoeven niet te checken of zij botsen met kogels.
- Als een kogel een botsing met een ufo detecteert, verwijdert hij zowel de ufo, als zichzelf uit het spel. Meer hoeft-ie niet te doen.
- Een kogel houdt ook in de gaten of-ie het scherm (aan de bovenkant) uitvliegt. Als dat gebeurt, verwijdert hij zichzelf uit het spel.
- Een kogel is nogal simpel in het bepalen van wanneer hij tegen een andere sprite botst: als z'n eigen x en y in de rechthoek van de andere sprite vallen, dan telt dat als botsing.
👉 Maak de klasse Bullit.
- Je kunt 'm testen door bij het starten van de game, gewoon meteen al een bullit aan te maken, en te kijken of die zich goed gedraagt bij botsingen of bij scherm uitvliegen.
- Kies een geschikte super-klasse.
- De constructor heeft alleen maar een lokatie nodig (x,y). Afbeelding en snelheid liggen al vast.
- Er is al een globale constante
bullitImageUrldie je voor de afbeelding kunt gebruiken. - Welke methode moet je overriden om code in te stoppen die checkt of je bullit een andere sprite raakt?
- Deze code kun je gebruiken voor die check:
return ( this.x >= otherSprite.x && this.x <= otherSprite.x + otherSprite.width && this.y >= otherSprite.y && this.y <= otherSprite.y + otherSprite.height ); - Welke methode moet je overriden om de code te bevatten die reageert op een
botsing? Gebruik de
remove()-methode (in de Sprite-klasse) om sprites uit het spel te halen. - De
update()methode kun je overriden om te checken of je bullit het scherm is uitgevlogen. Zorg er wel voor dat jesuper.update()aanroept.
Laten we eerst kogels vanaf een vaste positie afvuren.
👉 De event-handler voor het toetsenbord heeft bijnal alle bodige
code al aanboord. Je moet alleen de /* */-commentaar markers verwijderen, en
parameterwaarden kiezen.
👉 Test je programma. Je zou nu kogels moeten zien verschijnen als je op de spatie-balk drukt. Ondertussen moet je player-object natuurlijk wel nog steeds correct werken.
Net als de vorige stap, stelt deze weinig voor.
👉 Zorg ervoor dat de positie van nieuwe kogels zó gekozen wordt dat het lijkt als-of ze uit de punt van de player-raket komen.
Er is dus geen echte koppeling tussen de kogels en de player. Dat is niet nodig, en niet handig.
--DONE--
Gefeliciteerd met je browser-game!
👉 Commit je code voor alle opdrachten in dit document naar je persoonlijke DWA repo.
{{exCommit "Stuur je commit in" "Ufo-game-vraag-4"
exCommit}}