Estoy desarrollando un juego espacial en 2D sin fricción, y me resulta muy fácil hacer que un misil de referencia orbita su objetivo. Tengo curiosidad por las estrategias anti-órbita.
Un ejemplo simple es un misil de referencia que simplemente acelera directamente hacia su objetivo. Si ese objetivo se moviera perpendicularmente a la trayectoria del misil y luego se detuviera, la aceleración del misil hacia el objetivo no sería suficiente para superar su propia velocidad, y el misil podría conducir a la órbita alrededor del objetivo, como se muestra:
- En el cuadro 1, el misil se dirige directamente a su objetivo, sin problemas.
- En el cuadro 2, el objetivo se ha movido a una nueva posición como se demostró. El misil continúa acelerando directamente hacia el objetivo (en rojo), mientras se mueve hacia donde el objetivo solía estar (en negro) debido a su velocidad existente.
- En el cuadro 3, la velocidad del misil continúa transportando el misil alrededor del objetivo (negro) mientras el vector de aceleración intenta desesperadamente tirar del misil hacia el objetivo.
- En los fotogramas 4 y posteriores, el misil cae en una órbita potencialmente estable alrededor del objetivo y nunca alcanza su objetivo. Las flechas negras indican un vector de velocidad, mientras que las líneas rojas indican vectores de aceleración en el mismo momento en el tiempo.
Considerando que no hay fricción en el espacio, no hay nada que disminuya la velocidad del misil y colapse la órbita. Una posible solución sería apuntar "detrás" del objetivo, y esto haría que la órbita se cerrara, pero ¿cómo se hace esto desde el punto de vista de la programación?
¿Cómo hago para que un misil guía alcance su objetivo?
Respuestas:
En primer lugar, debes hacer todos los cálculos sobre qué aceleración aplicar en el marco de referencia del misil (ahí es donde el misil es estacionario y todo lo demás se mueve a su alrededor, también llamado "coordenadas de objeto" o "coordenadas locales" en los motores de juego, aunque en nuestro caso también queremos que la velocidad sea exactamente cero).
La idea, entonces, no es apuntar al objetivo, sino apuntar al lugar donde estará el objetivo en el momento estimado del impacto. Entonces el algoritmo general se ve así:
Calcule cuánto tiempo le tomará al misil alcanzar el objetivo. Si el objetivo está volando directamente hacia él (recuerde, el misil es estacionario ), puede ser tan simple como calcular la distancia / velocidad , en otros casos puede ser más complicado. Si el objetivo puede intentar evadir, no podrá hacer una estimación perfecta de todos modos, por lo que está bien no ser muy preciso.
Suponiendo que la velocidad constante (estimación de primer grado) o la aceleración constante (estimación de segundo grado) del objetivo, calcule dónde estará en el tiempo estimado anterior.
Calcule la aceleración que conducirá al misil a estar aproximadamente en el mismo lugar al mismo tiempo.
Vuelva a proyectar la aceleración desde el marco de referencia del misil al global, utilícelo.
La parte importante aquí es obtener el tiempo estimado en el estadio de béisbol en bruto, y no olvidar las capacidades de aceleración del misil mientras lo hace. Por ejemplo, una mejor estimación de "el objetivo está justo delante de nosotros y volando en nuestra dirección" sería resolver la ecuación.
distancia = velocidad x tiempo + 1/2 x aceleración x tiempo 2
... por el tiempo (velocidad negativa para usar objetos voladores recta de distancia desde el misil), con la solución que está buscando utilizando el estándar de fórmula cuadrática siendo ...
tiempo = (√ ( velocidad 2 + 2 x aceleración x distancia ) - velocidad ) / aceleración
Agregar parámetros adicionales (arrastre, por ejemplo) rápidamente convierte esto en ecuaciones diferenciales sin soluciones algebraicas. Es por eso que la ciencia de cohetes es tan difícil.
fuente
@Martin Sojka ya te dijo qué hacer. En lugar de mejorar su respuesta, quiero proponerle otro enfoque más simple: DELOCK
Como dije en la trayectoria proyectada de un vehículo? , los objetos con capacidades de dirección limitadas "proyectan" un par de círculos de sombra: dos regiones a las que no se puede llegar mediante dirección directa (un toro y un hipertoro en dimensiones más altas).
Cuando vea que su objetivo está entrando en una de esas sombras de dirección, puede dejar de dirigir su objetivo y mantener otra dirección durante un tiempo limitado.
El desencadenante de desenganche se puede calcular fácilmente al aproximar su tori con un (doble) cono *:
Simplemente tiene que calcular el producto escalar entre su vector de dirección (normalizado) y su vector de desplazamiento objetivo ( Objetivo - Objeto / | Objetivo - Objeto |).
A medida que el producto escalar llega a cero, su dirección objetivo se vuelve perpendicular a su dirección, lo que lleva a una trayectoria circular **. Cuando el objetivo cae en la región cian, puede invertir su dirección de dirección para que pueda colocarlo fuera del área inalcanzable y volver a dirigir.
* Para ser honesto, esto no es un cono ... es otro tipo de superficie reglada generada por (semi) revolución de dos líneas no paralelas alrededor de un eje que pasa por la intersección y perpendicular a la línea bisectriz; La proyección en un plano 2D es igual que el doble cono, pero el eje de rotación es perpendicular al que genera el cono.
** Es poco probable que esa trayectoria sea circular ni elíptica o incluso cerrada. Lo más probable es que la trayectoria siga una trayectoria similar a la de un espirógrafo (un hipotrocoide) en 2D o incluso otros monstruos en 3 y más dimensiones. No se puede alcanzar el centro de tales curvas de todos modos y se ven como círculos, así que la trayectoria es "circular".
fuente
Su sistema de guía se basa en el supuesto de que acelerar directamente hacia el objetivo eventualmente hará que los objetos colisionen. Dado que esa suposición es falsa, la guía AI basada en esa suposición tampoco tiene éxito.
Así que deja de acelerar directamente hacia el objetivo. Agregue algo de lógica para detectar si la posición del objetivo es algo perpendicular a la dirección del movimiento del misil. Si es así, entonces el misil necesita acelerar hacia el objetivo, pero también ralentizar su movimiento hacia adelante. Entonces, en lugar de ir directamente hacia el objetivo, sesga la dirección de su aceleración para que la velocidad actual en su dirección de movimiento se ralentice.
Además, necesitará un disparador para asegurarse de que no vaya demasiado lento. Por lo tanto, agregue un poco de velocidad de umbral de modo que, si está por debajo de ese umbral, deje de hacer la polarización.
Una última cosa: ningún sistema de guía será perfecto. La razón por la cual los misiles pueden interceptar objetivos en la vida real es que los objetivos se mueven mucho más lentamente que los misiles, y los objetivos no son particularmente ágiles (en términos relativos). Si sus misiles no van a ser muchas veces más rápidos que los objetivos que persiguen, fallarán mucho.
fuente
El método más simple y avanzado para usar en juegos (y en la vida real) es la navegación proporcional.
Bajo el cojinete Constant disminuir el rango de lógica (CBDR), cuando dos objetos (misiles y de destino) están viajando en la misma dirección sin cambio en la línea de visión entre sí, que van a chocar.
Sightline, o Line of Sight (LOS) es una línea imaginaria entre el misil y el objetivo: el vector entre la posición del misil y la posición del objetivo. La tasa de cambio angular de este LOS es la tasa de rotación de LOS.
Cuando la tasa de rotación de LOS se convierte en cero, la línea de visión ya no cambia: los dos objetos ahora están en curso de colisión. Piensa en ti mismo persiguiendo a alguien mientras juegas fútbol americano. Si lo conduce de una manera que su cuerpo se ve "congelado" en su campo de visión (la línea de visión entre usted y él ya no cambia), colisionará con él siempre que mantenga su aceleración de carrera para mantener su cuerpo congelado. tu vista
Bajo navegación proporcional (PN), el misil acelera "N" veces más rápido que la velocidad de rotación de LOS. Esto obligará al misil a dirigir el objetivo hasta que la tasa de rotación de LOS se convierta en cero, es decir, el misil y el objetivo aparecen congelados en el estado a medida que la línea de visión ya no cambia, ahora están en curso de colisión. La variable "N" se conoce como constante de navegación (un multiplicador constante).
El comando de guía de misiles se debe dar de la siguiente manera:
Aceleración = Velocidad de cierre * N * Tasa de LOS
La tasa LOS puede derivarse fácilmente midiendo el vector LOS (posición objetivo - posición del misil) y almacenando su variable. El vector LOS del nuevo marco (LOS1) se resta por el vector LOS del marco antiguo (LOS0) para generar un delta de LOS; ahora tiene una tasa de rotación LOS primitiva.
Para simplificar la velocidad de cierre, puede usar el vector LOS actual en su lugar, por lo tanto:
Aceleración = (target_pos - missile_pos) * LOS_delta * N
N es la constante de navegación: en el mundo real, generalmente se establece entre 3 y 5, pero la cifra factible real en el juego depende en cierta medida de la frecuencia de muestreo a la que deriva la tasa / delta de LOS. Pruebe un número aleatorio (comience desde 3) y aumente hasta 1500, 2000, etc. hasta que vea el efecto principal deseado en el juego. Tenga en cuenta que cuanto mayor sea la constante de navegación, más rápido reaccionará el misil a los cambios de velocidad de LOS al principio del vuelo. Si su modelo de simulación de cohete de referencia es algo realista, una constante de navegación excesiva podría sobrecargar la capacidad aerodinámica de su misil, por lo que debe usar un número equilibrado basado en prueba y error.
fuente
Como señalan las otras respuestas de Martin y Nicol, es probable que desee guiar su misil no directamente al objetivo, sino de una manera que lo haga colisionar con el objetivo más adelante. Sin embargo, el método descrito por Martin es complicado y el descrito por Nicol es ineficiente.
Una forma más simple, pero aún bastante eficiente, de guiar un misil es ajustando su ángulo de acuerdo con el cambio de ángulo entre el misil y el objetivo. En cada marca, calcula el ángulo desde el misil hasta el objetivo, y lo compara con el ángulo de la marca anterior. La diferencia es la diferencia exacta que desea marcar en el ángulo del misil. Entonces, si el ángulo era 0.77 en una marca y 0.75 en la siguiente, querrá ajustar el ángulo del misil en -0.02. Este método es simple, y siempre que el objetivo esté "delante" del misil, es muy eficiente en términos de ruta elegida. También se aplica a cualquier cantidad de dimensiones, no solo en 2d.
Tenga en cuenta, sin embargo:
Este método se rompe si el misil y el objetivo están exactamente a la misma velocidad y viajan en paralelo. Bueno, teóricamente todavía traza un curso de colisión para el misil, solo lleva un tiempo infinito :) en la práctica, el misil siempre debe ser más rápido que el objetivo, pero si tienen una velocidad idéntica, debe agregar una caja de esquina para identificar si son paralelos .
El método se rompe si el objetivo y el misil están volando exactamente en la misma línea pero en direcciones opuestas. Eso realmente no puede suceder en el mundo real, pero no es muy raro en un juego discreto. Debe agregar una verificación de mayúsculas y minúsculas al algoritmo anterior para probar esto.
Si su misil tiene una capacidad de giro limitada, simplemente haga que realice el giro máximo cada vez que necesite girar más que eso. Mientras el misil esté lo suficientemente lejos, seguirá funcionando. Si está demasiado cerca, vea la última viñeta.
Recuerde ser indulgente cuando verifique la colisión. En el mundo real, muchos misiles dependen de su ojiva para producir una "zona de muerte", por lo que solo necesitan acercarse al objetivo, no chocar con él.
Finalmente, en la práctica, el misil aún puede fallar , lo que nos lleva de vuelta a su pregunta original. Creo que una buena manera es deshabilitar el recorrido de referencia para algunos tics, dejando que alcance cierta distancia y luego volver a hacerlo. Creo que el método propuesto por fxiii para identificar zonas muertas es una excelente manera de detectar cuándo es necesario desactivar el recorrido de referencia.
fuente
Un par de opciones simples que han resultado ser "lo suficientemente buenas" para los juegos en los que he trabajado en el pasado:
1) Si la resolución de la escena que está mirando lo permite, entonces el objeto puede explotar cuando está cerca del objetivo (que es la forma en que creo que los misiles de referencia de día más comunes realmente funcionan en cualquier caso). Si su rango de órbita es aproximadamente el doble del tamaño del objeto, es probable que esto no funcione para usted, ya que terminaría viéndose mal.
Si su objetivo final en su solución es simplemente asegurarse de que su misil llegue al objetivo, entonces estoy a favor de que haga que llegue al objetivo. Nuevamente, esto solo dependerá de cómo se vea la solución.
2) Si encuentra que su misil está en ángulo recto con su objetivo, este podría ser el punto donde la cerradura 'se rompe', y el misil simplemente se mueve en línea recta a menos que el objetivo se coloque 'frente' al misil nuevamente.
Siempre prefiero soluciones simples siempre que sea posible. Si está haciendo un juego en el que el misil de referencia es solo una de las armas que se están utilizando, es probable que pueda salirse con la suya ya que es probable que los jugadores disparen una salva y luego vuelvan a sus armas de compromiso constante lo antes posible. Sin embargo, si está haciendo una simulación de misiles, entonces claramente una de las otras respuestas es la mejor opción.
Espero que esto ayude.
fuente
Como se ha dicho, debes apuntar el misil hacia donde se espera que esté el objetivo cuando llegues allí, en lugar de donde está el objetivo en este momento. Esto evitará que la mayoría de los misiles entren en órbita, pero una órbita aún es posible si el objetivo evade de forma correcta. Esta es una táctica legítima utilizada por los pilotos de aeronaves para esquivar los misiles entrantes, ya que el misil va mucho más rápido que tú, tendrá un radio de giro más grande y un giro agudo en el instante correcto hace que continúe. (Aunque aún podría estar en riesgo por una detonación de proximidad).
Dado que estamos lidiando con un misil que todavía puede rastrear y que todavía tiene empuje, obtienes una situación de órbita si el objetivo evade en una de las zonas de las que habla la publicación de FxIII.
Sin embargo, no estoy de acuerdo con su solución al problema. En cambio, programaría los misiles de esta manera:
Si el misil ha estado empujando a 90 grados en su línea de movimiento para 360 grados de movimiento, está en órbita. Ajuste el empuje a 120 grados desde la línea de movimiento. La órbita del misil se ampliará ya que no gira tan fuerte, pero el misil también se ralentizará, lo que le permitirá maniobrar mejor. Cuando el alcance al objetivo se abre a 1.25x el diámetro de la zona muerta (tenga en cuenta que este diámetro se basa simplemente y solo en la velocidad del misil, no se requiere ningún cálculo complejo en tiempo de ejecución) el misil vuelve a su comportamiento de seguimiento normal.
Alternativamente, use cabezas de buscadores más tontas: cuando el alcance del objetivo deja de contar, usted detona.
fuente
Sé que esta es una pregunta antigua, pero creo que hay algo que se ha perdido en las respuestas dadas hasta ahora. En la pregunta original, se le dijo al misil (o lo que sea) que acelerara hacia la posición del objetivo. Varias respuestas señalaron que esto estaba mal, y debe acelerar hacia donde cree que estará el objetivo en algún momento posterior. Esto es mejor pero aún está mal.
Lo que realmente quieres hacer no es acelerar hacia el objetivo, sino avanzar hacia el objetivo. La forma de pensar en esto es establecer su velocidad deseada apuntando al objetivo (o una proyección de la ubicación de los objetivos) y luego determinar qué aceleración podría aplicar mejor (dadas las restricciones que tenga, es decir, un misil probablemente no puede acelerar directamente en reversa) para alcanzar la velocidad deseada (recordando que la velocidad es un vector).
Aquí hay un ejemplo trabajado que implementé esta mañana, en mi caso para un jugador AI en un juego de simulación deportiva, donde el jugador está tratando de perseguir a su oponente. El movimiento se rige por un modelo estándar de "patada de deriva" donde las aceleraciones se aplican al comienzo de un paso de tiempo para actualizar las velocidades y luego los objetos se desplazan a esa velocidad durante la duración del paso de tiempo.
Publicaría la derivación de esto, pero he descubierto que no hay soporte de marcado matemático en este sitio. ¡Abucheo! Solo tendrá que confiar en que esta es la solución óptima, teniendo en cuenta que no tengo restricciones en la dirección de aceleración, que no es el caso de un objeto de tipo misil, por lo que eso requeriría algunas restricciones adicionales.
El código está en Python, pero debe ser legible con cualquier fondo de idioma. Para simplificar, supongo que cada paso de tiempo tiene una longitud de 1 y expreso la velocidad y la aceleración en unidades apropiadas para reflejar eso.
Tenga en cuenta que la función atan2 (a, b) calcula el tan inverso de a / b, pero asegura que los ángulos se asienten en el cuadrante correcto de un círculo, lo que requiere conocer el signo de a y b.
En mi caso, una vez que tengo la aceleración, la aplico para actualizar la velocidad
También compruebo la nueva velocidad contra la velocidad máxima dependiente de un jugador y la limito. En el caso de un misil, automóvil o algo con una velocidad de giro máxima (en grados por tic), simplemente puede mirar el ángulo de movimiento actual versus el ideal calculado y si este cambio es mayor de lo permitido, simplemente cambie el ángulo como tanto como sea posible hacia el ideal.
Para cualquier persona interesada en la derivación de esto, escribí la distancia entre el jugador y el objetivo después del paso, en términos de posición inicial, velocidad, tasa de aceleración y ángulo de aceleración, luego tomé la derivada con respecto al ángulo de aceleración. Al establecer eso en cero, se encuentran los mínimos de la distancia objetivo-jugador después del paso de tiempo en función del ángulo de aceleración, que es exactamente lo que queremos saber. Curiosamente, a pesar de que la tasa de aceleración estaba originalmente en las ecuaciones, se cancela haciendo que la dirección óptima sea independiente de cuánto puede acelerar realmente.
fuente
Estás utilizando una velocidad de giro constante. Eso es exactamente lo que está causando la agradable órbita perfectamente circular.
Un enfoque más realista para un sistema de guía sería variar la velocidad de giro con la distancia inversamente objetivo (menos distancia -> más velocidad de giro). Esto daría una espiral en lugar de una órbita, y garantizaría la colisión con un objetivo más lento.
También ofrece una ruta de vuelo mucho más realista. La velocidad de giro constante es anormalmente perfecta. También puede agregar variaciones aleatorias a la velocidad de giro para simular turbulencias. Una vez más, es mucho más realista y puede evitar escenarios de órbita en estado estacionario.
No hay necesidad de ecuaciones parciales.
fuente