![59599d6c9b659f7a887972455f4f07c4.png](https://img-blog.csdnimg.cn/img_convert/59599d6c9b659f7a887972455f4f07c4.png)
全世界人民对于奇幻故事都非常向往,如果能描绘自己的奇幻世界就太棒了。奇幻世界的基本要素除了故事,就是一张奇幻画风的地图了,或者叫Fantasy Map。
![63d01f1633d49977188aad0f00c87897.png](https://img-blog.csdnimg.cn/img_convert/63d01f1633d49977188aad0f00c87897.png)
![5bfd1397e4c1475618d12289d0d1c439.png](https://img-blog.csdnimg.cn/img_convert/5bfd1397e4c1475618d12289d0d1c439.png)
没看够?图片搜索“Fantasy Map”就能看到更多的奇幻地图。
但是手绘虽然简单,但非常耗时。于是“懒惰”的大家想出了一个办法,干脆用程序去画吧,只要轻点鼠标,一张漂亮的奇幻风格的地图就生成了。我发现比较好玩的在线奇幻生成器有
1.https://www.makeamap.cn/(非常好用,支持自定义修改)
2.https://azgaar.github.io/Fantasy-Map-Generator/
3.http://bl.ocks.org/Azgaar/b845ce22ea68090d43a4ecfb914f51bd
这些奇幻地图究竟是如何生成的呢?具体技术可以使用Javascript的SVG,或者C++生成png图片的库。不过这些不是本系列的重点,本系列主要参考了hereDragonsAround的博客,将与大家讨论如何用程序生成奇幻风格地图的内在逻辑。
这系列文章将分为六篇
1.基本海岸轮廓线
2.手绘风格的山
3.生物群落
4.森林与海洋
5.名称标签的摆放以及杂项
6.地图上生成蜿蜒河流的方法(附加)
好,现在开始吧。我们看到的奇幻地图可能都是某个大陆的部分,但如果一开始就绘制大陆的话非常麻烦。所以我们先从简单的岛屿开始,而地图边界自然而然地就用水域填充,岛屿是独立的,还能限制的奇幻故事发生的范围。
为了绘制岛屿的轮廓,我们先来生成一个圆。
![849b9a9c11f9e58d7b1a97a1f473584b.png](https://img-blog.csdnimg.cn/img_convert/849b9a9c11f9e58d7b1a97a1f473584b.png)
这玩意怎么看都不像一个岛屿对吧?这个圆太标准,我们尝试重新绘制它的边界。如下图a,在圆上随机选择几个采样点,然后用直线连接这些采样点,如下图b。另一种稍微复杂一些的方法是随机生成一些在指定范围内的点,然后用凸包连接它们,如下图c。
![c8c20b943a6a17e5cd5211a3277ef3ec.png](https://img-blog.csdnimg.cn/img_convert/c8c20b943a6a17e5cd5211a3277ef3ec.png)
岛屿边界直线又长又直,太难看了,好,我们把它们弄弯。如下图b,用随机函数添加几个蓝色控制点把长直线拆分成短折线。然后连接这些短折线的终点,然后用特殊的曲线算法,比如贝塞尔曲线,或者Catmull-Rom曲线。
![d6c0b3fd948247d5c00ab330af8ee6cd.png](https://img-blog.csdnimg.cn/img_convert/d6c0b3fd948247d5c00ab330af8ee6cd.png)
不要被贝塞尔曲线吓到了,我们只需要用二阶贝塞尔曲线即可,比如要生成a,b之间,c为控制点的二阶贝塞尔曲线,只需要按如下方式定义即可。t从0逐渐增加1时,f会有一条圆滑的轨迹,这就是贝塞尔曲线,不过是三个一阶乘法而已。
![ac2bd0a343d6a34c8fae1006a5b55f08.png](https://img-blog.csdnimg.cn/img_convert/ac2bd0a343d6a34c8fae1006a5b55f08.png)
另一个catmull-rom曲线稍微复杂一些,详细请看这篇文章。
如果之前使用凸包算法,那么到现在可能是这个样子
好了,我们有个近似圆形的轮廓线不规则的岛屿了。
![2f67c7e14059285dea1efe22991c611a.png](https://img-blog.csdnimg.cn/img_convert/2f67c7e14059285dea1efe22991c611a.png)
如果之前使用凸包算法,那么可能就是这个样子了。
![eda19bab8995a3712bf5891c344a26e9.png](https://img-blog.csdnimg.cn/img_convert/eda19bab8995a3712bf5891c344a26e9.png)
岛屿轮廓看起来还是怪怪的,对吧?特别是第一个,还是个圆嘛。
为生成不规则的轮廓。一种常见的技术是使用噪音,多次随机生成噪音并叠加,这样比较像自然景观,比如Perlin噪音,这个噪音的特点是噪音是连续的,非常适合生成连续的地形。
所谓Perlin噪音就是下图这种形状,不同的灰度代表着高度,黑色的RGB值为[0,0,0],代表着低地,白色的RGB值为[255,255,255]代表着高地。
![ac625fe9023cc57b069e5b0a897b23d4.png](https://img-blog.csdnimg.cn/img_convert/ac625fe9023cc57b069e5b0a897b23d4.png)
可以在这个网站上体验Perlin噪音生成的地形,比如下面这种:
![b39135b8198e79a9bd9c5b278f7df330.png](https://img-blog.csdnimg.cn/img_convert/b39135b8198e79a9bd9c5b278f7df330.png)
当然这就不是小岛了,那么再用不规则的圆围一圈就好了嘛。
![1184a0cde607c9493848d9e39a28f6ec.png](https://img-blog.csdnimg.cn/img_convert/1184a0cde607c9493848d9e39a28f6ec.png)
最终成果如下:
![25800ab19d784accfb0ed6ed63303f04.png](https://img-blog.csdnimg.cn/img_convert/25800ab19d784accfb0ed6ed63303f04.png)
边缘仍然太规则了,那么为边缘继续添加噪音,一种好方法就是为相邻的边缘添加相近的噪音,而不是互相独立,就能生成各种形状的边缘。伪代码如下:
![18bbd7f47927bf312c01a335e01ce3ad.png](https://img-blog.csdnimg.cn/img_convert/18bbd7f47927bf312c01a335e01ce3ad.png)
效果如下:
![fbae224282779ac030faa01a6b52ab2a.png](https://img-blog.csdnimg.cn/img_convert/fbae224282779ac030faa01a6b52ab2a.png)
先不要关注那些阴影与植被,但目前看来,海洋轮廓线还是不错的。
除了这些方法,还有一些其他方法,基本思想一样,先用少数控制点生成大轮廓,再继续细分,绘制出曲折的海岸线。
比如分形,使用多个分形叠加
![26a7c7d66fe34de66a824b56f2510f9e.png](https://img-blog.csdnimg.cn/img_convert/26a7c7d66fe34de66a824b56f2510f9e.png)
![09f67a2edbe4d0dab6ba57edae0f6d68.png](https://img-blog.csdnimg.cn/img_convert/09f67a2edbe4d0dab6ba57edae0f6d68.png)
RedBlobGame在他的文章中提到的方法是Voronoi图生成多边形地形。
![e30a35285f55b4583ae8c3a0608e9a64.png](https://img-blog.csdnimg.cn/img_convert/e30a35285f55b4583ae8c3a0608e9a64.png)
Martin O'Leary在他的文章使用的方法是直接用Delaunay三角形作为边界
![b5150a2736a8350544068c834aaba76d.png](https://img-blog.csdnimg.cn/img_convert/b5150a2736a8350544068c834aaba76d.png)
![2311798ad556f51a498e639074090dc2.png](https://img-blog.csdnimg.cn/img_convert/2311798ad556f51a498e639074090dc2.png)
或者干脆看看《文明5》使用六边形生成轮廓线,下图可以看到轮廓线与六边形边界并非完全重合。
![6d0fcdc068a73e4bf19683c8cd7b0125.png](https://img-blog.csdnimg.cn/img_convert/6d0fcdc068a73e4bf19683c8cd7b0125.png)
学会了生成小岛轮廓,那么生成更多岛屿轮廓自然不在话下。但是这里还有一个好玩的生成近岸群岛的方法。现在岛屿轮廓外围生成一个多边形,给这个多边形赋上地形高度,然后低于某个高度的删掉,就形成了近岸群岛了。
![68ba2d7cb2ebfbca3f0ba562e03310cd.png](https://img-blog.csdnimg.cn/img_convert/68ba2d7cb2ebfbca3f0ba562e03310cd.png)
好了,现在我们有了一个光秃秃的岛,下面尝试为它生成一些山。
下一篇:手绘风格的山