2D长方体碰撞-这是对的吗

2D Box Collision - Is this right?

本文关键字:长方体 碰撞 2D      更新时间:2023-10-16

我有一个2D盒子碰撞代码,它基本上循环通过名为"块"的列表中的每个块,并检查我是否靠近边等等。

除了方块的底部以外,它的效果非常好。当我跳到底部时,我希望我的球员能简单地"反弹"出来。它确实做到了,但它很有问题。这很难解释,所以我希望你们能发现我的底部碰撞代码出了什么问题。

以下是全部内容:

for(unsigned int i = 0; i<blocks.size(); i++){
Block &b = blocks.at(i);
if(!b.passable==true){
    //Check if we are on the sides
    if(y + height + vspeed >= b.worldY+2 && y + vspeed <= b.worldY+b.height)
    {
        //Right side
        if(x + hspeed <= b.worldX+b.width-1  && x + hspeed > b.worldX+b.width + hspeed-2)
        {
         x = b.worldX + b.width; hspeed = 0;
        }
        //Left side    
        if(x + width + hspeed >= b.worldX +1 && x + width + hspeed <= b.worldX + hspeed + 2)
        {
         x = b.worldX - width; hspeed = 0;
        }
    }
    //Check if we are on the top or the bottom
    if(x + width + hspeed >= b.worldX+2 && x + hspeed <= b.worldX+b.width-2)
    {
        if(y + height + vspeed >= b.worldY && y + height + vspeed <= b.worldY + vspeed + 1 && jumpstate=="falling")
            {
              y = b.worldY - height; jumpstate.assign("ground"); vspeed = 0;
            }
        if(y + vspeed <= b.worldY + b.height && y + vspeed >= b.worldY + b.height + vspeed - 1 && jumpstate=="jumping")
        {
            y = b.worldY + b.height; jumpstate.assign("falling"); vspeed = 0;
        }
        }
    }
}

我的猜测是应该设置vspeed = -vspeed;而不是vspeed = 0。完全弹性反弹意味着速度在长方体的侧面得到镜像。

如果将其设置为零,则根据执行更新的顺序,您可能不会在帧中移动。由于使用<=>=进行边界检查,因此在下一帧中,您仍将处于框内,再次调用反弹行为,并将头粘在块上。

我猜你的问题是不等式检查中的负数。例如,当下降时,我猜vspeed将为负值。根据您设置盒子原点的位置,这可能意味着条件

y + vspeed <= b.worldY + b.height

总是正确的。

顺便说一句,通过在速度上加上距离,你就假设了单位时间的神奇维度。这会使你的代码变得脆弱,因为如果你改变这个神奇的数字,那么你的方程就会出错。

试试,

 y + vspeed*unit_time <= b.worldY + b.height

如果您想在编译时处理单位(而不需要为乘法付费(,那么请使用boost.units

此外,

x + hspeed > b.worldX+b.width + hspeed-2

可以简化为

x > b.worldX+b.width-2

这个神奇数字2的意义是任何人都可以猜测的。(例如,你为什么有

//Check if we are on the sides
if(y + vspeed <= b.worldY+b.height)

但中有CCD_ 7

//Check if we are on the top or the bottom
if( x + hspeed <= b.worldX+b.width-2)

)