Les 7

Games maken en ervaren
1 / 54
next
Slide 1: Slide
InformaticaMiddelbare schoolhavo, vwoLeerjaar 4

This lesson contains 54 slides, with interactive quizzes and text slides.

time-iconLesson duration is: 60 min

Items in this lesson

Games maken en ervaren

Slide 1 - Slide

Deze les
  • Objecten
  • Afbeeldingen
  • Arrays

Slide 2 - Slide

Deze stijl van notatie heet (lower) camel case (camelCase). Belangrijkste kenmerk is dat bij samengestelde woorden of zinnen (zoals noFill of aantalBomen) de afzonderlijke elementen beginnen met een hoofdletter, behalve de eerste. Deze manier van noteren ken je vast van de iPhone. Behalve lower bestaat er ook Upper CamelCase die je zonder dat je het wist al kent van PlayStation en SpongeBob.

De laatste twee voorbeelden met Vijand wijken af van de afspraak, (want het begint met een hoofdletter). Deze notatie gaan we gebruiken voor het maken van (een klasse van) objecten. In de komende lessen leer je wat objecten zijn. 

We beginnen met een paar bijzondere objecten: afbeeldingen en lijsten.

Slide 3 - Slide

Hiernaast zie je een beeld waarin twee afbeeldingen als sprites worden gebruikt: een rij bomen als achtergrond en een kever die door de lucht vliegt. Die plaatjes laden we vooraf met de functie preload:



De afbeeldingen staan in aparte bestanden in jouw werkomgeving in de map images. Tussen de "" geef je aan waar het bestand staat. Het bestand kever.png is bijzonder, omdat hij een transparante achtergrond heeft.
Hierdoor lijkt het alsof kever door de lucht vliegt. Net als een getal of een tekst, kun je een plaatje opslaan in een variabele (zoals hier bomen en kever). In het vervolg van je programma kun je verwijzen naar deze variabelen.

Slide 4 - Slide

Een afbeelding is een voorbeeld van een (bijzonder) object.
Kenmerkend voor een object is dat er eigenschappen aan gekoppeld zijn. Zo heeft een afbeelding een breedte en hoogte in pixels. Door eerst de naam van het object te noemen en met een punt aan de eigenschap te verbinden, kun je eigenschappen gebruiken of opvragen: kever.width en kever.height.


Slide 5 - Slide

overloper: intro
In de volgende slides gaan we in stappen een spel maken dat overloper heet. Bij elke stap vertellen we je meer over de inhoud en de regels van het spel. Kortgezegd moet de speler proberen vanaf de linkerkant van het scherm de overkant te bereiken. Hierbij moet hij obstakels ontwijken. Als game character gebruiken we Jos: onze Javascript Object Sprite die je nog kent uit de vorige lessen.

Slide 6 - Slide

Open H2O05.js
(denk aan je bekijkJS.html)
  • Het raster bestaat uit cellen (vierkantjes) met een lengte die hier celGrootte heet. 
  • De functie tekenRaster() tekent op dit moment maar één cel. Maak een dubbele herhaling met een for-loop om het volledige raster te tekenen. Volg de instructies in het bestand of kijk terug naar de opdracht waar je dit hebt geleerd.
  • In de preload is een afbeeldingsobject brug gemaakt. Voeg deze afbeelding in als achtergrond. Let op: zorg dat het raster over de foto heen wordt getekend.
  • Voeg de sprite spriteJos in zodat je het eindresultaat in figuur 2.7 krijgt. Gebruik de variabelen xJos en yJos om Jos op de juiste plek te krijgen.

Slide 7 - Slide

Wat is de afmeting van de cellen (in pixels)?

Slide 8 - Open question

overloper: interactie met een sprite
Open H2O06.js (denk aan je bekijkJS.html). 
Druk hierbij op de pijl naar rechts. 
  • Breid de besturing uit, zodat Jos ook naar links en naar boven en onder kan.
Als Jos aan de linker- of rechterkant van het canvas is, kan hij niet verder. Dit is gedaan met de regel: xJos = constrain(xJos,0,width - celGrootte);
  • Zorg dat Jos ook boven en onder op het speelveld blijft.
  • Kopieer de code van hiernaast naar het eind van de draw.
  • Probeer nu ook eens: spriteJos.filter(ERODE); .

Slide 9 - Slide

Leg uit waarom de functie constrain gebruik maakt van het attribuut width - celGrootte.

Slide 10 - Open question

lijsten: arrays
Tot nu toe hebben we leren werken met afbeeldingen. 
Een afbeelding is een bijzonder voorbeeld van een object. 

Kenmerkend voor objecten is dat ze eigenschappen hebben zoals een breedte (foto.width) en dat je ze kunt vragen om iets te doen, zoals van grootte veranderen (foto.resize(50,50);).

Slide 11 - Slide

 aan)
Ook een lijst of array is een object. Het biedt de mogelijkheid om een reeks van gegevens die bij elkaar horen op te slaan onder één naam.
Dat zoiets handig kan zijn, laat de code hiernaast zien. Als je alle namen van je klasgenoten (of spelers van je game!) wilt opslaan, wordt het wel erg onhandig, als je die namen één voor één in aparte variabelen moet opslaan. De variabele klas is hier een array: een lijst met alle namen op onder één noemer.

Slide 12 - Slide

Een array is een reeds bestaande soort object (of klasse). Een nieuwe lijst maak je met new Array. Alle elementen van de lijst krijgen een volgnummer. We beginnen weer te tellen bij 0, dus let goed op: het tweede element ("Alice") heeft volgnummer 1, want bij "Bob" hoort volgnummer 0.


Slide 13 - Slide

Omdat een array een object is, heeft het net als een afbeelding eigenschappen en kun je het object vragen om iets te doen. Omdat een array een object is, heeft het net als een afbeelding eigenschappen en kun je het object vragen om iets te doen.

Om de inhoud van het derde element (met volgnummer 2) op te vragen uit de array klas gebruik je klas[2]; en met klas.length krijg je het aantal elementen in de lijst terug.

Slide 14 - Slide

Omdat een array een object is, heeft het net als een afbeelding eigenschappen en kun je het object vragen om iets te doen. Omdat een array een object is, heeft het net als een afbeelding eigenschappen en kun je het object vragen om iets te doen.
Om de inhoud van het derde element (met volgnummer 2) op te vragen uit de array klas gebruik je klas[2]; en met klas.length krijg je het aantal elementen in de lijst terug.
Er zijn heel veel voorgeprogrammeerde handelingen die je aan een array kunt vragen. De belangrijkste voor ons zijn:

Slide 15 - Slide

Omdat de elementen in een array een volgnummer meekrijgen, kun je ze met een for-loop (zie § 1.7) één voor één uitlezen en verwerken. Door klas.length te gebruiken, bepaalt de computer zelf hoe vaak de loop moet worden herhaald:



Bovenstaande code levert het resultaat van hiernaast. De teller n krijgt achtereenvolgens de waarde 0 t/m 3 (dus tot 4), want er wordt geteld tot (en dus niet tot en met) klas.length = 4. De namen staan 65 pixels uit de kantlijn. In dit geval komen de namen onder elkaar, omdat voor de verticale positie opnieuw de teller n is gebruikt. Omdat n steeds groter wordt, komen de namen steeds verder naar beneden.

Slide 16 - Slide

Open H2O07.js
(denk aan je bekijkJS.html)
De array vierkanten bevat de lengte van een zijde van drie vierkanten.
  • Gebruik de functie push() om in regel 12 jouw eigen naam aan de array namen toe te voegen.
  • Voeg in regel 13 een coderegel toe, zodat de array namen alfabetisch wordt gesorteerd. 
  • Met regel 21 wordt de omtrek van de vierkanten berekend en getoond. Regel 22 is voor de oppervlakte. Deze regel is nog niet af. Vul de regel aan, zodat de waarden overeenkomen met hiernaast.
  • Voeg in regel 14 een coderegel toe om het eerste element uit de array vierkanten te verwijderen.

Slide 17 - Slide

Open H2O08.js
(denk aan je bekijkJS.html)
Het is de bedoeling dat we het onderste beeld van hiernaast gaan programmeren. We zien zes huizen. Alle huizen hebben een nummer en een eigenaar. De bijbehorende gegevens staan in de twee arrays huisNummers en huisEigenaren (zie bovenaan in de code).
  • Maak een for-loop die de huidige regels 18 en 19 herhaalt. Gebruik de lengte van de array huisNummers om het juiste aantal herhalingen te krijgen.
  • Alle huizen hebben nummer 13, door het tweede argument van tekenHuis(kleur,13);Vervang het argument 13 door een stukje code, zodanig dat alle huizen een huisnummer uit de array huisNummers krijgen.

Slide 18 - Slide

Voer de volgende stappen uit om de namen van de huiseigenaren op de huizen te krijgen:
  • Voeg een extra parameter naam toe aan de functie tekenHuis.
  • Pas de regel text("naam",20,165); aan, zodat deze gebruik maakt van deze parameter
  • Pas de for-loop aan, zodat er bij het aanroepen van de functie tekenHuis gebruik gemaakt wordt van de array huisEigenaren.
De huizen hebben afwisselend de kleur lightgray en darkgrey. Dat is geprogrammeerd door in de for-loop, na het tekenen van een huis, toe te voegen: Als de waarde van de variabele kleur gelijk is aan “lightgray”, maak hem dan “darkgrey” en andersom.
  • Gebruik een if-else om de grijstint van de huizen te laten afwisselen.

Slide 19 - Slide

animatie: een array van plaatjes
Een sprite kan één plaatje zijn, maar de term sprite wordt ook vaak gebruikt voor een bewegende plaatje of animatie. De beweging of animatie ontstaat door verschillende beeldjes of frames achter elkaar te tonen. Vroeger werden voor het maken van tekenfilms 24 frames getekend voor maar één seconde film. Als je de frames goed op elkaar laat aansluiten, creëer je daarmee de illusie van een vloeiende beweging.

Hiernaast zie je zes beeldjes van Jos, die we nummeren van 0 t/m 5. In de volgende opdracht zijn ze gebruikt om een array van plaatjes te maken.

Slide 20 - Slide

uitleg code
  • var animatie = []; Met [] maak je een nieuwe, lege array.
  • loadImage("Jos-" + b + ".png"); In de for-loop wordt steeds een ander beeldje geladen, want de variabele b loopt van 0 t/m 5. We laden daarom achtereenvolgens de bestanden Jos-0.png t/m Jos-5.png.
  • animatie.push(nieuw_beeldje); De functie push voegt steeds een nieuw element toe aan de array animatie. Na het uitvoeren van de for-loop hebben we dus een lijst met beeldjes: de array animatie is gevuld.

Slide 21 - Slide

De volgende stap is om die beeldjes of frames achter elkaar te tonen. Hiervoor hebben we kennis gemaakt met de loopfunctie draw die steeds opnieuw wordt uitgevoerd. 
Met frameRate stel je in hoeveel loops er per seconde zijn. Voorbeeld: frameRate(2) zorgt voor 2 frames per seconde; elke frame of loop duurt dus 1 / 2 = 0,5 seconde. 

P5 kent een standaardvariabele frameCount die bijhoudt hoe vaak de loopfunctie draw is uitgevoerd vanaf het moment dat het programma geladen is.
Hiernaast zie je hoe je dit in de draw kunt gebruiken om elke loop (frame) een ander beeldje kunt laden.

Slide 22 - Slide

Open H2O11.js en bestudeer de code
Leg uit wat de betekenis is van de regel: breedte = animatie[0].width;

Slide 23 - Open question

De gebruikte plaatjes zijn maar klein. Ze worden groter op het canvas getoond dan ze werkelijk zijn. Hoeveel keer groter?

Slide 24 - Open question

Modulus
In de theorie maken we gebruik van een variabele nummer om het juiste beeldje uit de array te halen. Met een nieuwe operator kunnen we ook gebruik maken van frameCount. Deze wiskundige truc heet modulus.

De modulus is een bovengrens. In ons geval 6 (aantalBeeldjes = 6). Met modulo rekenen (hiervoor wordt het procentteken gebruikt) kunnen we nu de restwaarde van een deling bepalen. Dat klinkt ingewikkeld maar is met een paar voorbeelden is het te begrijpen:


Slide 25 - Slide

Als je afbeeldingen in je programma laadt, moet je goed letten op de bestandslocatie (de map of in het Engels: directory) en de precieze bestandsnaam. Als de computer de afbeelding niet kan vinden omdat je een klein foutje hebt gemaakt, laat hij Loading… zien. Onthoud dit: het zal je vast eens gebeuren!
In jouw werkomgeving staat in de map wizard in de submap opdracht_11B. Deze bevat een andere serie sprites met andere bestandsnamen en een ander aantal.

Slide 26 - Slide

De frameCount bevat het aantal keren dat de loopfunctie draw is uitgevoerd en wordt dus steeds met 1 verhoogd. Als we als volgnummer voor de array met beeldjes frameCount % aantalBeeldjes invullen, dan is de uitkomst achtereenvolgens 0, 1, 2, 3, 4, 5 en dan opnieuw 0, 1, 2, 3, 4, 5, etc.

Slide 27 - Slide

Je hebt nu kennis gemaakt met de bijzondere objecten afbeelding en lijst (array). Ze zijn bijzonder, omdat hun werking afwijkt van andere objecten, maar belangrijk voor nu is dat we hebben gezien dat ze eigenschappen hebben en dat je ze kunt vragen om een handeling uit te voeren.


Slide 28 - Slide

Het maken van programma’s met objecten wordt object-georiënteerd programmeren genoemd. Het is een bepaalde tactiek van programmeren, ook wel programmeer-paradigma genoemd, waarbij je eigenschappen en handelingen koppelt onder één noemer: het object.

Slide 29 - Slide

Stel we laten  een kever over het canvas bewegen. Er is een variabele kever voor de bijbehorende sprite en er zijn variabelen keverX en keverY om zijn positie mee te bepalen. Daarnaast is er code om de kever te laten bewegen.
Eigenlijk is dit onhandig, want dit zijn allemaal losse stukjes code en gegevens, terwijl ze eigenlijk bij elkaar horen. Net zoals bij de afbeeldingen en lijsten, willen we de kever vragen om informatie over zichzelf te geven of om iets voor ons te doen. We willen van de kever een object maken.

Je ziet hiernaast de declaratie van het object kever.

Slide 30 - Slide

Een eigenschap van een object heet een attribuut. In dit voorbeeld zijn er drie attributen: x, y en sprite. De eerste twee hebben we meteen een waarde gegeven, maar sprite blijft nog even leeg (omdat we daar straks in de preload een afbeelding inladen). Als je een attribuut nog niet meteen een waarde meegeeft, kun je dat aangeven met null. Let goed op het gebruik van { }, : en , bij het maken van een object. Dat luistert heel precies!

Slide 31 - Slide

Een handeling van een object heet een methode. Als we de kever vragen om te bewegen via de methode beweeg(), dan worden drie regels uitgevoerd. Deze regels gebruiken de attributen x, y en sprite, maar wel steeds voorafgegaan door this.

Slide 32 - Slide

Het gebruik van this is even wennen. Het is een verwijzing naar een attribuut of methode van het object zelf. In ons voorbeeld is dat (de) kever. Je schrijft dan this.x (en niet kever.x) omdat het gaat om eigenschappen en handelingen van dit object. Dat gebruiken van this doe je alleen bij het maken van een object. In het hoofdprogramma gebruik je de naam die je aan het object hebt gegeven; 
voor een attribuut:


Slide 33 - Slide

Open H2O18.js
(denk aan je bekijkJS.html)
Eerst werd Jos getekend met een zelfgemaakte functie. De coderegels staan nu als methode teken binnen het object jos.

Slide 34 - Slide

Hoeveel attributen heeft het object jos?

Slide 35 - Open question

Wat is op dit moment de waarde van het attribuut jos.x?

Slide 36 - Open question

Open H2O18.js
(denk aan je bekijkJS.html)
  • De methode teken heeft nu als parameter muispositieX. De bedoeling is dat Jos ook echt gaat meebewegen met de muis. Pas de regel jos.teken(500); aan, zodat Jos reageert op de x-positie van de muis.
We willen dat Jos groter wordt als hij naar rechts beweegt en kleiner als hij naar links beweegt.
  • Voeg de volgende regel toe aan teken in regel 9: this.schaal = this.x / (0.25*width);
  • Zorg dat in de tekst bovenaan behalve de x-positie ook de schaal van Jos wordt getoond.

Slide 37 - Slide

Pas de code aan, zodat Jos ook reageert op de y-positie van de muis.
  • Zorg dat de methode teken een extra parameter muispositieY krijgt.
  • Gebruik de functie constrain om te zorgen dat y (van Jos) tussen de 100 en 150 blijft.
  • Zorg dat bij het aanroepen van de methode teken de y-positie van de muis als parameter wordt meegegeven.

Slide 38 - Slide

Open H2O22.js
(denk aan je bekijkJS.html)
Hier zie je een bal die tegen de wanden van het canvas terugkaatst. De bal is hier een object. De beweging van de bal lijkt misschien wel op een beweging die je vaker in spellen ziet, maar het lijkt niet erg op de beweging van een echte bal.
In deze opdracht gaan we de bal natuurlijker laten vallen en stuiteren.

Slide 39 - Slide

Hoeveel attributen heeft object bal? En welke methodes heeft bal?

Slide 40 - Open question

Wat is de waarde van bal.y na het uitvoeren van de setup?

Slide 41 - Open question

Als een bal ergens tegenaan botst, verliest het doorgaans een deel van zijn snelheid. In dit geval verliest hij nog geen snelheid, omdat this.demping de waarde 1.0 heeft. Als dit wordt veranderd naar 0.95 verliest de bal 5% van zijn snelheid, want de nieuwe waarde is nog 95% (0.95) van de vorige waarde. Merk op: door canvas.width te gebruiken, maken we hier gebruik van het feit dat canvas zelf ook een object is!

Slide 42 - Slide

Voor welke (getals-) waarden van this.x weerkaatst de bal hier?

Slide 43 - Open question

  • Stel this.demping in op 0.95 en bekijk het resultaat.

Als je voldoende geduld hebt bij de laatste opdracht, dan heb je misschien gezien dat de bal op een gegeven moment tegen de rand van het canvas blijft plakken. Dat probleem lossen we straks in deze opdracht op. Eerst gaan we de beweging van de bal natuurlijker maken.
De bal beweegt op dit moment in een rechte lijn. In het echt valt een bal naar beneden, omdat de aarde eraan trekt. Tijdens het vallen gaat de bal steeds sneller: er is een versnelling. Als de bal weer omhoog beweegt, remt hij juist af, tot het hoogste punt waar de snelheid 0 is.

Slide 44 - Slide

  • Geef het attribuut snelheidY de beginwaarde 0 en demping de waarde 0.9.
  • Voeg een nieuw attribuut versnelling toe met beginwaarde 0.2.
  • Voeg als eerste regel van de methode beweeg de volgende coderegel toe: this.snelheidY += this.versnelling Bij elke stap in de beweging wordt nu 0.2 opgeteld bij de snelheid van dat moment.

Slide 45 - Slide

Bekijk het resultaat. Hoe zorgt deze regel ervoor dat de bal afremt als hij naar boven gaat?

Slide 46 - Open question

We zien opnieuw dat de bal op een zeker moment aan de rand van het canvas blijft plakken. Hoe kan dat? De tekening in figuur 2.35 toont schematisch wat er gebeurt. De hoogte van de bal wordt na elke loop van draw opnieuw berekend. De bal verplaatst zich hierdoor in stapjes. Op een bepaald moment komt de bal onder de rand van het canvas (groen gekleurd). De verticale snelheid moet dan omkeren, want de bal moet weer omhoog:this.snelheidY*=-0.95;

Slide 47 - Slide

Nu kan het gebeuren (het hoeft niet!), dat het middelpunt van de bal bij de eerstvolgende stap nog steeds onder de rand van het canvas zit (rood gekleurd). Het programma zal hierop reageren door opnieuw de snelheid om te keren, waardoor de bal weer naar beneden gaat. Dat was niet de bedoeling! Een manier om dit op te lossen is om de bal precies aan de onderkant van het canvas te plaatsen, op het moment dat deze op de groen gemarkeerde plek belandt: this.y = canvas.height - this.straal;

Slide 48 - Slide

Leg uit waarom this.straal hier nog van de hoogte van het canvas wordt afgetrokken.

Slide 49 - Open question

  • Pas de 2e if-structuur aan zodat er komt te staan: if (this.y>=canvas.height-this.straal) { zodat deze alleen nog reageert als de bal onderaan het canvas is.
  • Voeg daarna aan de regel this.y = canvas.height - this.straal; toe aan deze if-structuur.
  • Ziet het resultaat er echt uit? Pas desnoods de demping aan totdat je tevreden bent.

Slide 50 - Slide

Volgende les:
  • Dobbelstenen
  • Een object dat ja of nee antwoordt
  • Jager en prooi
  • Heet
  • Stoplicht
  • Een klasse van objecten
  • Een array van objecten

Slide 51 - Slide


Na deze les, 
wil ik...
de uitleg nog 1 keer horen
meer voorbeelden krijgen
meer oefeningen maken
de leerstof thuis nog even bekijken
overgaan naar nieuwe leerstof
nog meer te weten komen over de leerstof
niet meer te weten komen over de leerstof

Slide 52 - Poll


Hoe vond je 
deze les?
😒🙁😐🙂😃

Slide 53 - Poll

Volgende les
  • obfuscator
  • Zelf functies maken
  • Vallende ster
  • Jos

Slide 54 - Slide