2010-06-28 14 views
8

Estoy escribiendo un juego donde una gran cantidad de objetos tendrán "efectos de área" sobre una región de un mapa en mosaico en 2D.Estructura de datos efectiva para áreas espaciales superpuestas

características requeridas:

  • Varios de estos efectos de área pueden solaparse y afectar a la misma baldosa
  • Debe ser posible acceder de manera muy eficiente la lista de efectos de cualquier baldosa dada
  • Los efectos de área puede tener formas arbitrarias, pero normalmente tendrá la forma "hasta X distancia de las teselas del objeto que causa el efecto" donde X es un entero pequeño, generalmente 1-10
  • Los efectos de área cambiarán con frecuencia, por ejemplo como los objetos se mueven a diferentes lugares en el mapa
  • mapas podría ser potencialmente grandes (por ejemplo, 1000 x 1000 azulejos)

Qué estructura de datos que funciona mejor para esto?

Respuesta

2

Siempre que realmente tienen una gran cantidad de efectos de área ocurriendo simultáneamente, y que van a tener formas arbitrarias, me gustaría hacerlo de esta manera:

  • cuando se crea un nuevo efecto, es almacena en una lista global de efectos (no necesariamente una variable global, sólo algo que se aplica a todo el juego o la corriente de juego-mapa)
  • se calcula qué azulejos afecta, y almacena una lista de los azulejos contra el efecto
  • cada uno de los azulejos es notificado del nuevo efecto, y almacena una referencia de nuevo a él en una lista por losa (en C++ que haría uso de un std :: vector para esto, algo con almacenamiento contiguo , no un ligado lista)
  • terminando un efecto es manejado por iteración a través de los azulejos interesados ​​y la eliminación de las referencias a ella, antes de destruirlo
  • moverlo o cambiar su forma, se maneja mediante la eliminación de las referencias como más arriba, realizando los cálculos de cambio, y luego volviendo a unir las referencias en las teselas ahora afectadas
  • también debe tener una verificación invariante solo de depuración que recorre todo el mapa y verifica que la lista de teselas del efecto coincide exactamente con las teselas del mapa que la referencia.
+0

Gracias Kylotan: este parece ser el enfoque más "integral" para garantizar un acceso rápido. Creo que puedo terminar haciendo algo como esto, pero usando un enfoque de tipo cuadribanda para el almacenamiento por casilla, y tal vez algún tipo de memoria caché inteligente para las listas por casilla para evitar mucha duplicación de listas – mikera

+0

No entiendo qué beneficio obtienes del árbol cuádruple: un mapa de teselas es típicamente (por definición) un hash 2D desde la posición hasta las teselas. Normalmente, solo necesitas un árbol cuádruple cuando aún no tienes un sistema de búsqueda tan rápido (por ejemplo, para mundos continuos, no para mosaicos). – Kylotan

1

Generalmente BSP-Trees (o quadtrees o octrees).

+0

¿Qué pondrías entonces en los nodos para representar los efectos de área de una manera que sea compatible con una consulta y actualización eficiente? – mikera

1

Algunas soluciones de fuerza bruta que no se basan en la informática de lujo:

1000 x 1000 no es demasiado grande - sólo un meg. Las computadoras tienen Gigs. Podrías tener una matriz 2d. Cada bit en los bytes podría ser un 'tipo de área'. El 'área afectada' que es más grande podría ser otro poco. Si tiene una cantidad razonable de diferentes tipos de áreas, puede usar una máscara de bits de varios bytes. Si eso resulta ridículo, puede hacer que los elementos de la matriz apunten a listas de objetos de tipo de área superpuestos. Pero luego pierdes eficiencia.

También podría implementar una matriz dispersa utilizando una tabla hash fuera de las coordenadas (por ejemplo, clave = 1000 * x + y), pero esto es mucho más lento.

Si por supuesto si no te importa codificar las formas sofisticadas de informática, ¡generalmente funcionan mucho mejor!

+0

Habrá una gran cantidad de tipos de efectos, por lo que probablemente tenga que ser algún tipo de lista. pero luego está el problema potencial de que un solo efecto de "hasta 10 casillas" podría requerir la generación o actualización de 441 listas diferentes ...? – mikera

2

Por lo general, depende de la densidad de su mapa.

Si sabes que cada tesela (o parte principal de las teselas) contiene al menos un efecto, deberías usar una cuadrícula regular: una matriz 2D simple de mosaicos.

Si su mapa está débilmente lleno y hay un montón de mosaicos vacíos, tiene sentido usar algunos spatial indexes como árboles cuádruples o árboles R-BSP.

+0

Buenas ideas: supongo que el mapa probablemente tenga un 10-20% de cobertura con efectos de área, por lo que un enfoque de tipo de índice espacial es probablemente mejor – mikera

+0

Un índice espacial le permite no desperdiciar memoria para las teselas no utilizadas. Pero tenga en cuenta que la mayoría de dichos índices están diseñados para almacenar datos estáticos. Como entiendo, en su caso, todas las "áreas afectadas" pueden moverse a lo largo del mapa, por lo que deberá reconstruir/actualizar el índice espacial todo el tiempo. Esto puede causar una sobrecarga significativa. –

1

Si tiene un rango máximo conocido de cada efecto de área, puede usar una estructura de datos de su elección y almacenar las fuentes reales, que están optimizadas para la Prueba de colisión 2D normal.

Luego, cuando compruebe los efectos en un mosaico, simplemente verifique (estilo de detección de colisión optimizado para su estructura de datos) todas las fuentes de efectos dentro del rango máximo y luego aplique una función de prueba definida (por ejemplo, si el área un círculo, verifique si la distancia es menor que una constante; si es un cuadrado, verifique si las distancias xey están cada una dentro de una constante).

Si tiene una cantidad pequeña (< 10) de formas de "campos" de efectos, puede incluso hacer una detección de colisión única para cada tipo de campo de efecto, dentro de su rango máximo precalculado.

Cuestiones relacionadas