¿Dónde se debe colocar la lógica de detección de colisión?

19

Estoy desarrollando un pequeño motor de juego en 2D. Los personajes tienen un método de pintura que actualmente hace lo siguiente:

  1. Calcule la nueva posición del personaje según su velocidad, etc.
  2. Actualice la celda de la cuadrícula de colisión **
  3. Dibuja el personaje en la nueva posición

** He creado una cuadrícula de colisión para reducir el número de controles de intersección.

Ahora el algoritmo básico que he pensado para detectar la colisión es:

For Each Character
    Check intersection with characters in surrounding 8 cells

Simplemente puedo colocar este código en el método de pintura. Pero aquí está el problema que anticipo.

Supongamos que dos caracteres A y B se encuentran en celdas adyacentes en la cuadrícula de colisión. Ahora, según el algoritmo anterior en la iteración del carácter A, detectará que ha chocado con B. En la iteración para el carácter B, detectará que ha chocado con A.

Pero tengo una idea de que cuando A detecta que ha chocado con B, debería informarle a B que ha chocado con A. Esto ahorraría muchas comparaciones cuando hay más de 2 actores colisionando. Pero no estoy seguro de cómo manejar esto. Creo que en lugar de que cada personaje verifique su colisión, debería verificar la colisión dentro del bucle del juego.

¿Sería correcto este enfoque? ¿Cómo has manejado este tipo de problema? Pensé en la rejilla de colisión yo mismo. ¿Hay alguna alternativa a la lógica de cuadrícula de colisión?

Galleta
fuente
Perdón por hacer trampa, pero en una biblioteca de física 2D especializada. La física del juego suele ser muy aproximada, por lo que cualquier solución que no haga que el juego no sea jugable está bien, pero si quieres resolverlo correctamente, solo usa física especializada como Box2D ... :-D
user712092

Respuestas:

14

El enfoque habitual para la detección de colisiones es no hacer que A o B detecten colisiones por su cuenta.

En su lugar, primero mueve todos los objetos, luego hace que un sistema de colisión separado busque colisiones entre todos los pares de objetos, informando a cada objeto sobre las cosas con las que ha chocado, y finalmente renderiza todos los objetos.

Entonces, en esencia, en lugar de hacer "mover, verificar colisiones, dibujar" dentro de su función Paint (), divide "mover" y "dibujar" en funciones separadas que llama por separado (primero "mover" para cada objeto, luego "dibujar" para cada objeto). Y entre ellos, verifique las colisiones.

Nota avanzada: si alguno de sus objetos se mueve en reacción a las colisiones detectadas, es posible que deba repetir el paso "buscar colisiones entre todos los pares de objetos", en caso de que la respuesta de colisión de un objeto provoque otra colisión.

Trevor Powell
fuente
Esta es la forma correcta de hacer las cosas. Deje que los objetos manejen sus responsabilidades y el sistema de colisión debe decidir qué sucede cuando se encuentran con un obstáculo. También puede tener un rectángulo / cilindro de colisión (2d / 3d) alrededor de sus personajes como una especie de disparador temprano.
James P.
¡Excelente! Con respecto a la nota avanzada, ¿no deberían verificarse las colisiones solo para los objetos que se mueven en reacción a la colisión y los objetos con los que chocan en la nueva posición? Habrá una cadena de comprobaciones pero evitará comprobar la colisión de todos los objetos.
Cracker
Cómo manejar esto - gamedev.stackexchange.com/questions/13076/…
Cracker
1

Ejecuto un bucle para todos mis personajes en el bucle del juego como tú dices.

La forma en que lo hago es con un estado en cada uno de mis personajes, por lo que si A y B chocan mientras A verifica la colisión, A y B están configurados para golpear. Al comienzo del bucle de B, comprueba si ya se ha alcanzado, si es así, id no ejecuta el bucle.

Puse el código de efecto en el bucle para que cualquier acción que se debe tomar en B haya sucedido en el bucle de A, por lo que no debería haber ninguna razón para que B lo verifique, ya que esto podría estropear el resultado de la colisión, aunque esto puede ser diferente para usted .

Skeith
fuente
Pero en este caso, cuando A detecta la intersección con B, B.hit se establecerá en verdadero y, por lo tanto, B no verificará NINGUNA intersección. Pero si otro personaje C se cruza con B, ¿B no lo detectará?
Cracker
Lo siento, lo tengo. Como A no se cruza con C, C.hit seguirá siendo falso. B no verificará las colisiones. Pero C verificará y pasará la información a B de que hay una colisión entre B y C. ¡Genial!
Cracker
Pero supongo que si todos A, B y C se cruzan entre sí, habría un problema. A establecerá B.hit y C.hit en verdadero. B y C sabrán que han chocado con A. Pero dado que su propiedad de impacto es verdadera, no comprobarán la colisión. La colisión entre B y C pasará desapercibida.
Cracker
Puede colarse en un método similar colocando cada objeto de colisión viable en una colección de algún tipo, luego solo verificando la colisión con las cosas que vienen después del objeto en la colección. IE: A comprueba vs B, C, D; B comprueba vs C, D; C comprueba vs D. No es necesario comprobar cada uno de los que están detrás, ya que ya se verificó desde el turno del que está detrás. No es tan rápido como omitir por completo la colisión del elemento, pero no obstante es útil.
Lunin