自然的“水”流经节点网

时间:2009-12-25 22:53:11

标签: nodes

希望这很清楚。

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

问题在于我如何驱散水。

最初我让每个管道(滴水)跟踪“当前”和“完整”水砖的列表,它会将水直接分散到“当前”瓷砖,然后将它们切换到“完整” '适当时列出。通过获取已经“当前”图块的周围图块来扩展“当前”列表。在任何情况下,这都运作良好,水流得很好,但我无法弄清楚如何使它与大门一起工作 这样可以在特定点停止并重新允许水流(并再次停止等)。

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

这样就结束了我的困境。

代码是用python编写的。

编辑: 新想法。我可以让管道在节点中搜索一个合适的免费瓷砖,以便每次更新都放置水,但这似乎非常低效 - 特别是对于多个管道。

3 个答案:

答案 0 :(得分:3)

在游戏开发中出现了很多 - 在这个主题上有很多GDC演讲和Gamasutra / Game Developer杂志专题文章。我认为最适合您的目的是Jos Stam来自2003 GDC的“Real-Time Fluid Dynamics for Games”。

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

Gamasutra的

Mick West's article on fluid dynamics以某种方式扩展Stam的论文,可能会提高效果,所以你可能想从那里开始。

还有a recent Intel-sponsored GameDev article that offers a more complete solution,但它相当复杂,更专注于3d中的图形渲染方。

你可以看看 Dwarf Fortress 作为平铺2d流体力学的一个例子,但他的解决方案似乎有一堆处理快速流动或加压流体的问题;有时他的水移动方式比你预期的要慢得多,或者陷入困境中。

那些论文总结了数学和算法的方式比我可以填入Stack Overflow框更好,但我还想提出两点:

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

答案 1 :(得分: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

(这里可用的一个褶边是使“最远”以与其他水槽相等的距离为界,这样如果它们位于水槽之间,水坑中间的方块就会变空。)

这不太现实,并且不会让你有任何动态可言,但会在滴水管道下面保持连续的水坑,并在给予足够滴水的情况下填满可用空间。

答案 2 :(得分:0)

您的模型是否包含潜在差异或压力的概念?

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

相关问题