Implementazione della trasmissione in un gioco di automobili


23

Sto cercando di creare un semplice gioco di auto con cambi di marcia manuali. Tuttavia, sto avendo un po 'di problemi nell'attuare i cambi di marcia.

Ecco il mio codice attuale per la "macchina":

int gear = 1; // Current gear, initially the 1st
int gearCount = 5; // Total no. of gears

int speed = 0; // Speed (km/h), initially 0
int[] maxSpeedsPerGear = new int[]
{
    40,  // First gear max. speed at max. RPM
    70,  // Second gear max. speed at max. RPM
    100, // and so on
    130,
    170
}

int rpm = 0; // Current engine RPM
int maxRPM = 8500; // Max. RPM

public void update(float dt)
{
    if(rpm < maxRPM)
    {
        rpm += 65 / gear; // The higher the gear, the slower the RPM increases
    }

    speed = (int) ((float)rpm / (float)maxRPM) * (float)maxSpeedsPerGear[gear - 1]);

    if(isKeyPressed(Keys.SPACE))
    {
        if(gear < gearCount)
        {
            gear++; // Change the gear
            rpm -= 3600; // Drop the RPM by a fixed amount
            if(rpm < 1500) rpm = 1500; // Just a silly "lower limit" for RPM
        }
    }
}

Tuttavia, questa implementazione non funziona davvero. La prima marcia funziona bene, ma i seguenti cambi di marcia causano la caduta di velocità. Aggiungendo alcuni messaggi di debug, ottengo questi valori di velocità quando cambio al limite RPM:

Speed at gear 1 before change: 40
Speed after changing from gear 1 to gear 2: 41

Speed at gear 2 before change: 70
Speed after changing from gear 2 to gear 3: 59

Speed at gear 3 before change: 100
Speed after changing from gear 3 to gear 4: 76

Speed at gear 4 before change: 130
Speed after changing from gear 4 to gear 5: 100

Come puoi vedere, la velocità dopo ogni modifica è più lenta prima della modifica. Come prenderesti in considerazione la velocità prima del cambio di marcia in modo che la velocità non diminuisca quando cambi marcia?


1
Mi viene in mente questo eccellente tutorial approfondito: Car Physics for Games . Circa un terzo dell'articolo inizia a parlare della trasmissione della forza del motore.
Eric,

Risposte:


17

Calcola il nuovo numero di giri in base alla nuova marcia e alla velocità attuale della vettura.

speed = (int) ((float)rpm / (float)maxRPM) * (float)maxSpeedsPerGear[gear - 1]);

quindi: anziché:

rpm -= 3600; // Drop the RPM by a fixed amount

uso:

rpm = max(maxRPM,(float)maxRPM * (float)speed / (float)maxSpeedsPerGear[gear - 1]);

La velocità sarà ora la stessa prima e dopo il cambio di marcia, e puoi accelerare / decelerare da lì.

modifica: aggiunto max(maxRPM, calc)come si desidera limitarlo. Come in un'auto, ciò dovrebbe comportare una perdita di velocità piuttosto improvvisa


29

questo perché non vi è inerzia nel calcolo della velocità. lo calcoli come una conseguenza assoluta del regime motore e della marcia. ma quando si calcolano i nuovi giri / min dopo il cambio marcia, lo si riduce empiricamente di passi fissi di 3600 giri / min.

Questo è il tuo errore il menu a discesa del numero di giri non è fissato tra le marce. è possibile risolverlo creando un secondo array che memorizza il numero esatto di giri al minuto tra ciascuna marcia.

Il secondo modo per risolverlo è utilizzare calcoli basati fisicamente. Stai facendo una simulazione, quindi puoi fare un'integrazione numerica. Usando il tempo,dt integrazione eulul o integrazione Verlet. Questo sembra complesso con i nomi e tutti, ma in realtà non lo è.

Fondamentalmente significherebbe che si crea una tabella di ricerca per la coppia del motore a determinati regimi. Quindi si terrà conto della resistenza dell'aria che aumenta con il quadrato della velocità. Quindi la simulazione calcolerebbe la velocità successiva invertendo la seconda legge di Newton f=m a.
Per trovare a=f/m, quindi l'integrazione di Eulero: speed=speed+a*dt. la mè di circa 1200 (peso tipica auto).fè la forza derivata dalla coppia del motore, ridotta nel cambio e quindi convertita in forza utilizzando la formula della leva considerando il raggio della ruota. (un prodotto incrociato vettoriale di solito, ma può essere semplificato dalla moltiplicazione della coppia per il raggio. perché netwton / metri moltiplicato metri = newton).

in questo modo, il numero di giri del motore viene calcolato all'indietro, in funzione della velocità lineare della vettura.


2
Non c'è exact number of RPM drop between each gear. È un rapporto, come sottolinea @Baldrickk. E mentre è una buona idea avere l'uscita della trasmissione sia sulla coppia che sulla velocità, una discussione sulla resistenza al vento e l'integrazione del verlet è un po 'al di fuori dell'ambito della domanda, no?
Giustino,

Sì. per un punto sulla risposta alla domanda, consiglierei la risposta di Baldrickk. L'ho votato.
v

5

Gli ingranaggi sono usati come meccanismo di riduzione.

Usando una trasmissione semplificata con solo due rapporti nel cambio, un ingranaggio in entrata (il motore) e un ingranaggio in uscita (uno dei rapporti del cambio) abbiamo due rapporti di riduzione differenti.

Pertanto, per un ingranaggio di ingresso con x denti e un ingranaggio di uscita di x / 2 denti, la velocità dell'ingranaggio di uscita è il doppio della velocità dell'ingranaggio di ingresso (un rapporto due a uno)

rpm2 = rpm1 * gearRatio

dove:

gearRatio = teeth1 / teeth2

Quindi, invece di limitare ogni marcia in base alla velocità codificata, possiamo limitarla in base al rapporto. È quindi possibile calcolare la velocità per una specifica coppia (rpm Engine, gear) e, quando si cambia marcia, calcolare la velocità del motore data la velocità nota e una nuova coppia.

Per semplificare, usando solo un motore collegato a due marce:

rpmEngine = 5000

gearRatio[1] = 2 #low gear:  one rotation of the engine results in 2 rotations output
gearRatio[2] = 3 #high gear: one rotation of the engine results in 3 rotations output

vehicleSpeed = rpmEngine * gearRatio[selectedGear]

così:

selectedGear = 1
vehicleSpeed = rpmEngine * gearRatio[selectedGear] #5000 * 2 = 10000 

quando si passa alla seconda marcia, 10000 è la velocità, quindi collegando la stessa formula, ora abbiamo:

vehicleSpeed = 10000 #computed above
selectedGear = 2

quindi il nostro nuovo numero di giri:

rpmEngine = vehicleSpeed / gearRatio[selectedGear] #10000 / 3 = 3333.3

Quel 10000 sarebbe quindi ulteriormente ridotto da un differenziale (che può essere estratto come solo un altro ingranaggio, cercalo se necessario, scusami, può postare due maglie) e quindi dalla dimensione della ruota per calcolare la velocità di avanzamento in chilometri o miglia all'ora .

Dovresti tenere conto del fatto che il cambio in una marcia più bassa aumenta i giri del motore, quindi un approccio semplice è quello di controllare i giri massimi e limitare i giri dopo il cambio al regime massimo, riducendo così la velocità del veicolo.

Quindi, fondamentalmente, ogni volta che si verifica un cambio marcia, si calcola il regime del motore dalla velocità del veicolo, si limita di maxRPM e quindi si torna alla "normale" dove si aggiornano i giri dall'input dell'utente e si calcola la velocità in base a quello.

Per una simulazione realistica, devi prendere in considerazione almeno la coppia del motore (v.oddou's response) e lo slittamento della frizione, che combinati avrebbero questi effetti: - quando si sposta verso l'alto, supponendo che il cambio sia abbastanza veloce da non far diminuire il regime del motore , la velocità verrà aumentata mentre i giri del motore vengono abbassati fino a quando non vengono bilanciati: quando si sposta verso il basso, la velocità del veicolo verrà ridotta fino a quando il motore non verrà portato al nuovo regime, ma ciò probabilmente va oltre l'implementazione "semplice".


4

Tieni presente che una trasmissione manuale innestata è un dispositivo a due vie. Il motore può accelerare il veicolo, così come il veicolo (più specificamente il suo momento) può accelerare il motore.

Questo era un vero problema nelle prime trasmissioni manuali. Il cambio di marcia improvvisamente spingerebbe il motore a un numero di giri più elevato, facendo scattare i cicli di accensione fuori sincrono e probabilmente facendo arrestare il motore. Ciò è stato compensato dalla guida esperta in cui il conducente ha dovuto far girare il motore alla velocità corretta prima di rilasciare la frizione per innestare la trasmissione.

Questo fino a quando non è stato sviluppato il sincronismo . È un meccanismo che impedisce il coinvolgimento della trasmissione fino a quando le velocità di ingresso e uscita sono sincronizzate.

Quindi, ciò che suggerisco è di emulare il sincronismo e di non innestare la trasmissione fino a quando il regime del motore e la velocità della vettura non corrispondono ai loro livelli attuali.


2

La risposta esistente sembra troppo complessa. Per un gioco, RPM è solo un indicatore sullo schermo. La velocità effettiva è la variabile reale. Il rapporto di trasmissione determina il modo in cui si converte la velocità del motore in RPM. Cambiare marcia cambia il rapporto, ma non la velocità. Ovviamente, l'RPM cambia anche come l'inverso del rapporto di trasmissione.

Il sorpasso (oltre il limite di 8500 giri / min) è qualcosa che implementeresti separatamente, ma è una cosa negativa nelle auto e puoi lasciarla essere una brutta cosa nel tuo gioco.


2
La risposta esistente è esattamente ciò che fanno la maggior parte dei giochi che ho visto, anche semplici giochi arcade, perché non è poi così complesso. Gli RPM sullo schermo potrebbero essere solo un numero, ma quell'approccio ti dà sia il numero (che puoi comunque modificare per gli indicatori visivi), sia il comportamento per abbinare quei numeri
Selali Adobor,

2

Come altri hanno già detto, la velocità del veicolo dovrebbe essere il valore reale e gli RPM dovrebbero essere derivati ​​da quello. Il cambio di marcia dovrebbe far diminuire la velocità di rotazione di un motore perché il rapporto di RPM per km / h cambierà "istantaneamente", ma la velocità del veicolo no.

Suggerirei, tuttavia, che la coppia del motore dovrebbe aumentare con il regime fino a un certo limite e oltrepassarlo. La velocità con cui un veicolo accelera dovrebbe essere proporzionale alla coppia divisa per il rapporto di trasmissione, meno la resistenza dell'aria che è proporzionale al quadrato della velocità. Se le marce consecutive hanno un rapporto 1: 41: 1, si verificherà uno spostamento ottimale per l'accelerazione nel punto in cui la coppia nella marcia inferiore è scesa a circa il 70% di quella che sarebbe nella marcia superiore successiva.


2

Basandosi su @ v.oddou, usando

max(maxRPM, calc)

indurrebbe l'RPMS a massimizzarsi all'istante quando si cambiano le marce, non consentendo alcuna transizione regolare da marcia a marcia. Il modo corretto sarebbe risolvere gli RPM usando la variabile speed come equazione.

speed = (int) ((float)rpm / (float)maxRPM) * (float)maxSpeedsPerGear[gear - 1]);

Risolvi per rpm

rpm = (maxRPM * speed) / maxSpeedsPerGear[gear - 1] ;

poiché la marcia è 1 in più rispetto a prima, gli RPM saranno inferiori.

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.