伪随机数生成器
伪随机数生成器 (Pseudorandom Number Generator, PRNG) 是一种算法,用于生成一系列数值,这些数值的性质近似于随机数的性质。尽管这些数值看起来是随机的,但它们实际上是由一个初始值 (称为种子) 决定的,因此在相同种子的情况下其结果是确定的。这一特性也经常用于游戏中的无限地图生成中,通过此特性及其他函数来保证地图边缘的衔接平滑。
线性同余生成器
public static int LCGRandom(int v)
{
return (1140671485 * v + 12820163) % 16777216;
}
来源:https://en.wikipedia.org/wiki/Linear_congruential_generator
配对函数
康托配对
ContorPairing 的计算公式如下:
z = (a + b)(a + b + 1) / 2 + b
public static int CantorPair(int a, int b)
{
return (a + b) * (a + b + 1) / 2 + b;
}
寻路算法
广度优先搜索 (BFS)
这种算法会从起点开始,逐层向外扩展,直到找到目标点。它适用于寻找最短路径,但在复杂地图中效率较低。
深度优先搜索 (DFS)
Dijkstra 算法
A* 算法
跳点寻路算法 (Jump Point Search, JPS)
接下来介绍一些常用的迷宫生成算法。
细胞自动机 (Cellular Automata,CA)
细胞自动机 (Cellular Automata, CA) 是一种基于规则的数学模型,用来模拟复杂系统的动态行为。
细胞自动机简介
一个活细胞有两个或三个邻居时继续存活;
细胞自动机迷宫算法
规定迷宫范围如 64*64,创建 map 以及用于存储每次迭代结果的 newMap;
var length = 64;
var width = 64;
var map = new int[length, width];
var newMap = new int[length, width];
通过随机数算法填满整个区域范围,这里我们采用 LCG Random 并且将墙壁以占比 45 的量级填充:
for (int x = 0; x < length; x++)
{
for (int y = 0; y < width; y++)
{
newMap[x, y] = 1;
var r = GameMath.LCGRandom(GameMath.CantorPair(x, y)) % 50 + 50;
if (r < 55)
{
map[x, y] = 0;
}
else
{
map[x, y] = 1;
}
}
}
遍历整片地图,如果以当前遍历点为中心周围 9 个方格内执行如下判断:
如果中心点为墙,判断周围 8 个点是否存在 4 个及以上的墙壁;
如果满足则中心为墙壁,否则为空洞;
如果中心点为空洞,判断周围 8 个点是否存在 5 个及以上的墙壁;
如果存在则中心为墙壁;否则为空洞;
for (int x = 1; x < length - 1; x++)
{
for (int y = 1; y < width - 1; y++)
{
var wallCount = 0;
for (int i = x - 1; i <= x + 1; i++)
{
for (int j = y - 1; j <= y + 1; j++)
{
if (map[i, j] == 1)
{
wallCount++;
}
else
{
// continue;
}
}
}
if (map[x, y] == 1)
{
if (wallCount > 4)
{
newMap[x, y] = 1;
}
else
{
newMap[x, y] = 0;
}
}
else
{
if (wallCount > 4)
{
newMap[x, y] = 1;
}
else
{
newMap[x, y] = 0;
}
}
}
}
for (int x = 0; x < length; x++)
{
for (int y = 0; y < width; y++)
{
map[x, y] = newMap[x, y];
}
}
小结
Unity 中文社区持续征集内容投稿,欢迎与 Unity 官方分享你的技术笔记、项目 demo、行业经验、有趣案例,加入社区建设,繁荣内容生态,带领百万 Unity 中文开发者一同学习。
方式二:联系邮箱 learn-cn@unity.cn,投稿技术内容。
点击“阅读原文”,访问博主更多技术分享