Comment faire glisser le joueur en douceur contre le terrain

11

diagramme

Je fais un jeu isométrique. Lorsque le joueur essaie de marcher en diagonale dans un mur, je veux qu'il glisse doucement dessus, donc toute portion du mouvement qui est légale est utilisée, et tout ce qui est dans le sens de la normale est jeté. Les murs peuvent avoir n'importe quel angle, pas seulement vertical ou horizontal, et le joueur a un mouvement à 360 °.

J'ai l'impression d'être presque là mais je ne peux pas mettre la dernière pièce en place.

Mise à jour: bonnes nouvelles à tous! Je le fais fonctionner. Mais ... je suis un peu confus ce que je devrais normaliser et ce qui ne l'est pas. La normale doit juste être un vecteur unitaire, non? mais ensuite je mélange ça avec mon entrée donc je normalise ça - je me trompe?

Soit dit en passant, j'ai également constaté que je dois pousser le lecteur de 1 pixel dans la direction de la normale, afin qu'il ne reste pas coincé sur les choses - fonctionne bien.

Iain
la source

Réponses:

13

Projetez simplement votre vecteur de mouvement sur le plan normal, puis soustrayez le résultat de votre vecteur de mouvement.

Vector undesiredMotion = normal * (dotProduct(input, normal));
Vector desiredMotion = input - undesiredMotion;

Quelque chose comme ça de toute façon. Bien que dans votre joli diagramme, l'entrée semble être loin du mur, donc je suis légèrement confus.

Chris Howe
la source
désolé, il est censé être devant un mur vertical là-bas. dessin terrible
Iain
1
Je suis un peu confus au sujet du produit scalaire. Le produit scalaire n'est-il pas un scalaire?
Iain
1
Oui, mais vous le multipliez par la normale (un vecteur) pour obtenir le vecteur de votre mouvement indésirable. Un vecteur (x, y, z) multiplié par le scalaire s vous donne le vecteur (sx, sy, sz).
Chris Howe
Terminé, changé les variables pour, espérons-le, correspondre au diagramme. :)
Chris Howe
@Iain, j'essaie vraiment de comprendre comment utiliser cette réponse, mais je n'arrive pas à la comprendre. Lorsque je crée ce code exact, j'obtiens des desiredMotionrésultats vraiment étranges . Avez-vous déjà réussi à le faire fonctionner?
testez
1

Bien qu'il soit simple de supprimer simplement la composante du mouvement qui est dans le sens de la normale, il peut convenir à votre gameplay de faire pivoter le vecteur de mouvement à la place. Par exemple, dans un jeu d'action à la troisième personne, il peut être facile de se raccrocher légèrement aux murs et aux autres limites, vous pouvez donc deviner ce que le joueur a l'intention de faire.

// assume that 'normal' is unit length
Vector GetDesired(Vector input, Vector normal) {
   // tune this to get where you stop when you're running into the wall,
   // vs. bouncing off of it
   static float k_runningIntoWallThreshold = cos(DEG2RAD(45));

   // tune this to "fudge" the "push away" from the wall
   static float k_bounceFudge = 1.1f;

   // normalize input, but keep track of original size
   float inputLength = input.GetLength();
   input.Scale(1.0f / inputLength);

   float dot = DotProduct(input, normal);

   if (dot < 0)
   {
      // we're not running into the wall
      return input;
   }
   else if (dot < k_runningIntoWallThreshold)
   {
      Vector intoWall = normal.Scale(dot);
      intoWall.Scale(k_bounceFudge);

      Vector alongWall = (input - intoWall).Normalize();
      alongWall.Scale(inputLength);

      return alongWall;
   }
   else
   {
      // we ran "straight into the wall"
      return Vector(0, 0, 0);
   }
}
dash-tom-bang
la source
Agréable. Mais si vous évoluez par un facteur de fudge, cela vous fait-il cogner le long du mur plutôt que de le glisser, ou s'agit-il simplement de le peaufiner?
Chris Howe
Ma pensée est que vous le peaufiniez pour avoir l'air correct; certes, s'il est trop grand, il semblera que vous rebondissez, mais s'il est suffisamment subtil, cela vous empêchera de vous accrocher à de légers virages à la surface.
dash-tom-bang