Collisions AABB

author
Vince Désirée

Revenons un peu sur le concept de collision AABB.
AABB est le sigle de axis-aligned bounding box, soit en français: boite englobante alignée sur les axes. Ce terme désigne tout simplement la figure géométrique que forme un ensemble de points dans un repère cartésien, lorsque les côtés de cette forme géométrique sont alignés sur les axes du repère cartésien.
En 2D par exemple, le plan que représente l'écran de jeu est comme un repère cartésien avec les coordonnées cartésiennes: x pour l'horizontale, et y pour la verticale.

Pourquoi une "boite" ?

Généralement, dans un jeu, les éléments visuels doivent avoir une certaine surface pour qu'on puisse les voir. De ce fait, on ne peut pas se contenter de prendre en compte les coordonnées (x,y) d'un seul point, il faut une forme géométrique définie par plusieurs points.
Et on parle de boite, car, que ce soit en 2D ou 3D, les objets sont généralement pleins. C'est-à-dire qu'on n'est pas censé pouvoir passer à travers. Ça peut être, des personnages, des projectiles, des obstacles, etc.
Et d'ailleurs, même pour certains objets "vides" comme par exemple une porte, ou un sas, on aura généralement besoin de savoir si un personnage est ou non en contact avec pour déclencher une action. d'une certaine manière savoir si il y a quelque chose dans la boite.

Qu'est-ce qu'une collision ?

Du coup, maintenant que nos objets ont une certaine surface (en 2D) ou un certain volume (en 3D), nous voulons savoir quand ils entrent en contact avec d'autres objets.
Et pour faire ça, c'est-à-dire pour détecter une collision, il nous suffit simplement d'utiliser les coordonnées cartésiennes des points qui délimitent nos objets.
C'est grâce aux coordonnées que nous pourrons savoir si la surface (ou le volume en 3D) d'un objet A chevauche la surface (ou le volume) d'un objet B.
Par exemple avec un rectangle (ou un carré), les points vont par paire et forment des segments:
AB BC CD AD Et si le rectangle est aligné sur les axes (le fameux AA de AABB), on peut remarquer qu'à chaque fois les paires de points partagent une coordonnée:
A et B ont la même coordonnée y, du coup cette coordonnée délimitera le sommet de notre boite via le segment AB avec une coordonnée y_min. CD délimitera la coordonnée y_max du bas de la boite.
Même principe sur les coordonnées x_min et x_max avec les segments AD et BC.

[AABB-Limites-box.png]

Maintenant que nous avons 4 valeurs limites pour délimiter notre objet, nous allons pouvoir détecter les collisions.

Comment détecter les collisions ?

La méthode pour détecter les collisions AABB est simple et assez élégante, mais pas forcément très intuitive. Elle s'appuie sur un jeu 4 conditions qui ne seront toute true que si une collision se produit. S'il n'y a pas de collision, il y aura toujours 2 ou 3 conditions vrais, mais pas 4:

// nous avons 2 objets A et B et par soucis de simplicité nous allons considérer
// que les coordonnées de bordure son calculées et mises à disposition dans des propriétés
// sinon il suffit de calculer à partir du point d'origine et des dimensions
let A = {
  x_min = 5,
  x_max = 15,
  y_min = 5,
  y_max = 15
}
let B = {
  x_min = 20,
  x_max = 30,
  y_min = 20,
  y_max = 30
}
// la variable collision sera un booléen qui ne sera 'true' que si A et B entre en collision
// Pour être 'true', TOUTES les conditions doivent 'true'.
let collision = (
  A.x_min <= B.x_max // Le côté gauche de A est à gauche du côté droit de B
  &&
  B.x_min <= A.x_max // Le côté gauche de B est à gauche du côté droit de A
  &&
  A.y_min <= B.y_max // Le côté haut de A est au-dessus du côté bas de B
  &&
  B.y_min <= A.y_max // Le côté haut de B est au-dessus du côté bas de A
)

Dans le code ci-dessus, on peut constater qu'il n'y a que 2 conditions qui sont true, et donc le booléen est false, pas de collision.
Si on déplace A sur la droite jusqu'à ce que A.x_max = 25 on a 3 conditions true, mais toujours pas de collision, car A est au-dessus de B.
Pour qu'il y ait collision, on doit maintenant faire descendre A: A.y_max = 25.
Et là, les 4 conditions sont true donc collision == true, nous avons une collision !

On peut aussi détecter l'absence de collision

Selon les préférences de chacun, ou pour des raisons pratiques selon ce que vous essayez d'accomplir avec votre code, vous pouvez aussi opter pour l'option inverse, avec un booléen de non-collision qui reprend un peu le même principe que pour celui de collision.
Cette fois-ci, le booléen est à true lorsque A n'est pas en contact avec B:

// Même principe que tout à l'heure avec les bordure de A et B
let A = {
  x_min = 5,
  x_max = 15,
  y_min = 5,
  y_max = 15
}
let B = {
  x_min = 20,
  x_max = 30,
  y_min = 20,
  y_max = 30
}
// Cette fois on veut 'true' lorsqu'il n'y a pas de contact entre A et B
// Il suffit qu'UNE SEULE condition soit 'true' pour que le booléen soit 'true'
let noCollision = (
  A.x_max < B.x_min // Le côté droit de A est à gauche du côté gauche de B
  ||
  B.x_max < A.x_min // Le côté droit de B est à gauche du côté gauche de A
  ||
  A.y_max < B.y_min // Le côté bas de A est au-dessus du côté haut de B
  ||
  B.y_max < A.y_min // Le côté bas de B est au-dessus du côté haut de A
)

Dans le code ci-dessus, on peut constater qu'il y a 2 conditions à true, et donc le booléen est true, pas de collision.
Si on déplace A sur la droite jusqu'à ce que A.x_max = 25 nous n'avons plus qu'une seule des 4 conditions à true car la condition A.x_max < B.x_min passe de true à false. Mais A est encore au dessus de B, donc pas de collision.
Pour qu'il y ait collision, on doit maintenant faire descendre A: A.y_max = 25.
À partir de là, la dernière condition true passe à false et donc noCollision == false.

Pour mieux comprendre le concept, voici une démo "jouable" qui expose les conditions de collision AABB:

Nous utilisons les cookies pour personnaliser le contenu et analyser notre trafic. Veuillez décider quel type de cookies vous êtes prêt à accepter.