Les 6 - Botsingen detecteren

In een spel wil je ook kunnen detecteren wanneer twee objecten elkaar raken. Dit kan bijvoorbeeld een vijand en jouw karakter zijn. Een botsing detecteren heet ook wel 'collision detection'. In deze lesbrief ga je leren hoe je botsingen kunt detecteren in je programma.

Twee cirkels

Voor het botsen van twee cirkels wil je eigenlijk weten of de randen van de cirkels elkaar raken (of overlappen). We willen er dus achter komen of de situatie zoals in het plaatje zich voordoet:

alt text

In een plaatje ziet dat er leuk uit, maar hoe kom je hier nou achter? We hebben een botsing als het volgende waar is:

afstand tussen middelpunten <= straal1 + straal2

De straal kunnen we vinden in het Bal-object. En de afstand kunnen we bereken met behulp van de middelpunten. Hiervoor gebruik je de stelling van Pythagoras.

$$ \sqrt((x_2-x_1)^2+(y_2-y_1)^2) $$ Dus je neemt het verschil van x-coördinaten van je middelpunten. Dan het verschil van de y-coördinaten. Dan kwadrateer je beiden en tel je ze op. De laatste stap is de wortel te nemen en je hebt de afstand! P5 heeft veel van de wiskundefuncties van javascript ingebouwd. Zo ook sqrt(). Je hoeft dus niet Math.sqrt() te doen maar kunt direct sqrt() gebruiken. Handig toch? In code ziet dat er ongeveer zo uit:

let dx = xpos2 - xpos1;
let dy = ypos2 - ypos1;
if (sqrt(dx*dx + dy*dy) <= radius1 + radius2){
  // Botsing!
}

Object voor je speler

Voordat we echt het botsen gaan maken is het handig om voor de speler ook een object te maken. Maak er voor nu maar een cirkel van. Als je dit object hebt kun je verder met het maken van een functie om botsingen te controleren.

Botsingen controleren met twee balletjes

We gaan nu een functie maken om te checken of er een botsing is.

class Ball{
  constructor(xpos, ypos, radius, xspeed, yspeed, kleur) {
    this.xpos = xpos;
    this.ypos = ypos;
    ...
  }

  botsCheck(speler){
    // this.xpos geeft de xpos van het huidige balletje
    // bal.xpos geeft de xpos van het balletje dat je meegeeft als argument
    ...
  }
}

En net als het bewegen van balletjes ga je ook het controleren op een botsing iedere keer dat je de draw-loop doorloopt uitvoeren. Je draw loop krijgt dus een extra regel:

function draw(){
  for (...){
    ...
    bal.botsCheck(speler);
    ...
  }
}

Opdracht

Maak een spelerobject dat in het midden van het canvas begint. Maak de botsdetectie in je Bal-object en laat je spel stoppen als er een balletje tegen je speler botst.

Extra stof: Botsingen met rechthoeken

Je kunt ook twee rechthoeken met elkaar laten botsen. Dit is echter wel iets ingewikkelder. Je kunt het natuurlijk op dezelfde manier als met cirkels doen maar het ziet er dan niet zo netjes uit. De hoekjes zullen elkaar al overlappen voordat er een botsing is. Het werkt wel!

We bekijken alleen de situatie dat de rechthoeken 'recht' staan. Dus de zijden zijn evenwijdig met de horizontale en verticale as.

Als twee rechthoeken botsen heb je de volgende situatie: alt text

Dus je moet overlap hebben in de x-richting en de y-richting. Merk op dat de linkerbovenhoek de positie van je rechthoek is. Dus als ik rect(x, y, lengte, breedte) gebruik dan gelden de volgende coördinaten.

  • Linksboven: (x, y)
  • Linksonder: (x, y + breedte)
  • Rechtsboven: (x + lengte, y)
  • Rechtsonder: (x + lengte, y + breedte)

Stel nu dat ik twee rechthoeken heb, (x1, y1) met lengte1 en breedte1 en (x2, y2) met lengte2 en breedte2.

Om snel te controleren of er een botsing is gebruiken we een stukje logica. We gaan namelijke controleren of er NIET GEEN botsing is. Dus we kijken wat voorwaarden zijn om GEEN botsing te hebben en zetten er dan NIET omheen.

Wanneer is er geen botsing? Als:

  • x2 > x1 + lengte (rechthoek 2 ligt helemaal rechts van rechthoek 1) of
  • x1 > x2 + lengte (rechthoek 1 ligt helemaal rechts van rechthoek 2) of
  • y2 > y1 + breedte (rechthoek 2 ligt helemaal onder rechthoek 1) of
  • y1 > y2 + breedte (rechthoek 1 ligt helemaal onder rechthoek 2)

Dus we hebben een botsing als aan een van deze voorwaarden NIET is voldaan. In Javascript schrijf je OR met || en NOT met !. En het stukje code ziet er in ons geval als volgt uit:

if (!(x2 > x1 + lengte || x1 > x2 + lengte || y2 > y1 + breedte || y1 > y2 + breedte)){
  //Botsing!
}

Extra opdracht

Maak een canvas met twee bewegende rechthoeken en schrijf deze botsdetectie. Maak hiervoor eerst een stuk pseudocode voor jezelf.

results matching ""

    No results matching ""