Physique balancée pour le mouvement du joueur (voir Spider-Man 2 et Energy Hook)

Salut! Je suis Jamie Fristrom des Laboratoires Happion. Vous vous souvenez peut-être de moi dans des jeux tels que Die By The Sword, Spider-Man 2 et Schizoid… qui, sous une forme ou une autre, incluaient une corde. J'ai récemment travaillé sur un jeu appelé Energy Hook, récemment lancé sur Kickstarter, consacré à la corde. (De toute façon, il s'agit de votre faisceau de grappin à graviton.)


Je vais discuter de la manière dont j'aime mettre en œuvre un mécanisme de gameplay à corde pendante. Quand j'ai commencé à travailler sur Energy Hook, je faisais essentiellement tout avec mon propre code personnalisé. Je pense qu’il est possible d’utiliser simplement Unity et d’utiliser l’articulation configurable pour réaliser des tâches très similaires, mais à l’époque, elles n’étaient pas disponibles. De toute façon, je suis presque sûr que c'est le bon choix, car cela me permet de tout contrôler - et je peux le partager avec vous..


Les principes de base du swing comme je l’ai fait - en utilisant contraintes - sont en fait assez simples. (J'espère que vous n'êtes pas déçu quand vous voyez ce qu'il y a sous le capot.) Cela fonctionne de la même manière que vous fassiez un jeu en 2D ou en 3D, c'est simplement que les vecteurs sont différents, alors je commencerai par la 2D, puis discuter de quelques rides en allant à trois dimensions.

Cet article suppose également que vous utilisez un moteur de jeu tel que Unity qui peut effectuer une grande partie du travail, comme la diffusion de rayon contre la géométrie et l'orientation d'un personnage, avec de simples appels de fonctions. Si vous utilisez votre propre moteur, vous devrez peut-être faire le calcul vous-même.



Simulations physiques vs mouvement en boîte

Les simulations de jeu fonctionnent souvent de deux manières. La plupart des jeux à la troisième personne ont tout mis en conserve; animations et mouvements en boîte pour que tout soit parfait, les pieds du personnage ne glissent pas, directement du programme d'animation de l'animateur. L'alternative est une simulation beaucoup plus physique - vous simulez la physique: accélération, vitesse, gravité - beaucoup de jeux à la première personne le font, mais les jeux à la troisième personne ont tendance à l'éviter, car il est beaucoup plus facile d'avoir les pieds du personnage. slide et le matériel physique ne correspond pas à l'animation.

Si vous voulez faire une balançoire sans corde (par opposition à une balançoire en conserve, comme on le voit dans le tout premier Pitfall, ou les premiers jeux Spider-Man comme Neversoft sur PSX), une balançoire qui est en réalité un jeu physique. simulation et peut donc peut-être avoir la liberté et les nuances et le sentiment viscéral que la gravité et l’élan réels peuvent vous donner, alors vous voudrez le faire de la deuxième façon - ayez tout une simulation physique et évitez de mettre des choses en conserve qui tuent l'élan du personnage. Ensuite, tout va couler.

C'est comme ça que je fais les choses avec Energy Hook.


Il existe une tonne d'articles sur la simulation de la physique. En voici un avec une démo Flash intégrée. Vous pouvez effectuer l'intégration Euler ou Verlet, cela n'a pas d'importance. (Je ne vous apprendrai pas à propos de Euler contre Verlet ici, mais laissez-moi simplement dire que les concepts ne sont pas aussi effrayants qu'ils le paraissent.)

Supposons que nous fassions l'intégration osseuse d'os simple. Le temps de jeu de notre personnage pourrait ressembler à ceci, où l'accélération est déterminée par la gravité et la façon dont vous appuyez sur le manche:

 avatar.velocity = avatar.velocity + avatar.acceleration * deltaT; avatar.position = avatar.position + avatar.velocity * deltaT;

(Remarque: c’est une approximation approximative - vous pouvez obtenir une meilleure approximation, moins dépendante de la vitesse de trame, avec avatar.position = avatar.position + (avatar.oldvelocity + avatar.velocity) * deltaT / 2.0f, et vous pouvez obtenir une simulation proche de la perfection avec quelque chose comme ceci - mais vos joueurs ne le remarqueront probablement pas.)

Articles Similaires
  • Simulez des chiffons et des ragdolls avec une intégration simple de Verlet
  • Comment créer un moteur de physique 2D personnalisé

Le contraindre

Votre jeu a probablement un système permettant d’entrer en collision avec la géométrie du monde. Cela ressemble probablement à ceci:

 Vecteur testPosition = avatar.position + avatar.velocity * deltaT; Intersection de vecteur if (RayCast (position, testPosition, intersection sur)) // nous avons traversé un mur, retirons le caractère en arrière //, en utilisant la normale du mur // avec un espace de 1 unité pour l'espace de respiration testPosition = intersection + intersection.normal; 

Qu'advient-il de la vitesse de votre avatar quand ils frappent un obstacle? Cela n'a pas de sens pour votre avatar de conserver la même vitesse à travers le mur. Certains jeux peuvent vous rebondir, en utilisant la normale de l'endroit où vous avez intersecté pour refléter votre vitesse; d'autres jeux pourraient vous laisser glisser le long du mur; d'autres seront quelque part entre les deux. Regardons le code pour glisser le long d'un mur:

 avatar.velocity = (testPosition - avatar.position) / deltaT; avatar.position = testPosition;

(Si vous effectuez une intégration Verlet, où chaque image détermine déjà la vitesse simplement en regardant les données de position précédentes, cette étape est déjà faite pour vous.)

En outre, les jeux vidéo étant les choses les plus compliquées qu'ils soient, vous constaterez probablement souvent que la position de votre personnage se modifie soudainement d'une image à l'autre dans certains cas. Lorsque cela se produit, leur vitesse va à travers le toit. Ma solution à cela est simplement un hack: vérifiez si leur vitesse devient trop extrême et corrigez-la si c'est le cas..

Que fait ce code lorsque vous frappez un mur de biais? La première image modifie radicalement votre vélocité lorsque vous frappez le mur, mais vous pousse toujours à travers le mur. La prochaine image, votre avatar est à nouveau mis à jour dans le mur, puis repoussé à nouveau, mais maintenant la vitesse correspond à la nouvelle position de l'avatar, glissé le long du mur, moins son ancienne position, contre le mur, de sorte qu'il est parallèle au mur..

C’est une énorme simplification excessive de ce qui se passe dans le monde réel quand un objet se heurte à un autre, mais la plupart de vos joueurs ne le remarqueront pas et ne s'en soucieront pas..

À ce stade, cependant, nous avons réussi à contraindre la position et la vitesse de notre avatar avec les murs et les sols de notre jeu. Alors maintenant nous sommes prêts.

Contraindre avec des sangles au lieu de murs

Alors maintenant, imaginez que votre avatar est déjà attaché par une corde virtuelle à un point virtuel. En ce qui nous concerne, on peut simplement considérer qu’il s’agit d’un mur invisible circulaire ou sphérique. Nous pouvons tester la collision en vérifiant si vous vous êtes trop éloigné du centre du cercle et en ramenant l'avatar.

 if (amITethered) if (testPosition - tetherPoint) .Length ()> tetherLength) // nous avons dépassé la fin de notre corde // ramène l'avatar en arrière. testPosition = (testPosition - tetherPoint) .Normalized () * tetherLength; 

Maintenant, le même réglage de vitesse qui nous a fait glisser le long des murs nous fera également glisser le long de l'intérieur de ce cercle ou de cette sphère virtuelle.


Balancer la physique: tomber avec une longe - Frame 1
Balancer la physique: tomber avec une longe - Frame 2
Balancer la physique: tomber avec une longe - Frame 3

Un peu de subtilité et de nuance

À ce stade, vous avez un jeu oscillant. Mais il y aura probablement quelques petites choses à ce sujet qui gêneront vos joueurs et c'est là qu'un peu de piratage informatique peut améliorer les choses..

Slack, Springiness

En fonction de votre jeu et de la supposée simulation d'une longueur de corde, d'une bande élastique ou d'une poutre à grappin, vous pouvez avoir différentes approches du mou et de l'élasticité. Vous pouvez simuler beaucoup de choses en ajustant la longueur de l'attache. Si vous souhaitez vous détendre sur votre toile élastique ou votre poutre de grappin, vous pouvez raccourcir la longueur de l'attache à mesure que le joueur se rapproche du point d'attache:

 tetherLength = (avatar.position - tetherPoint) .Length ();

Mais si c'est une corde non élastique, vous quitteriez le longueur de l'attache intacte.

Pour le printemps, vous pouvez avoir un longueur désirée c'est fixe et un currentLength qui tente continuellement d'approcher le longueur désirée - cela sera également utile pour notre prochaine étape:

Mais je ne veux pas toucher le sol!

Que se passe-t-il si votre avatar commence dans un endroit bas et tente de se balancer? Il est évident qu'ils n'iront pas très loin. Une solution rapide consiste à vérifier à quelle hauteur le point sur lequel ils veulent se déplacer doit être au-dessus du sol et à raccourcir la longueur de leur attache pour qu'ils nettoient le sol..

Cependant, vous ne pouvez pas simplement le raccourcir d’un cadre, car ils vont soudainement se projeter dans les airs. longueur désirée c'est assez court pour ne pas toucher le sol et un currentLength qui approche rapidement longueur désirée vous obtiendrez l'autorisation que vous voulez.

L'avatar est en hausse

Si votre avatar est une figure humaniste, il n’a pas de sens de paraître constamment parfaitement vertical lorsqu’il se balance. En les orientant de manière à ce qu'ils aient l'air d'être suspendus à la corde - ils sont donc à l'envers s'ils font une boucle, par exemple - pourraient ressembler à ceci dans Unity:

 Vector myUp = (avatar.position - tetherPoint); avatar.rotation = Quaternion.LookRotation (avatar.rotation.forward, myUp);

Cela laissera l’avatar basculer en arrière. Vous pouvez également utiliser la vélocité de l'avatar pour l'attaquant (c'est ce que je fais) - ou les laisser tourner follement…

Envelopper autour des choses

Dans le monde réel, des cordes enveloppent des objets. Un moyen rapide de simuler cela dans votre code est de lancer un rayon le long de la corde virtuelle de chaque image, et si elle heurte quelque chose, créez un nouveau point de fixation à l’intersection de celle-ci. Cela n’aura pas l’air si l’avatar bascule ensuite sur une corde non collante, mais convient également pour une bande collante, une langue ou une poutre à grappin.

En peaufinant la façon dont vos cordes enroulées peuvent avoir un impact important sur le plaisir. S'enrouler brusquement autour d'un affleurement peut prendre le joueur par surprise et le frustrer. Nous avions une solution en trois étapes dans Spider-Man 2: si vous étiez trop près de l’affleurement, le Web se briserait; si vous étiez à mi-distance, le Web s'enroulerait; et si vous étiez loin, le web passerait par.


Considérations pour la 3D

Le plus difficile pour amener ce mécanicien 2D en 3D est de considérer l'interface du joueur - comment il choisit des points dans le monde. Différents jeux utilisent différentes méthodes pour choisir un tel point. Ratchet & Clank a des points fixes dans le monde que vous pouvez attaquer; avec le mod Quake Grappling-hook et Bionic Commando: Réarmé, dirigez la caméra vers ce que vous souhaitez attacher; Spider-Man 2 et Energy Hook diffusent des rayons par rapport au personnage et à l'endroit où ils intersectent une géométrie physique constituant le point d'attache..


Presque toutes ces méthodes impliquent la diffusion de rayons en fonction de la géométrie physique du monde, que ce soit le long de la ligne de la caméra ou du personnage au point du clic de la souris. L'intersection du rayon de diffusion détermine votre nouveau point d'attache..

Par exemple, voici un raycast ressemblant à une souris qui pourrait être bon pour un jeu à la première personne:

 RaycastHit wallData; if (Physics.Raycast (camera.position, camera.forward, out wallData, maximumTetherLength)) amITethered = true; tetherPoint = wallData.point; tetherLength = Vector3.Distance (wallData.point, avatar.position); 

Se cogner dans les choses

Se cogner contre des murs, etc., a également tendance à se produire beaucoup plus souvent dans un jeu 3D que dans un jeu en 2D, en particulier lorsque ce sont les murs auxquels vous vous attachez. Il y a une variété de choses que vous pouvez faire pour rendre cela moins ennuyeux.

  • Laissons le joueur se diriger dans les airs: la physique n'a pas grand-chose à dire à ce sujet mais elle se sent bien. C’est l’une des choses que nous avons faites dans Spider-Man 2 et pourquoi vous obtenez un jetpack dans Energy Hook.
  • Jouez une animation sympa: demandez à l'avatar de faire une sorte de retournement ou de rotation lorsqu'il touche un mur, puis cela ressemble moins à une erreur qu'à "je voulais faire ça!"
  • Gardez-les loin du mur: Ultimate Spider-Man a agi de la sorte. Si vous vous approchez trop près d'un mur, cela vous éloignera doucement de celui-ci. Cela semblait un peu bizarre si vous laissiez tomber le bâton et laissiez simplement votre avatar pendre dessus - ils flotteraient loin du mur sous un angle étrange - mais pour le reste du jeu, c'était une amélioration. (Vous pouvez éventuellement avoir le meilleur des deux mondes en vous éloignant seulement si le personnage atteint une certaine vitesse?)
  • Récompensez-les pour ne pas avoir heurté le mur: C'est la stratégie du Crochet d'énergie: apprenez au joueur à ne pas frapper les murs, en le récompensant pour ses élans propres. D'un côté, cela les encourage à se balancer bien; Par contre, quand ils se heurtent au mur, c'est beaucoup plus frustrant, parce qu'ils perdent leurs points de style.


Alors qu'est-ce que tu attends?

Allez-y et faites vos propres jeux de swing, et laissez-moi savoir ce que vous venez avec! Je ne peux jamais avoir assez de jeux de swing.

J'espère que vous avez trouvé cet article utile. Si tel est le cas, soutenez Energy Kookstarter ou votez pour Steam Greenlight. Merci!