Comment gérer les collisions d'angle en 2D?

22

J'écris un jeu XNA top down 2d. Depuis que c'est ma première, j'essaie d'écrire moi-même des trucs sur la physique et la collision pour l'apprendre.

Chaque fois que mon personnage sprite joueur tente de se déplacer dans une position où ses limites se croisent avec le bord d'un mur, je détermine un angle de rebond (angle d'incidence = angle de réflexion) et je fais rebondir le joueur sur le mur et éviter la collision .

J'ai du mal à comprendre comment faire face à la situation de mon sprite intersectant avec deux bords de mur simultanément, par exemple s'il atteint un coin.

collision en coin

Mon code me dit actuellement que deux bords de mur ont été intersectés mais pas quel bord il aurait touché en premier et donc quel bord rebondir.

Quel est le test mathématique pour choisir quel bord rebondir? C'est clair à voir en le regardant mais j'ai du mal à comprendre le test de mathématiques pour cela.

TerryB
la source
Merci Tetrad. J'ai vu celui-là mais il semblait que la balle se comporterait différemment de mon problème rectangulaire. Dans le cas illustré ci-dessus, le sprite rectangulaire aurait frappé le bord inférieur du mur et aurait rebondi. Le bord latéral du mur ne serait jamais entré dans l'équation. Je ne sais tout simplement pas comment exprimer cela dans le code et prendre cette décision.
TerryB

Réponses:

9

Si vous calculez la distance dans le Walll' Player Spritea déplacé, vous pouvez probablement baser sur le delta des coordonnées x et y des coins qui se croisent. J'espère que cela a du sens, je ne peux pas penser à une meilleure façon de le formuler.

Ainsi, par exemple, si vous regardez votre diagramme. Prenez la xvaleur du coin supérieur gauche du Player Sprite(après le déplacement) et soustrayez la xvaleur du coin inférieur droit du Wall. Faites la même chose pour les yvaleurs, puis voyez laquelle est la plus grande. La clé est que si l'un est plus grand que l'autre, il est Player Spriteprobablement recoupé de ce côté.

Voici un exemple d'image (c'est une sous-section de votre image avec mes propres lignes ajoutées):

exemple d'intersection

Maintenant, vous voyez ici que la ligne bleue est plus grande que la ligne verte. Dans ce cas, la ligne bleue est également du côté Player Spriteduquel le rebondirait.

Si les deux valeurs sont égales, elles frappent juste au coin.

Maintenant, il y a un léger problème à le faire de cette façon. Si le Player Spritevéhicule se déplace très rapidement ou que la collision est très proche du coin, il est possible que le Player Spritevéhicule puisse aller plus loin dans Wallla mauvaise direction. Dans ce cas, vous devrez probablement vérifier la vitesse de l'objet en mouvement. (Voir la réponse de Nathan Reed .)

Remarque: Je pense que j'essaie essentiellement de décrire la détection de collision SAT mentionnée par @Blau, mais j'ai passé beaucoup de temps à l'écrire, donc je vais la publier de toute façon. J'espère que cela vous aidera.

Richard Marskell - Drackir
la source
Merci Drackir! Et je suppose que si mon mur tourne par rapport au sprite, c'est un peu plus délicat mais le même principe s'applique. Recherchez le vecteur de déplacement de longueur minimale qui signifierait que le sprite n'entrerait pas en collision avec le mur. Ensuite, utilisez le mur normal à ce vecteur comme mon mur pour rebondir.
TerryB
@TerryB - La rotation y ajoute un peu plus de complexité. Vous voudrez peut-être lire sur les boîtes englobantes alignées sur l'axe (AABB). Fondamentalement, vous utilisez toujours le même principe que ci-dessus en testant la plus petite boîte dans laquelle s'insérera l'objet pivoté, mais dont les axes sont alignés sur les axes cartésiens. Imaginez si vous aviez un carré et que vous l'avez tourné de 45 degrés pour en faire un diamant. Calculer la collision serait difficile et coûteux, alors vérifiez d'abord si l'objet est même près de lui en utilisant l'AABB qui serait un carré où chaque point du diamant touche chaque côté au milieu.
Richard Marskell - Drackir
Ensuite, lorsque vous savez qu'il est proche, vous pouvez faire les calculs les plus coûteux pour voir s'ils se croisent sur des angles (ce qui devrait probablement être une autre question :)).
Richard Marskell - Drackir
1
-1 puisque le déplacement minimum ne donne pas toujours la bonne réponse à "quel bord est entré en collision en premier"; voir ma réponse.
Nathan Reed
@NathanReed - C'est pourquoi j'ai mentionné la vérification de la vitesse dans mon paragraphe "Maintenant, il y a un léger problème avec cela".
Richard Marskell - Drackir
15

Le déplacement minimum ne donne pas toujours la bonne réponse pour quel bord a été touché en premier. Considérez ce cas:

cas qui rompt l'algorithme de déplacement le plus court

Cela se produit lorsque la vitesse est suffisamment élevée pour que le bloc se déplace assez loin au cours d'une image. Pour détecter correctement l'arête frappée en premier, vous devrez configurer une équation linéaire à résoudre pour le temps de collision avec chaque arête. Dans ce cas décrit dans le diagramme de l'OP, les équations pertinentes sont:

timeXCollision = (player.left - wall.right) / -player.velocity.x
timeYCollision = (wall.bottom - player.top) / player.velocity.y

(Cela suppose un système de coordonnées X à droite et Y vers le haut.) En général, vous devez utiliser les signes des composants X et Y de player.velocity pour déterminer la paire d'arêtes à tester. Quoi qu'il en soit, une fois que les temps de collision sont calculés, la première des deux est la collision que vous devez gérer.

Nathan Reed
la source
1
Pourriez-vous fournir un exemple sur la façon dont vos deux variables pourraient être implémentées?
BjarkeCK
1

Vous avez besoin de la détection de collision SAT

Fondamentalement, vous devez rechercher le vecteur de déplacement minimum qui s'est soustrait à l'un des objets et ne les laisser se croiser.

Dans votre image, le déplacement minimum est le segment orange.

entrez la description de l'image ici

Blau
la source
4
-1 car le déplacement minimum ne donne pas toujours la bonne réponse à "quel bord est entré en collision en premier"; voir ma réponse.
Nathan Reed
qui demande ça?
Blau
La question est de demander cela. "Mon code me dit actuellement que deux bords de mur ont été intersectés mais pas quel bord il aurait touché en premier et donc quel bord rebondir."
Nathan Reed
première? le problème n'est pas quel est le premier, il entre en collision avec les deux bords en même temps, ... le problème est quel bord rebondir, vous avez choisi une méthode qui vous convient, j'ai choisi une méthode qui est bon pour moi, les deux sont valides
Blau
1
Si vous voulez prendre une décision de conception pour laisser les objets glisser les uns contre les autres comme ça, comme s'ils étaient arrondis ou biseautés dans les coins, c'est votre décision, et cela pourrait bien être la bonne chose pour votre gameplay. Mais je ne pense pas que la question porte sur une décision de conception; il demande mathématiquement comment faire rebondir les rectangles alignés les uns par rapport aux autres. Ce n'est pas une question d'interprétation; ce problème mathématique a une réponse claire et correcte à quel bord rebondir.
Nathan Reed
0

Répondu à une question similaire ici

Vous voudrez peut-être envisager de vérifier les positions précédentes-

Par exemple: si votre côté gauche était auparavant à droite de leur côté droit et que vous vous heurtez, une collision avec la droite s'est produite.

Si vous faites cela, résolvez simplement les collisions de l'axe y, vérifiez si vous entrez en collision avec quelque chose, puis résolvez les collisions de l'axe x.

ultifinitus
la source