游戏中的随机地形生成算法(一)

发表于2018-05-07
评论0 1.1w浏览
在很多游戏都有使用随机地形,这个系列就是针对随机地形生成算法展开的。本文以Unity为例,给大家介绍这个系列的第一篇。

我们首先明确一下思路,使用一个整形二维数组来存储地图信息,其中1代表障碍,0代表道路。
int[,] map;

我们还需要定义一个概率,来控制生成障碍的数量。
[Range(0,100)] //这行代码用来在面板上显示一个滑动条
public int probability;

以及如下变量。
//地图的长和高
public int width;
public int height;

//种子
public string seed;
//是否要使用随机种子
public bool useRandomSeed;

接下来请认真看,我们要生成地图了!
void RandomFillMap()  
    {  
        if (useRandomSeed)  
            seed = DateTime.Now.ToString();  
        System.Random pseudoRandom=new System.Random(seed.GetHashCode());  
        for (int i = 0; i < width; i++)  
        {  
            for (int j = 0; j < height; j++)  
            {  
                if (i == 0 || i == width - 1 || j == 0 || j == height - 1)  //边缘是墙  
                    map[i, j] = 1;  
                else  
                    map[i, j] = (pseudoRandom.Next(0, 100) < probability) ? 1 : 0;  //1是墙,0是空地  
            }  
        }  
    }  

在这段函数里,首先我们判断是否使用随机种子,如果是,将系统时间赋值给种子,这样可以保证每秒种子都不同。
随后我们定义了一个随机数,将seed的哈希码作为种子传入。
接着,我们使用了双重for循环来填充整个map二维数组。很清晰明了,不是吗?
很好,现在地图已经生成了,我们把它画出来看看吧。
void OnDrawGizmos()  
    {  
        if (map != null)  
        {  
            for (int i = 0; i < height; i++)  
            {  
                for (int j = 0; j < width; j++)  
                {  
                    Gizmos.color = map[i, j] == 1 ? Color.black : Color.white; //黑色代表道路,白色代表障碍  
                    Vector3 pos=new Vector3(-width/2+i+.5f,0,-height/2+j+.5f);  
                    Gizmos.DrawCube(pos,Vector3.one);  
                }  
            }  
        }  
    }  

这里我们使用gizmos来绘制地图,这意味着你在game视图中是看不到任何东西的,地图存在于scene视图中。

在Start中调用一下上述函数:
   void Start()
    {
map=new int[width,height];
        RandomFillMap();
    }

然后我们运行试试看吧!

可能看起来像一张二维码,但它绝对不是一个合格的地图。究其原因,是其中噪点太多了,我们应该尝试合并相邻的点,消除孤立的点。
int GetSurroundingWalls(int posX, int posY)  
{  
    int wallCount = 0;  
    for (int i = posX-1; i <=posX+1; i++)  
    {  
        for (int j =posY-1; j <=posY+1; j++)  
        {  
            if (i>= 0 && i < width && j >= 0 && j < height)  
            {  
                if (i != posX || j != posY)  
                    wallCount += map[i, j];  
            }  
            else  
            {  
                wallCount++;  
            }  
        }  
    }  
    return wallCount;  
}  

我们首先计算以每个点为中心的九宫格内墙的数量。
void SmoothMap()  
{  
    for (int i = 0; i < width; i++)  
    {  
        for (int j = 0; j < height; j++)  
        {  
            int surroundingTiles = GetSurroundingWalls(i, j);  
            if (surroundingTiles > 4)  
                map[i, j] = 1;  
            else if (surroundingTiles < 4)  
                map[i, j] = 0;  
        }  
    }  
}  

如果某点周围墙的数量大于4,我们把这点算作障碍。否则算作道路。

很好,现在修改一下前面的代码。
   void Start()
    {
map=new int[width,height];
        RandomFillMap();
SmoothMap();
    }

看下效果:

唔,感觉好多了。但还是有些噪点,我们选择多处理几次:
void Start()  
{  
   GenerateMap();  
}  
    void GenerateMap()  
    {  
        map=new int[width,height];  
        RandomFillMap();    //随机生成地图  
        for (int i = 0; i < 4; i++)  
        {  
            SmoothMap();  
        }  
    }  

再来看看:

这次好多了有木有~
来自:https://blog.csdn.net/qq_17758883/article/details/78180300

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

0个评论