前言
最近刚确定下来毕业设计要做的内容——一个2DRoguelike类型的游戏。因此研究了几天的地图生成算法,终于于如今成功制作了地图的生成。先放几张示意图感受一下:
是不是还蛮有感觉的呢!
一、核心思路
首先我们要明白的是一点。地图的随机生成方法有很多,但是前提是必须要保证这些地图区域的复杂性和连通性。因此虽然随机生成难度不大,但是合理性还是需要考虑的。
大体思路是这样的:
1.首先我们要随机生成一些墙和通路。这些是完全随机的。当然最外圈是必然是墙的。
2.接下来对这些完全随机生成的方块按照一定规则进行反复处理。
3.在完全处理过后,会生成一些并不连通的区域,打通他们。
4.在生成入口和出口。
二、随机生成墙和通路
这一段没什么好说的。不过如果按照我的算法来做的话,这个初始随机是墙和通路的概率是多少并无什么太大关系。我分别测试了20%、50%、80%的概率初始生成墙,发现最终的地图区别并没有什么明显的区别。
我的地图是15*15的。首先我定义了一个Map类。它代表着每一个地图的格子。当然这个类我的名字起的并不好,不过我也想不出什么更好的名字了,所以就干脆不变了。这个Map类里面包含这些属性:
public int type = 0;
//0通路 1墙 2复活点 3上楼点
public int RoundWallCount = 0;
public int x;
public int y;
//数据结构
public bool IsVisited = false;
type代表的是当前格子的类型。RoundWallCount指的则是当前格子周围的墙(type==1)的数量。x和y指的是当前格子的坐标。至于IsVisited在后面的打通部分有用处。
首先定义一个Map[,]的二维数组。作为我当前的全部地图。然后对这个地图进行初始化,完全生成一个15*15的地面。
Object OFloor = Resources.Load("Prefabs/Floor", typeof(GameObject));
for(int x = 0; x < 15; x++)
{
for(int y = 0; y < 15; y++)
{
GameObject GO = Instantiate(OFloor, PFloor) as GameObject;
GO.transform.position = new Vector3(x, y, 0);
}
}
这些地面是完全不需要规则的,只管生成就好。接下来就需要随机生成墙了。
for (int x = 0; x < 15; x++)
{
for (int y = 0; y < 15; y++)
{
Map[x, y] = new Map();
Map[x, y].x = x;
Map[x, y].y = y;
if (Random.Range(0, 100) < 50 ||x == 0 || y == 0 || x == 14 || y == 14)
{
Map[x, y].type = 1;
}
}
}
当然我的type的默认值是0.所以如果不是墙,那么并不需要赋值。
我放几张图表示一下这个算法生成的结果
二、循环处理地图
这时候我们发现这张图虽然有点感觉,但是不连通的区域实在是太多了。所以我们要进行一系列算法来修改地图,使这张地图尽可能地连通。
核心算法是这样的。反复进行以下操作:
1.取当前每一个格子周围的墙的数量
2.如果当前格子是墙,那么当他周围的墙<5个或者大于7个时,将其转变为路面
3.如果当前格子是路,那么当他周围的墙>=4个或者小于2个时,把他变成墙
for (int i = 0; i < 3; i++)
{
//记录墙的数量
for (int x = 1; x < 14; x++)
{
for (int y = 1; y < 14; y++)
{
//检查周围一圈墙的数量
Map[x, y].RoundWallCount = 0;
for (int tx = x - 1; tx < x + 2; tx++)
{
for (int ty = y - 1; ty < y + 2; ty++)
{
if (Map[tx, ty].type == 1)
{
Map[x, y].RoundWallCount