如何处理2D中的角碰撞?


22

我正在写一个自上而下的2D XNA游戏。自从我第一次上学以来,我一直在尝试自己编写物理学和碰撞学知识。

每当我的玩家精灵角色试图移动到其边界与墙的边缘相交的位置时,我都会计算出反弹角(入射角=反射角),并让玩家反弹出墙并避免碰撞。

我很难弄清楚如何处理我的精灵同时与两个墙边相交的情况,尽管它碰到了一个角落。

拐角碰撞

我的代码当前告诉我,两个墙的边缘已经相交,但是没有碰到哪个边缘,因此没有反弹。

选择哪个边缘反弹的数学测试是什么?看到它的时候很简单,但是我正在努力寻找它的数学测试。



谢谢Tetrad。我看到了一个,但看起来球的行为与我的矩形问题有所不同。在上面所示的情况下,矩形精灵会撞到墙的底部边缘并反弹。墙的侧边永远不会成为方程式。我只是不知道如何在代码中表达它并做出决定。
TerryB

Answers:


9

如果您计算已移动到的Wall距离Player Sprite,则可能可以基于相交的角的x和y坐标的增量。我希望这是有道理的,我想不出一种更好的措词方式。

因此,例如,如果您查看图表。就拿x的左上角的值Player Sprite(移动后),并减去x的右下角的价值Wall。对y值做同样的事情,然后看哪个更大。关键是,如果一个大于另一个,则Player Sprite可能在该侧相交。

这是一个图像示例(这是图像的一个小节,其中添加了我自己的行):

相交的例子

现在,您在这里看到蓝线大于绿线。在这种情况下,蓝线也在Player Sprite预期会反弹的一侧。

如果两个值相等,则它们将在角上。

现在,以这种方式进行操作存在一个小问题。如果Player Sprite行进速度非常快或碰撞非常靠近拐角处,则行进路线Player Sprite可能会Wall沿错误的方向进一步向行进。在这种情况下,您可能必须检查移动物体的速度。(请参阅内森·里德的答案。)

注意:我想我实际上是在描述@Blau提到的SAT碰撞检测,但是我花了很长时间写了这篇文章,所以无论如何我都要发布它。希望它将对您有所帮助。


谢谢德拉克!而且我猜想如果我的墙相对于精灵旋转,会比较棘手,但原理相同。寻找最小长度的位移矢量,这将意味着精灵不会与墙碰撞。然后使用垂直于该矢量的墙作为我的墙反弹。
TerryB

@TerryB-旋转为其添加了更多的复杂性。您可能需要阅读与轴对齐的边界框(AABB)。基本上,通过测试旋转对象将适合的最小框,但其轴与笛卡尔轴对齐,您仍然可以使用与上述相同的原理。想象一下,如果您有一个正方形并将其旋转45度以使其成为菱形。计算碰撞的难度和成本很高,因此,首先要使用AABB检查物体是否靠近它,AABB是一个正方形,菱形的每个点都接触到中间的每一侧。
理查德·马斯克

然后,当您知道它在附近时,您可以进行更昂贵的计算,以查看它们是否在角度上相交(这可能是另一个问题:)。
理查德·马斯克

1
-1,因为最小位移并不总是能正确回答“哪个边先碰撞”;看我的答案。
内森·里德

@NathanReed-这就是为什么我在“现在,以这种方式进行操作存在一点问题”段落中提到检查速度的原因。
理查德·马斯克

15

最小排量 不能总是给出其优势是先打正确的答案。考虑这种情况:

最短位移算法的情况

当速度足够高以致块在一帧中移动得很远时,就会发生这种情况。为了正确检测首先撞到哪个边缘,您需要建立一个线性方程来求解与每个边缘的碰撞时间。在OP的图表中描述的这种情况下,相关方程为:

timeXCollision = (player.left - wall.right) / -player.velocity.x
timeYCollision = (wall.bottom - player.top) / player.velocity.y

(这是假设X轴为X轴,Y轴为Y轴的坐标系。)通常,您必须使用player.velocity的X和Y分量来确定需要测试的一对边缘。无论如何,一旦计算出碰撞时间,这两者中的较早者就是您需要处理的碰撞。


1
您能否提供一个有关如何实现两个变量的示例?
BjarkeCK

1

你需要 SAT碰撞检测

基本上,您需要查找减去了其中一个对象的最小位移矢量,以使它们不相交。

在图像中,最小位移是橙色部分。

在此处输入图片说明


4
-1,因为最小位移并不总是能正确回答“哪个边先碰撞”;看我的答案。
内森·里德

谁在问那个?
2012年

问题是在问。“我的代码目前告诉我,两个墙的边缘已经相交,但是没有碰到哪个边缘,因此没有反弹。”
内森·里德

第一?问题不是第一个,它同时与两个边缘碰撞,...问题是反弹哪个边缘,您选择了一种对您有益的方法,我选择了一种方法对我很好,两个都有效
Blau 2012年

1
如果您要做出设计决策,让对象像这样相互滑过,好像它们是圆角或斜角,那是您的决定,并且很可能是您玩游戏的正确选择。但是我不认为问题在询问设计决策。它在数学上问如何使轴对齐的矩形彼此弹开。这不是解释问题;这个数学问题对于反弹的边缘有清晰正确的答案。
内森·里德

0

在这里回答了类似的问题

您可能要考虑检查以前的位置-

例如:如果您的左侧先前位于其右侧的右侧并且正在碰撞,则发生了右手碰撞。

如果这样做,只需解决y轴碰撞,检查是否与任何物体发生碰撞,然后解决x轴碰撞。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.