Implementación de transmisión en un juego de autos

23

Estoy tratando de crear un juego de autos simple con cambios de marcha manuales. Sin embargo, tengo algunos problemas para implementar los cambios de marcha.

Aquí está mi código actual para el "auto":

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

Sin embargo, esta implementación realmente no funciona. La primera marcha funciona bien, pero los siguientes cambios de marcha causan la caída de velocidad. Al agregar algunos mensajes de depuración, obtengo estos valores de velocidad al cambiar en el límite 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

Como puede ver, la velocidad después de cada cambio es más lenta antes del cambio. ¿Cómo tomaría en cuenta la velocidad antes del cambio de marcha para que la velocidad no disminuya al cambiar de marcha?

Manábreak
fuente
1
Recuerdo este excelente tutorial en profundidad: Física del automóvil para juegos . Aproximadamente una tercera parte del artículo comienza a hablar sobre la transmisión de fuerza del motor.
Eric

Respuestas:

17

Calcule las nuevas RPM en función de la nueva marcha y la velocidad actual del automóvil.

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

entonces: en lugar de:

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

utilizar:

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

La velocidad ahora será la misma antes y después del cambio de marcha, y puede acelerar / desacelerar desde allí.

editar: agregado max(maxRPM, calc)como quieras limitarlo. Como en un automóvil, esto debería resultar en una pérdida de velocidad bastante repentina

Baldrickk
fuente
29

Esto se debe a que no hay inercia en su cálculo de velocidad. solo se calcula como una consecuencia absoluta de las rpm y el engranaje del motor. pero cuando calcula las nuevas rpm después del cambio de marcha, lo baja empíricamente en pasos fijos de 3600 rpm.

Este es tu error. el menú desplegable de rpm no se fija entre engranajes. puede solucionarlo haciendo una segunda matriz que almacene el número exacto de caída de rpm entre cada marcha.

La segunda forma de solucionarlo es mediante el uso de cálculos físicos. Estás haciendo una simulación, por lo que puedes hacer una integración numérica. Usando el tiempo, dty la integración euler, o integración Verlet. Esto suena complejo con nombres y todo pero en realidad no lo es.

Básicamente significaría que crea una tabla de búsqueda para el par del motor a las rpm dadas. Entonces tendrías en cuenta que aumenta la resistencia del aire con el cuadrado de la velocidad. A continuación, la simulación calcularía la siguiente velocidad mediante la inversión de la segunda ley de Newton, f=m a.
Para encontrar a=f/m, a continuación, la integración de Euler: speed=speed+a*dt. el mes aproximadamente 1200 (peso típico del automóvil).fes la fuerza derivada del par motor, que se reduce a la caja de cambios y luego se convierte en fuerza usando la fórmula de la palanca al considerar el radio de la rueda. (un producto vectorial cruzado generalmente, pero puede simplificarse mediante la multiplicación de torque con radio. porque netwton / metros multiplicado metros = newtons).

de esta manera, las rpm del motor se calculan hacia atrás, en función de la velocidad lineal del automóvil.

v.oddou
fuente
2
No existe exact number of RPM drop between each gear. Es una relación, como señala @Baldrickk. Y aunque es una gran idea que la salida de la transmisión sea el par en lugar de la velocidad, una discusión sobre la resistencia al viento y la integración de verlet está un poco fuera del alcance de la pregunta, ¿no?
Justin
Sí. para un lugar en la respuesta a la pregunta, recomendaría la respuesta de Baldrickk. Yo lo voté.
v.oddou
5

Los engranajes se utilizan como mecanismo de reducción.

Usando una transmisión simplificada con solo dos relaciones en la caja de cambios, una velocidad de entrada (el motor) y una velocidad de salida (una de las relaciones de la caja de cambios) tenemos dos relaciones de reducción diferentes.

Entonces, para un engranaje de entrada con x dientes y un engranaje de salida de x / 2 dientes, la velocidad del engranaje de salida es el doble de la velocidad del engranaje de entrada (una relación de dos a uno)

rpm2 = rpm1 * gearRatio

dónde:

gearRatio = teeth1 / teeth2

Entonces, en lugar de limitar cada engranaje por la velocidad codificada, podemos limitarlo por relación. Luego puede calcular la velocidad para un par específico (rpm Motor, marcha) y, cuando se cambia la marcha, calcular la velocidad del motor dada la velocidad conocida y un nuevo par.

Para simplificar, usando solo un motor conectado a dos engranajes:

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]

asi que:

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

al cambiar a la segunda marcha, 10000 es la velocidad, por lo que al conectarlo en la misma fórmula, ahora tenemos:

vehicleSpeed = 10000 #computed above
selectedGear = 2

así nuestras nuevas rpm:

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

Ese 10000 se reduciría aún más por un diferencial (que puede resumirse como un engranaje más, búsquelo si es necesario, lo siento, puede publicar solo dos enlaces) y luego por el tamaño de la rueda para calcular la velocidad de avance en kilómetros o millas por hora .

Tendría que tener en cuenta el hecho de que cambiar a una velocidad más baja aumenta las rpm del motor, por lo que un enfoque simple es verificar las rpm máximas y limitar las rpm después del cambio a las rpm máximas, reduciendo así la velocidad del vehículo.

Básicamente, cada vez que ocurre un cambio de marcha, calcula las rpm del motor a partir de la velocidad del vehículo, la limita a las rpm máximas y luego vuelve a "normal" donde actualiza las rpm de la entrada del usuario y calcula la velocidad en función de eso.

Para una simulación realista, debe tener en cuenta al menos el par del motor (respuesta de v.oddou) y el deslizamiento del embrague, lo que combinado tendría estos efectos: - al subir, suponiendo que el cambio es lo suficientemente rápido como para que las rpm del motor no caigan , la velocidad se elevará mientras se reducen las rpm del motor hasta que se equilibren; al cambiar hacia abajo, la velocidad del vehículo se reducirá hasta que el motor se eleve a las nuevas rpm, pero esto probablemente va más allá de la implementación "simple".

cristiancrc
fuente
4

Tenga en cuenta que una transmisión manual activada es un dispositivo bidireccional. El motor puede acelerar el vehículo, al igual que el vehículo (más específicamente su impulso) puede acelerar el motor.

Este fue un problema real en las primeras transmisiones manuales. El cambio descendente repentinamente patearía el motor a una rpm más alta, lo que desalinearía los ciclos de encendido y posiblemente causaría que el motor se detuviera. Esto fue compensado por una conducción experta donde el conductor tuvo que acelerar el motor a la velocidad correcta antes de soltar el embrague para activar la transmisión.

Eso fue hasta que se desarrolló el synchromesh . Es un mecanismo que evita que la transmisión se active hasta que las velocidades de entrada y salida estén sincronizadas.

Entonces, lo que sugiero es que emule la sincronización y no active la transmisión hasta que las rpm del motor y la velocidad del automóvil coincidan en sus niveles actuales.

edgerunner
fuente
2

La respuesta existente parece demasiado compleja. Para un juego, RPM es solo un indicador en la pantalla. La velocidad real es la variable real. La relación de transmisión determina cómo convierte la velocidad del motor a RPM. Cambiar de marcha cambia la relación, pero no la velocidad. Obviamente, las RPM también cambian a la inversa de la relación de transmisión.

El exceso de revoluciones (el cambio descendente más allá de su límite de 8500 RPM) es algo que implementaría por separado, pero es algo malo en los automóviles y puede dejar que sea algo malo en su juego.

MSalters
fuente
2
La respuesta existente es exactamente lo que hacen la mayoría de los juegos que he visto, incluso juegos arcade simples, porque realmente no es tan complejo. Las RPM en la pantalla pueden ser solo un número, pero ese enfoque le da tanto el número (que puede ajustar para indicadores visuales de todos modos) como el comportamiento para que coincida con esos números
Selali Adobor
2

Como otros han mencionado, la velocidad del vehículo debe ser el valor real y las RPM deben derivarse de eso. El cambio ascendente debería hacer que la velocidad de rotación del motor disminuya porque la relación de RPM por km / h cambiará "instantáneamente", pero la velocidad del vehículo no lo hará.

Sin embargo, sugeriría que el par del motor debería aumentar con las RPM hasta cierto límite y superarlo. La velocidad a la que acelera un vehículo debe ser proporcional al par dividido por la relación de transmisión, menos el arrastre de aire que es proporcional al cuadrado de la velocidad. Si las marchas consecutivas tienen una relación de 1: 41: 1, se producirá un cambio óptimo para la aceleración en el punto en que el par en la marcha más baja haya caído a aproximadamente el 70% de lo que sería en la próxima marcha más alta.

Super gato
fuente
2

Basándose en @ v.oddou, utilizando

max(maxRPM, calc)

causaría que el RPMS se maximizara instantáneamente cuando se cambian los engranajes, lo que no permite una transición suave de engranaje a engranaje. La forma correcta sería resolver las RPM utilizando la variable de velocidad como una ecuación.

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

Resolver por rpm

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

Como el equipo es 1 más alto que antes, las RPM serán más bajas.

Estudios de desarrollo blanco
fuente