1

我有一个物理模拟,它允许你放置区域约束,这样里面的物体就不会离开那个区域。但是,如果一个原子越过区域约束的“墙”之一,它就会破坏物理模拟。为什么这样做?更新方法:

if (!atom.IsStatic)
{
    Vector2 force = Vector2.Zero;
    bool x = false, y = false;
    if (atom.Position.X - atom.Radius < _min.X)
    {
        force = new Vector2(-(_min.X - atom.Position.X), 0);
        if (atom.Velocity.X < 0)
            x = true;
    }
    if (atom.Position.X + atom.Radius > _max.X)
    {
        force = new Vector2(atom.Position.X - _max.X, 0);
        if (atom.Velocity.X > 0)
            x = true;
    }
    if (atom.Position.Y - atom.Radius < _min.Y)
    {
        force = new Vector2(0, -(_min.Y - atom.Position.Y));
        if (atom.Velocity.Y < 0)
            y = true;
    }
    if (atom.Position.Y + atom.Radius > _max.Y)
    {
        force = new Vector2(0, atom.Position.Y - _max.Y);
        if (atom.Velocity.Y > 0)
            y = true;
    }
    atom.ReverseVelocityDirection(x, y);
    if (!atom.IsStatic)
    {
        atom.Position += force;
    }
}
4

3 回答 3

3

我看到您正在使用恒定的时间步 T 进行计算。尽管在每一步建模碰撞时,您都应该使用等于任何原子到达任何障碍物之前的最短时间的时间步。

使时间步长可变,原子永远不会“穿过”障碍物。

PS 碰撞检测有很多优化,请阅读 gamedev 论文以获取相关信息。

PS一个错误?

force = new Vector2(-(_min.X - atom.Position.X), 0);

为 X 和 Y 反射分别创建力。当原子进入角落时会发生什么?只会施加第二个力。

PPS:使用 epsilon

更重要的一点:如果你使用浮点数,误差是累积的,你应该使用 eps:

abs(atom.Position.Y + atom.Radium - _max.Y) < eps

其中 eps 是一个远小于任务中正常大小的数字,例如 0.000001。

于 2009-10-22T23:53:43.133 回答
1

您似乎已经解决了问题,但我注意到“强制”似乎是错误的。它使原子远离边界,即使它在错误的一侧。假设一个原子射过 _max.X:

if (atom.Position.X + atom.Radius > _max.X)
    {
        force = new Vector2(atom.Position.X - _max.X, 0);
        ...
    }

现在“力”将在 +x 方向上,并且每次迭代时原子与墙壁的距离将加倍。繁荣!

于 2009-10-29T17:14:40.910 回答
0

你不知道吗,经过大约半小时的无意识黑客攻击,我想到了根本不应用位置校正。这就像一个魅力一样修复它。对于任何感兴趣的人,这是更新的代码:

if (!atom.IsStatic)
{
    if (atom.Position.X - atom.Radius < _min.X && atom.Velocity.X < 0)
    {
        atom.ReverseVelocityDirection(true, false);
    }
    if (atom.Position.X + atom.Radius > _max.X && atom.Velocity.X > 0)
    {
        atom.ReverseVelocityDirection(true, false);
    }
    if (atom.Position.Y - atom.Radius < _min.Y && atom.Velocity.Y < 0)
    {
        atom.ReverseVelocityDirection(false, true);
    }
    if (atom.Position.Y + atom.Radius > _max.Y && atom.Velocity.Y > 0)
    {
        atom.ReverseVelocityDirection(false, true);
    }
}
于 2009-10-23T10:59:09.513 回答