2D边界框碰撞

时间:2010-10-05 16:33:01

标签: c++ 2d bounding-box

我在写一个小型2D游戏时遇到了一些问题。我正在研究一个函数,如果玩家角色与一个区块碰撞,以及他碰撞的区块的哪一侧,我想找到它。

目前我有类似(伪代码)的东西:

if(PLAYER_BOX IS WITHIN THE BLOCKS Y_RANGE)
{
    if(PLAYER_BOX_RIGHT_SIDE >= BLOCK_LEFT_SIDE && PLAYER_BOX_RIGHT_SIDE <= BLOCK_RIGHT_SIDE)
    {
        return LEFT;
    }
    else if(PLAYER_LEFT_SIDE <= BLOCK_RIGHT_SIDE && PLAYER_LEFT_SIDE >= BLOCK_LEFT_SIDE)
    {
        return RIGHT;
    }
}
else if(PLAYER_BOX IS WITHIN BLOCK X_RANGE)
{
    if(PLAYER_BOTTOM_SIDE >= BLOCK_TOP_SIDE && PLAYER_BOTTOM_SIDE <= BLOCK_BOTTOM_SIDE)
    {
        return ABOVE;
    }
    else if(PLAYER_TOP_SIDE <= BLOCK_BOTTOM_SIDE && PLAYER_TOP_SIDE >= BLOCK_TOP_SIDE)
    {
        return BELOW;
    }
 }

我在这里有一些逻辑错误吗?或者我只是在我的代码中写错了什么?

ABOVE碰撞有效,但它不能识别它应该的横向碰撞,有时它不应该在它不应该的时候。

该游戏是SuperMario克隆,所以它是一个侧面滚动器2D平台游戏。

2 个答案:

答案 0 :(得分:2)

我猜这个问题是方向。

你真正想做的是首先考虑“玩家”的方向,然后进行检查。

如果你不知道玩家的移动方向,你可能会得到一个虚假命中的数字,具体取决于你的精灵移动的速度。

例如,如果您有移动方向(向上向下),那么您的代码可能如下所示:

select movedir
(
   case up:
     //check if hitting bottom of box
     break;
   case down:
     //check if hitting top of box

    etc

}

答案 1 :(得分:0)

您可能需要考虑使用移动增量来修改计算。

像这样(也是假的):


// assuming player graphics are centered
player_right = player.x + player.width / 2;
player_left = player.x - player.width / 2;

player_top = player.y - player.height / 2;
player_bottom = player.y + player.height / 2;

// assuming block graphics are centered as well
block_right = box.x + box.width / 2;
...

// determine initial orientation
if (player_right  block_right) orientationX = 'right';

if (player_top  block_top) orientationY = 'top';

// calculate movement delta
delta.x = player.x * force.x - player.x;
delta.y = player.y * force.y - player.y;

// define a rect containing where your player WAS before moving, and where he WILL BE after moving
movementRect = new Rect(player_left, player_top, delta.x + player.width / 2, delta.y + player.height / 2);

// make sure you rect is using all positive values
normalize(movementRect);

if (movementRect.contains(new Point(block_top, block_left)) || movementRect.contains(new Point(block_right, block_bottom))) {

    // there was a collision, move the player back to the point of collision
    if (orientationX == 'left') player.x = block_right - player.width / 2;
    else if (orientationX == 'right') player.x = block_left + player.width / 2;

    if (orientationY == 'top') player.y = block_top - player.height / 2;
    else if (orientationY == 'bottom') player.y = block_bottom + player.height / 2;

    // you could also do some calculation here to see exactly how far the movementRect goes past the given block, and then use that to apply restitution (bounce back)

} else {

    // no collision, move the player
    player.x += delta.x;
    player.y += delta.y;

}

如果您的玩家移动得非常快,这种方法会给你带来更好的效果,因为你实际上是在计算玩家是否会碰撞,而不是他们发生碰撞。