简介
我小的时候非常喜欢用 RPG Maker 制作 RPG 游戏。RPG游戏的地图通常可以分为用于探索的原野、用于补给整备的城镇以及用于锻炼升级的迷宫地牢。由于战斗与升级在游戏中通常占有较大的比重,因此在制作游戏的过程中,大部分的时间需要用来绘制迷宫地图。
尽管 RPG Maker 是一款易上手的游戏制作工具,制作者绘制一张地图仍然是一项耗时多且重复性强的工作,一张尺寸为50*50的迷宫地图通常需要0.5~2小时的绘制时间。如果能够让机器来生成绘制地图的工作,可以极大解放游戏作者的生产力,令人类聚焦在游戏人物塑造、主线/支线剧情与游戏系统设计等更有创造性的工作上。
本文介绍一种自动生成RPG迷宫的算法。用户只需要输入少量的地图参数(如地图尺寸、地图类型、装饰品的密度),就能够一键生成迷宫地图。本文基于 RPG Maker 实现了此算法,生成的地图可以一键保存为 RPG Maker 可使用的地图格式文件。
工具试用链接:huanggaole.github.io/autoRMmap/
通过这个教程学习如何将导出的地图引入RM项目:www.bilibili.com/video/BV1D5…
算法介绍
我们的算法分为6步:(a) 生成初始种子 (b) 生成洞穴 (c) 连通洞穴 (d) 生成湖泊与坑洞 (e) 生成墙壁 (f) 生成深色地板 (g) 生成装饰物 (h) 渲染最终地图图形
生成初始洞穴
首先,通过元胞自动机算法(Johnson, Yannakakis, and Tobelius 2010)生成自然洞穴。使用均匀分布概率r%将单元从地板转换为岩石状态;在笔者的实验中,r%等于50%。图1(a)为一个初始种子生成结果示意图,灰色的单元格为地板状态,白色的单元格为岩石状态。
然后将迭代的元胞自动机应用于生成的网格,每次迭代时检查每个单元的八个相邻单元格,如果该单元格的8-邻域单元格中有大于等于5个单元格为岩石,则在下一回合迭代开始时将此单元格修改为岩石单元格,否则在下一回合迭代开始时将此单元格修改为地板单元格。重复迭代100回合,当某一轮迭代回合开始时没有单元格发生变化,则迭代结束。图1(a)作为初始种子经过元胞自动机算法迭代完成后生成的结果如图1(b)所示。
连通洞穴
元胞自动机算法生成的洞穴有可能是不连同的多个独立子图,然而,在制作RPG游戏时,迷宫地图通常是完全连通,这样玩家控制的角色才能够从地图上的一个位置走到地图上的任意其他位置。因此我们需要将第1步中生成的初始洞穴连通成一个全连通的地图。
我们通过泛洪充填算法找到所有的洞穴连通分量,分别编号为1号、2号、… N号洞穴分量。对于一个包含N个洞穴分量的地图,我们可以通过添加N-1条连接通道将所有洞穴连接成一个全连通图。
我们通过随机游走的智能体(Agent)来连接两个洞穴,我们将一个智能体放置在i号洞穴分量内的任意一个单元格上,接着让这个智能体在地图上无视岩石障碍随机行走,当智能体遇到另一个编号为j的洞穴分量单元格时,智能体走过的路径作为通道单元格添加到地图中,同时将i号洞穴分量与j号洞穴分量合并为一个洞穴分量。
随机游走可能会导致形成的通道非常弯曲和复杂,而从美观的角度考虑,每次添加的通道应该尽可能地短,尽可能的简单。因此笔者每次将10个智能体随机放置在洞穴中,并让他们同时随机游走,每个智能体轮流各走一步。最先形成通道的智能体一定发现了10个智能体中步数最少的通道。我们将这条通道作为本次迭代添加进地图的通道。
在N-1次迭代之后,所有洞穴合并到一整个洞穴时,算法结束。图1(c)是图1(b)的洞穴连接结果。
生成湖泊与坑洞
为了增加地图的地貌多样性,笔者选择性地将岩石区域转化为湖泊或坑洞。岩石区域是指洞穴以外的封闭的障碍区域。
笔者通过泛洪填充算法找到所有岩石区域的连通分量,分别标记为1号、2号、... M号岩石区域。在笔者的实现中,用25%的概率分别将岩石区域转化为湖泊区域或坑洞区域。
图1(d)为图1(c)生成湖泊与坑洞的结果,有1个岩石区域转化为湖泊,1个岩石区域转化为坑洞。
生成墙壁
传统的2D日式RPG采用了一种正交平行透视,玩家只能观察到面向摄像机的墙壁,因此我们只需要生成每个洞穴区域北侧的墙壁。
笔者检索出有哪些洞穴单元格上方毗邻的3个连续的岩石单元格,那么这些洞穴单元格上方的2个单元格需要转变为墙壁单元格。如果一个洞穴单元格上方毗邻岩石单元格,但是没有毗邻3个连续的岩石单元格,那么笔者将这个洞穴单元格上方毗邻的岩石单元格转换为洞穴单元格,以免出现细碎的墙壁。
如图1(e)为图1(d)生成墙壁后的结果,可以看到为了不出现细碎的墙壁,一些岩石单元格被转变为洞穴单元格。
生成深色地板
为了让地面看起来更有层次感,笔者在洞穴内部画了一些深色的地板。这些地板通常是成簇存在的。
笔者在洞穴地面上随机采样0~5个深色地板种子点,对每个深色地板种子点分别使用广度优先搜索(BFS)将深色地板从种子单元格蔓延到周围的单元格,当遇到墙壁时停止蔓延,且每次蔓延都有20%的概率停止蔓延。
图1(f)为图1(e)生成深色地板后的结果。
生成装饰物
笔者根据生成物的生成密度,均匀地在地图上生成障碍物。装饰物的生成密度由用户指定。
不同类型的地形、墙壁上可以生成不同类型的装饰物。例如森林迷宫的地面上可以生成各种植物,沙漠迷宫的地面上的装饰物则以干枯的植物、沙漠植物与动物骨骼为主。地形与装饰物的对应关系可以通过配表法进行配置。
图1(g)为图1(f)生成装饰物后的结果。
渲染最终地图图形
笔者事先根据地图类型为洞穴区域、岩石区域、湖泊、坑洞、深色地板、装饰物配置特定的瓦片图像。
为了使生成的结果更加生动,更符合流行的美学话语,我们采用 Marching Squares 算法来实现自动贴图的效果(Maple 2003)。自动贴图是一种当放置在地图上时会根据自己毗邻的贴图自动纠正自己的图案,以便使自己与周围贴图连贯过渡的贴图。下图显示了基于同一份地图数据结构在采用 Marching Squares 实现自动贴图效果前后渲染的结果。
结果展示
图(a) 为最终实现工具的UI展示。
图(b) 为不同地图类型在相同尺寸下生成的地图,可以看出该算法的生成结果具有多样性与差异性,能够用同一套算法生成不同类型、不同结构的迷宫地图,且能够保证生成的地图是全连通、可用的。
上图展示了同一种类型的地图在不同地图尺寸下生成的结果。
上图展示了同一张地图用不同的装饰物密度生成装饰的结果。
为了展示该算法的效率,笔者进行了实验,记录在不同地图大小和不同饰品密度下生成一张地图所用的时间。该实验在MacBook Pro(2.2 GHz,6核英特尔酷睿i7处理器)的谷歌Chrome浏览器上进行了测试。我们在25x25、50x50、100x100、200x200的地图大小,以及0%、3%、10%、30%和100%的饰品密度下分别生成地图,每次连续生成100张地图,并计算一张地图的平均生成时间,如表1所示。通过记录结果可以看出,我们的算法速度很快,游戏制作者可以在相同的配置下快速生成多个地图,并从中选择与他的预期最相符的生成结果用于创作,或基于生成的结果进行二次创作(如添加机关、宝箱、事件剧情)后使用。
未来的工作
-
除了洞穴迷宫外,需要制作其他RPG游戏地图的生成器,如城镇地图、室内地图、原野地图、大地图。
-
除了全自动生成地图,能否加入人机协作生成地图的半自动生成地图方式,令生成结果可以在一定程度上对于用户更加可控。
-
目前游戏地图的生成规则通过人工抽象后用算法分步实现,能否引入机器学习的方法,通过少量样本(游戏地图的生产成本高,因此训练用的数据样本量不会太高)自动学习不同类型地图的生成规则。
-
目前每种单元格数据与瓦片图像的对应关系需要通过笔者配置。能否引入机器学习的方法,通过少量样本自动学习地图语义与瓦片的对应关系。
参考文献
[1] Johnson, L.; Yannakakis, G. N.; and Togelius, J. 2010. Cellular automata for real-time generation of infinite cave levels. In Proceedings of the 2010 Workshop on Procedural Content Generation in Games, 1–4.
[2] Maple, C. 2003. Geometric design and space planning using the marching squares and marching cube algorithms. In 2003 International Conference on Geometric Modeling and Graphics, 2003. Proceedings, 90–95.