2D平台游戏中的双轴碰撞问题

5
我正在使用C++和SDL制作一个小型2D平台/格斗游戏,但是我在碰撞检测方面遇到了很多问题。
游戏关卡由一系列瓷砖组成,我使用for循环遍历每个瓷砖(我知道这可能不是最好的方法,我可能需要帮助解决)。对于角色的每个侧面,我将其向该方向移动一个像素并检查碰撞(还要检查角色是否向该方向移动)。如果发生碰撞,我将速度设置为0并将玩家移动到瓷砖的边缘。
我的问题是,如果我先检查水平碰撞,并且玩家每帧垂直移动超过一个像素,则即使瓷砖在角色下方(或上方),它也会处理水平碰撞并将角色移动到瓷砖的侧面。如果我先处理垂直碰撞,则会出现相同的情况,只不过是在水平轴上。
如何在两个轴上处理碰撞而不出现这些问题?有没有比我现在做的更好的处理碰撞的方法?

你是在移动角色之前检查碰撞,还是在移动后再进行检查? - Henry Hammond
我在移动角色后进行检查。 - ausgat
2个回答

5
XNA的2D平台游戏示例也使用了基于瓷砖的碰撞检测。他们处理的方式非常简单,可能对你有用。这里是一个精简版的解释(去掉了特定于其演示程序的内容):
  1. 应用运动后,检查碰撞。
  2. 根据玩家的包围盒确定玩家重叠的瓷砖。
  3. 遍历所有这些瓷砖...
    1. 如果要检查的瓷砖不可通过:
    2. 确定玩家在非可通过瓷砖上重叠的X和Y轴距离
    3. 仅在浅轴上解决碰撞:
      1. 如果Y是浅轴(abs(overlap.y)< abs(overlap.x)),那么position.y + = overlap.y;同样,如果X是浅轴。
      2. 根据位置变化更新包围盒
    4. 进入下一个瓷砖...
如果你获取了代码并想看看他们具体在哪里做,请查看player.cs中的HandleCollisions()函数。

这可能听起来有点奇怪,但是什么是浅轴?我查了谷歌,没找到任何相关的信息。 - Dominic K
“浅轴”指的是碰撞所穿透程度较少的那个轴。例如,如果角色的位置在Y轴上计算为5个单位,在X轴上计算为10个单位,则Y轴就是浅轴。 - chaosTechnician

0

是的。基于向量的碰撞比基于瓦片的碰撞要好得多。将每个瓦片的边缘定义为线段(有捷径,但现在先忽略它们)。现在,为了判断是否发生了碰撞,请找到最近的水平和垂直线。如果您取lastPos.x * LineVector.y - lastPos.y * LineVector.x的符号,并将其与thisTurnsPos.x * LineVector.y - ThisTurnsPos.y * LinePos.x进行比较,如果这两个值的符号不同,则表示您已经越过了该线。这并没有检查您是否越过了线段的末端。您可以在相同的LineVector和curPosition之间形成一个点积(可能会有一些误差,但足够好),如果它是负数或大于线段的大小平方,则您不在该线段内,也没有发生碰撞。

现在这个问题相当复杂,你可能可以通过简单的网格检查来判断是否已经进入了另一个方块的区域。但是!使用向量的优点在于它解决了移动速度超过碰撞框大小的问题(更重要的是),您可以为碰撞使用非轴对齐线条。该系统适用于任何2D向量(并且通过一些调整,也适用于3D)。此外,它还允许您轻松地沿着碰撞框的边缘滑动角色,因为您已经完成了寻找碰撞后应该在哪里的99%的数学计算。

我略过了一些实现细节,但我可以告诉您,我已经在无数商业视频游戏中使用了上述方法,并且它非常有效。祝你好运!


我忘了提到我在游戏开发方面还比较新手,而且我正在开发的游戏相当简单。基于向量的碰撞检测听起来更好,但我觉得我还做不到。 - ausgat

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