• Facile

Ce cours est visible gratuitement en ligne.

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

Mis à jour le 05/12/2013

Sprites enrichis

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Jusqu'à présent, nous avons considéré les sprites (petits objets animés) comme une simple image, ou un simple ensemble d'images. Cependant, rien n'interdit, en se faisant son propre éditeur de sprite, de pouvoir rajouter des informations directement dans les images pour aider au calcul de collision, ou même à l'affichage.

Ce sera donc le graphiste qui rajoutera des informations qui nous seront fort utiles.

Voyons ici quelques concepts d'informations qu'on pourrait rajouter aux images.

Point chaud et point d'action

Ici, nous allons parler du point chaud et du point d'action. Ce sont des concepts qui simplifient bien la vie dans certains cas.
Le vieux logiciel de création Klick & Play utilisait ces concepts.

Le point chaud

Le point chaud ne concerne pas directement les collisions, mais il peut être utile d'en parler.

Regardons ensemble l'image suivante :

Image utilisateur

Vous avez reconnu ce cher Dhalsim, fakir combattant assez élastique dirons nous. Quand il donne un coup, il a une très grande portée ! Nous voyons ici deux images, l'une où Dhalsim ne donne pas de coup, et une où il donne un coup de pied bien tendu.
En bleu, j'ai dessiné les boîtes englobantes, elles ne sont pas de la même largeur. Cela va poser problème.

Problème

Imaginons que vous vouliez faire une animation de Dhalsim qui donne un coup de pied. Vous avez ces deux images, ci-dessus, et vous voulez faire l'animation.

Vous blittez donc tour à tour chaque image, un blit colle l'image à la position x,y de telle sorte que le coin supérieur gauche de l'image blittée soit à la coordonnée (x,y).

Conséquence immédiate : vous aurez un Dhalsim qui va vivement partir à droite quand il donnera un coup de pied, parce que dans une image, sa tête est à coté du coin supérieur gauche, et dans l'autre, elle est loin. L'animation va être complètement ratée.

La seule solution est de blitter la première image à une position (x,y), et de blitter la seconde à une position (x2,y) avec x2 < x, et de bien calculer x2 de façon à ce que le corps de Dhalsim reste au même endroit.

C'est extrêmement contraignant, surtout s'il faut faire ça avec chaque image.
Et pourtant, si on veut une belle animation, il faut calculer un x2 correct.

Insertion du point chaud

Pour palier ce problème, nous allons dire au graphiste que nous souhaitons des informations supplémentaires, et qu'il nous les donnera graphiquement.
Regardez les points rouges que j'ai mis au pied de Dhalsim dans chaque cas. Imaginez maintenant qu'on ait une fonction de blit qui affiche le personnage non pas en considérant que l'ancrage est en haut à gauche, mais qu'il est au niveau de ce point rouge.
Autrement dit, le point rouge est à la coordonnée (x,y) du blit, et Dhalsim se dessine autour.

Le problème est donc résolu : l'animation sera convenable.

A vous de programmer un éditeur qui permet au graphiste de définir un point chaud pour chaque image à blitter.
Vous savez, il y a deux possibilités de gérer les sprites : soit un sprite par surface, soit une planche de sprite sur la même surface et un blit partiel.
Dans le premier cas, chaque surface devra avoir un point chaud. Dans le deuxième, il y aura autant de points chauds que d'images dans la planche.

Un point chaud, c'est juste une coordonnée (x,y) locale à l'image. Dans la première image, on aura par exemple le point chaud qui a comme coordonnée (45,100), et dans la deuxième, il a comme coordonnée (167,100).

Ces coordonnées ne seront pas entrées à la main par le graphiste, mais en un clic : le graphiste a son image sur l'écran, il clique sur l'option "mettre point chaud" puis il clique sur son image entre les pieds de Dhalsim, et l'éditeur stocke la coordonnée de souris relative à l'image, tout simplement. Cela reste donc visuel. C'est la machine qui fait les calculs.

Notez qu'un point chaud à la coordonnée (0,0) est un point chaud en haut à gauche, donc ça nous ramène au cas du blit normal !

Blit sur le point chaud

Les librairies graphiques ne gèrent pas les points chauds. Elles fournissent une fonction "Blit" (SDL_BlitSurface par exemple) qui va blitter de tel sorte que le point (x,y) passé soit le coin supérieur gauche de l'image.

Pour créer une fonction "BlitAuPointChaud", il suffit de faire deux soustractions.
Soit une fonction :

void Blit(Image Source,Image Destination,int x,int y);

La fonction BlitAuPointChaud s'implémente ainsi :

void BlitAuPointChaud(Image Source,Image Destination,int x,int y,int xpointchaud,ypointchaud)
{
   Blit(Source,Destination,x-xpointchaud,y-ypointchaud);
}

Pour les utilisateurs de SDL, nous aurons :

void BlitAuPointChaud(SDL_Surface* Source,SDL_Surface* Destination,int x,int y)
{
   SDL_Rect R;
   R.x = x - xpointchaud;
   R.y = y - ypointchaud;
   SDL_BlitSurface(source,NULL,destination,&R);
}

Le point d'action

Le point d'action est un autre point que le graphiste peut mettre pour nous aider. Regardons le dessin suivant :

Image utilisateur

On peut voir ici plusieurs images de Ken donnant un coup. Regardez, j'ai placé à chaque fois un point violet à l'endroit du potentiel point d'impact.

L'idée est simple : c'est encore le graphiste qui va définir le "point d'action" pour chaque image ou le personnage donne un coup.
Et en tant que programmeur, je vais dire "si le personnage donne un coup, alors je regarde si le point d'action touche l'adversaire. Si c'est le cas, il se prend le coup, et seulement dans ce cas là".

Vous voyez, si Ken donne un coup de poing, seul le poing est dangereux. Si l'adversaire est derrière contre sa jambe, il n'a pas à se prendre le coup.

L'idée du point d'action permettra de tester une collision avec un simple algorithme du "Point dans AABB", vu tout au début de ce tutoriel !
Le graphiste rajoute la une information extrêmement enrichissante et qui simplifie la vie au programmeur.

Le point d'action est également une coordonnée (x,y) relative à l'image.
Si on veut savoir où se trouve le point d'impact sur l'écran, il suffit de faire l'opération suivante :

$xpointimpact = (xpositionperso - xpointchaud) + xpointaction$$ypointimpact = (ypositionperso - ypointchaud) + ypointaction$

On testera ensuite le point (xpointimpact,ypointimpact) dans l'algorithme "point dans AABB".

La difficulté de cette collision ne vient donc pas des fonctions utilisées, qui sont simples, mais de la conception d'un éditeur permettant de définir un point chaud et un point d'action pour chaque image.

Évidemment, le point d'action n'a de sens que si un coup est porté, et pas si le personnage est en attente. Alors on peut mettre un point d'action bidon, ou pas de point d'action du tout pour les autres images, et le considérer uniquement si le personnage est dans un statut offensif. À vous de définir tout ça selon vos besoins.

Sous AABB

La notion de sous AABB (ou Sub AABB, qu'on notera SAABB) va permettre des collisions plus fines, et pas tellement plus calculatoires. Cependant, tout comme les points chauds et points d'action, les informations de SAABB devront être fournies avec les sprites au programmeur, grâce à un éditeur créé pour l'occasion.

Définition

Regardons ensemble l'image suivante :

Image utilisateur

Nous voyons Ken dans plusieurs positions. Cependant, vous pouvez constater que j'ai rajouté des AABB autour de lui, dans chaque image. Ce sont les SAABB. J'en ai rajouté seulement quelques unes, mais qui permettent d'approximer la forme correctement.

Collision

Nous avons vu qu'un algorithme de collision dans ce cas là peut être simplement un algorithme de "Point dans AABB". Si nous considérons la AABB globale de l'image cible, vous restez trop approximatif dans notre cas : vous pouvez frapper l'air au dessus de l'épaule de Ken...

Pour un algorithme plus fin, on appellera plusieurs fois l'algorithme "Point dans AABB" dans chacune des SAABB. Si le point testé touche une seule SAABB, alors il y a collision.

Première optimisation

Si on veut tester la collision d'un point dans le personnage, avant de tester chaque SAABB, on testera d'abord la AABB entière, celle de l'image.
Si on ne touche pas cette AABB, inutile d'aller plus loin : il n'y a pas collision.
Sinon, on teste chacune des SAABB.

Deuxième optimisation

Nous pouvons considérer les SAABB en hiérarchie. Par exemple, vous voyez la première image, il y a plusieurs SAABB bleues côte à côte. Soit on les teste une par une, soit on teste d'abord la AABB de l'ensemble des boîtes bleues. Si on ne touche pas cette dernière, inutile de tester chacune des SAABB internes...

Davantage de sémantique

Vous savez, dans Street Fighter 2 ou autres jeux de combat, un personnage souffrira différemment si il prend un coup dans la tête, dans le corps, ou dans les jambes.

Regardez le dessin ci-dessus : j'ai fait exprès de dessiner en bleu les boîtes correspondant aux jambes, en jaune celle de la tête, en vert celle du torse, en violet celle des bras.
Si le graphiste respecte bien un tel codage de SAABB, alors on pourra détecter, lors d'une collision, dans quelle couleur de SAABB tape le point d'action de l'autre joueur.

C'est ce qu'on appelle rajouter de la sémantique directement au niveau des sprites.

Au lieu d'avoir une suite d'image sans données, on aura une banque de sprite, qui contiendra des images, mais aussi plein d'informations pour chaque image, informations qui auront été rentrées graphiquement à la souris avec un éditeur, et qui faciliteront énormément le travail des programmeurs.

Cette partie nécessite donc un travail en amont au niveau de la création des sprites pour être utilisable.
N'oubliez pas que les boîtes de jeux se programment souvent leurs propres éditeurs, leurs propres outils, en fonction de leurs besoins.

L'idée est de donner graphiquement le maximum de sémantique au niveau des images elles mêmes, pour simplifier la tâche du programmeur par la suite.

Exemple de certificat de réussite
Exemple de certificat de réussite