¿Cuáles son los buenos algoritmos para generar bordes / áreas estatales en mapas estelares 2D?

9

Estoy tratando de generar un mapa estelar bidimensional bastante grande que muestre diferentes facciones / estados, cada uno con uno o más sistemas estelares. Me gustaría crear automáticamente bordes / áreas para las facciones.

La idea es esencialmente pasar de algo como esto (los puntos representan sistemas estelares en un plano 2D, los colores son afiliaciones de facciones)

Sistemas estelares y su afiliación de facción

a esto

Sistemas estelares con áreas de facción

Generar mapas como este parece un requisito bastante común, por lo que mi pregunta real es esta: ¿existen algoritmos estándar para generar áreas de estado como se muestra? Si es así, ¿podrías señalarme? Si no, ¿se te ocurre un buen algoritmo (la idea básica o el pseudocódigo están bien)?

El rendimiento del algoritmo no es una preocupación principal para mí, por lo que prefiero tener un mapa "más bonito" que uno más rápido de generar. Esta pregunta similar ofrece un enfoque que probablemente sea aplicable a mi problema, aunque con alguna "prettificación" necesaria: Cómo crear un mapa a partir de un gráfico

Permítanme explicar a qué me refiero cuando digo más bonita: al final de la pregunta vinculada, la persona que pregunta presenta su resultado final después de implementar la respuesta aceptada. Mi primer problema aquí: las áreas para los nodos # 6, # 9 y # 12 son muy pequeñas y de forma extraña. Además, en lugar de los bordes afilados, preferiría una apariencia más suave y curva.

Mis propias ideas hasta ahora, incluidas las desventajas / preguntas respectivas que veo con ellas:

  • Genera un polígono de "casco convexo" para cada facción, luego expande un poco hacia afuera. Problemas: sin características cóncavas. Además, ¿cómo manejas las superposiciones?
  • Genere un gráfico voronoi para los puntos, luego use los bordes del polígono voronoi entre los sistemas vecinos de diferentes facciones como bordes. Problema: Polígonos grandes en los bordes del mapa: ¿cómo los identifico y los arreglo?
  • Genere un polígono de tamaño fijo para cada punto, una todos los polígonos para una sola facción (resultando en un "polígono de facción" grande y potencialmente complejo). Luego haz algo para conciliar las áreas superpuestas entre dos facciones. Problemas: ¿Cómo haría esto exactamente? No es exactamente un proceso trivial. ¿Qué pasa si hay superposición entre más de dos facciones?

Tu ayuda es apreciada.


Anexo: Después de pensar en las dos primeras respuestas y sus respectivos enfoques para resolver el problema, me di cuenta de que mis requisitos anteriores están incompletos.

Tengo que agregar que el mapa puede tener áreas escasamente pobladas, lo que significa que puede haber una estrella aislada o un grupo de estrellas. Me gustaría mostrar cada uno de esos grupos con su propia área de color contigua. Algo como esto:

Sistemas estelares con áreas de facción, diferentes grupos

Me doy cuenta de que esto podría necesitar un primer paso que identifique los grupos y luego ejecutar el algoritmo real para cada uno de los grupos.

Grüse
fuente
(lluvia de ideas) Es posible que pueda llenar el resto del espacio con ruido azul (por ejemplo, disco de Poisson ) y luego ejecutar voronoi para obtener una asignación de color. Los puntos agregados se asignarían a la región de fondo blanco.
amitp
@amitp ¡Hola, Amit, es un honor tenerte comentando aquí! He tomado una gran cantidad de inspiración y conocimiento práctico al leer sus artículos de Red Blob Games. Más sobre el tema: la idea de generar puntos adicionales tiene sentido, ¿alguna razón en particular por la que mencionas específicamente el ruido azul ?
Grüse
... Supongo porque parece una distribución más natural que otros sabores de ruido.
Grüse

Respuestas:

16

Creo que la idea de Voronoi es buena. Cada estrella se convierte en un punto de partida para Voronoi, y luego las regiones de Voronoi muestran las áreas de propiedad de cada facción. Sin embargo, hay algunos cambios que harán que funcione mejor:

  1. Como mencionaste, hay áreas vacías que no deberían asignarse a una facción. Voronoi creará grandes polígonos que se extenderán a áreas donde la facción no debería alcanzar. Para solucionar esto, use un algoritmo de ruido azul como el disco de Poisson para llenar el espacio desocupado con estrellas "que no pertenecen a nadie". El ruido azul es aleatorio pero distribuido de manera uniforme (también podría ser útil para generar sus ubicaciones de estrellas).
  2. Voronoi produce regiones en bloque. Para producir celdas más redondas, reemplace el cálculo del circuncentro de Voronoi con un cálculo de centroide. He escrito un poco sobre esto aquí con algunas imágenes de comparación.
  3. Voronoi produce polígonos, pero desea áreas redondas. En cada esquina, hay tres polígonos. Cuando los tres son la misma facción, puedes dejarlo solo. Cuando dos son la misma facción, introduce una curva bezier cuadrática que desplace el límite hacia la otra facción. Cuando las tres facciones son diferentes, puedes dejar la esquina sola o puedes introducir tres curvas bezier para alejar todas las fronteras una de la otra. No estoy seguro de cuál se ve mejor.

Aquí está la salida:

Mapa de Blobby

También escribí una página que te permite pintar las regiones para ver cómo se verían.

amitp
fuente
Esto encaja perfectamente con mi caso de uso, ¡muchas gracias! Debo decir que es igualmente impresionante y deprimente que hayas podido armar un ejemplo interactivo tan rápido, mientras que probablemente me tomará al menos unos días incluso reproducir lo que presentaste aquí :) Espero con interés ese artículo tutorial.
Grüse
4

Uno de los muchos métodos es un mapa de influencia . Puede buscar implementaciones de código específicas, pero el algoritmo básico es bastante simple.

Para cada objeto de facción (por ejemplo, sistema estelar), asigna un valor positivo (activo). Para todos los objetos de otras facciones, asigne un valor negativo (frío). La magnitud del calor o el frío debe basarse en la influencia que usted cree que el objeto ejerce sobre su entorno y sus vecinos. Estos valores no tienen que ser proporcionales si finalmente quieres mantener un "dmz" entre facciones.

Use estos detalles para crear una cuadrícula temporal (por ejemplo, matriz) que se aproxime a los píxeles de su mapa. Puede construir dicha cuadrícula con la resolución que desee, incluyendo 1: 1.

Luego, use la ecuación de transferencia de calor / campo para iterar y propagar las fuerzas de los objetos de facción (calor) contra las fuerzas de los objetos adversarios (frío) para cada celda vecina en la cuadrícula.

Enjuaga y repite para cada Facción en tu mapa creando cuadrículas de facción separadas para cada una.

Finalmente, interpola las cuadrículas de facciones para producir un contorno de influencia para cada facción. Luego transfiere esa cuadrícula de nuevo a tu mapa de píxeles dada la resolución que usaste para la cuadrícula (agregando cualquier color específico de facción, etc.).

El arte en este proceso es determinar cuánta influencia debe tener cada objeto y qué elementos del juego usas para cuantificar ese valor.

Además, los productos de este método se pueden usar para todo tipo de otras cosas, como la toma de decisiones.


Referencia adicional: hilo de discusión sobre los orígenes del mapeo de influencia .

J'Eight
fuente
Este enfoque debería ser obvio, pero nunca se me ocurrió. ¡Gracias por llamar mi atención! Un pensamiento: mis mapas pueden ser escasos en ciertas áreas, mientras que otras áreas están densamente llenas de estrellas de diferentes afiliaciones una al lado de la otra. ¿Hay alguna manera de usar diferentes tamaños de celda de cuadrícula para las diferentes áreas? Pensando a lo largo de las líneas de un quadtree o similar.
Grüse
2

Deberías mirar los diagramas de Voronoi. Aquí está la definición en wikipedia:

En matemáticas, un diagrama de Voronoi es una división de un plano en regiones basadas en la distancia a puntos en un subconjunto específico del plano.

Los puntos básicos generalmente se generan aleatoriamente y a menudo se denominan nodos. En su caso, cada nodo podría ser su estrella. De esa manera, la facción asociada con las estrellas se puede asociar con la celda voronoi que rodea a la estrella y cuando se ha calculado cada celda, se unen las que tienen la misma facción y deben tener un borde bastante limpio alrededor de las estrellas.

La biblioteca FastNoise tiene soporte para diagramas de Voronoi, por lo que tal vez deberías mirarlo.

Alisamiento de las regiones.

Mantenga sus estrellas en una "matriz segura" y use una copia de la misma donde realmente agregue más puntos mediante la interpolación de los vecinos más cercanos y genere el diagrama a partir de esos puntos. Debería darte regiones más suaves.

Otras ideas El algoritmo de la fortuna se basa en una línea recta que barre el plano cartesiano. Una idea interesante sería usar un círculo para barrer el avión desde el centro de su galaxia / espacio en su lugar, tal vez eso podría conducir a algunas formas interesantes también.

Manipulación de la geometría

Su última idea de combinar polígonos más pequeños en otros más grandes y luego arreglar los bordes requerirá algoritmos de spline avanzados para modificar las formas. No estoy seguro de si eso lo haría eficiente o atractivo. Estoy bastante seguro de que el diagrama de voronoi con teselación adicional es el camino a seguir, ya que soluciona el problema del borde por sí mismo e incluso puede ofrecer algunos datos adicionales por sí mismo, como la distancia desde los bordes (que podría usarse para determinar las zonas de conflicto entre las diferentes facciones, la probabilidad de encontrar diferentes tipos de barcos, etc.)

BadgerBadger
fuente
Tenga en cuenta que OP ya se refirió a una respuesta usando diagramas de Voronoi, por lo que conocen la técnica, pero han solicitado modificaciones específicas para cambiar la apariencia de los bordes. ¿Puede ampliar su respuesta para abordar esas solicitudes específicas?
DMGregory
Lo sentimos,
leí
¡Gracias por enmendar su respuesta! La idea de suavizado es interesante. Tengo dos problemas con el enfoque de Voronoi: Uno: ¿cómo puedo detectar y limitar los puntos "externos" para que los bordes no se extiendan hasta los bordes de la pantalla (vea la segunda imagen de mi pregunta). Dos: en áreas escasamente pobladas, Voronoi no da grandes resultados porque los polígonos se vuelven enormes. ¿Quizás haya una solución obvia para aquellos que no veo?
Grüse
¿Sería una opción para agregar puntos por su cuenta para enmarcar el área? Luego, cuando renderiza el gráfico, si una línea alcanza el borde real de la imagen, simplemente no la dibuja, ya que no formará parte del área de juego. El segundo problema debería poder solucionarse con el suavizado. Podría agregar más puntos cuando estén más separados para mantener algún tipo de "tamaño de cuadrícula" consistente.
BadgerBadger
@BadgerBadger sí, estoy experimentando con agregar puntos en este momento
Grüse