本文章首发于我的个人博客,希望大家多多支持!
Hi! This is Showhoop Studio!
你即将看到的是我的Unity随机地牢游戏的第一篇开发日记。这个游戏的灵感来源于小白的大冒险,我借鉴了它的主要玩法——也就是随机地牢,来作为练习,提高自己的游戏开发技术,同时也丰富一下自己的作品集。在这一篇日记中,我将详细为大家介绍一下我所采用的随机生成算法,供大家学习。 废话不多说,立马进入正题。
概览
在开始之前,我们先来看看效果(浅色为地面,深色为围墙障碍)。
正如你们所看到的一样,这个过程实际上非常的简单:通过若干个方块在平面内随机移动来生成地面,之后在其周围生成围墙,最后去掉中间那些意义不大的单独的墙。那么现在我们对这个过程有了一个基本的了解,然后我们便可以着手开始写代码了。
我们下面讨论的脚本代码不会有上面图片中那样的过程演示效果,是直接生成的!
数据结构
我们首先定义一些数据结构。显然对于上述过程我们应该采用一个二维数组来标记一个空间内的每一个小格,而每一个小格会有三种类型:地面,墙壁和空类型(注意,之前我们没有提到空类型,但实际上它是存在的,地面和墙壁没有充满整个空间,剩余的地方就是空的)。
// 包含空,地面和墙壁的枚举类型
private enum Grid {
empty, floor, wall};
// 整个可生成的正方形空间
private Grid[,] grid;
// 正方形空间的大小
// 你也可以使用public类型以便于调试
private int width = 30;
private int height = 30;
到这里我们已经迈出了第一步,接下来我们将开始定义“移动”的方块的数据结构,我们先姑且称之为indicator。
private struct Indicator
{
// Indicator的坐标位置
public Vector2 pos
// Indicator的方向
public Vector2 dir
}
// 一个Indicator类型的链表,它将包含若干个indicators
private List<Indicator> inds;
// Indicator转变方向的概率
private float chanceToTurn = 0.5f;
// 生成一个新的Indicator的概率
private float chanceToSpawn = 0.05f;
// 销毁一个Indicator的概率
private float chanceToDestroy = 0.05f;
// 同时存在的Indicators的最大数目
private int maxAmount = 10;
最后,我们需要指定地牢的填充比率。
填充比率指的是地面数量与整个网格空间格子数量的比率。这里我们不想让地牢充满整个空间,只让它充满一部分,以此增加其随机性。
private float fillRatio = 0.4f;
到这里,核心算法所需的所有变量都创建完毕了,接下来我们将具体实现核心算法。
核心算法
初始化
首先,我们需要一个初始化函数来配置好环境。
void Init()
{
// 初始化网格
grid = new Grid[width, height];
foreach(Grid sqr in grid)
{
sqr = Grid.empty;
}
// 初始化Indicator
inds = new List<Indicator>();
Indicator ind = new Indicator();
// 随机选择初始的方向
// RandomDirection()会随机生成一个Vector2的变量,稍后会提供
ind.dir = RandomDirection();
// 初始化生成位置
ind.pos = new Vector2(Mathf.RoundToInt(width / 2.0f), Mathf.RoundToInt(height / 2.0f));
inds.Add(ind);
}
生成地面
在初始化完成之后,我们就可以开始生成地面了。
void FloorGeneration()
{
// 在达到一定覆盖率之前,循环维持执行,但是while(true)可能会造成不可预计的后果
int counter = 0;
while(counter < 123456)
{
// 生成地面
foreach(Indicator