Reputation: 141
I have been working on a (kind of) gravity simulation using C# and Winforms, and I am getting some very weird behavior. It pretty much makes an object when you click, and is attracted to the other objects. The problem is that, unless they are within some weird distances, they will not be attracted in the positive directions (right, down.), but they are attracted upwards and to the left.
This is the update code:
public Vector GetGravEffect(GravObject other)
{
if ((Math.Abs(X - other.X) <= Mass * Form.DrawScale + other.Mass * Form.DrawScale) &&
(Math.Abs(Y - other.Y) <= Mass * Form.DrawScale + other.Mass * Form.DrawScale))
{
return new Vector(0, 0);
}
double tAngle = Math.Atan2((other.Y - Y), (other.X - X));
double tMagnitude = (GravModifier * Mass * other.Mass / ((Math.Pow((other.X - X), 2)) + (Math.Pow((other.Y - Y), 2))) * 1000);
Complex c = Complex.FromPolarCoordinates(tMagnitude, tAngle);
Vector r = new Vector(c.Real, c.Imaginary);
return r;
}
Full code is here: https://docs.google.com/open?id=0B79vmyWxBr-kTnUtQURPUlVidzQ
Thanks for any help!
Upvotes: 4
Views: 1593
Reputation: 6207
Problem is not in GetGravEffect method (it gives correct results), but in Update method. It completely ignores physical laws. You cannot sum values returned by GetGravEffect and consider it to be velocity. GetGravEffect returns force that one object attracts the other. You must sum these forces and then do additional computations that includes inertia, acceleration and time to calculate resulting velocity. Also casting X and Y to int is not good idea, because you looses much of accuracy, especially for slow velocities. With following corrected method it works great:
public void Update() {
Vector Force = new Vector(0, 0);
foreach (GravObject g in Form.Objects) {
if (this != g)
Force += GetGravEffect(g);
}
double TimeElapsedSinceLastUpdate = Form.Timer.Interval * 0.001;
Vector acceleration = Force / Mass;
Velocity += acceleration*TimeElapsedSinceLastUpdate;
X = (X + Velocity.X * Form.VelocityScale);
Y = (Y + Velocity.Y * Form.VelocityScale);
if (X + Mass * Form.DrawScale >= Form.Panels.Panel2.Width || X - Mass * Form.DrawScale <= 0)
Velocity.X *= -1;
if (Y + Mass * Form.DrawScale >= Form.Panels.Panel2.Height || Y - Mass * Form.DrawScale <= 0)
Velocity.Y *= -1;
}
Upvotes: 5