Una solución analítica para esto es difícil, pero podemos usar la búsqueda binaria para encontrar una solución dentro de la precisión requerida.
El barco puede alcanzar el punto más cercano en la órbita en el tiempo t_min :
shipOrbitRadius = (ship.position - planet.orbitCenter).length;
shortestDistance = abs(shipOrbitRadius - planet.orbitRadius);
t_min = shortestDistance/ship.maxSpeed;
La nave puede alcanzar CUALQUIER punto de la órbita en un tiempo menor o igual que t_max :
(Aquí, por simplicidad, supongo que el barco puede conducir a través del sol. Si desea evitar esto, entonces deberá cambiar a caminos que no sean de línea recta por al menos algunos casos. "Los círculos de besos" pueden verse bien y orbitales) mecánica-y, sin cambiar el algoritmo en más de un factor constante)
if(shipOrbitRadius > planet.orbitRadius)
{
t_max = planet.orbitRadius * 2/ship.maxSpeed + t_min;
}
else
{
t_max = planet.orbitRadius * 2/ship.maxSpeed - t_min;
}
Si nuestro período orbital es corto, podríamos mejorar en este límite superior eligiendo t_max
ser la primera vez después de t_min
que el planeta se acerque más a la posición de inicio de la nave. Tome cualquiera de estos dos valores de t_max
es menor. Vea esta respuesta posterior para obtener una derivación de por qué esto funciona.
Ahora podemos usar la búsqueda binaria entre estos extremos, t_min y t_max . Buscaremos un valor t que obtenga el error cercano a cero:
error = (planet.positionAtTime(t) - ship.position).squareMagnitude/(ship.maxSpeed*ship.maxSpeed) - t*t;
(Con esta construcción, error @ t_min> = 0 y error @ t_max <= 0, por lo que debe haber al menos una intersección con error = 0 para un valor t intermedio)
donde, para completar, la función de posición es algo así como ...
Vector2 Planet.positionAtTime(float t)
{
angle = atan2(startPosition - orbitCenter) + t * orbitalSpeedInRadians;
return new Vector2(cos(angle), sin(angle)) * orbitRadius + orbitCenter;
}
Tenga en cuenta que si el período orbital del planeta es muy corto en comparación con la velocidad de la nave, esta función de error puede cambiar los signos varias veces durante t_min a t_max. Simplemente haga un seguimiento del primer par + ve & -ve que encuentre y continúe buscando entre ellos hasta que el error esté lo suficientemente cerca de cero ("lo suficientemente cerca" es sensible a sus unidades y contexto de juego. El cuadrado de la mitad de la duración del cuadro puede funciona bien, eso asegura que la intercepción sea precisa dentro de un marco)
Una vez que tengas un buen t para minimizar errores, puedes apuntar la nave hacia planet.positionAtTime (t) y acelerar a fondo, seguro de que el planeta llegará a ese punto al mismo tiempo que tú.
Siempre puede encontrar una solución dentro de las iteraciones Log_2 ((2 * orbitRadius / ship.maxSpeed) / errorThreshold). Entonces, por ejemplo, si mi nave puede atravesar la órbita en 60 cuadros, y quiero una intersección precisa dentro de un cuadro, necesitaré alrededor de 6 iteraciones.