Revenir au sommaire Tutoriaux

Comment détecter la collision de 2 images qui ont des contours irréguliers
L.ROUVAREL & J.Y. QUEINEC
Dans tous les jeux "Professionnels" qui utilisent des Sprites il existe un moteur (programme spécialement conçu pour réaliser des déplacements d'images en tenant compte de l'image de fond, de la vitesse de déplacement , des collisions, des animations... et de bien d'autres effets). Nous n'allons pas prendre en compte tous ses paramètres et nous concentrer sur les Collisions. (pour le Déplacement voir le tutoriel32... )
.

Essai 1: Détection de collisions entre 2 images (l'image1 rentre en collision avec l'image2)

.Le cas le plus simple consiste à détecter une collision entre 2 images. Il suffit de verifier à partir des 4 points qui sont aux 4 coins de l'image:
if (image2.left<= image1.left<=image2.left+image2.width)
or (image2.right<= image1.right<=image2.right+image2.width) then
if (mage2.top<= image1.top<=image2.top+image2.height)
(or image2.bottom<= image1.bottom<=image2.bottom+image2.height) then collision
.

Essai 2: Détection de 2 images aux contours irréguliers.

.Il est rare que l'image qui bouge ressemble à un carré...l'image est certe mémorisée dans un Tbitmap ou Tpicture carré, mais le motif qui est à l'interieur est souvant loin d'avoir la même forme !!!
La première méthode n'est donc pas appropriée car si elle détecte bien le chevauchement des 2 images cela ne veux pas dire que les motifs qui sont dessus se sont touchés...c'est le cas dans certains jeux, rappelez vous combien vous avez ralé de perdre alors que vous n'avez pas été touché...
La premiére idée qui vient à l'esprit est de gérer une image comme un négatif de photo...enfin moi c'est la première que j'ai eu... pas vous ?? en d'autre terme avoir une couleur de fond facilement repérable. Prendre une couleur peu utilisé (éviter le noir qui sert souvant à entourer les sprites pour les faire ressortir) et dessiner tous ses dessins sur un fond, par exemple rouge (attention si votre dessin utilise le même rouge que celui du fond ces parties seront considérer comme le fond et n'entrainerons pas de collision !). Cela ne veux pas dire qu'on ne peut plus utiliser le rouge pour dessiner, le rouge pur =rgb(255,0,0), il est possible d'utiliser toutes les autres nuances rgb(254,0,0),rgb(253,0,0) etc...
Il faut maintenant determiner le morceau d'image qui contient l'image1 et l'image2, inutile de verifier tout l'écran. En limitant la zone du test de collision on accélère la vitesse de traitement.... Grâce aux coordonnées de nos 2 images (right,left,top,bottom) cela reste facile à réaliser, même si il faut y laisser quelques neurones pour y arriver .... On détermine alors une zone mémoire de la taille du rectangle englobant nos 2 images. Reste maintenant à verifier le chevauchement des dessins sur les 2 images.
- copier l'image 1 sur la zone mémoire
- copier point par point l'image 2 sur la zone mémoire, si (image2.canvas.pixel[x,y]<>rouge) and (zone_memoire.canvas.pixel[x,y]<>rouge) alors il y a collision
Ca commence à être bien...mais il y a mieux !!!
.

Essai 3 : Enfin nous y voilà... le InterSectRect

.En un mot la commande :InterSectRect va nous simplifier grandement la tache. Cette commande va nous retourner UNIQUEMENT le rectangle correspondant à l'intersection des 2 images. Super Cool ça... non :))
Il faudra ensuite tester dans ce rectangle si les morceaux de l'image1 et de l'image2 se chevauchent sur une partie dessinée... bref, un exemple et souvant plus clair !
var ax, ay : integer; 
OK : boolean;
collisionR : Trect; 
c1, c2 : tcolor; 

begin 
  ok := true 
  If not intersectrect(Collisionr, bounds(x1,y1,bitmap1.width,bitmap1.height),
                                   bounds(x2,y2, bitmap2.width, bitmap2.height))then
// maintenant que tu as le rectangle intersection il faut affiner pour savoir si les 
// lignes ou courbes non rouges se touchent. 
// On est donc obligé de tester les pixels individuellement dans chaque zone des
// bitmaps correspondant au rectangle collision 
// si les 2 pixels ne sont pas à rouge, il y a collision et on arrête
  begin
      for ay  := collisionR.top to collisionR.bottom do
      for ax :=  collisionR.left to collisionR.right do
     begin
        c1 := bitmap1.canvas.pixels[ax - x1, ay - y1];
        c2 := bitmap2.canvas.pixels[ax - x2, ay - y2];
        if (c1 <> clred) and (c2 <> clred) then
        begin
            ok := false;
            break;
       end;
    end;
end;
 
.

Améliorations possibles :

Ecrire cette procédure en assembleur ... si tu l'as fait, envoie la moi...ici

Revenir au sommaire Tutoriaux

Hit-Parade