Implementacja transmisji w grze samochodowej


23

Próbuję stworzyć prostą grę samochodową z ręczną zmianą biegów. Mam jednak problem z wprowadzeniem zmiany biegów.

Oto mój obecny kod „samochodu”:

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

Jednak ta implementacja tak naprawdę nie działa. Pierwszy bieg działa dobrze, ale kolejne zmiany biegów powodują spadek prędkości. Dodając niektóre komunikaty debugowania, otrzymuję te wartości prędkości podczas zmiany przy limicie 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

Jak widać, prędkość po każdej zmianie jest wolniejsza przed zmianą. Jak weźmiesz pod uwagę prędkość przed zmianą biegów, aby prędkość nie spadła podczas zmiany biegów?


1
Przypomina mi się ten doskonały dogłębny samouczek: Fizyka samochodów dla gier . Około jednej trzeciej artykułu zaczyna mówić o przenoszeniu siły silnika.
Eric,

Odpowiedzi:


17

Oblicz nowe obroty na podstawie nowego biegu i aktualnej prędkości samochodu.

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

więc: zamiast:

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

posługiwać się:

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

Prędkość będzie teraz taka sama przed zmianą biegów i po niej, a stamtąd można przyspieszyć / zwolnić.

edytuj: dodane, max(maxRPM, calc)jak chcesz to ograniczyć. Podobnie jak w samochodzie, powinno to spowodować dość nagłą utratę prędkości


29

dzieje się tak, ponieważ w obliczeniach prędkości nie ma bezwładności. wystarczy obliczyć to jako bezwzględną konsekwencję obrotów silnika i biegu. ale kiedy obliczasz nowe obroty po zmianie biegów, empirycznie obniżasz je o stałe 3600 obrotów na minutę.

To jest twój błąd. lista prędkości obrotowych nie jest ustalona między biegami. możesz to naprawić, tworząc drugą tablicę przechowującą dokładną liczbę spadków prędkości obrotowej między poszczególnymi biegami.

Drugi sposób to naprawić, używając obliczeń opartych na fizyce. Wykonujesz symulację, dzięki czemu możesz wykonać integrację numeryczną. Korzystanie z czasu dti integracji euler lub integracji Verlet. To brzmi skomplikowanie z nazwami i wszystko, ale tak naprawdę nie jest.

Zasadniczo oznaczałoby to utworzenie tabeli przeglądowej dla momentu obrotowego silnika przy danych obrotach. Następnie weźmiesz pod uwagę opór powietrza rosnący wraz z kwadratem prędkości. Następnie symulacja będzie obliczyć następną prędkość przez odwrócenie Newtonów drugie prawo, f=m a.
Aby znaleźć a=f/m, a następnie integrację Eulera: speed=speed+a*dt. mwynosi około 1200 (typowe masy samochodu). fto siła pochodząca z momentu obrotowego silnika, zredukowana do skrzyni biegów, a następnie przeliczona na siłę za pomocą formuły dźwigni, biorąc pod uwagę promień koła. (zwykle iloczyn wektorowy, ale można go uprościć przez pomnożenie momentu obrotowego przez promień. ponieważ mnożnik netto / metry pomnożony = niutony).

w ten sposób obroty silnika są obliczane do tyłu, w zależności od liniowej prędkości samochodu.


2
Nie ma exact number of RPM drop between each gear. Jest to stosunek, jak wskazuje @Baldrickk. I chociaż świetnym pomysłem jest, aby moc wyjściowa przekładni była raczej momentem obrotowym niż prędkością, dyskusja na temat odporności na wiatr i integracji Verleta jest nieco poza zakresem pytania, prawda?
Justin

Tak. za miejsce w odpowiedzi na pytanie poleciłbym odpowiedź Baldrickka. Głosowałem za tym.
v.oddou

5

Koła zębate są stosowane jako mechanizm redukcyjny.

Stosując uproszczoną skrzynię biegów z zaledwie dwoma przełożeniami w skrzyni biegów, jednym przełożeniem wejściowym (silnik) i jednym przełożeniem wyjściowym (jeden ze przełożeń skrzyni biegów) mamy dwa różne przełożenia redukcyjne.

Tak więc dla koła zębatego wejściowego z x zębami i koła zębatego wyjściowego x / 2 zębów prędkość koła zębatego wyjściowego jest dwa razy większa niż koła zębatego wejściowego (stosunek dwa do jednego)

rpm2 = rpm1 * gearRatio

gdzie:

gearRatio = teeth1 / teeth2

Zamiast więc ograniczać każdy bieg twardością zakodowaną na stałe, możemy ograniczyć go ze względu na stosunek. Następnie można obliczyć prędkość dla określonej pary (obr./min Silnik, bieg), a po zmianie biegu obliczyć prędkość silnika na podstawie znanej prędkości i nowej pary.

Upraszczając, wystarczy użyć silnika podłączonego do dwóch biegów:

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]

więc:

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

przy zmianie na 2. bieg, prędkość 10000 to prędkość, więc w tej samej formule mamy teraz:

vehicleSpeed = 10000 #computed above
selectedGear = 2

dlatego nasze nowe rpm:

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

Ten 10000 zostałby następnie zredukowany o różnicę (którą można wyodrębnić jako kolejny bieg, w razie potrzeby wyszukaj ją, przepraszam, możesz wystawić dwa ogniwa), a następnie o rozmiar koła, aby obliczyć prędkość jazdy w kilometrach lub milach na godzinę .

Należy wziąć pod uwagę fakt, że zmiana biegu na niższy powoduje zwiększenie prędkości obrotowej silnika, więc prostym podejściem jest sprawdzenie maksymalnej prędkości obrotowej silnika i ograniczenie prędkości obrotowej po zmianie na maksymalną prędkość obrotową, co zmniejsza prędkość pojazdu.

Zasadniczo, za każdym razem, gdy nastąpi zmiana biegów, obliczasz RPM silnika na podstawie prędkości pojazdu, ograniczasz go o max RPM, a następnie wracasz do „normalnej”, gdzie aktualizujesz obroty na podstawie danych wprowadzonych przez użytkownika i obliczasz na tej podstawie prędkość.

Aby uzyskać realistyczną symulację, należy wziąć pod uwagę co najmniej moment obrotowy silnika (odpowiedź v.oddou) i poślizg sprzęgła, które łącznie miałyby następujące skutki: - przy zmianie biegów, zakładając, że zmiana biegów jest wystarczająco szybka, aby obroty silnika nie spadły , prędkość będzie zwiększana, gdy obroty silnika będą obniżane, dopóki nie zostaną wyważone - podczas zmiany biegów prędkość pojazdu będzie obniżana, dopóki silnik nie zostanie podniesiony do nowych obrotów, ale prawdopodobnie wykracza to poza „prostą” implementację.


4

Pamiętaj, że zaangażowana manualna skrzynia biegów jest urządzeniem dwukierunkowym. Silnik może przyspieszyć pojazd, podobnie jak pojazd (a ściślej jego pęd) może przyspieszyć silnik.

Był to prawdziwy problem we wczesnych manualnych skrzyniach biegów. Zmiana biegu na niższy nagle spowodowałaby zwiększenie prędkości obrotowej silnika, powodując zsynchronizowanie cykli zapłonu i prawdopodobnie powodując zgaśnięcie silnika. Zostało to zrównoważone przez fachową jazdę, podczas której kierowca musiał zwiększyć obroty silnika do właściwej prędkości przed zwolnieniem sprzęgła w celu włączenia skrzyni biegów.

Tak było do momentu opracowania synchronizacji . Jest to mechanizm, który zapobiega włączaniu się transmisji, dopóki prędkości wejściowe i wyjściowe nie zostaną zsynchronizowane.

Sugeruję więc, aby emulować synchronizację i nie włączać skrzyni biegów, dopóki obroty silnika i prędkość samochodu nie zmienią się na ich obecnych poziomach.


2

Istniejąca odpowiedź wydaje się zbyt skomplikowana. W grze RPM jest tylko wskaźnikiem na ekranie. Rzeczywista prędkość jest rzeczywistą zmienną. Przełożenie przekładni określa sposób konwersji prędkości silnika na obroty. Zmiana biegów zmienia przełożenie, ale nie prędkość. Oczywiście prędkość obrotowa zmienia się również jako odwrotność przełożenia.

Przekroczenie (obniżenie limitu 8500 RPM) jest czymś, co można by wdrożyć osobno, ale to złe rzeczy w samochodach i możesz pozwolić, aby było to złe w swojej grze.


2
Istniejąca odpowiedź jest dokładnie tym, co robi większość gier, które widziałem, nawet proste gry zręcznościowe, ponieważ to naprawdę nie jest tak skomplikowane. RPM na ekranie może być po prostu liczbą, ale takie podejście daje zarówno liczbę (którą możesz i tak dostosować do wskaźników wizualnych), a także zachowanie pasujące do tych liczb
Selali Adobor

2

Jak wspomnieli inni, prędkość pojazdu powinna być rzeczywistą wartością, a obroty na tej podstawie powinny być wyprowadzone. Zmiana biegu na wyższy powinna spowodować zmniejszenie prędkości obrotowej silnika, ponieważ stosunek prędkości obrotowej na km / h „natychmiast” zmieni się, ale prędkość pojazdu się nie zmieni.

Sugerowałbym jednak, że moment obrotowy silnika powinien rosnąć wraz z prędkością obrotową do pewnego limitu i przekraczać ten limit. Szybkość, z jaką pojazd przyspiesza, powinna być proporcjonalna do momentu obrotowego podzielonego przez przełożenie skrzyni biegów, minus opór powietrza proporcjonalny do kwadratu prędkości. Jeśli kolejne przełożenia mają stosunek 1: 41: 1, wówczas optymalne przesunięcie dla przyspieszenia nastąpi w punkcie, w którym moment obrotowy na niższym biegu spadł do około 70% w stosunku do następnego wyższego biegu.


2

Opierając się na @ v.oddou, używając

max(maxRPM, calc)

spowodowałoby maksymalne zmniejszenie prędkości obrotowej przy zmianie biegów, co nie pozwalało na płynne przejście z biegu na bieg. Właściwym sposobem byłoby rozwiązanie dla RPM za pomocą zmiennej prędkości jako równania.

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

Rozwiąż dla rpm

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

ponieważ bieg jest o 1 wyższy niż wcześniej, obroty będą niższe.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.