Чому мій об’єкт рухається швидше на 45 градусів, ніж при 90 градусах?


32

У моїй грі є предмети, які рухаються швидше на 45 градусів, а потім на 90 градусів.

Кожен об’єкт має

  • Точка (х, у) положення
  • Напрямок Vector2D (x, y)
  • Внутрішня швидкість

І що я роблю під час оновлення, це те, що нова позиція обчислюється як:

position.x += direction.x * speed
position.y += direction.y * speed

Як це виправити? Я хочу, щоб він рухався з однаковою швидкістю під будь-яким кутом.


8
Нормалізуйте вектор напрямку перед використанням; проблема вирішена.
deceleratedcaviar

1
Довелося нормалізувати google :) знайшов цей корисний сайт fundza.com/vectors/normalize/index.html
Jason94

І якщо ви використовуєте введення користувача для керування цим об’єктом, пам’ятайте про блокування до 12,3,6,9 напрямків, як це пояснено для XNA devs: xona.com/2010/05/03.html . Це може бути те, що ви хочете (наприклад, у грі RPG) чи ні (наприклад, у грі в стилі Geometry Wars).
Xonatron

у старій грі Descent це була особливість .
Дж. Холмс

@ 32bitkid Так, дивіться також Doom straferunning
bobobobo

Відповіді:


55

Це можна пояснити теоремою Піфагора , яка є такою формулою:

a² + b² = c²

У вашому випадку, рухаючись праворуч, ви використовуєте (x: 1, y: 0), що дає нам

c² = 1 + 0 = 1
c = sqrt(1) = 1.00

Під час руху вгору і вправо ви використовуєте (x: 1, y: 1), що дає нам

c² = 1 + 1 = 2
c = sqrt(2) = 1.41

Отже, як бачите, довжина по діагоналі більша за довжину на осях кардинала.

Як уже згадували інші, вам слід просто нормалізувати вектор напрямку. Якщо ви використовуєте XNA, це робиться так:

var normalizedDirection = direction;
normalizedDirection.Normalize();
position += normalizedDirection * speed

Я даю вам +1 за допомогу в моєму питанні :)
Мартін.

12

Нормалізуйте вектор напрямку перед використанням.

Як пояснив MindWorX, це можна зрозуміти просто, якщо ви переживаєте за свої вектори напряму, можливо, доставляючи вам горе, переконайтеся, що вони є одиничними векторами (величина / довжина 1).

Length(Vector2(1, 1)) == 1.4142135623730951 // first hint of grief
Length(Vector2(1, 0)) == 1

Vector2(1, 1) * 2 == Vector2(2, 2)
Vector2(1, 0) * 2 == Vector2(2, 0)

Length(Vector2(2, 2)) = 2.8284271247461903 // second hint
Length(Vector2(2, 0)) = 2

Якщо нормалізується:

normal(Vector2(1, 1)) == Vector2(0.707107, 0.707107)
Length(Vector2(0.707107, 0.707107)) == 1 // perfect

14
Не корисна відповідь. Якби запитуючий знав, що означає "нормалізувати вектор вашого напрямку", він би не ставив питання.
Крістофер Джонсон

@KristopherJohnson було не ясно, що запитуючий не знав, як нормалізувати вектор. Хоча запитувач здається досить винахідливим, що це все одно не мало значення.
сповільненийкавіар

2
@KristopherJohnson: якщо запитуючий не знав, що означає "нормалізувати ваш вектор напряму", йому просто потрібно набрати це в Google, додати назву його мови та отримати код з поясненнями.
Лежать Раян

6

Як ви обчислюєте свій напрямок? Якщо 45 градусів (1,1), то це, звичайно, буде швидше, ніж 90 градусів(1,0) .

Я пропоную вам скористатися чимось подібним:

direction.x = Math.Cos(angleInRadians);
direction.y = Math.Sin(angleInRadians);

Щоб отримати кут в радіанах, вам доведеться помножити градуси на PI / 180або навіть краще, скористайтеся MathHelper. Напр.

angleInRadians = 45.0 * Math.PI / 180.0; // first method
angleInRadians = MathHelper.ToRadians(45f); //second method

6

Джейсон,

Замість того, щоб мати три атрибути об'єкта,

  • Точка (х, у) положення
  • Напрямок Vector2D (x, y)
  • Внутрішня швидкість

часто поєднувати напрямок і швидкість у векторі швидкості набагато простіше. Тоді у вас є лише два атрибути,

  • Точка (х, у) положення
  • Швидкість вектора2D (x, y)

Позиція оновлення

Коли вам потрібно оновити позицію об’єкта, це так само просто, як:

position.x += velocity.x * Δt;
position.y += velocity.y * Δt;

де Δt ваша дельта часу - або різниця в часі - або крок часу.

Оновлення положення та швидкості

Це також дуже легко керувати прискоренням (наприклад, від сили тяжіння). Якщо у вас вектор прискорення, ви можете оновити швидкість і положення разом так:

position.x += (velocity.x * Δt) + (0.5 * acceleration.x * Δt * Δt);
position.y += (velocity.y * Δt) + (0.5 * acceleration.y * Δt * Δt);

velocity.x += acceleration.x * Δt;
velocity.y += acceleration.y * Δt;

(Це в основному формула s = vt + ½at² з фізики 101.)

Застосування швидкості

Якщо ви хочете застосувати задану швидкість у деякому нормалізованому напрямку, ви можете встановити швидкість так:

velocity.x = normalizedDirection.x * speed;
velocity.y = normalizedDirection.y * speed;

Виведення швидкості

І якщо вам потрібно зробити зворотний - вивести швидкість і напрямок із заданого вектора швидкості - ви можете просто використовувати теорему Піфагора або .Length()метод:

speed = velocity.Length();

І як тільки швидкість відома, нормалізований напрямок можна обчислити, поділивши швидкість на швидкість (будьте обережні, щоб уникнути ділення на нуль):

if (speed != 0) {
    normalizedDirection.x = velocity.x / speed;
    normalizedDirection.y = velocity.y / speed;
} else {
    normalizedDirection.x = 0;
    normalizedDirection.y = 0;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.