Una soluzione analitica è difficile, ma possiamo usare la ricerca binaria per trovare una soluzione con l'accuratezza richiesta.
La nave può raggiungere il punto più vicino sull'orbita nel tempo t_min :
shipOrbitRadius = (ship.position - planet.orbitCenter).length;
shortestDistance = abs(shipOrbitRadius - planet.orbitRadius);
t_min = shortestDistance/ship.maxSpeed;
La nave può raggiungere QUALSIASI punto sull'orbita in un tempo inferiore o uguale a t_max :
(Qui, per semplicità, suppongo che la nave possa guidare attraverso il sole. Se vuoi evitarlo, dovrai passare a percorsi non rettilinei per almeno alcuni casi. "I circoli del bacio" possono sembrare belli e orbitali meccanica-y, senza modificare l'algoritmo di più di un fattore costante)
if(shipOrbitRadius > planet.orbitRadius)
{
t_max = planet.orbitRadius * 2/ship.maxSpeed + t_min;
}
else
{
t_max = planet.orbitRadius * 2/ship.maxSpeed - t_min;
}
Se il nostro periodo orbitale è breve, potremmo essere in grado di migliorare su questo limite superiore scegliendo t_max
di essere la prima volta dopo t_min
che il pianeta si avvicina alla posizione di partenza della nave. Prendi qualunque di questi due valori di t_max
è minore. Vedi questa risposta successiva per una derivazione del perché funziona.
Ora possiamo usare la ricerca binaria tra questi estremi, t_min e t_max . Cercheremo un valore t che porti l' errore vicino a zero:
error = (planet.positionAtTime(t) - ship.position).squareMagnitude/(ship.maxSpeed*ship.maxSpeed) - t*t;
(Usando questa costruzione, errore @ t_min> = 0 ed errore @ t_max <= 0, quindi deve esserci almeno un'intercettazione con errore = 0 per un valore t compreso tra)
dove, per completezza, la funzione di posizione è qualcosa come ...
Vector2 Planet.positionAtTime(float t)
{
angle = atan2(startPosition - orbitCenter) + t * orbitalSpeedInRadians;
return new Vector2(cos(angle), sin(angle)) * orbitRadius + orbitCenter;
}
Nota che se il periodo orbitale del pianeta è molto breve rispetto alla velocità della nave, questa funzione di errore può cambiare i segni più volte nell'intervallo da t_min a t_max. Tieni traccia della prima coppia + ve & -ve che incontri e continua a cercare tra loro fino a quando l'errore è abbastanza vicino a zero ("abbastanza vicino" è sensibile alle tue unità e al contesto di gioco. Il quadrato della metà della durata del fotogramma può funziona bene - ciò garantisce che l'intercettazione sia accurata all'interno di un frame)
Una volta che hai una bella t che minimizza gli errori, puoi semplicemente puntare la nave verso planet.positionAtTime (t) e andare a tutto gas, fiducioso che il pianeta raggiungerà quel punto nello stesso momento in cui lo fai.
È sempre possibile trovare una soluzione all'interno delle iterazioni Log_2 ((2 * orbitRadius / ship.maxSpeed) / errorThreshold). Quindi, ad esempio, se la mia nave può attraversare l'orbita in 60 fotogrammi e voglio un'intercettazione accurata entro un fotogramma, avrò bisogno di circa 6 iterazioni.