I have a method for orbiting a sprite (fleet) around another sprite (planet). The problem is that, over time, the fleet moves further away (very slowly, almost unnoticeable unless you let the orbit run for a few minutes).
public void Orbit()
{
// Planet's position - fleet position
Vector2 distanceToDestination = currentLocation.Position - position;
// Calculate fleet's rotation ( - right angle so fleet rotates clockwise)
rotation = MathHelper.WrapAngle((float)Math.Atan2(distanceToDestination.Y, distanceToDestination.X)) - Helpers.RightAngle;
// Get the direction that the fleet is facing
direction = new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation));
// Fleet position, thrust is set to 0.4f
position = Vector2.Add(position, direction * thrust);
// Fleet rectangle
rect = new Rectangle((int)position.X, (int)position.Y, fleetTexture.Width, fleetTexture.Height);
}
public static class Helpers
{
public const float RightAngle = (float)Math.PI / 2;
}
I would be grateful if the community could point out why my fleet is not maintaining a consistent orbit, which is what I want to achieve! Many thanks in advance.
If I understand what you are doing, you are trying to simulate orbital physics using a model sort of like that of a car driving around a circle (i.e. you're not modeling the acceleration of gravity perpendicular to the current velocity and numerically integrating it). Instead, you're doing this:
r
by a small amount d
Now, after each step, how far is your object from the center of the circle? Well, by the Pythagorean theorem, it's sqrt(r*r + d*d)
, which is going to be slightly larger than r
. Using a very large value for d
for emphasis:
That should account for your drift.
Incidentally, you don't need to use trig functions to construct a perpendicular to the distanceToDestination. It is much easier to simply cross it with the ±Z vector, the result will be (in 2d) ±(-distanceToDestination.Y, distanceToDestination.X)
.
Update: since you're not really simulating orbital physics, why not solve the problem analytically?
public static Vector2 Orbit(Vector2 center, Vector2 startPos, float speed, float time)
{
// positive speed means CCW around the center, negative means CW.
var radiusVec = (startPos - center);
var radius = radiusVec.Length();
var angularVelocity = speed / radius; // Add check for divide by zero
Vector2 perpendicularVec = new Vector2(-radiusVec.Y, radiusVec.X);
return center + (float)Math.Cos(time * angularVelocity) * radiusVec + (float)Math.Sin(time * angularVelocity) * perpendicularVec;
}