Как сделать так, чтобы игрок плавно скользил по местности

11

диаграмма

Я делаю изометрическую игру. Когда игрок пытается пройти по диагонали в стену, я хочу, чтобы они плавно скользили по ней, чтобы любая часть движения, которая была бы законной, использовалась, и все, что в направлении нормали, отбрасывалось. Стены могут быть под любым углом, не только вертикальным или горизонтальным, а у игрока 360 движений.

Я чувствую, что я почти на месте, но я не могу поставить последний кусок на место.

Обновление: отличная новость всем! У меня это работает. Но ... я немного запутался, что мне следует нормализовать, а что нет. Нормаль просто должна быть единичным вектором, верно? но затем я смешиваю это со своим вкладом, поэтому я нормализую это - я не прав?

Кстати, я также обнаружил, что мне нужно подтолкнуть игрока на 1 пиксель в направлении нормали, чтобы он не застрял на вещах - работает хорошо.

Iain
источник

Ответы:

13

Просто спроецируйте ваш вектор движения на плоскость нормали, а затем вычтите результат из вашего вектора движения.

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

Как-то так или иначе. Хотя в вашей прекрасной диаграмме ввод, кажется, находится далеко от стены, поэтому я немного запутался.

Крис Хоу
источник
извините, он должен быть перед вертикальной стеной там. ужасный рисунок
Иан
1
Я немного запутался насчет точечного продукта. Разве точечный продукт не скаляр?
Иэн
1
Да, но вы умножаете его на нормаль (вектор), чтобы получить вектор вашего нежелательного движения. Вектор (x, y, z), умноженный на скаляр s, дает вам вектор (sx, sy, sz).
Крис Хоу
Готово, переменные изменены, чтобы, надеюсь, соответствовать диаграмме. :)
Крис Хоу
@ Я действительно пытаюсь понять, как использовать этот ответ, но я не могу понять его. Когда я создаю этот точный код, я получаю действительно странные desiredMotionрезультаты. Вы когда-нибудь работали?
тест
1

Хотя просто убрать компонент движения, который направлен в сторону от нормали, вам может потребоваться повернуть вектор движения в соответствии с вашим игровым процессом. Например, в экшн-игре от третьего лица может быть легко зацикливаться на стенах и других границах, поэтому вы можете сделать некоторые предположения относительно того, что намерен игрок.

// 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);
   }
}
штрих-кот-бэнг
источник
Ницца. Но если вы масштабируете с помощью коэффициента выдумки, это заставит вас столкнуться со стеной, а не скользить вдоль нее, или это просто случай ее настройки?
Крис Хоу
Я думаю, что вы настраиваете это, чтобы выглядеть хорошо; конечно, если он слишком большой, это будет выглядеть так, будто вы подпрыгиваете, но если он достаточно тонкий, он просто не даст вам застрять на небольших изгибах на поверхности.
дэш-том-бэнг