而对于平台动作(Platformer)类型的 Roguelike 来说,精妙的关卡设计显得更加重要了,于是大家也在考虑其它方式,比如预生成大量关卡模块再随机选择、整合,或者混合两种方式来做。预生成关卡的例子大家耳熟能详的应该是《盗贼遗产(Rogue Legacy)》和《以撒的燔祭(The Binding of Isaac)》这些,玩家每通过一个房间都会整体切换到另一个全新的房间,而这些房间都是开发者事先设计好的,只是排列按照开发者的控制来进行随机并调整参数。

这一次我们就要对这种预生成关卡的 Roguelike 多做一些了解。这篇文章的内容有多个来源,我们进行了整合。具体来源列在下面的参考内容中。本文主要来源是 Dead Cells 开发团队的 Sébastien Bénard 发表于 Gamasutra 的文章:Building the Level Design of a procedurally generated Metroidvania: a hybrid approach 一文,我们已经取得了他的授权进行编译。

Spelunky 的地图生成

《洞穴探险(Spelunky)》想必大家不会陌生。我最早的时候一度以为它是完全随机生成的,因为引入了绳索和炸弹巧妙的解决了出现死图的问题。后来经过了解,才发现它原来也是预生成关卡的。

这部分内容的编译并没有去取得授权,因为 indienova 的会员 @highway★ 已经进行了翻译:《Spelunky 关卡生成》[1],下面有部分内容来自该文章。

算法的第一部分是生成关卡的 Critical Path(通路),关卡由 16 个房间按照 4x4 的网格组成。方法是先在第一排随机找到一个起始房间,然后随机使相邻的房间成为通路的一部分,一直到最后一排,生成出口。找到通路之后,连接这些房间,然后再随机补充上非通路部分的房间,打通这些房间。如图顺序所示:
 


Dead Leaf Images数据 dead ops arcade_Dead Leaf Images数据


Spelunky 地图的分步生成


然后为这些房间随机选取对应的预定义好的关卡模块。根据 Spelunky 的教学文章[3],这里有 4 种不同的房间类型:
 


Dead Leaf Images数据 dead ops arcade_xml_02


放置对应的预制地图块


0:不在 Critical Path 上,不会产生任何出口(可被忽略的)次要房间

1:左右一定有出口

2:左右下一定有出口,如果有 2 号 Room 在上方,也一定有上方出口

3:左右上一定有出口

将这些不同类型的随机房间放到对应的位置上,地图基本上就生成了。(上图视频截图来自:Game Maker's Toolkit,不知道 @卡姐 Cara 做过字幕没有)

不过我们在玩游戏的时候,会发现各个房间都有很大不同,看起来不像是预先定义好的,至少不像 Rogue Legacy 那样明显。这是因为 Derek Yu 为每个房间的每个 Tile 都定义了更多的随机属性,这些属性的变动不会对这个房间形成本质上的影响,但是却会实现这样的效果:即使是使用了同样的预定义模块,但是表现还是有很大差别。这也是为何一开始好多人以为它是纯随机生成的原因。

如果对 Spelunky 地图生成有兴趣,@highway★ 的译文提供了更多细节。下面的参考中也有其它相关链接。

Dead Cells 的地图:遇到困难

下面让我们回到主题上,Dead Cells 的关卡是如何生成的。

Motion Twin 的 Dead Cells 创造了 Roguelite+银河战士恶魔城的全新类型:RogueVania,玩家将在相连世界中体会逐渐探索的乐趣,且游戏将兼有 Roguelike 游戏的重复可玩性和刺激的永久死亡体验。是一款相当优秀的游戏,indienova 也有幸参与了部分中文化工作。
 


Dead Leaf Images数据 dead ops arcade_https_03


Dead Cells 在 TIG Source[4] 上就吸引了大量的关注,后来,这款游戏的开发/策划/关卡设计 Sébastien Bénard / @deepnightfr 特地在 TIG 写了一篇关于 Dead Cells 关卡生成的文章,在 Gamasutra 也有发表[5]。我们虽已获得翻译授权,但是这部分内容并不是单纯的译文,希望能够给有兴趣的开发者提供一些信息。

最开始,大约在 2015 年,他们想要采用传统的方式制作每一个关卡,但是很快就发现,以他们的二手手游账号交易团队规模,根本没有足够的时间做到足够好。于是,他们想要找到一种新的制作方式。而在这款游戏之前,他们已经开发了一些 Web 游戏,而且已经多次使用过 PCG 程序生成方式来制作游戏,拥有不少经验,所以,他们想到了利用程序来生成关卡。

很快,原型就出来了,他们欣喜的发现,这给游戏带来了很大的重玩性。不仅如此,Permadeath(永久死亡)机制还使得游戏更加刺激,需要玩家更多的靠技巧和本能来完成游戏,而不是单纯的背版。总体来说,非常棒。

不过新的问题很快浮现了,虽然新鲜感很强,但是生成的不精妙的关卡问题很多,而且关卡的不一致性也造成玩家无法很好的沉浸其中。

柳暗花明

在纯手工打造和纯随机生成两者间,开发团队陷入了两难的境地。他们必须要寻找新的方式。这时,他们幸运的遇到了 Spelunky 的开发者(原文并没有提及是否是 Derek Yu),为他们提供了新的思路,那就是我们上面刚刚讲到的混合随机以及手工预先制作关卡,以实现既多样化又连贯的玩家体验。这样,Dead Cells 遇到的问题应该可以得到解决了!

另外,Sébastien 还提到了两个灵感来源

1.《超越光速(FTL: Faster Than Light)》。他们认为这款游戏虽然是基于程序生成的,却有着精心规划的情节和非常一致的宇宙,非常值得深入研究;

2.来自 Valve 的《求生之路(L4D: Left For Dead)》。这一个可能出乎大家的预料,不过确实,开发团队从这款游戏上学到了很多东西。

我在准备这篇文章的时候,也找来了 Left For Dead 的 AI 讲稿[6] 看了看,果然有料!虽然是讲稿,但是还是能了解到一些关于这款游戏设计的闪光点,基础的比如寻路、处理障碍等,高级一些的包括动态改变关卡、动态生成僵尸以提升性能,以及动态调节游戏节奏等,而这些高级的动态生成都是基于被 Valve 称为 AI Director(人工智能导演) 的系统完成的。

这个 AI Director 可以动态调节游戏的节奏,实现像电影一样的节奏控制。比如,一次激战之后,会调整敌人生成,甚至移除部分敌人,让玩家进行短暂的喘息。而当有玩家陷入紧急状态的时候,敌人也会相应减少一些,等等……讲稿中提供了一份按照既定节奏生成敌人和根据游戏进程动态生成敌人的对比图。可以看到,有了 AI Director 的自动调校,游戏的节奏变得很棒。


Dead Leaf Images数据 dead ops arcade_c#_04


L4D 的 AI Director 自动调整游戏节奏


显然,除了地图以外,Dead Cells 在 Roguelike 上想得更多,走得更远。他们开发了自己的 AI Director 系统,用在游戏中以动态调节游戏节奏。

技术实现

接下来说到地图生成的实现。经过多次的试验和探索,最后技术实现分为六个步骤:

1)先为关卡设置固定的元素,包括:整体设计风格,不同地点如何衔接,如何开启新的通路等基本要素。这些都是需要事先设计,在以后也不会随着随机生成而改变。
 


Dead Leaf Images数据 dead ops arcade_xml_05


2)然后设计一大堆预制的关卡地图块,他们也将这些地图块称为 Tile(可以叫做预制地图块)。这些地图块都有着不同的表现和可配置参数,这里是一些在 CastleDB 中制作的预制地图块:
 


Dead Leaf Images数据 dead ops arcade_开发者_06


事实上,每一个房间都有着自己独特的平台布局和用途。一个藏宝房间看起来绝对不会像一个商店,而着重于战斗的房间也不同于着两者。正如前面提到这些预制关卡会有不同的参数,所以这些预制地图块在实际使用中会产生很多不同的表现,比如出入口的位置变化等等。
 


Dead Leaf Images数据 dead ops arcade_开发者_07


每个房间还有特定的主题属性,例如监狱房间就绝不会出现在下水道关卡中。这样可以给予每个大关卡不同的特性,举个例子:下水道关卡的预制地图块都设计得很紧凑,无法跳跃,那么玩家就要准备好自己的应对策略,在这个关卡中一以贯之。
 


Dead Leaf Images数据 dead ops arcade_https_08


3)在准备好这些精心设计过的预制地图块之后,就需要将它们通过富有逻辑的、有趣的方式组合起来。所以他们为每个大关卡创建了原型图(概念图),通过节点达到对每一个场景预制地图块的可视化管理。

关卡设计从出入口开始,然后添加特殊房间(宝藏、商店等等),最后添加战斗和探索的部分。
 


Dead Leaf Images数据 dead ops arcade_c#_09



Dead Leaf Images数据 dead ops arcade_Dead Leaf Images数据_10


这个原型图给后面的程序生成提供了数据:大关卡长度,特殊预制地图块的数量,迷宫的复杂度,入口和最近的出口之间有多少预制地图块等等。这样,开发者们就可以对生成的大关卡地图做出宏观的控制,比如,堡垒关卡可能就比较平铺直叙,而下水道关卡则可能蜿蜒曲折。

4)一旦这些准备设计工作完成,就可以开始生成关卡了。针对每一个节点,系统都会尝试使用一个随机的预制地图块房间,当然这些预制地图块要符合当前设定关卡的主题。然后检查这个得到的预制地图块是否符合设计要求(入口的位置和数量,类型,等等)。如果结果并不符合要求,那么就尝试下一个。然后,voilà!结束!不过,还有……

5)接下来,敌人。关卡中的敌人由前面提到的原型图定义,之前定义了多少个战斗地图块,也就对应多少敌人。举个例子:如果在下水道关卡原型中定义了 250 个战斗地图块,并且定义了每个战斗地图块中应该有多少敌人,例如每 5 个地图块中有一个敌人,那么就放置 50 个敌人到地图中就可以了。
 


Dead Leaf Images数据 dead ops arcade_Dead Leaf Images数据_11


每个敌人都有自己的限制和属性,比如有些危险的敌人可能 10 个战斗地图块才出现一次,有些敌人只能出现一次,有些不能与其它敌人出现在同一平台,有些敌人需要较大空间以便移动,等等。

6)最后一步是生成各种宝物和劫掠品,这也是不可缺少的。开发者在这里卖了个关子,说是秘密,我觉得大家可以根据自己的需要怎么做都可以。
 


Dead Leaf Images数据 dead ops arcade_开发者_12


以上就是大概的思路。是不是自己也可以动手试一试了?

总结

我来一个快速的总结:

1.对于平台动作游戏(Platformer)来说,混合随机生成和预制地图是一个已经被验证的优秀方案;

2.开发者需要找到适合自己游戏数据的一个架构;

3.各个预制地图块应该有多种可调整参数,以便实现多样化。