碰撞检测并保持物体上的动量

时间:2012-03-07 05:50:45

标签: math sdl d

我一直在实施各种形式的简单碰撞检测,结果各不相同。我有一个相当不错的碰撞检测工作版本,但有些奇怪的行为让我无法解决。

仅供参考,我正在制作一个简单的乒乓球比赛,并试图改善碰撞。我得到的问题是球在顶部或底部碰撞桨。在这些情况下,球在桨的上方(或下方)盘旋并且不移动。我猜这是因为我正在检查碰撞以及我如何改变球的移动速度。

我想实现一种区分顶部/底部和左/右碰撞的方法,但这是唯一可行的方法:

static void CheckCollision(PActor object1, PActor object2, PInput pinput)
{
    if ( CheckObjectCollision( object1, object2 ) )
    {
        AdjustMoveSpeed( object1, object2, pinput );
    }
}



static bool CheckObjectCollision(PActor object1, PActor object2)
{
    int object1LeftBound = object1.position.x;
    int object1RightBound = object1.position.x + object1.actorTextureXSize;
    int object1TopBound = object1.position.y;
    int object1BottomBound = object1.position.y + object1.actorTextureYSize;

    int object2LeftBound = object2.position.x;
    int object2RightBound = object2.position.x + object1.actorTextureXSize;
    int object2TopBound = object2.position.y;
    int object2BottomBound = object2.position.y + object2.actorTextureYSize;

    if ( object1RightBound < object2LeftBound )
        return false;

    if ( object1LeftBound > object2RightBound )
        return false;

    if ( object1BottomBound < object2TopBound )
        return false;

    if ( object1TopBound > object2BottomBound )
        return false;

    return true;        
}

我猜我遇到的一些问题的根源是AdjustMoveSpeed函数,这里是:

static void AdjustMoveSpeed(PActor object1, PActor object2, PInput pinput)
{
    PVector prevMouseLocation = pinput.GetPrevMouseLocation();
    PVector currMouseLocation = pinput.GetCurrMouseLocation();

    int currentMoveSpeed;
    int nextMoveSpeed;

    if (typeid(object1) == typeid(PBall))
    {

        object1.moveSpeed.x *= -1;  

        if ( typeid(object2) == typeid(PPlayer) )
        {
            currentMoveSpeed = object1.moveSpeed.y;
            nextMoveSpeed = prevMouseLocation.y  - currMouseLocation.y;

            object1.moveSpeed.y = (prevMouseLocation.y  - currMouseLocation.y) * -1; 

        }
        else
        {
            if (object1.moveSpeed.y > 0)
                object1.moveSpeed.y *= -1;
        }
    }
    else if (typeid(object2) == typeid(PBall))
    {

        object2.moveSpeed.x *= -1;

        if ( typeid(object1) == typeid(PPlayer) )
        {
            currentMoveSpeed = object1.moveSpeed.y;
            nextMoveSpeed = prevMouseLocation.y  - currMouseLocation.y;

            object2.moveSpeed.y = (prevMouseLocation.y  - currMouseLocation.y) * -1; 
        }
        else
        {
            if (object2.moveSpeed.y > 0)
                object2.moveSpeed.y *= -1;
        }
    }       
}

我试图用AdjustMoveSpeed做的是首先检查哪个物体是球,然后将x移动速度乘以-1以反转它的方向。在此之后,我检查另一个对象是否是一个玩家,如果是这样,我将y移动速度设置为前一个鼠标位置和当前鼠标位置之间的差异。这是为了让玩家可以选择更改球速度,或者添加旋转。

我已经尝试检查物体之间的交叉点,以便我可以得到一个特定的一侧,结果是球只是在屏幕中间飞行而没有实际击中任何一个桨。

如何正确检查两个正方形物体的碰撞检测?

如何修复AdjustMoveSpeed以使其在碰撞检测中正常工作?

最后,如何保持当前速度球的动量大于击中前后鼠标位置的差异?

我已经尝试过比较currentMoveSpeed和nextMoveSpeed的绝对值但是球不会改变y速度。像这样:

if ( abs(currentMoveSpeed) < abs(nextMoveSpeed )
    object1.moveSpeed.y = (prevMouseLocation.y  - currMouseLocation.y) * -1;
else
  object1.moveSpeed.y *= -1

2 个答案:

答案 0 :(得分:6)

Pong非常简单,不是每一帧移动球并检查与桨的碰撞,实际上你可以解决桨和球碰撞时的等式 - 如果那个时候小于一帧,发生碰撞。

这完全消除了球在球拍中移动速度过快的问题,这个问题困扰着使用天真碰撞检测方法的许多乒乓球克隆。

此解决方案称为continuous collision detection - 有关详细信息,请参阅this answer

答案 1 :(得分:2)

如果球被卡在桨上而不是弹跳,可能是因为它不断地来回改变方向。如果球朝向球拍,球应该只会反弹。

if (sgn(object1.moveSpeed.x) == sgn(object1.x - object2.x)) {
  // Ball is already moving away from the paddle, don't bounce!
}
else {
  // Ok to bounce!
  object1.moveSpeed.x *= -1;
}