Sto cercando di creare movimenti di auto realistici usando i vettori


12

Ho cercato con impazienza come farlo e ho trovato questo http://www.helixsoft.nl/articles/circle/sincos.htm Ci ho provato, ma la maggior parte delle funzioni mostrate non funzionavano, ho appena ricevuto degli errori perché non esistevano. Ho osservato le funzioni cos e sin ma non capisco come usarle o come far funzionare correttamente il movimento della macchina usando i vettori. Non ho un codice perché non sono sicuro di cosa scusarmi.

Qualsiasi aiuto è apprezzato.

MODIFICARE:

Ho delle restrizioni che devo usare il motore TL per il mio gioco, non mi è permesso aggiungere alcun tipo di motore fisico. Deve essere programmato in c ++. Ecco un esempio di ciò che ho ottenuto provando a seguire ciò che è stato fatto nel link che ho fornito.

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);


Devi definire un "movimento realistico della macchina"
Maik Semder,

1
Presumo che la tua angolazione provenga dal volante, forse. La lunghezza dovrebbe essere l'entità della tua velocità. Così l'ultimo frammento di codice potrebbe essere qualcosa sulla falsariga di: carVecloityX = length* cos(angle);, carVelocityZ = length *sin(angle);, a parte questo, si prega di dire che cosa il vostro contributo è e come la vettura dovrebbe comportarsi. In questo momento, dovrebbe virare sul piano terra, ma ancora una volta, questo non è affatto generale. Lì ci hai appena fatto un passo di integrazione di Eulero grezzo ...
Teodron,

Risposte:


23

Creare un movimento della macchina abbastanza buono non è difficile (ma questo post sarà piuttosto lungo). Dovrai "simulare" un paio di forze di base per rendere la macchina in movimento fisicamente plausibile.

(Tutti gli esempi di codice sono pseudocodici.)

Accelerazione

Innanzitutto, avrai ovviamente bisogno di accelerazione. Qualcosa di semplice come farebbe la seguente riga:

acceleration_vector = forward_vector * acceleration_input * acceleration_factor
  • forward_vector - Un vettore che punta nella stessa direzione della macchina.
  • acceleration_input - L'ingresso dovrebbe essere nell'intervallo [-1, 1].
  • acceleration_factor - Il valore dell'accelerazione (pixel / secondo ^ 2 o qualunque sia la tua unità).

Timone

Lo sterzo è anche abbastanza semplice. In linea di principio, ciò che farai è ruotare il vettore anteriore dell'auto in modo che punti in un'altra direzione.

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

Tuttavia, potresti riscontrare una complicazione qui. Se il tuo input è tramite una tastiera, il suo valore sarà -1 o 1, il che significa che la tua auto girerebbe istantaneamente. Puoi risolvere questo problema usando un'interpolazione lineare molto semplice (lerping):

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

L'importo dovrebbe dipendere dal tempo in modo tale che il movimento non dipenda dalla frequenza dei fotogrammi. L'importo dovrebbe essere tra [0, 1] e più piccolo è, più agevole sarà la transizione tra il vecchio e il nuovo vettore.

(A questo punto scoprirai che la macchina sterzerà anche se è ferma. Per evitare ciò, moltiplica steer_angleper current_speed / max_speeddove max_speedè definita una costante da te.)

In movimento

Ora applicheremo l'accelerazione e sposteremo la macchina di un certo numero di pixel in base alla sua velocità, accelerazione e sterzo. Vorremmo anche limitare la velocità dell'auto in modo che non finisca per muoversi all'infinito.

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

La tua auto ora sta scivolando

Se ho ragione, ora la tua auto dovrebbe sembrare scivolare ogni volta che giri come se fosse sul ghiaccio. Questo perché non c'è attrito. Su un'auto reale c'è un alto attrito laterale (a causa delle ruote che non sono in grado di ruotare lateralmente: P).

Dovrai ridurre la velocità laterale. Non riducendolo completamente, puoi anche far sembrare la macchina alla deriva.

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

Dato che stiamo parlando di attrito, potresti anche voler avere una forza (di attrito) che riduca la tua velocità in modo tale che quando smetti di accelerare, la tua auto alla fine si fermerà.

 backwards_friction = -velocity_vector * backwards_friction_factor

Il tuo codice per spostare la macchina ora dovrebbe apparire così:

// 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

Note di chiusura

Ho menzionato come applicare lerping allo sterzo; Penso che potresti dover fare la stessa cosa per l'accelerazione e forse anche per l'angolo di sterzata (dovrai memorizzare i loro valori dal fotogramma precedente e derivarne da quello). Anche tutti i vettori relativi all'auto (avanti, destra, su) devono essere di lunghezza 1.

Inoltre, l'attrito è un po 'più complicato di quello che ho mostrato qui. Dovresti sempre assicurarti che la sua lunghezza non sia mai maggiore di quella dell'accelerazione necessaria per fermare la macchina (altrimenti l'attrito farebbe muovere la macchina nella direzione opposta). Quindi dovresti avere qualcosa del tipo:

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))

Caspita, questa è un'ottima risposta!
ezolotko,

0

A giudicare dalla tua domanda, suppongo che tu sia relativamente nuovo nella programmazione (il che è ok-a proposito!). Suggerirei di utilizzare i framework esistenti in quanto la simulazione realistica delle auto è uno degli aspetti più difficili della fisica per ottenere il risultato giusto.

Non hai menzionato le restrizioni 2D / 3D, quindi vado avanti e ti suggerisco di scaricare Havok SDK (gratuito per uso non commerciale) e ottenere una semplice demo attiva e funzionante (in realtà hanno demo che finiscono fuori dalla scatola [get compilato sul tuo sistema, tutto il codice è lì], non devi fare nulla per farlo compilare ... basta aprire il progetto e premere build).

Una volta che hai un'idea degli aspetti dietro le quinte della fisica dell'auto (anche se non vedrai l'implementazione effettiva della fisica, che è nascosta, vedrai le interfacce), credo che sarai in una posizione migliore per farlo bene quando inizi da solo.

Ho anche fatto una domanda simile non molto tempo fa. Anche i collegamenti possono aiutare. Ed ecco un altro link .


Dopo aver visto la tua modifica, sembra che tu stia cercando di cambiare semplicemente la velocità della macchina in base agli angoli calcolati (che non è realistico tra l'altro, quindi dovresti cambiare la domanda originale per riflettere quella). Se gli angoli fanno parte della domanda (che non puoi cambiare) e devi usare gli angoli per calcolare la nuova velocità, segui ciò che @teodron ha inserito nei commenti.

Un altro modo è usare solo i vettori. Ci sono molti approcci che usano i vettori, ne presenterò uno.

Una velocità è direzione * magnitudine (dove la grandezza è velocità e la direzione è un vettore normalizzato). Calcola la velocità e la direzione attuali dell'auto. Prendi la direzione e aggiungi un vettore (chiamiamolo D') ad esso che è perpendicolare ad esso. Questo cambierà la velocità della macchina. Nessun angolo con cui scherzare (anche se puoi usare gli angoli per determinare la lunghezza del vettore perpendicolare che può essere il fattore di rotazione [vedi sotto])

Come calcolareD' : Per trovare il vettore perpendicolare, prendere la direzione della velocità originale, attraversarlo con il vettore di direzione che arriva verso lo schermo in cui l'ordine in cui si attraversano i vettori determina la direzione del vettore perpendicolare. Quindi moltiplica questo fattore perpendicolare con un fattore di virata che determina la velocità con cui l'auto gira.


Vorrei ma non mi è permesso usare un motore fisico, il gioco è 3D e tutto ciò che devo cambiare sono i vettori X e Z che ho solo bisogno di capire quali sono.
bobthemac,

@bobthemac: è una domanda da fare? Se sì, modifica la tua domanda per evidenziare le restrizioni che hai e magari pubblica un codice pertinente in modo da avere qualcosa su cui costruire. A proposito, l'ultimo link potrebbe essere quello che stai cercando in termini di comprensione della funzionalità.
Samaursa,

Ho aggiunto le informazioni richieste e ho consultato i collegamenti forniti, ma ancora non li capisco.
bobthemac,

@bobthemac: guarda la mia modifica
Samaursa,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.