【问题标题】:2D Bounding box collission2D边界框碰撞
【发布时间】:2011-04-21 09:54:27
【问题描述】:

我在编写的一个小型 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 平台游戏。

【问题讨论】:

  • 如果你能提供真实的代码,你的问题会更容易回答。请做。编辑:我认为 PLAYER_BOX_RIGHT_SIDE 与玩家的 x 坐标(玩家 x + 精灵宽度)正确偏移?
  • 是的,所有偏移都得到了正确处理。

标签: c++ 2d bounding-box


【解决方案1】:

我猜问题是方向。

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

如果您不知道玩家移动的方向,您可能会根据精灵移动的“速度”获得错误命中数。

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

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

    etc

}

【讨论】:

    【解决方案2】:

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

    类似这样的东西(也是伪的):

    
    // 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;
    
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-18
      • 2013-04-01
      • 2012-09-05
      • 1970-01-01
      • 2015-02-01
      • 2014-02-04
      • 2015-02-02
      相关资源
      最近更新 更多