如何在物理引擎中有效地模拟静态矩形网格?

时间:2011-07-16 23:11:43

标签: c# physics game-physics farseer

我正在制作一个太空射击游戏,它发生在一个大型地牢中,该地牢由大型矩形组成,用于定义墙壁。使用Farseer Physics对游戏中的所有内容进行物理模拟。但是有一个问题:我希望地牢看起来足够大,但这需要我的网格中至少有80x80个矩形,这意味着在最坏的情况下,我有6400个物理模拟的物体,这不完全是性能友好,你可以猜到。

我的临时解决方案是在垂直切片中划分网格,这样,对于每一列,使用布尔添加操作添加所有矩形,然后使用生成的凹多边形创建一个主体。它会稍微提高性能,但是多边形容易陷入混乱,变得不存在,阻塞通常应该遍历的方式甚至变得无效并导致Farseer崩溃。

我一直在考虑制作某种算法,以某种方式找到最大的墙壁区域,并将它们合并为一个大矩形,并继续为较小的矩形做这个,直到所有的孔都被填满,但我不知道如何实现这一点。它似乎是完美的解决方案,因为它解决了性能问题以及我现在所拥有的凹形多边形混乱。有没有人知道如何实现这样的东西?

完全停止使用物理引擎并不是一个解决方案,因为我游戏中的很多东西都依赖它。

编辑:这是一个关于身体现在如何看起来的一个小例子:(每个数字都是一个身体) http://i.imgur.com/6x06o.png

这就是我希望他们成为的样子:

enter image description here

3 个答案:

答案 0 :(得分:1)

我可能没有正确理解这个问题,但是让我提出一个算法,我认为这有点暗示解决你的问题。

您的问题始于矩形贪婪,其中正方形免费非免费。从一开始, free 正方形是我们要用它们构建墙的方格,非自由正方形是空心空间。

  1. Foreach free square围绕该方块执行扩展,并查看该方块可以属于的最大区域。通过扩展我的意思是从该广场向所有方向前进,同时可以用免费方块构建一个区域。将这个最大的区域与给定的免费方块相关联。
  2. 选择具有最大关联区域的方块,并通过围绕该方块展开来构建合并的墙。属于此合并的方块标记为非自由。如果没有更多的免费方块,则转到第1步。
  3. 完成后,您应该将最大可能的墙块组合在一起。

    通过围绕 free 方块的扩展来澄清,我的意思是在所有可用方向上从给定方块开始构建假设的最大矩形。

    矩阵n*m矩阵的此算法的复杂性直观地围绕O(n*n*m*m)。在实践中,我认为你的数据会很快。请注意,此算法不提供最少数量的对象,而是最大化所有区域的总和(根据您的问题)。我认为,就复杂性而言,最小化身体总数的问题要困难得多。

答案 1 :(得分:1)

这是我在我的一个游戏中使用的(不是在C#中):

首先创建一个包含实心墙的数组,创建一个类似Wall的结构,其中包含xywidthheight,很多,每个街区一个。

然后循环遍历它们并合并具有相同yheight的那些,并且是邻居(x₁ + width₁ = x₂)。

然后再次循环,这次使用x代替y(反之亦然),并使用width代替height(反之亦然)。

这未经过优化,但您可以对其进行修改以加快速度。这是我在游戏中使用的实现,对你来说可能太慢了。

运行它会生成38个实体(与您发布的示例中的实体数量相同):

在最后两个步骤中颠倒顺序会生成36个实体:

答案 2 :(得分:0)

使用Farseer时,应使用 EDGES ,而不是使用如此多的实体构建地图/世界/等级,这可能会导致性能问题。

如果您能找到将地图转换为连续顶点坐标列表的方法,可能是跟踪墙并生成列表的算法,那么您可以这样做......

创建1个主体并添加FIRST边缘:

Body dungeon = BodyFactory.CreateEdge(world, start, end);

然后按顺序循环遍历所有其他顶点坐标,然后将每个新边连接到前一个边端坐标。 (按顺序将边缘链接在一起直到完成)

FixtureFactory.AttachEdge(start, end, dungeon);

这导致1个身体而不是35 +。