Implementasi transmisi dalam permainan mobil

23

Saya mencoba membuat game mobil sederhana dengan perubahan gigi manual. Namun, saya mengalami sedikit kesulitan menerapkan perubahan gigi.

Ini kode saya saat ini untuk "mobil":

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

Namun, implementasi ini tidak benar-benar berfungsi. Roda gigi pertama berfungsi dengan baik, tetapi perubahan gigi berikut menyebabkan penurunan kecepatan. Dengan menambahkan beberapa pesan debug, saya mendapatkan nilai kecepatan ini ketika mengubah pada batas 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

Seperti yang Anda lihat, kecepatan setelah setiap perubahan lebih lambat sebelum perubahan. Bagaimana Anda mempertimbangkan kecepatan sebelum perpindahan gigi agar kecepatan tidak turun saat mengganti gigi?

manabreak
sumber
1
Saya teringat tutorial mendalam yang sangat baik ini: Fisika Mobil untuk Game . Sekitar sepertiga dalam artikel mulai berbicara tentang transmisi tenaga mesin.
Eric

Jawaban:

17

Hitung RPM baru berdasarkan gigi baru dan kecepatan mobil saat ini.

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

jadi: bukannya:

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

menggunakan:

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

Kecepatan sekarang akan sama sebelum dan sesudah perubahan gigi, dan Anda dapat mempercepat / mengurangi kecepatan dari sana.

sunting: ditambahkan max(maxRPM, calc)saat Anda ingin membatasi. Seperti di dalam mobil, ini seharusnya menghasilkan kehilangan kecepatan yang cukup mendadak

Baldrickk
sumber
29

ini karena tidak ada inersia dalam perhitungan kecepatan Anda. Anda hanya menghitungnya sebagai konsekuensi absolut dari putaran dan engine engine. tetapi ketika Anda menghitung rpm baru setelah perpindahan gigi ke atas, Anda menurunkannya secara empiris dengan memperbaiki putaran 3600 rpm.

Ini salahmu. dropdown rpm tidak diperbaiki di antara gigi. Anda dapat memperbaikinya dengan membuat larik kedua yang menyimpan jumlah drop rpm yang tepat di antara setiap gigi.

Cara kedua Anda dapat memperbaikinya, adalah dengan menggunakan perhitungan berbasis fisik. Anda sedang melakukan simulasi, sehingga Anda dapat melakukan integrasi numerik. Menggunakan waktu,, dtdan integrasi euler, atau integrasi Verlet. Ini terdengar rumit dengan nama dan semuanya tetapi sebenarnya tidak.

Pada dasarnya itu akan berarti bahwa Anda membuat tabel pencarian untuk torsi mesin pada rpms yang diberikan. Maka Anda akan mempertimbangkan beberapa hambatan udara meningkat dengan kuadrat kecepatan. Maka simulasi akan menghitung kecepatan berikutnya dengan membalik newton hukum kedua f=m a,.
Untuk menemukan a=f/m, maka integrasi Euler: speed=speed+a*dt. yang madalah sekitar 1200 (berat mobil khas). fadalah gaya yang berasal dari torsi mesin, direduksi ke gearbox, dan kemudian dikonversi menjadi gaya menggunakan rumus tuas dengan mempertimbangkan jari-jari roda. (produk lintas vektor biasanya, tetapi dapat disederhanakan dengan penggandaan torsi dengan jari-jari. karena netwton / meter dikalikan meter = newton.)

dengan cara ini, rpm mesin dihitung mundur, sebagai fungsi dari kecepatan mobil linier.

v.oddou
sumber
2
Tidak ada exact number of RPM drop between each gear. Ini adalah rasio, seperti yang ditunjukkan oleh @Baldrickk. Dan sementara itu ide yang bagus untuk memiliki output transmisi menjadi torsi daripada kecepatan, diskusi tentang hambatan angin dan integrasi verlet sedikit di luar ruang lingkup pertanyaan, bukan?
Justin
Iya nih. untuk jawaban atas pertanyaan saya akan merekomendasikan jawaban Baldrickk. Saya membatalkannya.
v.oddou
5

Roda gigi digunakan sebagai mekanisme reduksi.

Menggunakan transmisi yang disederhanakan dengan hanya dua rasio di gearbox, satu gear input (engine) dan satu output gear (salah satu rasio gearbox) kami memiliki dua rasio reduksi yang berbeda.

Jadi untuk gigi input dengan gigi x dan gigi output gigi x / 2, kecepatan gigi output adalah dua kali kecepatan gigi input (rasio dua banding satu)

rpm2 = rpm1 * gearRatio

dimana:

gearRatio = teeth1 / teeth2

Jadi, alih-alih membatasi setiap gigi dengan kecepatan hardcode, kita dapat membatasi dengan rasio. Anda kemudian dapat menghitung kecepatan untuk pasangan tertentu (rpm Engine, roda gigi), dan, ketika roda gigi berubah, hitung kecepatan mesin berdasarkan kecepatan yang diketahui dan pasangan baru.

Untuk mempermudah, gunakan hanya mesin yang terhubung ke dua gigi:

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]

begitu:

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

ketika beralih ke gigi ke-2, 10000 adalah kecepatan, jadi menghubungkannya dengan formula yang sama, kita sekarang memiliki:

vehicleSpeed = 10000 #computed above
selectedGear = 2

jadi rpm baru kami:

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

10000 itu kemudian akan dikurangi lebih jauh dengan diferensial (yang dapat diabstraksi hanya sebagai gigi lain, lihatlah jika diperlukan, maaf, dapat memposting dua tautan yang menonjol) dan kemudian dengan ukuran roda untuk menghitung kecepatan gerak dalam kilometer atau mil per jam .

Anda harus memperhitungkan fakta bahwa bergeser ke gigi yang lebih rendah meningkatkan rpm engine, jadi pendekatan sederhana adalah memeriksa maxRPM dan membatasi rpm setelah beralih ke rpm maksimum Anda, sehingga mengurangi kecepatan kendaraan.

Jadi pada dasarnya, setiap kali terjadi perpindahan gigi, Anda menghitung putaran mesin dari kecepatan kendaraan, batasi dengan kecepatan maksimum, dan kemudian kembali ke "normal" di mana Anda memperbarui rpm dari input pengguna dan menghitung kecepatan berdasarkan itu.

Untuk simulasi yang realistis, Anda harus memperhitungkan setidaknya torsi mesin (jawaban v.oddou) dan selip kopling, yang digabungkan akan memiliki efek ini: - ketika menggeser ke atas, dengan asumsi pergeseran cukup cepat sehingga rpm mesin tidak jatuh , kecepatan akan dinaikkan ketika rpm engine diturunkan sampai mereka seimbang - ketika menggeser ke bawah, kecepatan kendaraan akan diturunkan sampai engine dinaikkan ke rpm baru tetapi ini mungkin melampaui implementasi "sederhana".

cristiancrc
sumber
4

Perlu diingat bahwa transmisi manual yang digunakan adalah perangkat dua arah. Mesin dapat mempercepat kendaraan, sama seperti kendaraan (lebih spesifik momentumnya) dapat mempercepat mesin.

Ini adalah masalah nyata dalam transmisi manual awal. Downshifting tiba-tiba akan menendang mesin ke rpm yang lebih tinggi, membuang siklus pengapian tidak sinkron dan mungkin menyebabkan mesin macet. Ini diimbangi dengan mengemudi ahli di mana pengemudi harus memutar mesin ke kecepatan yang benar sebelum melepaskan kopling untuk melakukan transmisi.

Itu sampai synchromesh dikembangkan. Ini adalah mekanisme yang mencegah transmisi dari terlibat sampai kecepatan input dan output sinkron.

Jadi, yang saya sarankan adalah Anda meniru synchromesh dan tidak menggunakan transmisi sampai putaran mesin dan kecepatan mobil sesuai dengan level mereka saat ini.

edgerunner
sumber
2

Jawaban yang ada tampaknya terlalu rumit. Untuk sebuah game, RPM hanyalah sebuah indikator di layar. Kecepatan aktual adalah variabel nyata. Rasio roda gigi menentukan bagaimana Anda mengubah kecepatan engine menjadi RPM. Mengubah persneling mengubah rasio, tetapi bukan kecepatannya. Jelas, RPM juga berubah sebagai kebalikan dari rasio roda gigi.

Overrevving (menurunkan gigi melewati batas 8500 RPM Anda) adalah sesuatu yang akan Anda terapkan secara terpisah, tetapi itu adalah hal yang buruk di dalam mobil dan Anda dapat membiarkannya menjadi hal yang buruk dalam permainan Anda.

MSalters
sumber
2
Jawaban yang ada adalah persis seperti apa yang dilakukan sebagian besar game, bahkan game arcade sederhana, karena sebenarnya tidak terlalu rumit. RPM di layar mungkin hanya berupa angka, tetapi pendekatan itu memberi Anda nomor (yang dapat Anda atur untuk indikator visual), dan perilaku yang cocok dengan angka-angka itu
Selali Adobor
2

Seperti yang telah disebutkan orang lain, kecepatan kendaraan harus menjadi nilai sebenarnya dan RPM harus diturunkan dari itu. Upshifting harus menyebabkan kecepatan rotasi mesin menurun karena rasio RPM per km / jam akan "langsung" berubah tetapi kecepatan kendaraan tidak.

Saya menyarankan, bagaimanapun, bahwa torsi mesin harus meningkat dengan RPM hingga batas tertentu dan melampaui itu. Laju di mana kendaraan berakselerasi harus proporsional dengan torsi dibagi dengan rasio roda gigi, minus hambatan udara yang sebanding dengan kuadrat kecepatan. Jika roda gigi berurutan memiliki rasio 1: 41: 1, maka pemindahan gigi yang optimal untuk akselerasi akan terjadi pada titik di mana torsi pada gigi bawah turun menjadi sekitar 70% dari apa yang akan terjadi pada gigi lebih tinggi berikutnya.

supercat
sumber
2

Membangun @ v.oddou, menggunakan

max(maxRPM, calc)

akan menyebabkan RPMS memaksimalkan secara instan ketika roda gigi digeser, tidak memungkinkan transisi yang mulus dari gigi ke gigi. Cara yang tepat adalah dengan memecahkan untuk RPM menggunakan variabel kecepatan sebagai persamaan.

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

Pecahkan untuk rpm

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

karena gigi 1 lebih tinggi dari sebelumnya, RPM akan lebih rendah.

White Development Studios
sumber