¿Por qué mi objeto se mueve más rápido a 45 grados que a 90 grados?

32

Tengo objetos en mi juego que se mueven más rápido a 45 grados que a 90 grados.

Cada objeto tiene

  • Posición del punto (x, y)
  • Dirección Vector2D (x, y)
  • Int velocidad

Y lo que hago durante una actualización es que la nueva posición se calcula como:

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

¿Cómo corrijo esto? Quiero que se mueva con la misma velocidad en cualquier ángulo.

Jason94
fuente
8
Normalice su vector de dirección antes de usarlo; problema resuelto.
deceleratedcaviar
1
Tuve que google normalizar :) encontré este sitio útil fundza.com/vectors/normalize/index.html
Jason94
Y si está utilizando la entrada del usuario para controlar este objeto, tenga en cuenta que debe bloquear las instrucciones 12,3,6,9 como se explica aquí para los desarrolladores de XNA: xona.com/2010/05/03.html . Puede ser algo que desee (como en un juego de rol) o no (como en un juego de estilo Geometry Wars).
Xonatron
en el antiguo juego Descent , esta era una característica .
J. Holmes
@ 32bitkid Sí, ver también Doom straferunning
bobobobo

Respuestas:

55

Esto se puede explicar con el Teorema de Pitágoras , que es la siguiente fórmula:

a² + b² = c²

En su caso, cuando se mueve hacia la derecha, está usando (x: 1, y: 0) que nos da

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

Cuando se mueve hacia arriba y hacia la derecha, está usando (x: 1, y: 1) que nos da

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

Como puede ver, la longitud en diagonal es más larga que la longitud en los ejes cardinales.

Como otros han mencionado, simplemente debe normalizar su vector de dirección. Si usa XNA, se hace así:

var normalizedDirection = direction;
normalizedDirection.Normalize();
position += normalizedDirection * speed
William Mariager
fuente
Te doy +1 por tu ayuda en mi pregunta :)
Martin.
12

Normalice su vector de dirección antes de usar.

Como lo explicó MindWorX, esto puede entenderse simplemente, si te preocupa que tus vectores de dirección puedan darte pena, asegúrate de que sean vectores unitarios (magnitud / longitud de 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

Si está normalizado:

normal(Vector2(1, 1)) == Vector2(0.707107, 0.707107)
Length(Vector2(0.707107, 0.707107)) == 1 // perfect
caviar desacelerado
fuente
14
No es una respuesta útil. Si el interlocutor supiera lo que significa "normalizar su vector de dirección", no habría hecho la pregunta.
Kristopher Johnson
@KristopherJohnson no estaba claro si el interlocutor no sabía cómo normalizar un vector. Aunque el interrogador parece lo suficientemente ingenioso como para no importar de todos modos.
Caviar desacelerado
2
@KristopherJohnson: si el interlocutor no sabía lo que significa "normalizar su vector de dirección", solo tiene que escribir eso en Google, agregar el nombre de su idioma y obtener un código con explicaciones.
Lie Ryan
6

¿Cómo estás calculando tu dirección? Si 45 grados es (1,1), entonces ciertamente será más rápido que 90 grados (1,0).

Te sugiero que uses algo como esto:

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

Para obtener el ángulo en radianes, tendrás que multiplicar tus grados con PI / 180o incluso mejor, usar MathHelper. P.ej.

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

Jason

En lugar de tener tres atributos de objeto,

  • Posición del punto (x, y)
  • Dirección Vector2D (x, y)
  • Int velocidad

A menudo es mucho más fácil combinar la dirección y la velocidad en un vector de velocidad. Entonces solo tienes dos atributos,

  • Posición del punto (x, y)
  • Vector2D (x, y) velocidad

Puesto de actualización

Cuando necesita actualizar la posición del objeto, es tan simple como:

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

¿Dónde Δtestá su delta de tiempo, o diferencia de tiempo, o paso de tiempo?

Actualización de posición y velocidad

También es muy fácil manejar la aceleración (como la gravedad). Si tiene un vector de aceleración, puede actualizar la velocidad y la posición juntas de la siguiente manera:

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;

(Esta es básicamente la fórmula s = vt + ½at² de Física 101.)

Aplicando una velocidad

Si desea aplicar una velocidad dada en una dirección normalizada, puede establecer la velocidad de esta manera:

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

Derivando una velocidad

Y si necesita hacer lo contrario, derivando la velocidad y la dirección de un vector de velocidad dado, simplemente puede usar el teorema de Pitágoras o el .Length()método:

speed = velocity.Length();

Y una vez que se conoce la velocidad, la dirección normalizada se puede calcular dividiendo la velocidad por la velocidad (teniendo cuidado de evitar dividir por cero):

if (speed != 0) {
    normalizedDirection.x = velocity.x / speed;
    normalizedDirection.y = velocity.y / speed;
} else {
    normalizedDirection.x = 0;
    normalizedDirection.y = 0;
}
Todd Lehman
fuente