Estoy creando un juego de estrategia bidimensional basado en turnos usando c ++ y SFML-2.0. El movimiento se basa en la distancia en lugar de en la cuadrícula, con varias piezas diferentes en forma de triángulo que, en un giro dado, cada una puede rotar en su lugar o avanzar.
El movimiento funcionará de tal manera que el jugador seleccione una ubicación para que la pieza se mueva, lo que genera un camino potencial para que la pieza tome. Una vez que el jugador confirma su decisión, la pieza se moverá a lo largo de ese camino a la ubicación deseada. Las rutas están limitadas por dos factores: distancia, qué tan lejos puede llegar una pieza, teniendo en cuenta cualquier giro (por lo tanto, si hay una curva, será la longitud a lo largo de la curva, y no directamente de un punto a otro); y ángulo de dirección, qué tan lejos puede girar la pieza en cualquier punto (y hasta todos) mientras se mueve (por ejemplo, de -30 a 30 grados).
Mi pregunta es, ¿cómo debo determinar el rango de ubicaciones potenciales que el jugador puede seleccionar para mover la pieza?
No estoy completamente seguro de qué ecuaciones y / o algoritmos usar aquí. Mi plan original era extremadamente complicado, hasta el punto de que era casi imposible de implementar, y mucho menos explicar, y en este punto estoy totalmente perdido con el proyecto estancado.
¿Cómo puedo determinar el alcance que puede mover una unidad, teniendo en cuenta su radio de giro?
Por ejemplo, en la imagen de abajo. Las líneas roja, azul y verde tendrían la misma longitud. El círculo morado indica el rango de movimiento que la unidad puede mover. (La forma es probablemente inexacta y las líneas probablemente no son en realidad la misma longitud, pero se entiende la idea)
fuente
Respuestas:
Genere un campo de flujo o distancia, utilizando Dijsktra's.
Esencialmente, complete una cuadrícula utilizando el algoritmo Dijkstra sin destino (probablemente un nombre diferente para eso; no lo sé). Simplemente tome cada nodo abierto, calcule vecinos accesibles, insértelos en la lista abierta, establezca en la lista cerrada, actualice la ruta "siguiente" del nodo principal, según corresponda, etc. Al determinar el costo para llegar a un nuevo nodo, tenga en cuenta las limitaciones de giro.
El resultado ahora será que tiene una red de todos sus nodos sobre cómo volver al inicio. Los nodos a los que no se puede llegar no habrán sido tocados por el primer paso. Los nodos a los que se puede llegar tendrán un elemento "siguiente nodo a lo largo de la mejor ruta posible hacia el padre" calculado para que pueda resaltar todos los nodos y luego usar esta información para mostrar o ejecutar la ruta de movimiento cuando el usuario se desplaza o hace clic en las áreas resaltadas.
fuente
Una solución de fuerza bruta sería:
Entonces, comenzando con el círculo azul, procesarías tus caminos y terminarías con el círculo púrpura. Luego puede usar esos puntos con un punto central en la unidad para hacer los triángulos rojos necesarios para mostrar la forma. (Solo hacer esa imagen me hace darme cuenta de que esa forma no es correcta, pero será interesante ver qué es realmente correcto)
fuente
Voy a ampliar la solución de Sean en una respuesta separada, ya que representa un enfoque diferente de lo que inicialmente estaba proponiendo.
Esta solución probablemente representa el método más accesible. Requiere particionar su entorno en nodos. Sí, se trata de reintroducir un enfoque basado en la cuadrícula, pero se puede hacer relativamente bien o se puede utilizar para encontrar una ruta amplia con un posicionamiento más fino manejado dentro del nodo. Cuanto más gruesa sea la estructura del nodo, más rápido será el pathfinding.
El gran problema aquí es que en realidad estás lidiando con el frente del barco, por lo que muchas soluciones de búsqueda de caminos tradicionales no se pueden usar sin modificación. Por lo general, son independientes de la ruta, ya que no les importa cómo llegaste al nodo en el que te encuentras. Eso funciona bien cuando la aceleración, la desaceleración y el giro son instantáneos y libres. Desafortunadamente para ti girar no es gratis. Sin embargo, dado que realmente hay una información adicional que se elimina en esta simplificación, podemos codificarla como otra variable. En física, esto se conocería como espacio de fase.
Asumiendo 2 dimensiones por ahora, puede extrapolar por 3:
Normalmente, necesitaría un nodo para cada posición de coordenadas discreta permitida. Por ejemplo:
Etc. Construiría un nodograma de puntos adyacentes y los conectaría por adyacencia espacial. Entonces usarías el algoritmo de Dijkstra, matando nodos que excedan el valor de movimiento permitido para el turno, hasta que no queden nodos vivos y no explorados que permanezcan conectados a nodos explorados. Cada nodo realiza un seguimiento de la menor distancia requerida para alcanzarlo.
Para expandir este método para que pueda usarse con Rotación, imagine este mismo nodograma en 3 dimensiones. La dirección Z corresponde a la rotación / orientación, y es cíclica, lo que significa que si sigue viajando en la dirección + Z volverá a donde comenzó. Ahora, los nodos correspondientes a posiciones adyacentes solo están conectados a través de la cara que corresponde a esa dirección. Usted itera sobre los nodos conectados a nodos ya explorados como de costumbre. Recomendaría restringir a N, NE, E, SE, S, SW, W, NW en este esquema.
Esta solución puede decirle todas las regiones accesibles del espacio, así como el mejor camino para llegar allí, cuánta rotación tiene cuando llega allí y todas las orientaciones que podría tener cuando llegue allí.
Luego, al ejecutar la ruta, puede interpolar / dividir cúbicamente su camino para que parezca más auténtico.
fuente
Parece que es posible que primero deba decidir cómo desea exactamente que funcione el encendido sobre la marcha. Opciones como:
Si se mueven dentro del cono, primero gire, luego comience a moverse. Esta es la solución más fácil de implementar y de seguir. También es menos interesante, así que no me gustaría usarlo.
Giro continuo mientras se mueve, hasta un total de 45 grados. Este es mucho más complicado y, con suerte, el que buscas. Integrar numéricamente sobre el camino usando un paso de tiempo fijo es probablemente la forma más fácil de acercarse a este. Su cono estará limitado por el giro máximo (+ X grados en cada paso) y mínimo (-X grados en cada paso).
La mejor manera de atravesar el espacio con el segundo de estos requisitos depende en gran medida del entorno en el que se moverán. Si hay muchos obstáculos por los que hay que sortear, las cosas pueden volverse realmente difíciles y muy caras. Sin embargo, si no lo hay, entonces puede cargar por adelantado (e incluso disminuir) la rotación para terminar en la ubicación deseada.
Tengo la sensación de que es posible que haya cubierto solo parcialmente los temas sobre los que tenía una pregunta, así que siéntase libre de agregar más en los comentarios y puedo ampliar la discusión.
fuente