Une solution analytique à cela est difficile, mais nous pouvons utiliser la recherche binaire pour trouver une solution avec la précision requise.
Le navire peut atteindre le point le plus proche sur l'orbite dans le temps t_min :
shipOrbitRadius = (ship.position - planet.orbitCenter).length;
shortestDistance = abs(shipOrbitRadius - planet.orbitRadius);
t_min = shortestDistance/ship.maxSpeed;
Le navire peut atteindre N'IMPORTE QUEL point sur l'orbite dans un temps inférieur ou égal à t_max :
(Ici, pour plus de simplicité, je suppose que le navire peut traverser le soleil. Si vous voulez éviter cela, vous devrez passer à des chemins non linéaires dans au moins certains cas. Les "cercles de baisers" peuvent sembler agréables et orbitaux. mécanique-y, sans changer l'algorithme de plus d'un facteur constant)
if(shipOrbitRadius > planet.orbitRadius)
{
t_max = planet.orbitRadius * 2/ship.maxSpeed + t_min;
}
else
{
t_max = planet.orbitRadius * 2/ship.maxSpeed - t_min;
}
Si notre période orbitale est courte, nous pourrions être en mesure d'améliorer cette limite supérieure en choisissant la t_max
pour la première fois après t_min
que la planète s'approche le plus près de la position de départ du navire. Prenez la plus t_max
petite de ces deux valeurs de . Voir cette réponse ultérieure pour une dérivation de pourquoi cela fonctionne.
Maintenant, nous pouvons utiliser la recherche binaire entre ces extrêmes, t_min et t_max . Nous rechercherons une valeur t qui ramènera l' erreur près de zéro:
error = (planet.positionAtTime(t) - ship.position).squareMagnitude/(ship.maxSpeed*ship.maxSpeed) - t*t;
(En utilisant cette construction, erreur @ t_min> = 0 et erreur @ t_max <= 0, donc il doit y avoir au moins une interception avec erreur = 0 pour une valeur t entre les deux)
où, pour être complet, la fonction de position est quelque chose comme ...
Vector2 Planet.positionAtTime(float t)
{
angle = atan2(startPosition - orbitCenter) + t * orbitalSpeedInRadians;
return new Vector2(cos(angle), sin(angle)) * orbitRadius + orbitCenter;
}
Notez que si la période orbitale de la planète est très courte par rapport à la vitesse du navire, cette fonction d'erreur peut changer plusieurs fois les signes sur la plage de t_min à t_max. Gardez simplement la trace de la première paire + ve & -ve que vous rencontrez et continuez à chercher entre elles jusqu'à ce que l'erreur soit assez proche de zéro ("assez proche" étant sensible à vos unités et au contexte de jeu. Le carré de la moitié de la durée de l'image peut fonctionne bien - qui garantit que l'interception est précise dans un cadre)
Une fois que vous avez un joli t minimisant les erreurs, vous pouvez simplement pointer le vaisseau sur planet.positionAtTime (t) et aller à plein régime, confiant que la planète atteindra ce point en même temps que vous.
Vous pouvez toujours trouver une solution dans les itérations Log_2 ((2 * orbitRadius / ship.maxSpeed) / errorThreshold). Ainsi, par exemple, si mon vaisseau peut traverser l'orbite en 60 images et que je souhaite une interception précise à l'intérieur d'une image, j'aurai besoin d'environ 6 itérations.