Movimiento curvo entre dos puntos


15

¿Cuál es una buena técnica para permitir que un objeto se mueva entre puntos en un movimiento curvo agradable?

La posición final también podría estar en movimiento, como la trayectoria de un misil de referencia.

Respuestas:


11

Asumiendo que quiere que esto sea una cosa cuadro por cuadro (donde el objetivo podría incluso estar moviéndose), y no una trayectoria calculada previamente, esto es realmente increíblemente simple:

En cada cuadro, compare el vector de velocidad del misil con el vector ( objetivo de posición - misil de posición ) ; es decir, el vector que apunta desde el misil al objetivo. Cada cuadro, si los dos vectores no tienen la misma dirección, gire el vector de velocidad un poco hacia el otro vector, de modo que cada cuadro del misil se acerque un poco más a su objetivo.

Puede determinar si gira en sentido horario o antihorario observando el signo del producto cruzado entre los dos vectores.


[Editar] Código XNA-ish (no tengo XNA para probar esto):

//Once a frame:

//Get vector spanning from missile to target
Vector2 vectorToTarget = target.Position - missile.Position;

//Convert to Vector3 to do cross-product
Vector3 vectorToTarget3 = new Vector3(vectorToTarget, 0);
Vector3 missileVelocity3 = new Vector3(missile.Velocity, 0);

//Rotate clockwise/counter-clockwise is determined by sign of cross-product
int crossProductSign = Vector3.Cross(missileVelocity3, vectorToTarget3).Z;

//Positive cross-product means rotate counter-clockwise, negative is clockwise
double rotationAngle = 0;
if(crossProductSign > 0)
    rotationAngle = -0.05;
else if(crossProductSign < 0)
    rotationAngle = 0.05;

//I'm not sure how to do rotation in XNA, but the internets tell me it's something like this:
missile.velocity = Vector2.Transform(missile.velocity, Matrix.CreateRotationZ(rotationAngle))

Tenga en cuenta que, dado que rotationAnglesolo tiene tres valores posibles, todos los valores posibles de Matrix.CreateRotationZ(rotationAngle)se pueden almacenar en caché para que no tenga que llamarlo a cada cuadro.


¿Podría proporcionar algún pseudocódigo ya que soy nuevo en todo esto? Actualmente solo estoy trabajando en la 2da dimensión para eliminar algunas complicaciones.
anonymouse

@anonymouse: claro, prueba esto
BlueRaja - Danny Pflughoeft

15

Hay dos técnicas posibles:

La primera técnica es hacer una simulación basada en cuadros . Esto es bueno si estás haciendo algo como un misil autodirigido en el juego, que no tiene que golpear tu objetivo exactamente.

En este caso, desea rastrear la posición y la velocidad del objeto. Cada cuadro mira la dirección hacia el objetivo y la dirección del movimiento actual, y ajusta la velocidad adecuadamente.

Si ajusta la velocidad al instante, su misil siempre alcanzará el objetivo. Pero si ajusta la velocidad en una pequeña cantidad cada cuadro, su misil se curvará hacia el objetivo, y si se curva lo suficientemente lento, el objetivo podría esquivarlo.

La segunda técnica es usar un método paramétrico . Esto es útil para animar cosas donde quieres alcanzar tu objetivo de forma precisa y previsible.En este caso, generalmente toma el "tiempo" como parámetro y lo pone en una función de algún tipo.

Un conjunto de funciones particularmente útiles son las ecuaciones de movimiento que aprendiste en la física de secundaria. Al aplicarlos a ambos ejes, puede obtener trayectorias balísticas. Con un poco de matemática, puede determinar los parámetros iniciales para alcanzar un objetivo, incluso uno móvil, si se mueve de manera predecible.

XNA también proporciona una serie de funciones de interpolación y movimiento curvo. Eche un vistazo a la documentación por Vector2 y paraMathHelper . Estos proporcionan algunas funciones de interpolación que puede usar e incluso combinar para hacer cosas interesantes. Por ejemplo, disparando un misil: Lerp(interpolar linealmente) la posición de su misil desde su punto inicial a una posición objetivo, y también elevar esa posición objetivo desde algún objetivo inicial a la posición real (cambiante) del objeto objetivo. Esto le dará un buen efecto de "bloqueo".

(También hay algunas funciones para las curvas que producen, por ejemplo: CatmulRom, Hermite. Estos son probablemente más difícil de utilizar con éxito con un objetivo en movimiento, sin embargo.)

Si observa el "alivio" (en el contexto de la animación), puede obtener algunas funciones de interpolación más interesantes que pueden proporcionarle efectos interesantes como la aceleración.

Ahora, puedes decir que esta técnica da algunos resultados extraños a medida que tu objetivo se mueve. Sin embargo, en la práctica, siempre que su proyectil se mueva más rápido que su objetivo, generalmente se ve bien. Si es un problema, probablemente debería estar utilizando una técnica basada en marcos de todos modos.


3

Es posible que desee buscar ondas sinusoidales o posiblemente curvas de Bezier . No sé si el enfoque de onda sinusoidal es normal, pero no puedo ver por qué sería tan pobre.


El uso de curvas Bezier con B-Splines permite una representación bastante precisa de cualquier curva. Si necesita precisión, las estrías del ermitaño cúbico son un poco más precisas. Tenga en cuenta que, a veces, la inexactitud proporciona un agradable toque de organicidad.
doppelgreener

+1 para las curvas de Bezier. Para el uso descrito, es probablemente el más fácil y el más controlable.
ggambett

1

Puede echar un vistazo a Comportamientos de dirección, según lo definido por Craig Reynolds: http://red3d.com/cwr/steer/

Esto se usa a menudo en la IA para que los NPC se muevan hacia su objetivo.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.