基本碰撞问题

时间:2014-03-11 01:06:04

标签: c++ console-application collision-detection collision

我有一个sprite类,我正在制作一个碰撞函数。如果两个精灵碰撞,我希望函数返回true。当我调用该函数时,我传递了所需的移动对象X和Y位置以及它的高度和宽度。调用精灵是我想要检查的对象。例如,如果我想检查玩家1的移动是否会与玩家2的精灵相交,我会说Player2.Collide(p1X,p1Y,p1H,p1W)。

bool Sprite::Collides(int x, int y, unsigned short w, unsigned short h) const
{
    if ((x == this->GetWidth() + this->GetLeft()) && 
        (y >= this->GetTop() && y <= this->GetTop() + this->GetHeight()) || 
        ((x + w) == this->GetLeft()) && 
        (y >= this->GetTop() && y <= this->GetTop() + this->GetHeight()))
        return true;
else if ( (y == this->GetHeight() + this->GetTop()) && 
              ((x >= this->GetLeft() && x <= this->GetLeft() + this->GetWidth()) || 
              ((y + h) == this->GetTop() && (x >= this->GetLeft() && x <= this->GetLeft() + this->GetWidth()))))
        return true;
    return false;
}

精灵总是长方形。我似乎忘记检查碰撞的一些条件。如果矩形完全碰撞然后一切正常,但是如果我向上移动然后试图抵挡另一个,它将会滑过。似乎我接近的每个方向都有类似的行为,它只适用于某些部分。你能帮助我找到我忘了检查的东西吗?

1 个答案:

答案 0 :(得分:1)

我认为你需要再次检查你的实际情况的逻辑,不应该

(x == this->GetWidth() + this->GetLeft())

你的if语句中那部分是否会造成碰撞?在那之后你有一个&&。因此,在这种情况下,它需要触摸顶部和右侧,而不是右侧或顶部???

我也认为以上这一行应该是:

(x <= this->GetWidth() + this->GetLeft())

此外,根据您的实际移动条件(即速度等),上述情况可能真的是

(x <= this->GetWidth() + this->GetLeft() - 1)

让我们解释减1: 如果你有两个物体,一个直接向上移动,另一个直接向下移动,即垂直和彼此平行,那么GetWidth + GetLeft会产生一个“过去”,而不是碰撞条件。

示例Sprite每个4 x 4相对于彼此垂直移动:

Sprite A @ (0, 2)          Sprite B @ (4, 2)

   0     1     2     3        0     1     2     3
-------------------------  -------------------------
|     |     |     |     |  |     |     |     |     |
-------------------------  -------------------------
|     |     |     |     |  |     |     |     |     |
-------------------------  -------------------------
|     |     |     |     |  |     |     |     |     |
-------------------------  -------------------------
|     |     |     |     |  |     |     |     |     |
-------------------------  -------------------------

Sprite A @ (0, 1)          Sprite B @ (4, 3)

   0     1     2     3   
-------------------------
|     |     |     |     |
-------------------------
|     |     |     |     |     0     1     2     3
-------------------------  -------------------------
|     |     |     |     |  |     |     |     |     |
-------------------------  -------------------------
|     |     |     |     |  |     |     |     |     |
-------------------------  -------------------------
                           |     |     |     |     |
                           -------------------------
                           |     |     |     |     |
                           -------------------------

Sprite A @ (0, 0)          Sprite B @ (4, 4)

   0     1     2     3   
-------------------------
|     |     |     |     |
-------------------------
|     |     |     |     |
-------------------------
|     |     |     |     |
-------------------------
|     |     |     |     |     0     1     2     3
-------------------------  -------------------------
                           |     |     |     |     |
                           -------------------------
                           |     |     |     |     |
                           -------------------------
                           |     |     |     |     |
                           -------------------------
                           |     |     |     |     |
                           -------------------------

当精灵a位于位置(0,0)时,然后GetWidth + GetLeft = (0 + 4)是精灵实际结束的右侧。如果另一个精灵完全垂直向下移动x位置4,那么你的算法会将其标记为碰撞,而实际上它们只是彼此紧密地移动。这就是- 1的用武之地。

另外,您确实要确保小心屏幕几何图形。我的意思是,许多屏幕从左上角移动到像素(0, 0)到右下角是像素(positive X, positive y)。你的第二个条件:

(y >= this->GetTop() && y <= this->GetTop() + this->GetHeight())

可能需要:

( (y + h - 1) >= this->GetTop() || y <= (this->GetTop() + this->GetHeight() - 1) )

第一部分需要更改,因为最初您正在测试输入对象的TOP与要测试的对象的TOP相撞。你真正想要的是输入的BOTTOM,用你要测试的对象的顶部进行测试。

在尝试执行这种类型的编码时,我总是发现一件非常有用的事情,就是用实际的基于像素的示例数字来绘制非常简单的草图,这样我就可以在编码之前将其可视化。

我希望所有这些都有帮助: - )