4

我正在开发一个 2D 平台游戏,我想知道实现表面(碰撞)检测的最佳(性能方面)方法是什么。

到目前为止,我正在考虑构建一个由线条列表构成的关卡对象列表,并沿着线条绘制瓷砖。

替代文字 http://img375.imageshack.us/img375/1704/lines.png

我认为每个对象都保存着他行走的表面的 ID,以便在上坡/下坡时轻松操纵他的 y 位置。

像这样的东西:

//Player/MovableObject class
MoveLeft()
{
    this.Position.Y = Helper.GetSurfaceById(this.SurfaceId).GetYWhenXIs(this.Position.X)
}

因此,我用来检测“在表面上掉落/行走”的逻辑是一个简单的点(玩家的小腿)-接触线(表面)检查(具有一些安全近似值 - 假设在线上 1-2 个像素)。

这种方法可以吗?我一直很难找到有关此问题的阅读材料,因此请随时删除链接/建议。

4

8 回答 8

3

长期使用基于多边形的 2D 平台游戏,让我给你一些建议:

制作基于图块的平台游戏。

现在,直接回答您关于碰撞检测的问题:

你需要让你的世界几何“实体”(你可以让你的玩家对象成为一个点,但让它变得实体更好)。我所说的“实心”是指 - 你需要检测玩家对象是否与你的世界几何体相交。

我试过“玩家是否越过了这个世界几何的边缘”,但实际上是行不通的(即使它似乎在纸上可行——浮点精度问题不会是你唯一的问题)。

网上有很多关于如何在各种形状之间进行交叉测试的说明。如果您刚刚开始,我建议使用 Axis-Aligned Bounding Box (AABB)。

制作基于图块的平台游戏比制作任意几何图形的平台游戏要容易得多、多得多、多得多得多。所以从瓷砖开始,检测与 AABB 的交叉点,然后一旦你开始工作,你就可以添加其他形状(例如斜坡)。

一旦检测到交叉路口,您必须执行碰撞响应。同样,基于图块的平台游戏是最简单的 - 只需将玩家移动到被碰撞的图块之外(你是移动到它上面还是移动到一边? - 这将取决于碰撞 - 我将离开如何做到这一点锻炼)。

(PS:你可以用方形瓷砖得到很好的结果——例如,看看 Knytt Stories。)

于 2010-06-07T04:05:35.053 回答
1

我在处理 2D 碰撞检测方面玩得很开心。如果您不提前计划,看似简单的问题很容易变成一场噩梦。

在面向对象的意义上做到这一点的最好方法是创建一个通用对象,例如classMapObject。这有一个位置坐标和斜率。由此,您可以将其扩展为包括其他形状等。

从那开始,让我们处理与 Solid 对象的碰撞。假设只有一个块,比如 32x32,你可以从 left, right, top 和 bottom 击中它。或者,根据您的编码方式,同时从顶部和左侧击中它。那么你如何确定角色应该走哪条路呢?例如,如果角色从顶部撞到块,要站立,编码不正确,您可能会无意中将角色推到一边。

那你该怎么办?我为 2D 游戏所做的,是在决定如何对碰撞做出反应之前查看人的先前位置。如果角色的 Y 位置 + 高度在方块上方并向西移动,那么我会先检查顶部碰撞,然后再检查左侧碰撞。但是,如果角色的 Y 位置 + 高度低于块的顶部,我会检查左侧碰撞。

现在假设你有一个有倾斜的块。块宽 32 像素,高 32 像素,x=32,高 0 像素,x=0。 有了这个,你必须假设角色只能从顶部撞击和碰撞这个块才能站立。 使用此块,如果是左/右/下碰撞,则可以返回 FALSE 碰撞,但如果是顶部碰撞,则可以声明如果角色在 X=0,则返回碰撞点 Y=0 . 如果 X=16,Y=16 等等。

当然,这都是相对的。您将检查多个块,因此您应该将角色方向的所有可能更改存储到临时变量中。因此,如果字符在 X 方向上与块重叠 5,则从该变量中减去 5。累积 X 和 Y 方向上所有可能的变化,将它们应用到角色的当前位置,并在下一帧将它们重置为 0。

祝你好运。稍后我可以提供更多示例,但我在我的 Mac 上(我的代码在 WinPC 上) 这与经典的《洛克人》游戏 IIRC 中使用的碰撞检测类型相同。这也是一个视频:http ://www.youtube.com/watch?v=uKQM8vCNUTM

于 2010-06-04T22:43:43.023 回答
1

看看它是如何在 XNA 的Platformer Starter Kit项目中完成的。基本上,瓷砖有枚举来确定瓷砖是否可以通过,不可通过等,然后在你的水平上你GetBounds的瓷砖,然后检查与玩家的交叉点并确定要做什么。

于 2010-06-04T21:56:07.720 回答
0

我使用了一种有限的碰撞检测方法,它在非常不同的基础上工作,所以我会把它扔在这里以防它有帮助:

黑白的次要图像。无法通过的像素是白色的。构造一个字符的掩码,它只是当前设置的任何像素。要评估预期的移动,请从次要图像中读取该蒙版的像素,并查看是否有白色的返回。

要检测与其他对象的碰撞,请使用相同类型的方法,但使用足够的深度来覆盖所有可能的对象,而不是使用布尔值。完全以其对象编号的“颜色”将每个对象绘制到辅助对象。当您阅读蒙版并获得非零像素时,“颜色”就是您点击的对象编号。

这解决了 O(n) 时间内所有可能的冲突,而不是计算交互的 O(n^2)。

于 2010-06-07T05:35:55.293 回答
0

创建自己的碰撞检测算法并不容易。一个简单的困难示例是:如果您的角色以足够高的速度移动,以至于在两帧之间它将从一条线的一侧移动到另一侧怎么办?那么您的算法将没有时间在两者之间运行,并且永远不会检测到碰撞。

我同意 Tiendil 的观点:使用图书馆!

于 2010-06-04T22:07:17.747 回答
0

我会这样做:

  1. 严格没有碰撞线。只有实体形状(盒子和三角形,也许是球体)
  2. 2D BSP,2D 分区以存储所有级别的形状,或“扫描和修剪”算法。每一个都将非常强大。Sweep 和 prune 与插入排序相结合,可以轻松地处理数千个可能发生碰撞的对象(如果不是数十万个),并且 2D 空间分区将允许根据需要快速获取附近所有可能发生碰撞的形状。

让物体在表面上行走的最简单方法是每帧先让几个像素下降,然后获取物体碰撞的表面列表,然后将物体移动到表面法线的方向。在 2d 中它是垂线。这种方法会导致对象在非水平表面上向下滑动,但您可以通过稍微改变法线来解决此问题。此外,您必须每帧运行几次碰撞检测和“将对象推开”例程,而不仅仅是一次。这是为了处理对象在堆中或它们接触多个表面的情况。

于 2010-06-07T05:04:06.750 回答
0

我推荐Farseer Physics。这是一个强大而强大的物理引擎,应该能够处理您需要的任何事情!

于 2010-06-04T22:45:55.997 回答
0

您可以尝试使用其中一种物理引擎,例如Box2DChipmunk。他们拥有自己先进的碰撞检测系统和许多不同的奖励。当然它们不会加速你的游戏,但它们适用于任何现代设备上的大多数游戏

于 2010-06-04T16:45:52.330 回答