在2D平台游戏中,如何确保玩家在斜坡上平稳移动?


18

我正在为2D平台游戏开发物理引擎。我正在使用分离轴定理进行碰撞检测。地面是由定向包围盒构成的,播放器是与轴线对齐的包围盒。(具体来说,我使用的是《实时碰撞检测》一书中的算法,该算法使用SAT对OBB执行扫掠碰撞检测)。我在碰撞响应中使用了一个很小的(接近零)恢复系数,以确保动态对象不会穿透环境。

该引擎通常运行良好,只是我担心可能会出现的一些极端情况。例如,在图中,A,B和C是地面。玩家沿着B向A左转。在我看来,由于不准确,玩家方块在继续向上和向左移动时可能会略低于方块B。因此,当到达A时,玩家的左下角可能会与A的右侧发生碰撞,这是不希望的(因为这样做的目的是使玩家在A的顶部上方平稳移动)。当玩家位于方框C的顶部,向B的左侧移动时,似乎会发生类似的问题-B的最极端点可能会与玩家的左侧发生碰撞,而不是玩家的左下角在上下滑动B以上

Box2D似乎通过存储其边缘形状的连接性信息来解决此问题,但是我不太确定它是如何使用此信息来解决问题的,并且在查看代码后,我并没有真正掌握它的作用。

任何建议将不胜感激。


通用物理引擎非常适合效果和坠落之类的东西,但不适用于角色物理,如答案部分所述。考虑为角色编写“静态”物理,这样您就可以100%地控制自己,并为其余角色使用正确模拟的动力学。
米2014年

Answers:


14

平台与物理

这些边缘情况很多。好玩的平台游戏者并不会以任何一种物理上精确的方式表现,而玩家希望在像Mario这样的“完美”平台游戏者数年之后所获得的控制和行为很难通过Box2D或其他物理引擎等通用技术来实现。大多数优秀的平台游戏玩家在其播放器控制器中均不使用任何通用物理或碰撞响应。

产生船体

关于您的特定问题,最好的解决方案是停止使用盒子作为基础。使用一系列连接的线段(船体)。这使得碰撞检测引擎仅关注实际可行走的表面,而不关注AB和BC之间存在的“伪”边缘。实际上,Box2D就是这样做的。这些形状用于生成向外的表面,将它们链接在一起以形成船体。

即使在基于图块的游戏中,或者在两个AABB对象彼此相邻作为地板的情况下,也需要此设置。碰撞引擎将拾取那些垂直边缘并使玩家抓住它们。有一些可以帮助但不能消除问题的技巧。解决方案是仅使用一个代表曲面的线段,而不是一个完整的2D框。

在一般情况下,您可以通过以下方式生成船体:将多边形相互裁剪,然后将裁剪点连接到边列表中。

倾斜表面

由于您的示例包含一个坡度,并且您提到的是恢复原状和其他物理属性,因此,我将指出您很快就会注意到的其他一些问题,这进一步说明了为什么通用碰撞检测和响应不适用于平台开发人员。首先,尝试站在倾斜的平台上,跳起来,然后着陆。您可能会注意到角色着陆时会“滑动”一点。问题在于您生成的接触法线通常会从倾斜的表面指出。然后,在解决碰撞时,将玩家朝该方向推出。即使角色是直接跌倒的,着陆时他也会被推起并向右偏一点,从而产生滑动。可以通过考虑相对速度来破解它,

您要注意的第二个问题(更难解决)是,当您尝试在斜坡上快速运行时会发生什么。玩家将在坡道上“跳跃”。即使在当今大多数AAA游戏中,这也非常明显。它不仅看起来很傻,而且如果您的游戏要求玩家脚踩在地面上跳跃,那么这将使它难以从斜坡滑下并跳到一半,因为玩家仅在斜坡的一小部分接触斜坡。花费下来的时间。一个更简单的解决方法是在玩家移动时简单地进行一些射线投射,如果玩家没有跳跃并且先前在地面上,则将其位置向下捕捉到最近的表面(如果它非常靠近玩家)。

如果您试图模拟玩家的速度,摩擦力和恢复力,就好像他是一个普通的刚体一样,您可能会发现,在坡道上奔跑时,玩家会飞向空中。除非跌倒/跳下,否则玩家的动作应限制在水平方向。当然,如果您使用的是老龄的平台游戏玩家,您可能会注意到,玩家的水平速度通常在水平表面和倾斜表面之间是恒定的。在上/下坡时也需要考虑到这一点。

您最终还会遇到许多其他奇怪的情况。如果您想做一个好的平台游戏者,那么最好是独立于物理平台实现平台游戏玩家控制器,并对所需的运动和控制行为进行硬编码,而不是依赖于通用物理原理和碰撞响应算法。


感谢您的回复。我曾考虑过将代表地面的盒子简化成线条,但实际上我并不认为这本身就能解决问题。例如,如果接地盒现在是直线,并且如果玩家站在C线上并向B左行,则由于不准确,玩家盒可能略低于C线。然后,玩家盒的左边缘仍可能与B线碰撞并导致意外碰撞,
Nick Kovac 2012年

除非有其他机制可以阻止这种情况发生。Box2D使用线而不是盒子来解决问题并不是事实,而是Box2D使用链形,它使用线段之间的连接信息来防止发生某些碰撞。目前的主要问题是我不太了解如何精确执行此操作的详细信息。
尼克·科瓦奇

您还从通用物理引擎中获取了一些想法并将其应用于平台游戏,从而提出了有关该问题的其他一些非常好的观点。我见过类似的引擎可以实现您所讨论的想法(修改斜坡的碰撞法线,并将玩家吸引到斜坡上),因此至少这些问题很容易解决。对我来说,主要的难点是与数值错误有关的棘手的边缘情况。
尼克·科瓦奇

@Kovsa:同样,当您摆脱不应该是碰撞的一部分的边缘时,那些特殊的错误也会消失。将边缘链接在一起以形成不间断的形状。设计关卡时,我还建议将顶点对齐在一起,以使曲面上没有任何小缝隙。与在3D网格编辑器中设计关卡的方式没有什么不同。
肖恩·米德迪奇

嗯...我不认为我会遵循。在我的图表中,如果将边缘链接在一起以形成不间断的形状,我将得到一个由三个线段组成的形状:方框A,B和C的顶部,对吗?即使是单个形状,我仍然需要针对线A,线B,线C然后分别执行碰撞检测,对吗?除非您要使用的算法可以检测盒子与组合形状之间的碰撞,否则?我假设那时不会是SAT,因为一系列边缘可能是凹形的?
尼克·科瓦奇

5

我认为这两个问题都可以通过将您的盒子当作碰撞响应来解决,就像它们具有圆角(半径与您的数值误差相似)一样。这将使A和B之间以及B和C之间的相交角的有效组合表面更加平滑。

因此,如果向左移动的玩家碰到A的角,则碰撞法线将是对角线,而不是纯粹向右,因此允许继续向上和向下运动。


但是,在回顾我对平台物理学的了解时,一个更典型的解决方案是使玩家的形状更加圆滑,而不必考虑地形。特别是考虑将玩家的形状做成胶囊状(中间伸展的圆(2D)/球体(3D)),然后您的碰撞法线自然会接近垂直,从而消除了任何抓球问题。

您说您正在使用专门用于OBB的碰撞算法,但是在找到OBB-OBB碰撞后,您仍然应该能够对整个OBB内的形状进行进一步测试。


嗯,有趣的主意...您将如何实施它?但是,这确实与使用盒子的简单性背道而驰:(我同意,对于确定的解决方案,这似乎应该是一个普遍的问题,但是除了正在做的事情之外,我真的找不到关于它的任何内容。在Box2D的我贴在他们的论坛类似的问题,希望能够得到更深入的了解。
尼克·科瓦奇

抱歉,我没有任何实现细节,我不是这类物理引擎代码的专家。但是,对于不基于软糖因素的解决方案,我确实有一个更好的主意-请参阅我的编辑。
凯文·里德

1
请注意,尽管使用圆角形状确实可行,但从数学上来说,它更加复杂,并且可能导致平台游戏者的行为不佳。玩家期望对站立在壁架上的角色具有接近完美的像素控制,例如,圆形形状或多或少将使圆形变得不可能,并且角色会意外地滑出壁架。
肖恩·米德迪奇

壁架:哦!好,不像我想的那么简单。
凯文·里德

是的,考虑了一下之后,胶囊方法似乎更适合3D游戏,而不是2D平台游戏。对我来说,拥有完美的像素控制绝对是我的首要任务(就像所有那些旧的2D平台游戏一样)。但是必须有一个允许使用盒子的解决方案!
Nick Kovac 2012年
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.