阻止世界碰撞检测

时间:2012-03-19 13:15:07

标签: xna collision

我目前正在使用XNA中的块世界引擎,无法使碰撞检测和处理正常工作。世界在一个以(z * width * width + y * width + x)索引的数组中,并包含由字节表示的不同块。一切都很好,花花公子。或者我想。

我尝试了不同的碰撞处理技术,我目前正在使用一个版本来计算玩家/摄像机的方向,然后将其添加到位置我用半个a检查每个矢量(x,y和z)单位偏移(以补偿1.0的块大小)与世界相关,仅在结果为零时应用它。到现在为止还挺好。现在当我直接走到一个角落时出现问题,因为直到我进入立方体之前,x轴和z轴才相交/碰撞。

那我怎样才能在块世界中正确计算碰撞检测和处理?

我真的很喜欢这方面的一些意见,最好是在更高/概念层面,但代码示例当然也是受欢迎的。



为了进一步解释我的情况,基于@ A-Type的回复:

所以,让我们更准确地帮助我理解你。我的角色在每个方向上只有一个单位,这应该会使事情变得更容易。

首先,你是否应该首先更新我的角色位置并检查之后的碰撞?这将是我首选的碰撞检测方法,但如果它更容易,我会先检查并在可能的情况下稍后再移动。

嗯,我知道玩家只能交叉8个立方体(在你的例子中为12)并且圆角似乎也是一个非常好的主意,但我不太看到从12个立方体的过渡(再次在你的例子,我的只有8)只有3.这不会导致同样的问题,角色立方体的角落不会被考虑在内吗?

我试图实现这个但失败了,所以我认为更多的理论可能会这样做。 (我实际上已经将碰撞检测工作了,但在那些情况下我完全失去了速度,而不仅仅是在碰撞方向。)



谢谢你的时间! 卡尔

2 个答案:

答案 0 :(得分:1)

利用您的世界格式创建比检查每个块更有效的碰撞算法。

假设你的块有一个3D字节数组,0是一个空白区域,我强烈建议将你的玩家位置四舍五入到你世界的一组网格空间,并检查是否有任何这些空格不是0.然后针对非空块执行碰撞处理代码。

例如,如果你的角色是身高2和宽度/深度1(就像来自Minecraft的Steve),他最多可以同时交叉12个网格空间(他的头部4个,腰部4个,腰部4个)脚),至少2(如果他与网格完全对齐)。

将角色的身体转换为网格术语。将角色的位置四舍五入到网格单元格,然后检查它周围的12个空格(如果他是2x1)。如果有任何非空,请在这些块和您的角色之间执行冲突解决。您检查哪些相邻的块取决于您舍入的方向。例如,如果您的角色的位置是(3.4,2.7,1.1),您可以将其舍入为(3,3,1),然后检查1个大的块。 X方向,Y方向1小时,Z方向1大,因为你分别向下,向上和向下四舍五入。

我希望也许这是可以理解的。如果没有,只需评论。我不知道为什么会这样,但我似乎无法解释这个概念,特别是因为我已经做了近一年这样的事情。

答案 1 :(得分:1)

好吧,让我们再给它一次。在任何有效的系统中,碰撞检测有两个基本阶段。如果愿意的话,有宽相和窄相。宽相使用不准确但廉价的方法来确定两个对象是否可以相交,并将这些对象传递到窄相位。窄阶段采用我们的两个候选对象并应用更复杂的物理来调解碰撞。

对于基于网格的世界,我们有一种非常简单而有利的广角碰撞方法。这就是网格本身。我们可以使用玩家的位置和大小来确定他可能相交的8个街区(我们将从现在开始使用你的情况)。请注意,在我的原始答案中,我似乎正在谈论将其缩小到3个块 - 我使它变得比它需要的更复杂,特别是对于1块字符。最简单的方法是:将角色的中心四舍五入到网格的,即8个角的角相交的位置。然后选择那8个块用于窄相位测试。一定要使用中点舍入,而不是使用整数时默认的地板舍入。即,如果值为1.53,则应舍入为2,并将1.49999舍入为1。

现在,狭窄的阶段I并没有真正涵盖太多。您询问是先移动还是移动,我认为您需要先移动它。我不是物理模拟大师,但我知道你首先想要计算碰撞方向(角色中心减去区块中心)。深度是该向量的长度。如果您的块是1宽,那么您不希望该长度小于1;这表明它们相交(有点基本上)。

现在,有许多方法可以从碰撞中“恢复”对象。我建议确定对象碰撞哪个轴最少。也就是说,如果碰撞方向向量的X分量最小,则意味着您的玩家最接近于X方向上的碰撞 out 。在该方向上施加与X方向上的碰撞深度成比例的反向力。或者,如果您选择,只需将角色的位置设置为您想要的距离,而不必担心力量。但是你只想在一个基本方向上移动角色。这使事情变得更简单,并且不会阻碍沿着地面或沿着墙壁移动。

以这种方式思考:让我们说你的角色因重力而落入地面的每一帧。现在,让我们说当他落入这个框架时,他位于中间位置。这意味着他与他下面的块的碰撞深度是(0.5,0.3,0.5)(其中X是侧面,Y是向上,Z是向前)。如果你在所有这些方向上施加恢复力,你将会将玩家向左移动,向后移动并在地面上重新移动。最后一点是你想要做的唯一部分。因此,忽略较大的碰撞轴,只恢复较小的(Y)碰撞。现在你的角色的水平运动是畅通无阻的,他仍然高于地面。