Je développe un moteur physique pour un jeu de plateforme 2D. J'utilise le théorème de l'axe de séparation pour la détection de collision. La surface du sol est construite à partir de boîtes englobantes orientées, avec le joueur comme une boîte englobante alignée sur l'axe. (Plus précisément, j'utilise l'algorithme du livre "Détection de collision en temps réel" qui effectue une détection de collision balayée pour les OBB utilisant SAT). J'utilise un coefficient de restitution assez petit (proche de zéro) dans la réponse à la collision, pour garantir que les objets dynamiques ne pénètrent pas dans l'environnement.
Le moteur fonctionne généralement bien, c'est juste que je suis préoccupé par certains cas de bord qui pourraient éventuellement se produire. Par exemple, dans le diagramme, A, B et C sont la surface du sol. Le joueur se dirige à gauche le long de B vers A. Il me semble qu'en raison de l'inexactitude, la boîte du joueur pourrait être légèrement en dessous de la boîte B alors qu'elle continue vers le haut et vers la gauche. Quand il atteint A, le coin inférieur gauche du joueur peut alors entrer en collision avec le côté droit de A, ce qui ne serait pas souhaitable (car l'intention est que le joueur se déplace en douceur sur le dessus de A). Il semble qu'un problème similaire puisse se produire lorsque le joueur est au-dessus de la case C, se déplaçant vers la gauche vers B - le point le plus extrême de B pourrait entrer en collision avec le côté gauche du joueur, au lieu que le coin inférieur gauche du joueur glisse vers le haut et la gauche au-dessus de B.
Box2D semble gérer ce problème en stockant des informations de connectivité pour ses formes de bord, mais je ne sais pas vraiment comment il utilise ces informations pour résoudre le problème, et après avoir regardé le code, je ne comprends pas vraiment ce qu'il fait.
Toutes les suggestions seraient grandement appréciées.
Réponses:
Plateforme et physique
Ces cas marginaux sont nombreux. Les bons jeux de plateforme amusants ne se comportent d'aucune manière physiquement précise, et le contrôle et le comportement que les joueurs attendent après des années de jeux de plateforme "parfaits" comme Mario sont incroyablement difficiles à mettre en œuvre avec des techniques générales comme vous le faites avec Box2D ou d'autres moteurs physiques. La plupart des bons plates-formes n'utilisent aucun type de physique générique ou de réponse aux collisions dans leurs contrôleurs de joueurs.
Générer des coques
Concernant votre question spécifique, la meilleure solution est de ne plus utiliser de boîtes comme terrain. Utilisez une série de segments de ligne connectés (une coque). Cela permet au moteur de détection de collision de se concentrer uniquement sur les surfaces réellement praticables et de ne pas regarder le "faux" bord qui existe entre AB et BC. C'est ce que fait Box2D, en fait. Les formes sont utilisées pour générer les surfaces extérieures, qui sont liées entre elles pour former une coque.
Vous en avez besoin même dans les jeux basés sur des tuiles, ou dans des situations où vous avez deux objets AABB à côté d'autres agissant comme plancher. Le moteur de collision ramassera ces bords verticaux et amènera le joueur à les attraper. Il existe des hacks qui peuvent aider, mais pas éliminer le problème. La solution consiste à n'avoir qu'un seul segment de ligne représentant la surface plutôt qu'une boîte 2D complète.
Vous pouvez générer les coques dans le cas générique en coupant les polygones les uns contre les autres et en joignant les points de clip dans une liste de bords.
Surfaces inclinées
Étant donné que votre exemple comprend une pente et que vous mentionnez la restitution et d'autres propriétés physiques, je soulignerai quelques autres problèmes que vous remarquerez bientôt, ce qui illustre davantage pourquoi la détection de collision générique et la réponse ne fonctionnent pas bien pour les plateformes. Tout d'abord, essayez de vous tenir sur la plate-forme inclinée, sautez, puis atterrissez. Vous remarquerez probablement que le personnage "glissera" un peu lors de l'atterrissage. Le problème est que la normale de contact que vous générez sera généralement indiquée depuis la surface inclinée. Puis, lors de la résolution de la collision, le joueur est poussé dans cette direction. Même si le personnage est tombé tout droit, il sera poussé vers le haut et un peu vers la droite lors de l'atterrissage, ce qui entraînera le glissement. Cela peut être piraté en tenant compte des vitesses relatives,
Le deuxième problème que vous remarquerez, qui est beaucoup plus difficile à résoudre, est ce qui se passe lorsque vous essayez de courir rapidement sur une rampe. Le joueur va "sauter" sur la rampe. C'est très visible même dans la plupart des jeux AAA aujourd'hui. Cela semble non seulement idiot, mais si votre jeu nécessite que le joueur soit posé au sol pour sauter, il est difficile de descendre une rampe et de sauter à mi-chemin, car le joueur ne contacte la rampe que pendant une petite partie de la le temps passé à descendre. Une solution plus simple consiste à simplement lancer des rayons lorsque le joueur se déplace et à aligner la position du joueur sur la surface la plus proche (si elle est très proche du joueur) si le joueur ne saute pas et était auparavant au sol.
Vous pouvez également constater que le joueur se lance dans les airs en montant une rampe si vous essayez de modéliser la vitesse, la friction et la restitution sur le joueur comme s'il était un corps rigide normal. Le mouvement du joueur doit être limité au mouvement horizontal à moins de tomber / sauter. Bien sûr, si vous jouez à des jeux de plateforme plus anciens, vous remarquerez peut-être que la vitesse horizontale du joueur est souvent constante entre les surfaces horizontales et les surfaces inclinées. Cela doit également être pris en compte lors de la montée / descente des pentes.
Il y aura également un certain nombre d'autres cas de coins étranges que vous rencontrerez éventuellement. Si vous essayez de faire un bon jeu de plateforme, il est vraiment préférable d'implémenter un contrôleur de lecteur de plateforme séparé de la physique et de coder en dur le comportement de mouvement et de contrôle que vous souhaitez, plutôt que de vous fier à la physique générique et à l'algorithme de réponse aux collisions.
la source
Je pense que les deux problèmes pourraient être résolus en traitant vos boîtes, à des fins de réponse aux collisions, comme si elles avaient des coins arrondis (d'un rayon similaire à votre erreur numérique). Cela rendra la surface combinée efficace des coins de réunion entre A et B et B et C plus lisse.
Ainsi, si le JOUEUR se déplaçant vers la gauche frappe le coin de A, la normale de collision serait diagonale plutôt que purement vers la droite, permettant ainsi la poursuite du mouvement de gauche à droite.
Cependant, une solution plus typique, en examinant ce que je sais de la physique des plateformes, consiste à donner au joueur une forme plus arrondie et à laisser le terrain tranquille. En particulier, envisagez de faire de la forme du joueur une capsule (cercle étiré au milieu (2D) / sphère (3D)) - vos normales de collision seront naturellement presque verticales, éliminant tout problème de capture.
Vous dites que vous utilisez un algorithme de collision spécifiquement pour les OBB, mais vous devriez toujours pouvoir, après avoir trouvé une collision OBB-OBB, utiliser un autre test contre une forme qui est entièrement dans l'OBB.
la source