模拟末日之火

2020-07-24 14:19:27

几天前,我在浏览HN时发现了一篇关于Doom http://fabiensanglard.net/doom_fire_psx/.中如何实现Fire的文章。它非常简单,结果出乎意料地好。我无法停止,只能立即尝试用JavaScript实现。我设法让它工作,并增加了一些额外的控制。既然我发现原文还需要一点消化才能理解。我想用我自己的话(希望更简单)谈谈它是如何实现的。

要在像素网格中生火,基本思想是遍历每个像素,并将其上方的每个像素更新为“更酷”。我们一遍又一遍地做。这样,如果我们将所有底线像素设置为“最热”。我们可以看到,只是坐着,让它长大。就像这样:

如果我们把它做大,并根据数字把火的颜色涂在上面。看起来是这样的。

但那看起来并不真的像火,它太“线性”了。让它看起来像火的诀窍是在火是如何“生长”的过程中增加一些随机性。

首先,我们不是总是让上面的像素变得“更酷”,而是只有50%的机会这样做。所以有50%的机会上面的像素会变冷,50%的上面的像素不会改变。它看起来是这样的:

看起来好多了。下一步,当我们寻找上面的像素时,我们可以随机向左或向右添加移位,而不是直接向上移动。在代码中,当我们遍历每个像素时,找到上面的像素,然后更新该像素,或更新其左侧的像素,或更新其右侧的像素。结果如下所示:

现在它开始看起来像火了。让我们尝试添加更多像素,并将其呈现在画布上,而不是HTML上,以获得更好的性能。我们还将获得像素边界和编号的游乐设施。

在原文中,作者给读者留下了一个模拟风的练习。如果你知道火是如何产生的,就会非常简单地知道风是可以模拟的。当更新上面的像素时,我们需要做的就是调整左移或右移。如果我们更多地向左移动,会导致像素向左倾斜,这使得它看起来像是从右向左吹的风。同样的情况也会发生在另一条路上。

通过逐渐更新像素的底部使其变得更“凉爽”,可以模拟火焰的褪色。它不仅会“淡出”底部,还会“淡出”上面的所有像素,因为它们是被传播的。

火焰强度基本上意味着像素在向上传播时需要多长时间才能“降温”。目前,我们将其降温的机率设定为50%。因此,如果我们想让火势更“猛烈”,我们只需要让LET变得更不可能降温即可。