使钻石平方分形算法无限化
我想生成一个无限大的地图,正在用Python来实现这个目标。不过,我发现噪声库总是无法正常工作(它们似乎找不到我的VS2010,而且用纯Python实现的话速度会慢得多)。所以,我打算使用菱形-平方算法。
请问,有没有什么办法可以让这个地图在技术上变得无限大呢?
如果不行的话,我是不是应该回去试着让某个Python的噪声库正常工作呢?
4 个回答
你可以从底部向上应用中点位移吗?假设你在一个离散的网格上工作,想要生成一个MxN的区域。首先,给自己一个权重函数w(i)。从每个点开始,应用一个随机位移,权重为w(0)。然后,对每隔一个点应用一个随机位移,权重为w(1),并将位移传播到中间的点。接着,每隔四个点应用一次位移,权重为w(2),同样进行传播。这样,你就可以生成任意大小的网格,而不需要事先假设大小。
如果存在某个N,使得w(i > N) = 0,那么当你达到这个N时就可以停止生成——这点很重要,因为你希望生成过程能够结束!你可能想要一个w函数,它从1开始,增加到某个值,然后再降到0;增加的部分模拟了地形在100公里左右的粗糙度,而下降的部分则模拟了整个行星大致是球形的事实。如果你是在做火星而不是地球,你可能希望w(i)的值更大,因为火星有个叫做塔尔西斯隆起的地方。
现在,把随机函数替换成一个看起来随机但实际上是确定性的函数,基于点的坐标(比如把坐标输入到SHA1哈希中)。这样,每当你生成网格的某个特定部分时,它看起来都会是一样的。
你应该能够用类似的方式做钻石-方块算法;你只需要交替改变位移的形状。
最新版本的噪声模块(可以在http://pypi.python.org/pypi/noise/1.0b3找到)提到它“修复了在Windows上用Visual C++编译的问题”——你可以再试试这个版本。我在我的电脑上(Python 2.7.1,MinGW,Windows 7)安装和使用都没问题。
如果你把你的瓷砖(tiles)排成一个x,y的网格,并且为每个瓷砖设置随机数生成器,比如用random.seed((x,y)),那么每次你回到同一个地方时,它都会重新生成相同的地形。
使用钻石-平方算法时,每个瓷砖的两个边会依赖于相邻的瓷砖;不过这种依赖关系并不会一直延续到整个瓷砖。如果你让每个瓷砖依赖于它前面的瓷砖(也就是上面和左边的瓷砖),并写一个create_fake_tile函数,假设所有前面瓷砖的值都是0,那么你会得到一个“坏”的瓷砖,其中右边的列和底部的行是下一个瓷砖所依赖的正确值。如果你在屏幕上绘制每个画面时,从第一行和第一列之前的瓷砖开始,那么你看到的世界部分就会是正确的。
这件事是可以做到的。你可以把你的场景分成一个个“小块”,然后在每个小块里使用中点位移算法(我更喜欢这样称呼它)。
每个小块的大小要足够大,这样一个角落的高度就不会太依赖于另一个角落的高度。这样一来,你就可以随时创建和销毁这些小块,并且在新出现的角落设置一个独立的随机高度。
这个高度值(还有小块内部的随机性)必须根据小块的位置来生成,这样每次你得到的都是同样的小块。