在C#中模拟重力:我的方法或实现出错?

时间:2016-05-26 15:37:55

标签: c# physics game-physics

我正在尝试制作一个简单的2D物理引擎。发动机将重力定义为90度(直线向下)的10个单位。在宇宙中,存在物理实体,每个物理实体都具有由速度和方向组成的速度。每次实体更新时,我都会将重力矢量添加到每个实体的速度矢量中。

如果实体静止或平行于重力矢量移动,它会下降,否则它会起作用。我的意思是,说和物体是在表面上方45度角拍摄的,它会向上,弯曲到顶点,然后继续平行于表面。重力似乎会随着上升而改变速度,但不会使物体再次下降。

我想知道我正在采取什么方法来解决这个问题,或者我的解决方案在代码中的实现是否有问题。

更新功能:

public static void UpdateAll()
    {

        foreach (var entity in Entities)
        {
            entity.Velocity.AddVector(Universe.Gravity.Speed, Universe.Gravity.Direction);
        }

        var iterator = 1;
        foreach (var entity in Entities)
        {

            for (var index = iterator; index < Entities.Count; index++)
            {
                //Collision Detection
            }

            entity.Update();

            iterator++;
        }
    }

添加矢量功能:

public void AddVector(float speed, int direction)
    {
        var radiansA = Angles.DegreesToRadians(SetDirection);
        var radiansB = Angles.DegreesToRadians(direction);

        var vAx = SetSpeed * (float) Math.Cos(radiansA);
        var vAy = SetSpeed * (float) Math.Sin(radiansA);
        var vBx = speed * (float) Math.Cos(radiansB);
        var vBy = speed * (float) Math.Sin(radiansB);

        var magX = vAx + vBx;
        var magY = vAy + vBy;

        var magnitude = (float) Math.Sqrt(Math.Pow(magX, 2) + Math.Pow(magY, 2));

        var theta = Angles.RadiansToDegrees((float) Math.Atan2(magY, magX));

        SetSpeed = magnitude;
        SetDirection = theta;
    }

编辑:我删除了一些评论所建议的if语句,但结果仍然相同。

已解决:评论中指出了代码错误,并更新了添加功能以反映所需的更改。

1 个答案:

答案 0 :(得分:4)

不确定为什么需要测试方向。无论物体如何移动,都应添加重力矢量。如果它向上移动,它将减慢速度。如果它向下移动,它将加速。如果它水平移动或根本不移动,它将开始下降。无论如何,这是通过添加重力矢量来实现的。

速度也应该是矢量。它应该有一个x和y组件。然后所有这些&#34;方向&#34;东西可能会被丢弃。因此,使用x和y定义的向量。然后,所有速度计算将减少为简单的矢量加法。这使得所有数学运算都比使用角度简单得多。

public struct Vector
{
    public Vector(int x, int y)
    {
        this.X = x;
        this.Y = y;
    }

    public int X { get; }
    public int Y { get; }

    public static Vector operator +(Vector a, Vector b)
    {
        return new Vector(a.X + b.X, a.Y + b.Y);
    }

    public float Magnitude
    {
        get
        {
            int d = X * X + Y * Y;
            if (d == 1 || d == 0) {
                return d;
            } else {
                return (float)Math.Sqrt(d);
            }
        }
    }

    public override string ToString()
    {
        return $"Vector({X}, {Y})";
    }
}

在每次速度变化后,也无需计算幅度和角度。只需从适当的属性中获取这些值,就可以从向量中获取这些值。 (刚添加了Magnitude属性作为示例)

Vector speed, gravity;
...
//Calculate new speed: 
speed += gravity;

另一个有用的运算符重载是向量乘以常量

public static Vector operator *(double c, Vector a)
{
    return new Vector((int)Math.Round(c * a.X), (int)Math.Round(c * a.Y));
}