在2D平台游戏中使用瓷砖检测碰撞

4

我和我的团队正在使用C++/SDL/OpenGL开发一款2D平台游戏,我们已经定义了一个碰撞系统,但在检测与瓷砖地图的碰撞时遇到了问题。

瓷砖地图中的瓷砖大小为32x32,因此我们试图定义玩家在X和Y方向上的最大速度小于32,因为如果速度超过瓷砖大小,则在检测碰撞时位置将会更新,而这个速度将超过32,导致位置跳过一个瓷砖,从而造成大量的验证问题。因此,目前我们将X和Y方向的速度限制在30以内,但我们不知道如何使速度超过瓷砖大小而又不失去与可能被跳过的某些瓷砖的完整碰撞检测。

3个回答

3

扫描测试

基本上,与其简单地检测盒子/盒子之间的碰撞,您需要检查您的静止级别几何盒子与将移动的移动盒子形成的形状之间的碰撞(位置)到(位置+速度)。


那么,您的意思是在检查碰撞期间仅在检查碰撞结果为false时更新位置,而不是在检查之前移动盒子? - oscar.rpr
1
如果你的盒子/扫描盒检查为false,那么你可以继续前进,只需将你的盒子移动到它想去的地方即可。如果是true,你需要找出在dt期间何时变为true。我建议使用二分搜索,在其中沿着(位置+速度alpha)变化你的扫描盒第二个点,其中alpha在0.0和1.0之间变化。当你发现碰撞发生的时间时,只需将你的盒子的最终位置设置为(位置+速度alpha)。 - genpfault
非常感谢你的答案。我已经应用了这种方法,效果非常好。 - oscar.rpr

1
你如何定义速度?我们假设它是每秒像素数,为了允许更高的速度,你应该每秒检测多次碰撞。因此,伪代码如下:
double time = GetElapsedTime();
player.updatePosition(speed * time);

现在可能比这更复杂,但你懂的;要么像这样做,要么使用精确的碰撞检测(我曾经找到一篇很棒的文章,但似乎找不到了),该方法使用方程式“预测”物体何时何地发生碰撞。


1

我使用过的一种方法是:

在移动角色或其他精灵时,通过确定它经过的所有矩形形状的瓦片。

举个例子:

on tick:
   player-box = (player.x, player.y) - (player.x + player.width, player.y + player.height)
   player-delta.x = (player-speed.x × (now - last-updated))
   player-delta.y = (player-speed.y × (now - last-updated))
   player-end-box = player-box + player-delta
     { i.e. player-end-box = ( player-box.top-left.x + player-delta.x,
                               player-box.top-left.y + player-delta.y ) -
                             ( player-box.bottom-right.x + player-delta.x,
                               player-box.bottom-right.y + player-delta.y ) }
   player-collided = ( min (player-box.top-left.x, player-end-box.top-left.x),
                       min (player-box.top-left.y, player-end-box.top-left.y) ) -
                     ( max (player-box.bottom-right.x, player-end-box.bottom-right.x),
                       max (player-box.bottom-right.y, player-end-box.bottom-right.y) )

然后,您可以对player-collided的每个角取模32,以确定玩家(或任何精灵)已经(尝试)遮挡的瓷砖。

通常,您可能希望在玩家实际大小上放置一个小的“边距”插图,以避免1像素或2像素的重叠...(即将起始框设置为比实际精灵小几个像素),具体取决于您的玩家控制的准确性和精灵与一个瓷砖之间的大小差异。

请注意,非常快速(每次更新多个瓷砖)的对角线移动会使此方法无效,但对于非常快速的线性(水平或垂直)移动效果很好。如果您在对角线上移动得“太快”,则应考虑将起始和结束矩形连接成多边形(不规则六边形),并测试每个瓷砖是否包含该六边形的任何部分。

  for each tile in (big rectangular area):
      if tile is inside polygon (hexagon of movement):
          add tile to list of collisions

这实质上是对于常见的二维情况下完整边界几何检查的优化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接