Détection de collision 2D

11

Supposons que j'utilise ce personnage.

oiseau
(source: iconbug.com )

Comment implémenteriez-vous la détection de collision? L'utilisation d'une boîte englobante ne semble pas être une bonne approximation, car la forme de l'oiseau n'est nulle part près d'un carré.

Je pensais avoir une sorte de structure de données en quadruple arbre à l'intérieur de l'objet qui représente des parties de l'image. Chaque feuille peut être soit false(dans le cas où elle couvre l'espace blanc / transparent à l'extérieur de l'oiseau) ou true(dans le cas où elle représente une zone de l'oiseau, c'est-à-dire le bec, l'œil, etc.). Ensuite, testez en quelque sorte le seul obstacle de la scène pour une collision avec l'oiseau.

Mais mes problèmes dans mon approche sont:

  1. Je ne sais pas comment initialiser l'arbre quad.
  2. Une fois que l'arbre quad est initialisé, je ne sais pas comment le traverser et l'utiliser une fois que l'obstacle est dans les coordonnées de l'image.

Comment feriez-vous la détection de collision avec des caractères non carrés?

LE: L'autre approche que j'ai vue était d'utiliser plusieurs boîtes englobantes. Par exemple, j'aurais une ou quelques boîtes de délimitation pour le bec, puis quelques-unes pour les cheveux ou la queue. Mais cela peut devenir fastidieux. S'il s'agit d'une approche valide dans mon cas, comment générer ces boîtes englobantes? Je doute que je devrais les faire coder en dur dans mon programme.

LE2: Je me soucie des collisions assez précises. Je ne peux pas imaginer comment un seul cadre ou cercle englobant peut au moins approximativement décemment cette forme, donc cette approche ne fonctionnera pas.

async
la source
2
Une note générale: j'utiliserais les deux, une boîte englobante et une vérification plus granulaire: la vérification granulaire aura une pénalité de performance plus élevée, donc vous voulez qu'elle s'exécute aussi rarement que possible. Par conséquent, cochez d'abord la boîte englobante et seulement si cela est atteint, allez plus loin et testez votre approche plus granulaire (quelle qu'elle soit).
Philip Allgaier
Merci, je prévoyais de le faire de toute façon, mais je ne suis pas tout à fait sûr de ce que le «contrôle granulaire» devrait être. :)
asynchrone
1
Le seul détail important manque: que voulez-vous en faire? Vous souciez-vous des collisions exactes? Êtes-vous heureux d'approcher le personnage avec un cercle? Voulez-vous que les particules de poussière entrent en collision avec les yeux du personnage séparément des autres?
Anko
@Anko Comment pouvez-vous approximer cette forme avec un cercle? Je me soucie des collisions assez précises - pas vraiment précises en pixels, mais quelque chose qui aura l'air bien / naturel -.
async
1
Comme ça . Que signifient même «bon» et «naturel»? Est-ce une question philosophique?
Anko

Réponses:

12

Collisionneur de cercle. Assez bien pour cela, je dirais à moins que vous ne fassiez quelque chose d'extraordinaire avec certaines parties affectées par la physique ou la collision qui semble artificielle, et même si vous avez besoin de le diviser en plusieurs parties, j'ai une chose à vous dire:

Ne le compliquez pas trop.

Vous n'avez pas besoin d'une structure d'arbre quadruple complète pour cela. Disposez simplement plusieurs cases ou cercles dans un tableau droit, puis coupez-les tous. Cela ne peut pas être suffisamment critique pour les performances et vous ne gagnerez pas beaucoup en utilisant un arbre quadruple.

Jonkel
la source
3
Oui, faites simplement un petit tableau de plusieurs formes si une seule forme ne le couvre pas. Par exemple: i.imgur.com/Dd4yyGN.png
MichaelHouse
Merci Jonkel & @ Byte56. Utiliser quelques formes semble la bonne solution dans ma situation. Simple à mettre en œuvre, précis et rapide. Je ne peux pas croire que je suis passé directement aux arbres quad sans y penser! Euh.
asynchrone
Un collisionneur circulaire pour le corps et un rectangulaire pour le bec, pour plus de précision.
Kroltan
14

Un processus de vérification en deux étapes

À la première étape, vous cochez la case de délimitation et s'il n'y a pas de collision, le test est terminé. En cas de collision, vous passez au deuxième passage

Lors de la deuxième passe , si vous voulez plus de précision et que vous voulez une vraie solution de pixel parfait, vous pouvez le faire, une passe de vérification de pixel parfait

Étant donné que votre image est un PNG (ou tout autre format de fichier contenant un canal alpha), ce serait plutôt facile

  1. Calculez la zone d'intersection entre cet objet dans la scène et l'oiseau, en générant un simple rectangle d'intersection sur les deux images
  2. Dans cette intersection, vérifiez que chaque pixel a une valeur alpha> 0 dans les DEUX images
  3. Si de tels pixels existent, vous avez obtenu votre collision. Sinon non

Si vous regardez le canal alpha de vos images, vous pouvez voir comment il contient déjà toutes les informations dont vous pourriez avoir besoin pour une collision parfaite en pixels

canal alpha de l'image

Les collisions parfaites au pixel sont généralement coûteuses, donc faire une estimation grossière au début avec une boîte englobante ou une figure de collision plus détaillée (comme celle suggérée par Anko) peut vous faire gagner un temps précieux

La boîte de délimitation de collision détaillée "plus fine" Anko a suggéré:

cadre de délimitation plus détaillé

PS: Si votre image a un halo, un effet ou un autre canal alpha non 0 autour duquel vous ne voulez pas entrer en collision, le seuil de l'algorithme peut facilement être ajusté pour s'adapter à cela

codemonkey
la source
1
Je vous remercie! Mais je n'aurai pas besoin d'une précision parfaite des pixels après tout. Une excellente réponse sera cependant utile à une date ultérieure.
asynchrone
bien sûr, mec, oui, la collision parfaite de pixels est presque toujours une exagération, sauf dans les jeux qui en ont vraiment besoin (comme les combattants 2D)
codemonkey
3

J'utiliserais un cercle pour le corps et un seul rectangle pour le bec, mais c'est juste mon opinion. Trop compliquer votre géométrie de collision peut cependant ralentir votre application, vous doublez (ou plus) pratiquement le nombre de caractères à l'écran.

igrad
la source
0

Vous pourriez peut-être utiliser une sorte de collisionneur de polygones / bords bancal.

Je ne sais pas exactement comment cela fonctionnerait, mais:

deux objets: objet 1: l'oiseau (o1), objet 2: la chose qui pourrait frapper l'oiseau (o2)

1) Définissez une forme englobante qui est un polygone qui correspond étroitement au premier objet (o1) en question.

2) Obtenez les bords de o1, o2 qui pourraient éventuellement entrer en collision sans pourraient éventuellement entrer en collision sans que o2 ne passe par o1 ou vice versa.

Avec la position et la taille de la forme (o2), vous pourriez probablement isoler les bords (de o1) qui ne peuvent pas être heurtés, que ce soit parce qu'ils sont "derrière" un autre bord (de o1) qui est plus proche de o2. Si vous aviez un triangle rectangle dont l'hypoténuse était tournée vers le haut et vers la droite et un rectangle se rapprochant directement de lui (avec le côté long le long de l'axe des x), alors vous pouvez dire quelles arêtes omettre parce qu'elles commencent et que les valeurs y sont toutes les deux soit au-dessus ou en dessous du rectangle.

3) Déterminez si l'un des points sur une arête de o2 est identique à un point sur l'une des arêtes de o1 que vous avez sélectionnée à l'étape 2.

ce concept fonctionne probablement mieux pour entrer en collision de polygones (c'est-à-dire des objets aux bords nets), mais vous pouvez peut-être traiter un cercle comme un long bord (par exemple, si o2 était un cercle).

Jeremy Harton
la source