0

希望这会足够清楚。

我有一张由瓷砖制成的 2d 地图,我希望“水”穿过这张地图。它从管道中流出到特定的瓷砖上,然后需要像水一样填充所有瓷砖才能到达另一个特定的瓷砖。我目前将地图输入到游戏中,每个图块都是一个节点,每个节点都连接到它周围的所有适当图块。我将节点存储在排序数组中,首先按 x,然后按 y。此外,一些瓷砖是“门”瓷砖,可以阻止水流过它们。这些是同一节点图块网格的一部分,仅在活动时被标记。

问题是我如何分散水。

最初,我让每根管道(滴水的)跟踪“当前”和“满”水瓦的列表,它会将水直接分散到“当前”瓦,然后将它们切换到“满”列表时合适的。“当前”列表通过获取已经“当前”图块的周围图块来扩展。无论如何,这很好用,水流很好,但我不知道如何使它与闸门一起工作,以便可以停止并重新允许水流(然后再次停止,等等。 ) 在特定点。

现在我有它,水倾倒到一个且只有一个瓦片中,然后当一个瓦片有太多水时,它会将水逐渐推到随机相邻的瓦片上(除非瓦片是一个活动门。)这个问题是水在已经填满的瓷砖周围“晃动”,而不是“向外流动”。它最终会到达那里,但流动不那么自然。

我的困境就这样结束了。

代码是用python编写的。

编辑:新想法。我可以让管道在节点中搜索合适的免费瓷砖以在每次更新时放置水,但这似乎非常低效——尤其是使用多个管道时。

4

3 回答 3

3

这在游戏开发中出现了很多——有很多关于这个主题的 GDC 演讲和 Gamasutra/Game Developer 杂志的专题文章。我认为最适合您的目的是来自 2003 GDC的Jos Stam的“游戏实时流体动力学”。

他描述了一种通过线性回溯执行平流的简化方法,该方法存在一些问题,但对不可压缩流体效果很好(也就是说,它对水的效果比对气体的效果更好)。线性回溯基本上意味着他在空间中的每个点(即你的瓷砖)建立了一个表示流体密度的网格,然后对于每一帧访问每个点并询问,“基于周围点的压力,流体可能在哪里从哪里来?” 事实证明,这比以另一种方式解决(“从这一点开始的流体要去哪里?”)更容易。

Mick West 关于 Gamasutra 流体动力学的文章以某些可能提高性能的方式扩展了 Stam 的论文,因此您可能希望从那里开始。

最近英特尔赞助的 GameDev 文章也提供了更完整的解决方案,但它相当复杂,并且更多地关注 3d 中的图形渲染方面。

您可以查看Dwarf Fortress以获取平铺 2d 流体力学的示例,但他的解决方案似乎在处理快速流动或加压流体方面存在许多问题;有时他的水流比你想象的要慢得多,或者被困在街区和角落里。

这些论文对数学和算法的总结比我塞进 Stack Overflow 盒子要好,但我也想提出两点一般性观点:

  1. 水模拟在计算上非常昂贵。由于您使用的是 Python,这可能会导致真正的性能问题——请务必设置一些方法来分析您的算法以查找热点,以防您的循环花费太长时间以至于它会杀死帧速率。您可能不得不求助于Numeric Python来获得基于 C 的快速数组操作。
  2. 游戏开发中的数学比大多数人预期的要多得多!
于 2009-12-26T05:54:33.007 回答
2

关于假设的一些启发式方法:

  • 离散的“水滴”,每个水滴恰好占据一个正方形
  • 水在给定的瓷砖上永远不会超过一个高度,
  • 水始终保持连续
  • 当障碍物升起时,它们就像墙壁
  • 当障碍消失时,它们就像开放的广场

对于每个水坑,维护一个边缘方块列表和边缘旁边的开放方块。

当障碍物下降时

amend the lists of edge and open squares for any puddles that were touching it

当障碍物上升时

if (it was covered)
    pick a non-wall square next to it at random, and add the drop from the barrier there.
amend the lists of edge and open squares for any puddles next to the block

当您添加一滴时:

if (the square "under" the pipe is empty)
   fill it
else
   consult the list of edge square associated with the pool under the pipe, and select the one closest to the pipe (if more than one is closest, choose from the candidates at random), and fill it.  
amend the lists of edge and open squares for the puddle (be prepared to merge with neighboring puddles if necessary)

当你删除一滴

 find the edge (not open!) square farthest from the sink (or randomly select from the equivalent candidates), and empty it
 amend the lists of edge and open squares for the puddle

(此处可用的装饰是使“最远”以与其他水槽的距离相等的距离为界,因此如果水坑中间的正方形在水槽之间,则它们可以变成空的)

这不是很现实,也不会给你带来任何动力,但会在滴水管“下方”保持连续的水坑,并在有足够滴水的情况下填满可用空间。

于 2009-12-26T04:55:07.290 回答
0

您的模型是否包含电位差或压力的概念?

假设一个空瓷砖的压力为零,一个完整的瓷砖压力为 10。如果两块瓷砖之间有一根管道,那么水会流动以平衡压力,门会关闭管道,所以没有任何东西流动。

于 2009-12-25T23:03:07.700 回答