Uma solução analítica para isso é difícil, mas podemos usar a pesquisa binária para encontrar uma solução com a precisão necessária.
A nave pode chegar ao ponto mais próximo da órbita no tempo t_min :
shipOrbitRadius = (ship.position - planet.orbitCenter).length;
shortestDistance = abs(shipOrbitRadius - planet.orbitRadius);
t_min = shortestDistance/ship.maxSpeed;
A nave pode atingir QUALQUER ponto da órbita em tempo menor ou igual a t_max :
(Aqui, por simplicidade, presumo que o navio possa dirigir pelo sol. Se você quiser evitar isso, precisará mudar para caminhos não lineares por pelo menos alguns casos. "Beijar círculos" pode parecer agradável e orbital mecânica-y, sem alterar o algoritmo por mais que um fator constante)
if(shipOrbitRadius > planet.orbitRadius)
{
t_max = planet.orbitRadius * 2/ship.maxSpeed + t_min;
}
else
{
t_max = planet.orbitRadius * 2/ship.maxSpeed - t_min;
}
Se nosso período orbital for curto, poderemos melhorar esse limite superior, escolhendo t_max
a primeira vez depois t_min
que o planeta se aproximar mais da posição inicial da nave. Tome qualquer um desses dois valores t_max
menor. Veja esta resposta posterior para obter uma derivação de por que isso funciona.
Agora podemos usar a pesquisa binária entre esses extremos, t_min e t_max . Procuraremos um valor t que obtenha o erro próximo de zero:
error = (planet.positionAtTime(t) - ship.position).squareMagnitude/(ship.maxSpeed*ship.maxSpeed) - t*t;
(Usando essa construção, erro @ t_min> = 0 e erro @ t_max <= 0, portanto, deve haver pelo menos uma interceptação com erro = 0 para um valor t intermediário)
onde, para completar, a função position é algo como ...
Vector2 Planet.positionAtTime(float t)
{
angle = atan2(startPosition - orbitCenter) + t * orbitalSpeedInRadians;
return new Vector2(cos(angle), sin(angle)) * orbitRadius + orbitCenter;
}
Observe que, se o período orbital do planeta for muito curto comparado à velocidade da nave, esta função de erro poderá alterar os sinais várias vezes ao longo do intervalo de t_min a t_max. Apenas acompanhe o par mais antigo de ve e -v que você encontrar e continue pesquisando entre eles até que o erro esteja próximo o suficiente de zero ("perto o suficiente" sendo sensível às suas unidades e ao contexto de jogo. O quadrado da metade da duração do quadro pode funciona bem - que garante que a interceptação seja precisa dentro de um quadro)
Depois de ter um bom t minimizador de erros, basta apontar a nave para planet.positionAtTime (t) e acelerar a toda velocidade, confiante de que o planeta alcançará esse ponto ao mesmo tempo que você.
Você sempre pode encontrar uma solução nas iterações Log_2 ((2 * orbitRadius / ship.maxSpeed) / errorThreshold). Por exemplo, se minha nave puder atravessar a órbita em 60 quadros e eu desejar uma interceptação precisa dentro de um quadro, precisarei de cerca de 6 iterações.