β

随机生成 Tile Based 地图之——洞穴

近几年,独立游戏中采用了 Roguelike 形式的作品越来越多,这也从侧面证明了玩家对这类游戏需求的增长。如果您还不了解 Roguelike 是怎么一回事,那么可以查阅我们之前转载的本站作者写过的一篇文章:《Roguelike 到底是啥-讲讲 Roguelike 相关知识》。Roguelike 有很多基本要素,那么对开发者来说,有几项是需要花时间去做的。比如随机地图的生成,就是整个 Roguelike 游戏的基础之一。我们也曾经介绍过其它的一些方法,比如《一种 Roguelike 地牢生成算法》以及《Troy: 我是如何设计地牢的》等。那么今天我们就来介绍一种另外一种随机地图生成方法,它可以说非常的简单。这就是今天的主题:随机生成洞穴类的地图。

今天用到的核心方法是:细胞自动机(Cellular Automata),关于它的更多信息可以查阅这里,这个链接有一切关于细胞自动机的内容。

这个教程的内容生成的地图是基于 Tile 的。

实现方法

首先,我们要生成一幅随机地图,我们通过控制随机数的范围分布来实现它。一般情况下,我们采用小于 50% 的几率来生成墙,其余的就是地面。地面是可行走的,而墙则是可碰撞的。

生成后的地图应该是一个二维数组 mapArray,接下来我们开始遍历整个数组的每个元素,采用的规则(我们叫它 4-5 规则)如下:

  1. 如果当前元素是墙,那么周围超过 4 个墙就还保持为墙
  2. 如果当前元素是地板,那么周围超过 5 个墙就变为墙
  3. 循环直至完成
  4. 重复循环 4~5 次就可以得到结果

核心循环部分写成伪代码就是这样:

for each element in mapArray {                // 循环
    count = checkNeighborWalls(element)       // 取得元素周围墙的数量
    if element == WALL                        // 取得元素
        element = (count >= 4) ? WALL : FLOOR // 如果当前元素是墙,那么周围超过 4 个墙就还保持为墙 
    else
        element = (count >= 5) ? WALL : FLOOR // 如果当前元素是地板,那么周围超过 5 个墙就变为墙
    endif
}

为了便于大家理解,我特地做了演示例子。(按“下一步”可以继续下一步的生成,“重新生成”则重新生成一幅地图的原始数据。不妨多多尝试看看生成的结果。)

怎么样?看了还是挺有趣的吧?生成的确实像是一个洞穴呢~已经可以用这样的地图来做一些游戏了(至于做什么就看您的想象了)。

问题所在

经过多次生成之后,会发现,生成的地图也不是那么尽如人意,比如像这样的还好:

Good

可是还会有很多完全分离的情况:

Bad

而且,除了不联通之外,还有很重要的一点:如果空洞太大的话,会很无聊呢。除非找到很适合的游戏玩法,不然,一般情况下我们还是希望洞穴的内容比较复杂,路线比较曲折才好,不是么?

那么,可以想办法改进一下

改进方法

其实归纳一下规则,其实就是:

规则 1:

  1. 按照一定几率初始化数据;Winit(p) = rand(0, 100) < 45%
  2. R(p) 是周围一圈墙的数目;
  3. 如果一个元素周围墙数大于等于 5,那么就是墙。W'(p) = R(p) >= 5

而如果我们想要让大片空地也放入一些墙,那么,我们可能要做多一些判断。现在采用的一个方法是:再向外扩大一圈,如果这个范围内的墙少于特定的数目(比如 2),那么同样也放一个墙到这个元素位置上。可以写为 R2(p) <= 2

那么规则就会变成:

规则 2:

  1. 按照一定几率初始化数据;Winit(p) = rand(0, 100) < 45%
  2. Rn(p) 是周围 n 圈墙的数目;
  3. W'(p) = R1(p) >= 5 || R2(p) <= 2

当然,上面这个是可行的方法之一,我们可以很灵活的组合判断的方法。目前我采用的一个规则是:

采用规则:

  1. 按照 40% 几率初始化数据;Winit(p) = rand(0, 100) < 40%
  2. 重复四次:W'(p) = R1(p) >= 5 || R2(p) <= 2
  3. 重复三次:W'(p) = R1(p) >= 5

下面这个例子就是我采用的规则得到的结果:(按“下一步”可以继续下一步的生成,“重新生成”则重新生成一幅地图的原始数据。不妨多多尝试看看生成的结果。)

怎么样?是不是看起来有意思多了?当然偶尔也还会出现不联通的现象,那这时候就需要我们用代码来打通它们了,也不是难办的事情,留给大家自己尝试去吧。

对比一下

我将两种方式采用同样的初始数据放在一起做了一下比较,可以看到这两种方式还是有很大不同的:(按“下一步”可以继续下一步的生成,“重新生成”则重新生成一幅地图的原始数据。不妨多多尝试看看生成的结果。)

最后

好了,我们完成了一个简单的 PCG 游戏的基础功能,下面可以在这个基础上做我们自己的 Roguelike 游戏啦。

我还是做了一个演示,如图所示:

demo

查看本教程的演示
手机建议用横屏观看

这篇教程的基础来自于这篇文章:Cellular Automata Method for Generating Random Cave-Like Levels,如果希望从原文中找到线索,不妨去看看。好文章但愿它不会消失……

我们通过对细胞自动机的简单了解可以发现,其实我们可以自行制定很多规则,来让数据变得更加奇妙或者出乎预料,如果您自行实现了很奇妙的算法,不妨让我们也了解一下哦。

最后,如果有实现上的问题,或者其它疑问,请到我们的论坛相应的帖子里来讨论:

前往 indienova 论坛讨论
作者:indienova 独立游戏新闻,评测,开发教学
你的独立游戏第一站
原文地址:随机生成 Tile Based 地图之——洞穴, 感谢原作者分享。

发表评论