Dans un jeu de plateforme 2D, comment s'assurer que le joueur se déplace en douceur sur un terrain en pente?

18

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.

Nick Kovac
la source
Un moteur de physique générale est idéal pour les effets et les boîtes qui tombent et tout cela, mais pas pour la physique des personnages, comme indiqué dans la section des réponses. Envisagez d'écrire de la physique «statique» pour votre personnage, afin de pouvoir contrôler à 100% et utiliser une dynamique correctement simulée pour le reste.
Domi

Réponses:

14

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.

Sean Middleditch
la source
Merci pour votre réponse. J'avais envisagé de réduire les cases qui représentent le sol en lignes, mais je ne pense pas que cela résoudra le problème en soi. Par exemple, si les cases au sol sont maintenant des lignes, et si le joueur se tient sur la ligne C et se déplace vers la gauche vers B, en raison de l'inexactitude, il est possible que la case du joueur soit légèrement en dessous de la ligne C. Ensuite, le bord gauche de la case du joueur pourrait encore entrer en collision avec la ligne B et provoquer cette collision indésirable,
Nick Kovac
sauf s'il existe un autre mécanisme pour empêcher que cela se produise. Ce n'est pas le fait que Box2D utilise des lignes au lieu de boîtes qui résout le problème, c'est que Box2D utilise une forme de chaîne, qui utilise des informations de connectivité entre les segments de ligne pour empêcher certaines collisions de se produire. Le principal problème en ce moment est que je ne comprends pas très bien comment cela se passe exactement.
Nick Kovac
Vous avez soulevé d'autres points très intéressants sur les problèmes liés à la prise d'idées de moteurs de physique génériques et à leur application aux jeux de plateforme. J'ai vu des moteurs similaires qui mettent en œuvre les idées que vous avez discutées (modification de la normale de collision pour les pentes et aspiration du joueur sur la pente), donc au moins ces problèmes sont assez facilement résolubles. Le principal point d'achoppement pour moi est les cas délicats liés aux erreurs numériques.
Nick Kovac
@Kovsa: encore une fois, ces erreurs particulières disparaissent lorsque vous vous débarrassez des bords qui ne devraient pas faire partie de la collision en premier lieu. Enchaînez les bords ensemble pour former une forme ininterrompue. Lors de la conception de votre niveau, je vous recommande également de rapprocher les sommets afin de ne pas avoir de petites crevasses dans les surfaces. Pas vraiment différent de la façon dont vous concevez le niveau dans un éditeur de maillage 3D.
Sean Middleditch
Hmm ... Je ne pense pas que je suis. Dans mon diagramme, si j'enchaîne les bords pour créer une forme ininterrompue, j'obtiendrais une forme composée de trois segments de ligne: le haut des cases A, B et C, non? Même s'il s'agit d'une forme unique, je devrais toujours effectuer une détection de collision séparément contre la ligne A, puis B, puis C, n'est-ce pas? À moins que vous vouliez un algorithme capable de détecter une collision entre la boîte et cette forme combinée? Je suppose que ce ne serait pas SAT alors, car une série d'arêtes pourrait être concave?
Nick Kovac
5

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.

Kevin Reid
la source
Hmm, idée intéressante ... comment feriez-vous pour l'implémenter? Cela va cependant un peu à l'encontre de la simplicité d'utilisation des boîtes: (Je suis d'accord qu'il semble que cela devrait être un problème commun avec une solution définitive, mais je ne trouve vraiment aucune couverture à ce sujet ... à part ce qui est fait dans Box2D. J'ai posté une question similaire sur leur forum pour, espérons-le, avoir plus d'informations
Nick Kovac
Je n'ai pas de détails d'implémentation, désolé - je ne suis pas un expert sur ce type de code moteur physique. Cependant, j'avais une meilleure idée d'une solution qui n'est pas basée sur des facteurs de fudge - voir ma modification.
Kevin Reid
1
Notez que bien que l'utilisation de formes arrondies fonctionne, c'est à la fois plus complexe mathématiquement et cela peut entraîner un comportement sous-optimal pour les plateformes. Les joueurs s'attendent à avoir un contrôle presque parfait sur les personnages se tenant sur des rebords, par exemple, quelles formes arrondies rendront plus ou moins impossibles, et les personnages glisseront de manière inattendue.
Sean Middleditch
Ledges: D'oh! OK, pas aussi simple que je le pensais.
Kevin Reid
Oui, après y avoir réfléchi, l'approche capsule semble peut-être plus adaptée à un jeu 3D qu'à un jeu de plateforme 2D. Avoir un contrôle parfait des pixels est définitivement une priorité pour moi (comme c'était le cas dans tous ces anciens plateformes 2D). Mais il doit y avoir une solution qui permette d'utiliser des boîtes!
Nick Kovac