Pregunta

¿Cómo manejan los juegos con gravedad la relación entre cosas en movimiento como jugadores, monstruos u objetos y el piso? ¿El jugador está constantemente "cayendo en" el piso y ser rebotado de nuevo?

Hay dos formas de reaccionar a las colisiones que he encontrado: mover al jugador de regreso a su ubicación anterior antes de la colisión y probar la nueva posición antes de moverse para ver si daría lugar a una colisión, pero no veo cómo cualquiera de estos podría tratar con una plataforma que se está elevando hacia arriba y necesita poder levantar al jugador. Estoy mirando esto desde una perspectiva de diseño de juegos en 2D, pero imagino que ocurre el mismo problema en el diseño de juegos en 3D. ¿Alguna pista? ¿Alguna referencia que deba consultar? Gracias.

¿Fue útil?

Solución

Es posible que desee consultar Preguntas frecuentes sobre la gravedad de GameDev.net para algunos información básica.

Dado que estás haciendo un juego y no eres un modelador de física muy preciso, podemos evitar hacer Integraciones de Euler . Si su necesidad de precisión aumenta, el método de integración más popular que veo usado es un Runge-Kutta (RK4 ) integración . Lo más probable es que no los necesite para un juego simple, pero definitivamente se usan en simulaciones de física más avanzadas y juegos en 3D. La desventaja de usar RK4 es una complejidad ligeramente mayor y un poco más lenta. Sin embargo, es muy preciso, pero por ahora, sigamos con el buen Euler.

Hice una pregunta similar, " Cómo ¿Aplico la gravedad a mi juego de pelota que rebota? " ;, y obtuve varias buenas respuestas. Lo primero que harás es elegir una constante de gravedad arbitraria para tu juego. En mi aplicación de pelota que rebota, uso una constante de gravedad predeterminada de 2000px / s. Querrás jugar con esta constante de gravedad para obtener el efecto deseado para tu juego en particular.

A continuación, debes asegurarte de que estás renderizando tu juego y actualizando tus objetos de juego de forma independiente. Esto es para evitar que sus objetos en el juego se muevan realmente rápido en computadoras rápidas y lento en computadoras lentas. Desea que la física y la velocidad con la que se mueven sus objetos sean independientes de la velocidad de la computadora. Un buen artículo sobre esto es Física del juego: ¡corrige tu tiempo! .

Entonces, ¿cómo hacemos eso? Lleva un registro de cuánto tiempo ha pasado desde la última llamada a su método de actualización. Creé 2 hilos, aunque no es directamente necesario. Tengo un hilo de actualización del juego y un hilo de renderizado. El hilo de actualización controla la actualización de las posiciones de los objetos en el juego. El hilo de actualización sabe cuándo se llamó anteriormente, la hora actual y, a partir de eso, calcula el tiempo transcurrido desde que se llamó al método de actualización.

Para aplicar la gravedad, simplemente agregaremos a la velocidad Y de nuestro objeto por nuestra constante de gravedad multiplicada por el tiempo transcurrido.

private long previousTime = System.currentTimeMillis();
private long currentTime = previousTime;

public void updateGame()
{
    currentTime = System.currentTimeMillis();
    float elapsedSeconds = (currentTime - previousTime) / 1000f; 

    foreach(GameObject gameObject in gameObjects)
    {
        // Apply gravity to velocity vector
        gameObject.velocity.y += (gravityConstant * elapsedSeconds); 

        // Move objects x/y position based off it's velocity vector
        gameObject.position.x += (gameObject.velocity.x * elapsedSeconds); 
        gameObject.position.y += (gameObject.velocity.y * elapsedSeconds);

    }

    checkCollisions();

    previousTime = currentTime;
}

Eso moverá todos sus objetos en función de sus vectores de velocidad y les aplicará gravedad según su constante de gravedad. ¡Lo mejor de todo es que lo hace independientemente de la velocidad de las computadoras!

Para responder a su otra pregunta, sí, los objetos tendrán constantemente la "fuerza". de gravedad en su vector y. Por lo tanto, estará constantemente chocando con el piso. Sin embargo, una cosa que desea hacer es usar un valor de Epsilon para eventualmente llevar la velocidad de su gameObject a cero. Luego, durante la detección de colisión como parte de su proceso de poda, generalmente puede omitir la verificación de si un objeto que no se mueve está colisionando con algo (¡pero no al revés!).

Lo que me gusta hacer con las colisiones es que una vez que encuentro objetos colisionando (penetrando entre sí), los separaré por su distancia mínima de traslación (MTD) que los separa. Este paso es clave, de lo contrario obtendrá el error que se ve con frecuencia en los juegos de objetos `` atascados '' juntos moviéndose nerviosamente. Una vez que se separan, calculo mi respuesta de colisión.

Al usar este método, funcionará bien en el escenario descrito de una plataforma ascendente. La plataforma continuará subiendo, el gameObject se separará usando el MTD entre sí y la plataforma y, naturalmente, se elevará con i

Otros consejos

Un enfoque utilizado en algunos juegos es hacer trampa: tener un estado separado para caminar vs en el aire. Mientras camina, el motor del juego puede determinar la pendiente de la superficie sobre la que se camina y, si no es demasiado empinada, mover el personaje en la dirección de la superficie y darle al personaje la ubicación vertical adecuada en relación con la superficie.

En cuanto a la física, me estoy convirtiendo en un fanático de la integración verlet como se describe en Gamasutra : Física avanzada de personajes . Simplifica las ecuaciones de actualización física (¡no tiene que hacer un seguimiento de la velocidad!) Y simplifica las colisiones (¡no tiene que ajustar la velocidad!). Dicho esto, tiene algunos matices si necesita precisión.

No soy específicamente un programador de juegos, pero así lo entiendo:

  • en un mundo ideal con una '' velocidad de fotogramas infinita '', detectaría la colisión precisamente en el momento en que ocurrió, y usaría un poco de física estándar para modelar las nuevas velocidades y aceleraciones de los cuerpos después de la colisión ( vea un libro de texto de mecánica estándar de la escuela secundaria, o varios libros titulados cosas como "Física para programadores de juegos")
  • en realidad, debido a que tiene una velocidad de cuadro fija y, por lo tanto, los cuerpos solo se mueven con una cierta granularidad, generalmente necesita agregar un truco adicional, como calcular por adelantado la ruta relativa que los cuerpos viajarán en el siguiente cuadro y ver si alguno de los caminos se cruza
  • si se cruzan, entonces el punto de intersección será en realidad una estimación , pero un poco inexacta, del punto en el que los cuerpos realmente habrían chocado; entonces tiene la opción de no preocuparse y tomar esa estimación como el punto de intersección e interpolar linealmente para obtener las velocidades en el punto de colisión, o hacer un cálculo más preciso ahora que ha descubierto que se intersecarán, para obtener el punto / tiempo / velocidades reales de colisión

Además de modelar colisiones, un buen enfoque es también modelar transferencias continuas de energía (o impulso, o simplemente velocidad, dependiendo de la complejidad de su simulación). Cuando su jugador está parado en una plataforma, almacene esa información en el objeto que representa la plataforma, y ??cada vez que se ajuste la velocidad del objeto, puede aplicar directamente ese cambio al jugador así vinculado u otros objetos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top