我有一个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;
}
精灵总是长方形。我似乎忘记检查碰撞的一些条件。如果矩形完全碰撞然后一切正常,但是如果我向上移动然后试图抵挡另一个,它将会滑过。似乎我接近的每个方向都有类似的行为,它只适用于某些部分。你能帮助我找到我忘了检查的东西吗?
答案 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,用你要测试的对象的顶部进行测试。
在尝试执行这种类型的编码时,我总是发现一件非常有用的事情,就是用实际的基于像素的示例数字来绘制非常简单的草图,这样我就可以在编码之前将其可视化。
我希望所有这些都有帮助: - )