Dlaczego mój obiekt porusza się szybciej o 45 stopni niż o 90 stopni?

32

W mojej grze mam obiekty, które poruszają się szybciej o 45 stopni niż o 90 stopni.

Każdy obiekt ma

  • Pozycja punktu (x, y)
  • Kierunek Vector2D (x, y)
  • Int prędkość

A podczas aktualizacji robię to, że nowa pozycja jest obliczana jako:

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

Jak to naprawić? Chcę, aby poruszał się z tą samą prędkością pod dowolnym kątem.

Jason94
źródło
8
Przed użyciem znormalizuj wektor kierunku; problem rozwiązany.
spowolniłaviar
1
Musiałem google normalizować :) znalazłem tę przydatną stronę fundza.com/vectors/normalize/index.html
Jason94
A jeśli używasz danych wejściowych użytkownika do kontrolowania tego obiektu, pamiętaj o blokowaniu w 12,3,6,9 kierunkach, jak wyjaśniono tutaj dla XNA devs : xona.com/2010/05/03.html . Może to być coś, czego chcesz (na przykład w grze RPG) lub nie (na przykład w grze w stylu Geometry Wars).
Xonatron,
w starej grze Descent była to funkcja .
J. Holmes,
@ 32bitkid Tak, zobacz także Doom straferunning
bobobobo

Odpowiedzi:

55

Można to wyjaśnić twierdzeniem Pitagorasa , który jest następującą formułą:

a² + b² = c²

W twoim przypadku, kiedy poruszasz się w prawo, używasz (x: 1, y: 0), co daje nam

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

Poruszając się w górę i w prawo używasz (x: 1, y: 1), co daje nam

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

Jak widać, długość po przekątnej jest dłuższa niż długość na osiach kardynalnych.

Jak wspomnieli inni, należy po prostu znormalizować wektor kierunku. Jeśli używasz XNA, robi się to tak:

var normalizedDirection = direction;
normalizedDirection.Normalize();
position += normalizedDirection * speed
William Mariager
źródło
Daję ci +1 za pomoc w moim pytaniu :)
Martin.
12

Przed użyciem należy znormalizować wektor kierunku.

Jak wyjaśniono w MindWorX, można to po prostu zrozumieć, jeśli martwiąc się o swoje wektory kierunkowe, które mogą wywoływać u Ciebie żal, upewnij się, że są to wektory jednostkowe (wielkość / długość 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

Jeśli znormalizowany:

normal(Vector2(1, 1)) == Vector2(0.707107, 0.707107)
Length(Vector2(0.707107, 0.707107)) == 1 // perfect
zwalniał
źródło
14
Nie pomocna odpowiedź. Gdyby pytający wiedział, co oznacza „normalizacja wektora kierunku”, nie zadałby tego pytania.
Kristopher Johnson
@KristopherJohnson nie było jasne, że pytający nie wiedział, jak znormalizować wektor. Chociaż pytający wydaje się na tyle zaradny, że i tak nie ma to znaczenia.
spowolniłaviar
2
@KristopherJohnson: jeśli pytający nie wiedział, co oznacza „normalizacja wektora kierunku”, wystarczy, że wpisze to w google, doda nazwę swojego języka i otrzyma kod z objaśnieniami.
Lie Ryan,
6

Jak obliczasz swój kierunek? Jeśli 45 stopni to (1,1), to na pewno będzie szybciej niż 90 stopni (1,0).

Sugeruję użycie czegoś takiego:

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

Aby uzyskać kąt w radianach, musisz pomnożyć swoje stopnie, PI / 180a nawet lepiej, użyć MathHelper. Na przykład.

angleInRadians = 45.0 * Math.PI / 180.0; // first method
angleInRadians = MathHelper.ToRadians(45f); //second method
grzmot
źródło
6

Jason,

Zamiast mieć trzy atrybuty obiektu,

  • Pozycja punktu (x, y)
  • Kierunek Vector2D (x, y)
  • Int prędkość

często o wiele łatwiej jest połączyć kierunek i prędkość w wektor prędkości. Masz tylko dwa atrybuty,

  • Pozycja punktu (x, y)
  • Prędkość Vector2D (x, y)

Aktualizacja pozycji

Gdy musisz zaktualizować pozycję obiektu, jest to tak proste, jak:

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

gdzie Δtjest twoja delta czasu - lub różnica czasu - lub krok czasu.

Aktualizacja pozycji i prędkości

W ten sposób jest również bardzo łatwo poradzić sobie z przyspieszeniem (np. Grawitacyjnym). Jeśli masz wektor przyspieszenia, możesz zaktualizować prędkość i położenie razem w następujący sposób:

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;

(Jest to w zasadzie wzór s = vt + ½at² z fizyki 101.)

Stosowanie prędkości

Jeśli chcesz zastosować określoną prędkość w jakimś znormalizowanym kierunku, możesz ustawić prędkość w następujący sposób:

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

Wyprowadzanie prędkości

A jeśli potrzebujesz zrobić odwrotność - wyprowadzając prędkość i kierunek z danego wektora prędkości - możesz po prostu użyć twierdzenia Pitagorasa lub .Length()metody:

speed = velocity.Length();

A gdy prędkość jest znana, znormalizowany kierunek można obliczyć, dzieląc prędkość przez prędkość (uważając, aby nie podzielić przez zero):

if (speed != 0) {
    normalizedDirection.x = velocity.x / speed;
    normalizedDirection.y = velocity.y / speed;
} else {
    normalizedDirection.x = 0;
    normalizedDirection.y = 0;
}
Todd Lehman
źródło