使用勾股定理进行碰撞检测是不可靠的

Collision detection using the Pythagorean theorem is being unreliable?

本文关键字:不可靠 碰撞检测 勾股定理      更新时间:2023-10-16

对象常常可以相互穿过?此外,当计算动量时,精灵偶尔会在碰撞时形成斑点,一起移动而不是反弹。

代码对大多数碰撞都有效,但它经常失败。什么好主意吗?

xV = X速度。yV = Y速度。每一帧,这个速度值被添加到四边形的X和Y位置。

bool Quad::IsTouching(Quad &q)
{
    float distance = 0;
    float combinedRadius = (size/2) + (q.GetSize()/2);
    distance = sqrt(pow(q.GetX() - GetX(), 2) + pow(q.GetY() - GetY(), 2));
    if(distance < combinedRadius)
    {
        return true;
    }
    return false;
}
void Quad::Collide(Quad &q)
{
    float mX, mY, mX2, mY2, mXTmp, mYTmp;
    mX = mass * xV;
    mY = mass * yV;
    mXTmp = mX;
    mYTmp = mY;
    mX2 = q.GetMass() * q.GetxV();
    mY2 = q.GetMass() * q.GetyV();
    mX = mX2;
    mY = mY2;
    mX2 = mXTmp;
    mY2 = mYTmp;
    xV = mX/mass;
    yV = mY/mass;
    q.SetxV(mX2/q.GetMass());
    q.SetyV(mY2/q.GetMass());
}

我也遇到了同样的问题,下面是我制作的一个快速视频来演示这个问题。

解决这个问题的方法是计算碰撞的确切时间,这样粒子就会以新的速度移动迭代/时间步长的剩余时间。要做到这一点,你必须在更新位置之前检查是否会发生碰撞,所以:sqrt((x1 - x2 + dt * (vx1 - vx2))^2 + (y1 - y2 + dt * (vy1 - vy2))^2) <= distance .

你也可以用一个更简单的解决方案,你稍微移动两个物体,这样它们就不会再碰撞了。这将导致创建器不准确,但确实需要更少的计算:

dx = x1 - x2;
dy = y1 - y2;
d = sqrt(dx^2 + dy^2);
D = r1 + r2;
if(d < D)
{
    s = (d - D) / (2 * d);
    x1 = x1 + s * dx;
    x2 = x2 - s * dx;
    y1 = y1 + s * dy;
    y2 = y2 - s * dy;
}

你指的是什么类型的碰撞?弹性的还是非弹性的?对于弹性碰撞,代码将失败,您必须创建一个额外的属性来防止两个对象在接触时粘在一起。你还必须通过循环或if语句来确保,如果一个物体与另一个物体同时穿过另一个物体的位置,那么这两个物体将以与碰撞速度成正比的角度分开。使用适当的物理公式。

作为一个推断的、潜在的问题(没有提供速度、大小等的值,所以我不能肯定地说),你没有考虑到四轴是完全接触。也就是distance == combinedRadius。因此,当这为真时,检查失败,然后对象在下一个tick继续移动…直接穿过彼此

将支票更改为distance <= combinedRadius。此外,你可能只是得到了一个隧道效应,因为物体足够小,移动速度足够快,在每一个滴答声中它们都穿过彼此。有多种方法可以解决这个问题,其中一些是:施加最大速度和最小尺寸;增加物理检查的帧率;使用连续碰撞检查而不是离散检查:参见维基百科关于主题

的文章