Implémentation de la transmission dans un jeu de voiture

23

J'essaie de créer un jeu de voiture simple avec des changements de vitesse manuels. Cependant, j'ai un peu de mal à implémenter les changements de vitesse.

Voici mon code actuel pour la "voiture":

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

Cependant, cette implémentation ne fonctionne pas vraiment. La première vitesse fonctionne bien, mais les changements de vitesse suivants entraînent une baisse de vitesse. En ajoutant des messages de débogage, j'obtiens ces valeurs de vitesse lorsque je change à la limite de 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

Comme vous pouvez le voir, la vitesse après chaque changement est plus lente avant le changement. Comment prendriez-vous en considération la vitesse avant le changement de vitesse afin que la vitesse ne baisse pas lors du changement de vitesse?

manabreak
la source
1
Je me souviens de cet excellent didacticiel approfondi: Car Physics for Games . À environ un tiers de l'article commence à parler de la transmission de force du moteur.
Eric

Réponses:

17

Calculez le nouveau régime en fonction du nouveau rapport et de la vitesse actuelle de la voiture.

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

donc: au lieu de:

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

utilisation:

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

La vitesse sera désormais la même avant et après le changement de vitesse, et vous pourrez accélérer / décélérer à partir de là.

modifier: ajouté max(maxRPM, calc)comme vous voulez le limiter. Comme dans une voiture, cela devrait entraîner une perte de vitesse assez soudaine

Baldrickk
la source
29

c'est parce qu'il n'y a pas d'inertie dans votre calcul de vitesse. vous le calculez simplement comme une conséquence absolue du régime moteur et du rapport. mais lorsque vous calculez le nouveau régime après le passage de la vitesse, vous le réduisez empiriquement par pas fixes de 3600 tr / min.

C'est ton erreur. la liste déroulante du régime n'est pas fixe entre les engrenages. vous pouvez le corriger en créant un deuxième tableau stockant le nombre exact de chutes de tours entre chaque vitesse.

La deuxième façon de résoudre ce problème consiste à utiliser des calculs physiques. Vous faites une simulation, vous pouvez donc faire une intégration numérique. Utilisation de l' dtintégration time, et euler ou de l'intégration Verlet. Cela semble complexe avec des noms et tout, mais ce n'est pas le cas.

Fondamentalement, cela signifierait que vous créez une table de recherche pour le couple moteur à un régime donné. Ensuite, vous tiendriez compte d'une certaine résistance de l'air augmentant avec le carré de la vitesse. Ensuite , la simulation calculerait la vitesse suivante en inversant la deuxième loi newtons, f=m a.
Pour trouver a=f/m, puis l' intégration d' Euler: speed=speed+a*dt. l' mest d' environ 1200 (poids de voiture typique). fest la force dérivée du couple moteur, réduite dans la boîte de vitesses, puis convertie en force à l'aide de la formule du levier en tenant compte du rayon de la roue. (un produit vectoriel vectoriel en général, mais peut être simplifié par la multiplication du couple avec le rayon.

de cette façon, le régime du moteur est calculé à l'envers, en fonction de la vitesse linéaire de la voiture.

v.oddou
la source
2
Il n'y en a pas exact number of RPM drop between each gear. C'est un ratio, comme le souligne @Baldrickk. Et bien que ce soit une bonne idée d'avoir la sortie de la transmission sous forme de couple plutôt que de vitesse, une discussion sur la résistance au vent et l'intégration de verlet est un peu en dehors de la portée de la question, non?
Justin
Oui. pour une place sur la réponse à la question, je recommanderais la réponse de Baldrickk. Je l'ai voté.
v.oddou
5

Les engrenages sont utilisés comme mécanisme de réduction.

En utilisant une transmission simplifiée avec seulement deux rapports dans la boîte de vitesses, un engrenage d'entrée (le moteur) et un engrenage de sortie (l'un des rapports de la boîte de vitesses), nous avons deux rapports de réduction différents.

Donc, pour un engrenage d'entrée avec x dents et un engrenage de sortie de x / 2 dents, la vitesse de l'engrenage de sortie est le double de la vitesse de l'engrenage d'entrée (un rapport de deux à un)

rpm2 = rpm1 * gearRatio

où:

gearRatio = teeth1 / teeth2

Ainsi, au lieu de limiter chaque vitesse par une vitesse codée en dur, nous pouvons la limiter par rapport. Vous pouvez ensuite calculer la vitesse pour une paire spécifique (rpmEngine, gear) et, lorsque la vitesse est changée, calculer la vitesse du moteur en fonction de la vitesse connue et d'une nouvelle paire.

Pour simplifier, en utilisant simplement un moteur connecté à deux vitesses:

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]

alors:

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

lors du passage en 2ème vitesse, 10000 est la vitesse, donc en branchant que dans la même formule, nous avons maintenant:

vehicleSpeed = 10000 #computed above
selectedGear = 2

ainsi notre nouveau rpm:

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

Ce 10000 serait ensuite encore réduit par un différentiel (qui peut être résumé comme juste un autre engrenage, recherchez-le si nécessaire, désolé, peut afficher deux liens), puis par la taille de la roue pour calculer la vitesse au sol en kilomètres ou en miles par heure .

Vous devez tenir compte du fait que le passage à une vitesse inférieure augmente le régime moteur.Une approche simple consiste donc à vérifier le régime maximal et à limiter le régime après le passage à votre régime maximal, réduisant ainsi la vitesse du véhicule.

Donc, fondamentalement, chaque fois qu'un changement de vitesse se produit, vous calculez le régime moteur à partir de la vitesse du véhicule, le limitez par maxRPM, puis revenez à la "normale" où vous mettez à jour le régime à partir de l'entrée utilisateur et calculez la vitesse en fonction de cela.

Pour une simulation réaliste, vous devez prendre en compte au moins le couple moteur (réponse de v.oddou) et le glissement de l'embrayage, qui combinés auraient ces effets: - lors du passage à la vitesse supérieure, en supposant que le changement de vitesse est suffisamment rapide pour que le régime moteur ne chute pas , la vitesse sera augmentée tandis que le régime moteur est abaissé jusqu'à ce qu'ils soient équilibrés - lors du rétrogradage, la vitesse du véhicule sera réduite jusqu'à ce que le moteur soit augmenté au nouveau régime, mais cela va probablement au-delà de la mise en œuvre "simple".

cristiancrc
la source
4

Gardez à l'esprit qu'une transmission manuelle engagée est un appareil bidirectionnel. Le moteur peut accélérer le véhicule, tout comme le véhicule (plus précisément son élan) peut accélérer le moteur.

C'était un vrai problème dans les premières transmissions manuelles. La rétrogradation donnerait soudainement un coup de pied au moteur à un régime plus élevé, ce qui mettrait les cycles d'allumage hors de synchronisation et pourrait entraîner le calage du moteur. Cela a été compensé par une conduite experte où le conducteur a dû faire tourner le moteur à la bonne vitesse avant de relâcher l'embrayage pour engager la transmission.

C'était jusqu'à ce que le synchromesh soit développé. Il s'agit d'un mécanisme qui empêche la transmission de s'engager jusqu'à ce que les vitesses d'entrée et de sortie soient synchronisées.

Donc, ce que je suggère, c'est que vous émuliez le synchroniseur et n'engagiez pas la transmission jusqu'à ce que le régime moteur et la vitesse de la voiture correspondent à leurs niveaux actuels.

edgerunner
la source
2

La réponse actuelle semble beaucoup trop complexe. Pour un jeu, le RPM n'est qu'un indicateur à l'écran. La vitesse réelle est la variable réelle. Le rapport de démultiplication détermine la façon dont vous convertissez le régime moteur en tr / min. Changer de vitesse change le rapport, mais pas la vitesse. De toute évidence, le régime change également comme l'inverse du rapport de démultiplication.

Une surrévolution (rétrogradation au-delà de votre limite de 8500 tr / min) est quelque chose que vous implémenteriez séparément, mais c'est une mauvaise chose dans les voitures et vous pouvez laisser cela être une mauvaise chose dans votre jeu.

MSalters
la source
2
La réponse actuelle est exactement ce que font la plupart des jeux que j'ai vus, même les simples jeux d'arcade, car ce n'est vraiment pas si complexe. Le RPM à l'écran n'est peut-être qu'un nombre, mais cette approche vous donne à la fois le nombre (que vous pouvez modifier pour les indicateurs visuels de toute façon) et le comportement pour correspondre à ces chiffres
Selali Adobor
2

Comme d'autres l'ont mentionné, la vitesse du véhicule devrait être la valeur réelle et le régime devrait en être dérivé. Le changement de vitesse devrait entraîner une diminution de la vitesse de rotation d'un moteur car le rapport tr / min par km / h changera "instantanément" mais pas la vitesse du véhicule.

Je dirais cependant que le couple moteur devrait augmenter avec le régime jusqu'à une certaine limite et tomber au-delà. La vitesse à laquelle un véhicule accélère doit être proportionnelle au couple divisé par le rapport de transmission, moins la traînée d'air qui est proportionnelle au carré de la vitesse. Si les rapports consécutifs ont un rapport 1: 41: 1, alors le changement optimal pour l'accélération se produira au point où le couple dans le rapport inférieur est tombé à environ 70% de ce qu'il serait dans le rapport supérieur suivant.

supercat
la source
2

En s'appuyant sur @ v.oddou, en utilisant

max(maxRPM, calc)

entraînerait le max du RPMS instantanément lorsque les vitesses sont changées, ne permettant pas une transition en douceur d'un engrenage à l'autre. La bonne façon serait de résoudre les RPM en utilisant la variable de vitesse comme équation.

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

Résoudre pour rpm

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

étant donné que le rapport est 1 supérieur à ce qu'il était auparavant, les régimes seront inférieurs.

White Development Studios
la source