4

我一直在使用 C# 和 Winforms 进行(某种)重力模拟,我得到了一些非常奇怪的行为。当您单击时,它几乎会生成一个对象,并被其他对象吸引。问题是,除非它们在一些奇怪的距离内,否则它们不会被正向(右、下)吸引,而是被向上和向左吸引。

这是更新代码:

    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;
    }

完整代码在这里:https ://docs.google.com/open?id=0B79vmyWxBr-kTnUtQURPUlVidzQ

谢谢你的帮助!

4

1 回答 1

5

问题不在于 GetGravEffect 方法(它给出正确的结果),而在于 Update 方法。它完全无视物理规律。您不能对 GetGravEffect 返回的值求和并将其视为速度。GetGravEffect 返回一个物体吸引另一个物体的力。您必须对这些力求和,然后进行额外的计算,包括惯性、加速度和时间,以计算得到的速度。将 X 和 Y 转换为 int 也不是一个好主意,因为您会损失很多准确性,尤其是对于慢速。使用以下更正的方法,效果很好:

    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;
    }
于 2012-05-20T03:17:21.417 回答