Estoy buscando crear movimientos realistas de automóviles usando vectores

12

He visto cómo hacer esto y encontré este http://www.helixsoft.nl/articles/circle/sincos.htm. Lo he intentado pero la mayoría de las funciones que se mostraron no funcionaron. porque no existieron He visto las funciones cos y sin, pero no entiendo cómo usarlas o cómo hacer que el movimiento del automóvil funcione correctamente usando vectores. No tengo código porque no estoy seguro de qué hacer, lo siento.

Cualquier ayuda es apreciada.

EDITAR:

Tengo restricciones de que debo usar el motor TL para mi juego, no tengo permitido agregar ningún tipo de motor de física. Debe programarse en c ++. Aquí hay una muestra de lo que obtuve al intentar seguir lo que se hizo en el enlace que proporcioné.

if(myEngine->KeyHeld(Key_W))
    {
        length += carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_S))
    {
        length -= carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_A))
    {
        angle -= carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_D))
    {
        angle += carSpeedIncrement;
    }

    carVolocityX = cos(angle);
    carVolocityZ = cos(angle);

    car->MoveX(carVolocityX * frameTime);
    car->MoveZ(carVolocityZ * frameTime);
Bobthemac
fuente
Visite este sitio para ver los comportamientos de dirección: red3d.com/cwr/steer
MichaelHouse
Necesitas definir "movimiento realista del automóvil"
Maik Semder
1
Supongo que su ángulo proviene del volante, tal vez. La longitud debe ser la magnitud de tu velocidad. Así que el último fragmento de código podría ser algo en la línea de: carVecloityX = length* cos(angle);, carVelocityZ = length *sin(angle);, aparte de eso, por favor díganos cuál es su entrada y cómo el coche debe comportarse. En este momento, debe girar en el plano de tierra, pero de nuevo, esto no es del todo general. Ahí acabas de hacernos un paso crudo de integración de Euler ...
teodron

Respuestas:

23

No es tan difícil crear un movimiento de automóvil bastante bueno (pero esta publicación será bastante larga). Tendrá que "simular" un par de fuerzas básicas para que el automóvil se mueva físicamente.

(Todos los ejemplos de código son pseudocódigo).

Aceleración

Primero, obviamente necesitarás aceleración. Algo tan simple como lo haría la siguiente línea:

acceleration_vector = forward_vector * acceleration_input * acceleration_factor
  • forward_vector - Un vector que apunta en la misma dirección que el automóvil.
  • acceleration_input - La entrada debe estar en el intervalo [-1, 1].
  • acceleration_factor - El valor de la aceleración (píxeles / segundo ^ 2, o cualesquiera que sean sus unidades).

Direccion

La dirección también es bastante simple. En principio, lo que hará es rotar el vector delantero del automóvil para que apunte en otra dirección.

steer_angle = steer_input * steer_factor
new_forward_vector = rotate_around_axis(forward_vector, up_vector, steer_angle)

Sin embargo, puede encontrar una complicación aquí. Si su entrada es a través de un teclado, su valor será -1 o 1, lo que significa que su automóvil giraría instantáneamente. Puede solucionar esto usando una interpolación lineal muy simple (lerping):

 amount = time_since_last_frame * steer_lerp_factor
 forward_vector = lerp(forward_vector, new_forward_vector, amount)

La cantidad debe depender del tiempo, de modo que su movimiento no dependa de su velocidad de fotogramas. La cantidad debe estar entre [0, 1] y cuanto menor sea, más suave será la transición entre los vectores antiguos y nuevos.

(En este punto, encontrará que el automóvil girará incluso si está parado. Para evitarlo, multiplique steer_anglepor current_speed / max_speed, donde max_speedes una constante definida por usted).

Moviente

Ahora aplicaremos la aceleración y moveremos el automóvil un cierto número de píxeles en función de su velocidad, aceleración y dirección. También queremos limitar la velocidad del automóvil para que no termine moviéndose infinitamente rápido.

current_speed = velocity_vector.norm()
if (current_speed < max_speed)
{
    velocity_vector += acceleration_vector * time_since_last_frame
}

position_vector += velocity_vector * time_since_last_frame

Tu auto ahora se está deslizando

Si estoy en lo cierto, su auto ahora debería parecer estar deslizándose cada vez que gira como si estuviera en hielo. Esto se debe a que no hay fricción. En un automóvil real hay una alta fricción lateral (debido a que las ruedas no pueden girar hacia los lados: P).

Necesitará reducir la velocidad lateral. Al no reducirlo por completo, también puede hacer que el automóvil parezca estar a la deriva.

 lateral_velocity = right_vector * dot(velocity_vector, right_vector)
 lateral_friction = -lateral_velocity * lateral_friction_factor 

Como estamos hablando de fricción, es posible que también desee tener una fuerza (de fricción) que reduzca su velocidad de manera que cuando pare de acelerar, su automóvil finalmente se detenga.

 backwards_friction = -velocity_vector * backwards_friction_factor

Su código para mover el automóvil ahora debería verse así:

// Friction should be calculated before you apply the acceleration
lateral_velocity = right_vector * dot(velocity_vector, right_vector)
lateral_friction = -lateral_velocity * lateral_friction_factor
backwards_friction = -velocity_vector * backwards_friction_factor
velocity_vector += (backwards_friction + lateral_friction) * time_since_last_frame


current_speed = velocity_vector.norm()
if (current_speed < max_speed)
{ 
    velocity_vector += acceleration_vector * time_since_last_frame
}

position_vector += velocity_vector * time_since_last_frame

Notas de cierre

Mencioné cómo debe aplicar lerping a la dirección; Creo que es posible que tenga que hacer lo mismo para la aceleración y posiblemente también para el ángulo de dirección (tendrá que almacenar sus valores del cuadro anterior y aprender de eso). Además, todos los vectores relativos al automóvil (adelante, derecha, arriba) deben ser de longitud 1.

Además, la fricción es un poco más complicada de lo que mostré aquí. Siempre debe asegurarse de que su longitud nunca sea mayor que la de la aceleración necesaria para que el automóvil se detenga (de lo contrario, la fricción haría que el automóvil se mueva en la dirección opuesta). Entonces deberías tener algo como:

dt = time_since_last_frame
backwards_friction.resize(min(backwards_friction.norm(), velocity_vector.norm() / dt))
lateral_friction.resize(min(lateral_friction.norm(), lateral_velocity.norm() / dt))
Paul Manta
fuente
Wow, esta es una gran respuesta!
ezolotko
0

A juzgar por su pregunta, voy a suponer que usted es relativamente nuevo en la programación (lo cual está bien, por cierto). Sugeriría usar los marcos existentes, ya que la simulación realista de automóviles es uno de los aspectos más difíciles de la física.

No mencionó las restricciones 2D / 3D, así que voy a seguir adelante y sugerirle que descargue Havok SDK (gratuito para uso no comercial) y obtenga una demostración simple en funcionamiento (en realidad tienen demostraciones que se ejecutan fuera de la caja [get compilado en su sistema, todo el código está ahí], no tiene que hacer nada para que se compile ... solo abra el proyecto y presione compilar).

Una vez que tenga alguna idea sobre los aspectos detrás de escena de la física del automóvil (aunque no verá la implementación real de la física, eso está oculto, podrá ver las interfaces), creo que estará en una mejor posición para hacerlo bien cuando empiezas por tu cuenta.

También hice una pregunta similar no hace mucho tiempo. Los enlaces allí también pueden ayudar. Y aquí hay otro enlace .


Después de mirar su edición, parece que está buscando simplemente cambiar la velocidad del automóvil dependiendo de los ángulos calculados (eso no es realista por cierto, por lo que debe cambiar la pregunta original para reflejar eso). Si los ángulos son parte de la pregunta (que no puedes cambiar) y tienes que usar los ángulos para calcular la nueva velocidad, entonces ve con lo que @teodron puso en los comentarios.

Otra forma es usar solo vectores. Existen múltiples enfoques utilizando vectores, voy a presentar uno.

Una velocidad es dirección * magnitud (donde la magnitud es velocidad y la dirección es un vector normalizado). Calcule la velocidad y dirección actuales del automóvil. Tome la dirección y agregue un vector (llamémoslo D') que sea perpendicular a él. Esto cambiará la velocidad del automóvil. No hay ángulos perder el tiempo con (aunque se puede usar ángulos para determinar la longitud del vector perpendicular que puede ser que a su vez el factor [ver más adelante])

Cómo calcularD' : Para encontrar el vector perpendicular, tome la dirección de la velocidad original, crúcela con el vector de dirección que viene hacia la pantalla donde el orden en que cruza los vectores determina la dirección del vector perpendicular. Luego multiplique este factor perpedicular con algún factor de giro que determina qué tan rápido gira el automóvil.

Samaursa
fuente
Lo haría, pero no se me permite usar un motor de física, el juego es 3D y todo lo que necesito cambiar son los vectores X y Z, solo necesito resolver cuáles son.
bobthemac
@bobthemac: ¿Es esta una pregunta de tarea? En caso afirmativo, edite su pregunta para señalar las restricciones que tiene y quizás publique algún código relevante para que tengamos algo en qué construir. Por cierto, el último enlace puede ser lo que estás buscando en términos de comprensión de la funcionalidad.
Samaursa
He agregado la información que solicitó y miré los enlaces proporcionados, pero aún no la entiendo.
bobthemac 05 de
@bobthemac: Vea mi edición
Samaursa