Araba oyununda şanzıman uygulaması


23

Manuel vites değişiklikleriyle basit bir araba oyunu yaratmaya çalışıyorum. Ancak, vites değişikliklerini uygulamakta biraz zorlanıyorum.

İşte "araba" için şu anki kodum:

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

Ancak, bu uygulama gerçekten işe yaramıyor. İlk vites iyi çalışıyor, ancak aşağıdaki vites değişimleri hız düşmesine neden oluyor. Bazı hata ayıklama mesajları ekleyerek, RPM sınırında değiştirirken şu hız değerlerini elde ederim:

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

Gördüğünüz gibi, her değişiklikten sonraki hız değişimden önce daha yavaş. Vites değişiminden önce, vites değiştirirken hızın düşmemesi için hızı nasıl dikkate alırsınız?


1
Bu mükemmel kapsamlı eğitici bilgiyi hatırlatıyorum: Oyunlar için Araba Fiziği . Makalede yaklaşık üçte biri motor gücü iletimi hakkında konuşmaya başlar.
Eric,

Yanıtlar:


17

Yeni vitesi ve aracın o anki hızını temel alarak yeni RPM'yi hesaplayın.

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

öyleyse: yerine:

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

kullanın:

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

Vites değişiminden önce ve sonra hız aynı olacaktır ve oradan hızlandırabilir / yavaşlayabilirsiniz.

düzenleme: max(maxRPM, calc)sınırlamak istediğiniz gibi eklendi . Bir arabada olduğu gibi, bu durum ani bir hız kaybıyla sonuçlanmalıdır.


29

Bunun nedeni, hız hesaplamanızda atalet olmamasıdır. motor devri ve teçhizatın mutlak bir sonucu olarak hesaplarsınız. ancak vites değiştirdikten sonra yeni devri hesapladığınızda, 3600 dev / dak. sabit adımlarla ampirik olarak düşürürsünüz.

Bu senin hatan. Devir düşürme devir sayısı arasında sabit değildir. Her dişli arasında tam devir / dakika düşme sayısını depolayan ikinci bir dizi yaparak bunu düzeltebilirsiniz.

Bunu düzeltmenin ikinci yolu, fiziksel tabanlı hesaplamaları kullanmaktır. Simülasyon yapıyorsunuz, böylece sayısal bir entegrasyon yapabilirsiniz. Zaman dtve euler entegrasyonu veya Verlet entegrasyonunu kullanma. Bu isimlerle karmaşık geliyor ve hepsi ama aslında değil.

Temelde, verilen devirlerde motor torku için bir arama tablosu oluşturduğunuz anlamına gelir. O zaman hızın karesiyle artan hava direncini hesaba katarsınız. O zaman simülasyon bir sonraki hızı Newton'un ikinci yasasını tersine çevirerek hesaplardı f=m a.
Bulmak için a=f/mdaha sonra Euler entegrasyonu: speed=speed+a*dt. m1200 (tipik araç ağırlığı) ile ilgilidir. fmotor torkundan türetilen, şanzımana indirgenmiş ve daha sonra tekerleğin yarıçapı dikkate alınarak kol formülü kullanılarak zorlanmaya dönüştürülür. (genellikle bir vektör çapraz ürünüdür, ancak tork yarıçapı ile çarpılmasıyla basitleştirilebilir. çünkü netwton / metre çarpı metre = newton.)

Bu şekilde, motorun devri, lineer araç hızının bir fonksiyonu olarak geriye doğru hesaplanır.


2
Yok exact number of RPM drop between each gear. @Baldrickk'in işaret ettiği gibi bir orandır. Ve aktarımın çıktısının hız yerine tork olması harika bir fikir olsa da, rüzgar direnci ve vert entegrasyonu tartışması sorunun kapsamı dışında kalıyor, değil mi?
Justin,

Evet. soruyu cevaplamak için bir nokta için Baldrickk'in cevabını tavsiye ederim. Ben oyladım.
v.oddou

5

Dişliler bir indirgeme mekanizması olarak kullanılır.

Şanzımanda sadece iki oran, basitleştirilmiş bir şanzıman, bir giriş dişli (motor) ve bir çıkış dişli (dişli kutusunun oranlarından biri) kullanarak iki farklı redüksiyon oranına sahibiz.

Bu nedenle, x dişli bir giriş dişlisi ve x / 2 diş çıkış dişlisi için, çıkış dişlisinin hızı giriş dişlisinin iki katıdır (iki-bir oran)

rpm2 = rpm1 * gearRatio

nerede:

gearRatio = teeth1 / teeth2

Bu yüzden her bir vitesi sabit kodlanmış hız ile sınırlamak yerine, oranını sınırlayabiliriz. Daha sonra belirli bir (rpmEngine, dişli) çifti için hızı hesaplayabilir ve vites değiştirildiğinde, bilinen hız ve yeni bir çift verilen motor hızını hesaplayabilirsiniz.

Basitleştirmek için, sadece iki vitese bağlı bir motor kullanarak:

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]

yani:

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

2. vitese geçerken, hız 10000'dür, yani aynı formüle takarak şu anda elimizde:

vehicleSpeed = 10000 #computed above
selectedGear = 2

bu nedenle yeni devir sayımız:

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

Bu 10000 daha sonra bir farkla azaltılabilir (başka bir dişli olarak soyutlanabilir, gerektiğinde yukarı bak, üzgünüm, jut iki bağlantı koyabilir) ve saatte kilometre hızını kilometre cinsinden hesaplamak için tekerlek boyutuyla daha da azaltılabilir. .

Daha düşük bir vitese geçmenin motor devrini yükselttiği gerçeğini göz önünde bulundurmanız gerekir, bu nedenle basit bir yaklaşım maxRPM'yi kontrol etmek ve devirden sonra devir sayısını azami devir / dakikaya düşürmek ve böylece araç hızını düşürmektir.

Temel olarak, her vites değişimi gerçekleştiğinde, engineRPM'yi araç hızından hesaplar, maxRPM ile sınırlar ve sonra rpm'yi kullanıcı girişinden güncellediğiniz ve hızını hesapladığınız "normal" değerine geri dönersiniz.

Gerçekçi bir simülasyon için, en azından motor torkunu (v.oddou'nun cevabı) ve birleştirilmiş debriyaj kaymasını dikkate almanız gerekir: - vites değiştirirken, vitesin motor devrinin düşmeyeceği kadar hızlı olduğunu varsayarsak motor devri düzelene kadar düşürülürken hız artacaktır - vites düştüğünde, motor devri yeni devire yükseltilinceye kadar araç hızı düşürülecek ancak bu muhtemelen "basit" bir uygulamanın ötesine geçecektir.


4

İlgili bir manuel şanzımanın iki yönlü bir cihaz olduğunu unutmayın. Motor, aracı (örneğin özellikle momentumu) motoru hızlandırabildiğinden aracı hızlandırabilir.

Bu, erken manuel yayınlarda gerçek bir problemdi. Vites küçültme, aniden motoru daha yüksek bir devir / dakikaya fırlatır, ateşleme devrelerini senkronize eder ve muhtemelen motorun durmasına neden olur. Bu, şanzımanı devreye sokmak için debriyajı serbest bırakmadan önce sürücünün motoru doğru hıza döndürmesi gereken uzman sürüşü ile dengelenmiştir.

Senkromeç gelişene kadar öyleydi. Giriş ve çıkış hızları senkronize olana kadar şanzımanın devreye girmesini önleyen bir mekanizmadır.

Bu yüzden benim önerdiğim, senkromeçleri taklit etmeniz ve motorun devri ile araç hızı mevcut seviyelerinde eşleşene kadar şanzımanla bağlantı kurmamanız.


2

Mevcut cevap çok karmaşık görünüyor. Bir oyun için, RPM sadece ekrandaki bir göstergedir. Gerçek hız, gerçek değişkendir. Vites oranı, motor devrini RPM'ye nasıl dönüştüreceğinizi belirler. Dişlileri değiştirmek oranı değiştirir ancak hızı değiştirmez. Açıkçası, RPM aynı zamanda dişli oranının tersi olarak da değişiyor.

Aşırı zorlama (8500 RPM limitinizi düşürmek) ayrı olarak uyguladığınız bir şeydir, ancak arabalarda kötü bir şeydir ve oyununuzda kötü bir şey olmasına izin verebilirsiniz.


2
Var olan cevap tam olarak gördüğüm oyunların çoğu, hatta basit arcade oyunları. Çünkü o kadar da karmaşık değil. Ekrandaki RPM sadece bir sayı olabilir, ancak bu yaklaşım size hem sayıyı (hem de görsel göstergeler için
ince

2

Diğerlerinin de belirttiği gibi, araç hızı gerçek değer olmalı ve RPM bundan türetilmelidir. Vites değiştirme, motorun dönme hızının düşmesine neden olmalıdır çünkü km / s başına RPM oranı "anında" değişecek ancak araç hızı değişmeyecektir.

Bununla birlikte, motor torkunun RPM ile belirli bir sınıra kadar artması ve bunun ötesine geçmesi gerektiğini tavsiye ederim. Bir aracın hızlanma hızı, dişli oranına bölünmüş torkla, hız karesiyle orantılı eksi hava sürüklemesiyle orantılı olmalıdır. Ardışık viteslerin 1: 41: 1 oranına sahip olması durumunda, daha düşük vitesdeki torkun bir sonraki yüksek viteste olacağının yaklaşık% 70'ine düştüğü noktada hızlanma için en uygun kayma meydana gelir.


2

@ V.oddou üzerine bina, kullanma

max(maxRPM, calc)

vites değiştirilirken RPMS'in anında maksimuma çıkmasına neden olur, dişliden vitese geçişi mümkün kılmaz. Doğru yol, hız değişkenini bir denklem olarak kullanan RPM'leri çözmektir.

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

Rpm için çözün

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

vites 1 öncekinden daha yüksek olduğundan, RPM'ler daha düşük olacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.