首页 > 解决方案 > 碰撞前对象暂存

问题描述

我正在做台球游戏。目前,当一个球与另一个球高速碰撞时,并不总是能正确计算碰撞。我知道问题是什么,但我不是 100% 确定如何解决它。

假设两个球以这些速度运动: 在此处输入图像描述

通常情况下,当检测到碰撞时,球之间会有一些重叠,如下所示: 在此处输入图像描述

目前,我的物理引擎将在此时处理碰撞。这不会产生预期的结果,因为这不是球在现实中碰撞的地方——球不会相互穿过。所以,我们需要将球备份到它们真正碰撞的地方。看起来像这样: 在此处输入图像描述

我正在寻找一种有效的算法来帮助我做到这一点。目前,我有一个非常幼稚和低效的方法 - 我将两个球移动到碰撞前的位置,并在碰撞时刻采取非常小的步骤。当然,这是非常低效的。这是它的样子:

void CBallCollision::StageCollision()
{
    double sumOfRadii = mBall1->GetRadius() + mBall2->GetRadius();

    mBall1->SetCenter(mBall1->GetLastLocationOnTable().first, mBall1->GetLastLocationOnTable().second);
    mBall2->SetCenter(mBall2->GetLastLocationOnTable().first, mBall2->GetLastLocationOnTable().second);
    double timeStep = 0.008;
    double tolerance = 0.1 * min(mBall1->GetRadius(), mBall2->GetRadius());
    int iter = 0;
    while (GetDistance() > sumOfRadii)
    {
        double xGoal1 = mBall1->GetX() + mBall1->GetVelocityX() * timeStep;
        double yGoal1 = mBall1->GetY() + mBall1->GetVelocityY() * timeStep;
        pair<double, double> newCoords1 = mBall1->LinearInterpolate(xGoal1, yGoal1);
        
        double xGoal2 = mBall2->GetX() + mBall2->GetVelocityX() * timeStep;
        double yGoal2 = mBall2->GetY() + mBall2->GetVelocityY() * timeStep;
        pair<double, double> newCoords2 = mBall2->LinearInterpolate(xGoal2, yGoal2);

        double dist = (pow(newCoords1.first - newCoords2.first, 2) + pow(newCoords1.second - newCoords2.second, 2));
        if (abs(dist - sumOfRadii) > tolerance)
        {
            timeStep *= 0.5;
        }
        else
        {
            mBall1->SetX(newCoords1.first);
            mBall1->SetY(newCoords1.second);
            mBall2->SetX(newCoords2.first);
            mBall2->SetY(newCoords2.second);
        }
        iter++;
        if (iter > 1000)
        {
            break;
        }
    }
}

如果我不对迭代次数设置上限,程序就会崩溃。我确信有一种更有效的方法来解决这个问题。任何帮助表示赞赏。

标签: c++collision-detectiongame-enginegame-physics

解决方案


推荐阅读