AABB碰撞响应(推回碰撞对象)

时间:2015-03-22 15:07:58

标签: c++ vector collision-detection

我的C ++游戏碰撞检测有问题。我首先尝试了AABB并成功地检测到碰撞,但问题是我希望能够互相推动,所以我采用了一种基本的解决方案,将两个物体推回一半的距离。但是这只会使物体彼此成45度角。Link to GIF explaining what i mean

如果您不想阅读本段内容

所以我认为我需要一个方向来推送对象,所以我尝试修改教程中的一些代码。方向是两个对象中心之间的归一化向量。然后将一半的碰撞深度与标准化矢量相乘,使它们在相反的方向上被推动。这有效,但它使用圆形碰撞(它使用半径+半径来计算碰撞深度),这意味着我不能使用不同宽度和高度的矩形,例如32x64 48x32(我不得不使用32x32 48x48 64x64等等等等)。这是一个很大的问题,因为我需要使用不同宽度和高度的纹理

所以再一次回到AABB并让它能够互相推动,所以你就完全停下来了。但问题是,当我在一个轴上碰撞时,我无法在另一个轴上移动。例如,如果我按住向上和向左并与LEFT上的墙碰撞,我会完全停止而不是在没有墙的情况下继续向上移动。

所以我想要帮助 AABB碰撞,物体相互推动,一半的距离穿过正确的方向,或者只是简单的AABB,你完全停止但是能够在另一个轴上碰撞时沿非碰撞方向行走,例如Holding down up and down would result in this

1 个答案:

答案 0 :(得分:2)

这里有一些关于AABB碰撞检查的事情:

假设您有两个盒子对象:O1(x,y,宽度,高度)和O2(x,y,宽度,高度),其中' x'并且' y'是盒子对象的左下角。

让我们说你用步骤S(x,y)移动O1

为了避免碰撞完全停止,你应该将你的碰撞检查分成两部分 - 一旦碰撞为水平,一次为垂直。

因此,移动后得到原点差异:diff = vec2(O1.x + S.x - O2.x, O1.y + S.y - O2.y)

在继续之前,你应该检查这两个对象是否永远不会重叠:

if( (diff.x < -O1.width || diff.x > O2.width) && (diff.y < -O1.height || diff.y > O2.height) return;

如果它们从不重叠,则无需限制运动,我们只是跳过碰撞。

然后我们开始约束水平运动:

  1. 如果diff.x小于-O1.width,则O1位于最左侧。它可以在水平方向上自由移动。所以S.x保持不变。

  2. 如果diff.x大于O2.width,则O1位于最右侧,并且可以在水平方向上自由移动。所以S.x保持不变。

  3. 否则,我们遇到O1在水平方向上重叠O2的情况。因此,只需检查if(diff.x<0) S.x -= O1.width+diff.x;if(diff.x>=0) S.x += O2.width-diff.x;

  4. 您的水平移动应该在S.x准备就绪。现在,按照同样的原则,照顾你的垂直运动:

    1. 如果diff.y小于-O1.height,则O1远低于S.y。它可以在垂直方向上自由移动。所以diff.y保持不变。

    2. 如果O2.height大于S.y,则O1远远超出,并且可以在垂直方向上自由移动。所以if(diff.y<0) S.y -= O1.height+diff.y;保持不变。

    3. 否则,我们的情况是O1在垂直方向上与O2重叠。因此,只需检查if(diff.y>=0) S.y += O2.height-diff.y;S(x,y)

    4. 从本质上讲,最后你有一个{{1}},其中包含你的新安全&#39;移动步骤。 你所要做的就是用S移动O1,然后在下一步重复这个过程。