collision-detection - tag - ontriggerenter
Colisiones entre los objetos del juego y el piso con respecto a la gravedad? (5)
Además de las colisiones de modelado, 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á de pie 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 u otros objetos así enlazados.
¿Cómo manejan los juegos con gravedad la relación entre mover objetos como jugadores, monstruos u objetos y el suelo? ¿El jugador está constantemente "cayendo" en el piso y siendo rebotado?
Dos formas de reaccionar a las colisiones que he encontrado son mover al jugador a su ubicación anterior antes de la colisión, y probar la nueva posición antes de moverme para ver si se produciría una colisión, pero no veo cómo cualquiera de estos podría lidiar con una plataforma que está subiendo y necesita poder levantar al jugador. Estoy viendo esto desde una perspectiva de diseño de juegos en 2D, pero imagino que el mismo problema ocurre en el diseño de juegos en 3D. ¿Algún consejo? ¿Alguna referencia que deba verificar? Gracias.
No soy específicamente un programador de juegos, pero este es mi entendimiento:
- en un mundo ideal con una "velocidad de fotogramas infinita", detectaría la colisión en el momento exacto 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 (consulte un estándar alto libro de texto de mecánica escolar, o varios libros titulados cosas como "Física para programadores de juegos")
- en realidad, debido a que tienes una velocidad de fotogramas fija y por lo tanto los cuerpos solo se mueven con una cierta granularidad, generalmente necesitas agregar un truco adicional, como calcular de antemano la ruta relativa que los cuerpos recorrerán en el siguiente fotograma y ver si alguno de los caminos se cruzan
- si se cruzan, entonces el punto de intersección será en realidad una estimación , pero ligeramente inexacta, del punto en el que los cuerpos realmente habrían chocado; luego 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 cruzan, para obtener el punto / hora / velocidades actuales de colisión
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 pronunciada, mover el personaje en la dirección de la superficie y darle al personaje la colocación vertical adecuada con respecto a la superficie.
En cuanto a la física, me estoy convirtiendo en un fanático de la integración de verlet como se describe en Gamasutra: Advanced Character Physics . Simplifica las ecuaciones de actualización de la 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.
Uno de los libros de texto más completos sobre este tema es la Detección de colisión en tiempo real de Christer Ericson . Él tiene un blog compañero también. Las matemáticas de Eric Lengyel para programación de juegos en 3D y gráficos por computadora también son útiles.
Es posible que desee consultar las preguntas frecuentes de gravedad de GameDev.net para obtener información básica.
Ya que estás haciendo un juego y no eres un modelador de física altamente preciso, podemos hacer las integraciones de Euler . Si su necesidad de precisión aumenta, el método de integración más popular que veo utilizado es una integración de Runge-Kutta (RK4) . Lo más probable es que no los necesite para un juego simple, pero definitivamente se utilizan en simulación de física más avanzada y juegos en 3D. La desventaja con el uso de RK4 es una complejidad ligeramente mayor y un poco más lenta. Sin embargo, es muy preciso, pero por ahora, sigamos con el buen ole 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 debes hacer es elegir una constante de gravedad arbitraria para tu juego. En mi aplicación de bola de rebote utilizo 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.
Luego, debes asegurarte de que estás renderizando tu juego y actualizando los objetos de tu juego de forma independiente. Esto es para evitar que sus objetos en el juego se muevan realmente rápido en computadoras rápidas y ralentice 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 Game Physics: ¡arregla tu tiempo! .
¿Entonces cómo hacemos eso? Mantiene 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 en los objetos del juego. El subproceso de actualización sabe cuándo se llamó previamente, la hora actual y desde allí 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 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 tus objetos en función de sus vectores de velocidad y les aplicará gravedad en función de tu constante de gravedad. Lo mejor de todo es que lo hace independientemente de la velocidad de las computadoras.
Para responder a tu otra pregunta, sí, los objetos tendrán constantemente la "fuerza" de la gravedad en su vector y. Entonces colisionará constantemente con el piso. Sin embargo, una cosa que quiere hacer es usar un valor de Epsilon para eventualmente llevar la velocidad de su GameObject a cero. Luego, durante la detección de colisiones como parte de su proceso de poda, por lo general, puede omitir la comprobación si un objeto que no se mueve está colisionando con algo (¡no al revés!).
Lo que me gusta hacer con las colisiones es que una vez que encuentro objetos colisionando (penetrándome), los apartaré por su distancia de traducción mínima (MTD) que los separa. Este paso es clave; de lo contrario, obtendrás el error que se ve con frecuencia en los juegos de objetos "pegados" que se mueven nerviosos. Una vez que están separados, calculo mi respuesta de colisión.
Al usar este método funcionará bien en su escenario descrito de una plataforma ascendente. La plataforma seguirá aumentando, el gameObject se separará usando el MTD entre sí mismo y la plataforma y, naturalmente, se levantará con él.
Si necesita ayuda con la respuesta de colisión, le sugiero que mire: