Collisions par Masque

On entend beaucoup parler de problèmes de ralentissements pour des jeux utilisant beaucoup les collisions, devant effectuer beaucoup de calculs ce qui fait ramer le jeu.
Après quelques test que j’ai fait, j’ai remarqué, ou plutôt vérifié (j’avais déjà remarqué ce phénomène auparavant mais à échelle réduite ce qui fait que je n’avais pas la certitude de son existence), que les collisions sont vérifiées avec la méthode du Pixel Perfect, qui consiste à comparer la position X;Y de tous les pixels de deux Sprites et annoncer une collision lorsque deux positions dans chacun des deux Sprites coïncident.

Il existe aussi une autre technique de vérification de collision, la méthode par Masque qui nécessite dans la plupart des cas beaucoup moins de calculs.
Elle consiste à appliquer un masque de collision, un rectangle de position X;Y donnée, à chaque sprite sur lesquels seront effectués les tests.
Ce rectangle n’est pas obligé de couvrir l’intégralité du sprite, par exemple dans les maniac-shooters la hitbox est très réduite par rapport au sprite du joueur.

J’ai essayé de recenser toutes les collisions possibles entre deux masques :


J’en ai trouvé 14.
Les calculs, au lieu de vérifier la position de tous les pixels, ce qui reviendrait pour deux Rectangles rouges de taille 64x96 à effectuer jusqu’à (64x96)(64x96)=37 748 736 comparaisons, évidemment on va pas immédiatement comparer tous les pixels autrement le lag serait énorme pour une seule collision, on ferait des tests pour voir si l’objet peut déjà être en collision en fonction de leur taille et position etc…
Bref, alors que pour, par exemple la toute première collision on aurait ça :

[code]
En considérant le point X;Y l’origine en haut à gauche de masque :

A.X = Position X de A
A.Y = Position Y de A
A.L = Largeur de A
A.H = Hauteur de A

B.X = Position X de B
B.Y = Position Y de B
B.L = Largeur de B
B.H = Hauteur de B[/code]

[code]Si :

(A.X) > (B.X)
(A.X) < (B.X)+(B.L)
(A.Y) > (B.Y)
(A.Y) < (B.Y)+(B.H)
Alors :

Collision (Haut-Gauche) entre A et B [/code]
Je pense donc que deux conditions puissent être ajoutées :

[code]Collision par Masque :

Argument 1 : Objet A
Argument 2 : Objet B

Renvoie vrai si une des collisions du schéma au dessus est vraie[/code]

[code]
Couverture par Masque :

Argument 1 : Objet A (recouvert par l’objet B)
Argument 2 : Objet B (recouvrant l’objet A)

Renvoie vrai si l’objet A est totalement recouvert par l’objet B (dernière collision du schéma)[/code]
Voilà, ça n’est pas très difficile à coder amha et je peux si nécessaire fournir les différents calculs nécessaires à la vérification des collisions.
Voilà.

(Ca en fait un paquet de lignes z’avez intérêt à avoir compris …)

Exact.

Là où ça se complique, c’est quand les Sprites possédant ces masques ont subi une rotation, les formules ne sont plus du tout simples.
Ça reste faisable, il y aurait peut être éventuellement ( je dis bien éventuellement, é-ven-tu-el-le-ment, éventuellement ) possibilité de généraliser ces masques aux autres objets que les sprites et permettre les tests de collisions entre différent types d’objets pour peu qu’il supporte un masque.

C’est à ce moment là qu’on pourrait choisir d’utiliser la Collision Pixel-Perfect à la place, la collision par masque ne serait pas la seule possible, nous donnant alors le choix.
Et si un sprite qui a été tourné a un test de masque de collision effectué sur lui, celui-ci sera fait en prenant en compte que le masque, lui n’a pas tourné.

D’ailleurs, ce masque de collision pourrait être défini lors de la création de l’objet, avec en attributs l’origine du masque sur le sprite et le point (X+L);(Y+H), comme je l’ai expliqué plus haut le masque ne doit pas être forcément de la taille du sprite (il l’est cependant par défaut) , cela permettrait ainsi d’éviter l’utilisation d’objet tierces.

Moi j’ai trouvé une solution qui marche très bien et qui est bien plus précis que les collision de game develop

Imagine que ton joueur soit un carrer de 16 X 16 par exemple
tu fait un sorte de coller une mini barre sur chaque coté de carrer
tu met ses barre en invisible et la marche carrément bien mieux
par conte si tu fait pivoter ton joueur, je ne sais pas si sa va marcher

Ca n’a absolument rien à voir.

Du même avis qu’Orion-Pyro
En tout cas les calculs du 1er post sont plutôt impréssionants, bravo :slight_smile:
L’idée des masques est bonne :slight_smile:

Je préfère plutôt m’arranger pour que les masques et les tests de collisions des masques fonctionnent avec un Sprite tourné, plutôt que de ne pas faire tourner le masque : C’est beaucoup trop trompeur pour l’utilisateur qui ne comprendra pas pourquoi ça marche pas.
( Et utiliser le pixel perfect ferait perdre toute l’utilité des masques. )

Moi aussi, je préfère que le masque tourne aussi :slight_smile:

Dans ce cas il faudrait énormément de formules de calcul supplémentaires et le pixel perfect ne serait pas moins approprié.
Je vais faire des tests avec les collisions de chez Construct au niveau des masques et je vous dit ce que ça donne et mes impressions.

Ça resterait je pense quand même moins couteux.
Et ça aurait toujours son utilité si on ne veut pas que tout l’objet puisse entrer en collision avec les autres objets. :slight_smile:

Voilà ce qui est fait chez Construct :
Le masque de collision fait par défaut la même taille que le sprite.
En cas de rotation, le masque est actualisé de manière à couvrir entièrement le sprite.

Je n’ai pas testé en cas de rotation avec un masque de collision personnalisé mais je devine que ça doit être actualisé de la même façon mais à échelle différente proportionnelle au masque de départ.

Ce genre de comportement au niveau des masques de collision serait suffisant dans GameDevelop et, encore une fois, très utile.
En cas de masque de collision personnalisé il faudrait cependant utiliser des objets tierces en les liant à un objet.

La prochaine version devrait comporter un système de masque qui permettra de tester la collision entre les objets, incluant les objets de types différents.
Pour les objets style Boite 3D/Texte, le masque sera un rectangle. Pour les objets Sprite, le masque par défaut sera également un rectangle mais pourra être modifié dans l’éditeur d’objet ( On pourra insérer plusieurs rectangles de taille pouvant être choisie afin de dessiner le masque voulu ).

Et les masques s’adapteront aux rotations/élargissements.

Super, merci beaucoup 4ian!
ça veut dire qu’on aura plus besoin de créer un sprite pour tester des collision intérieur à un objet :slight_smile:
Nouvelle très bonne raison de patienter pour la prochaine version!