Detección de colisión 2D

11

Asumamos que estoy usando este personaje.

pájaro
(fuente: iconbug.com )

¿Cómo implementaría la detección de colisión? El uso de un cuadro delimitador no parece ser una buena aproximación, porque la forma del pájaro no está cerca de un cuadrado.

Estaba pensando en tener una especie de estructura de datos de árbol cuádruple dentro del objeto que represente partes de la imagen. Cada hoja puede ser false(en caso de que cubra el espacio blanco / transparente fuera del ave) o true(en caso de que represente un área del ave, es decir, pico, ojo, etc.). Luego, de alguna manera, pruebe el único obstáculo en la escena para colisión con el pájaro.

Pero mis problemas en mi enfoque son:

  1. No sé cómo inicializar el árbol cuádruple.
  2. Una vez que se inicializa el árbol cuádruple, no estoy seguro de cómo atravesarlo y usarlo una vez que el obstáculo está dentro de las coordenadas de la imagen.

¿Cómo haría la detección de colisión con personajes no cuadrados?

LE: El otro enfoque que he visto fue utilizar múltiples cuadros delimitadores. Por ejemplo, tendría una o algunas cajas delimitadoras para el pico, y luego algunas para el cabello o la cola. Pero puede volverse tedioso. Si este es un enfoque válido en mi caso, ¿cómo generaría esos cuadros delimitadores? Dudo que tenga que tenerlos codificados en mi programa.

LE2: Me importan las colisiones bastante precisas. No puedo imaginar cómo un solo cuadro delimitador o círculo puede al menos aproximarse decentemente a esa forma, por lo que este enfoque no funcionará.

asíncrono
fuente
2
Una nota general: usaría ambos, un cuadro delimitador y una verificación más granular: la verificación granular tendrá una penalización de rendimiento más alta, por lo que desea que se ejecute lo menos posible. Por lo tanto, primero marque el cuadro delimitador y solo si se golpea, vaya un nivel más profundo y pruebe su enfoque más granular (lo que sea que sea).
Philip Allgaier
Gracias, estaba planeando hacer eso de todos modos, pero no estoy completamente seguro de cuál debería ser el 'control granular'. :)
async
1
Falta el único detalle importante: ¿Qué quieres hacer con él? ¿Te preocupan las colisiones exactas? ¿Estás contento de aproximar al personaje con un círculo? ¿Quieres que las partículas de polvo choquen con los ojos del personaje por separado del resto?
Anko
@ Anko ¿Cómo puedes aproximar esa forma con un círculo? Me interesan las colisiones bastante precisas, no realmente precisas en píxeles, sino algo que se verá bien / natural.
async
1
Al igual que este . ¿Qué significan incluso "bueno" y "natural"? ¿Es esta una pregunta filosófica?
Anko

Respuestas:

12

Colisionador circular. Lo suficientemente bueno como para decirlo, a menos que esté haciendo algo elegante con ciertas partes afectadas por la física o el choque que parece poco natural, e incluso si necesita dividirlo en varias partes, tengo algo que decirle:

No lo compliques demasiado.

No necesita una estructura de árbol cuádruple completa para esto. Solo tiene varios cuadros o círculos en una matriz recta y luego se cruzan con todos ellos. Esto no puede ser un rendimiento lo suficientemente crítico y no ganará mucho al usar un árbol cuádruple.

Jonkel
fuente
3
Sí, solo haz una pequeña variedad de varias formas si una sola forma no la cubre. Por ejemplo: i.imgur.com/Dd4yyGN.png
MichaelHouse
Gracias Jonkel y @ Byte56. Usar algunas formas parece la solución correcta en mi situación. Fácil de implementar, preciso y rápido. ¡No puedo creer que salté directamente a los árboles cuádruples sin considerar esto! Uh
async
Un colisionador circular para el cuerpo y un rectangular para el pico, para mayor precisión.
Kroltan
14

Un proceso de verificación en dos pasos

En el primer paso, marca la casilla delimitador , y si no hay colisión allí, la prueba ha terminado. Si hay una colisión, pasa al segundo pase

En la segunda pasada , si quieres más precisión y quieres una verdadera solución de píxeles perfectos, entonces puedes hacer eso, una pasada de verificación de píxeles perfectos

Dado que su imagen es un PNG (o cualquier otro formato de archivo que contenga un canal alfa), esto sería bastante fácil

  1. Calcule el área de intersección entre ese único objeto en la escena y el pájaro, generando un simple rectángulo de intersección en ambas imágenes
  2. Dentro de esa intersección, verifique que cada píxel tenga un valor alfa> 0 en AMBAS imágenes
  3. Si existen tales píxeles, tienes tu colisión. De otra manera no

Si observa el canal alfa de sus imágenes, puede ver cómo ya tiene toda la información que pueda necesitar para una colisión perfecta de píxeles

canal alfa de la imagen

Las colisiones perfectas en píxeles suelen ser caras, por lo que hacer una estimación aproximada al principio con un cuadro delimitador o una figura de colisión más detallada (como la que sugirió Anko) puede ahorrarle un tiempo precioso

El cuadro de límite de colisión detallado "más fino" Anko sugirió:

cuadro delimitador más detallado

PD: Si su imagen tiene un halo, un efecto u otro canal alfa distinto de 0 con el que no desea colisionar, el umbral del algoritmo se puede ajustar fácilmente para adaptarse a ese

codemonkey
fuente
1
¡Gracias! Pero no necesitaré una precisión perfecta de píxeles después de todo. Sin embargo, una excelente respuesta será útil en una fecha posterior.
async
por supuesto amigo, sí, la colisión perfecta de píxeles es casi siempre una exageración, excepto en los juegos que realmente lo necesitan (como los luchadores 2D)
codemonkey
3

Usaría un círculo para el cuerpo y un solo rectángulo para el pico, pero esa es solo mi opinión. Sin embargo, complicar demasiado su geometría de colisión puede ralentizar su aplicación, prácticamente está duplicando (o más) el número de caracteres en la pantalla.

igrad
fuente
0

Tal vez podría usar algún tipo de colisionador poligonal / borde inestable.

No estoy seguro exactamente cómo funcionaría esto, pero:

dos objetos: objeto 1: el pájaro (o1), objeto 2: lo que podría golpear al pájaro (o2)

1) Defina una forma delimitadora que sea un polígono que se ajuste estrechamente al primer objeto (o1) en cuestión.

2) Obtenga los bordes de o1, o2 que posiblemente podrían colisionar sin que posiblemente puedan colisionar sin que o2 pase a través de o1 o viceversa.

Con la posición y el tamaño de la forma (o2) probablemente podría aislar los bordes (de o1) que no pueden ser golpeados, ya sea porque están "detrás" de otro borde (de o1) que está más cerca de o2. Si tenía un triángulo rectángulo cuya hipotenusa estaba hacia arriba y hacia la derecha y un rectángulo que se acercaba directamente (con el lado largo a lo largo del eje x), puede decir qué aristas omitir porque son valores iniciales y finales y son ambos encima o debajo del rectángulo.

3) Determine si uno de los puntos en un borde de o2 es el mismo que un punto en cualquiera de los bordes de o1 que seleccionó en el paso 2.

este concepto probablemente funciona mejor para colisionar polígonos (es decir, cosas con bordes claros), pero tal vez pueda tratar un círculo como un borde largo (por ejemplo, si o2 fuera un círculo).

Jeremy Harton
fuente