Jak sprawić, by gracz płynnie ślizgał się po terenie

11

diagram

Tworzę grę izometryczną. Kiedy gracz próbuje wejść po przekątnej do ściany, chcę, aby gładko się po niej ślizgała, aby każda część ruchu była zgodna z prawem, a wszystko w kierunku normalnym zostało wyrzucone. Ściany mogą być pod dowolnym kątem, nie tylko pionowym lub poziomym, a gracz ma ruch 360 stopni.

Czuję, że już prawie jestem, ale nie mogę umieścić ostatniego kawałka na miejscu.

Aktualizacja: świetna wiadomość dla wszystkich! Mam to działa. Ale ... Jestem trochę zdezorientowany, co powinienem normalizować, a co nie. Normalna po prostu musi być wektorem jednostkowym, prawda? ale potem miksuję to z moim wkładem, więc normalizuję to - czy się mylę?

Nawiasem mówiąc, odkryłem również, że muszę przesunąć odtwarzacz o 1 piksel w kierunku normalnym, aby nie utknęły na czymś - działa dobrze.

Iain
źródło

Odpowiedzi:

13

Po prostu rzutuj wektor ruchu na normalną płaszczyznę, a następnie odejmij wynik od wektora ruchu.

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

W każdym razie coś takiego. Chociaż na twoim pięknym schemacie wejście wydaje się być z dala od ściany, więc jestem nieco zdezorientowany.

Chris Howe
źródło
przepraszam, że powinien być tam przed pionową ścianą. okropny rysunek
Iain
1
Jestem trochę zdezorientowany co do produktu kropkowego. Czy produkt kropkowy nie jest skalarem?
Iain
1
Tak, ale mnożymy go przez normalny (wektor), aby uzyskać wektor niepożądanego ruchu. Wektor (x, y, z) pomnożony przez skalar s daje wektor (sx, sy, sz).
Chris Howe
Gotowe, zmieniono zmienne, aby mam nadzieję, że pasują do diagramu. :)
Chris Howe
@Iain Naprawdę staram się zrozumieć, jak korzystać z tej odpowiedzi, ale nie mogę jej zrozumieć. Kiedy tworzę ten dokładny kod, mam naprawdę dziwne desiredMotionwyniki. Czy kiedykolwiek sprawiłeś, że to działało?
test
1

Chociaż usunięcie elementu ruchu w kierunku normalnym jest proste, to może być odpowiednie dla twojej gry, aby zamiast tego obrócić wektor ruchu. Na przykład w grze akcji dla trzeciej osoby może być łatwo rozłączyć się na ścianach i innych granicach, więc możesz zgadywać, co zamierza gracz.

// 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
źródło
Miły. Ale jeśli skalujesz według współczynnika kruszenia, czy to powoduje, że zderzasz się ze ścianą, a nie przesuwasz się wzdłuż niej, czy to tylko kwestia ulepszenia?
Chris Howe
Myślę, że poprawiasz go, aby wyglądał dobrze; z pewnością, jeśli będzie zbyt duży, będzie wyglądać, jakbyś się podskakiwał, ale jeśli będzie wystarczająco subtelny, po prostu powstrzyma cię od zawieszenia się na lekkich zakrętach na powierzchni.
dash-tom-bang