游戏地图是许多游戏不可或缺的一部分,而能够自我变化的游戏地图则更丰富了游戏的内容,例如《挺进地牢》、《以撒的结合》、《死亡细胞》等游戏都采用了随机地图这一机制,给游戏带来丰富多样的变化,也使得游戏延长了寿命。
我自己很喜欢玩,并且之后也打算制作一款利用这种机制的游戏,所以我这次就尝试用Unity制作一下生成地图的这个功能。
这就是生成的最终效果,下面来分享一下我的实现步骤。
我的大致思路是这样:
- 首先随机在地图上创建一些房间
- 然后将他们重叠的部分进行移动并调整到合适的位置
- 筛选出符合条件的房间,然后以每个房间的中心点为结点进行三角剖分运算后,生成最小生成树以确定连通关系
- 最后将路径转换成曼哈顿距离的路径来完成道路的样貌。
下面开始实现
新建并打开工程之后,我们先将需要的资源导入到工程中。除了美术资源以外,我还用到了Delaunay脚本,用于保存表达房间之间连接关系的最小生成树。而RandomFromDistribution脚本中提供了用于计算房间大小的随机分布算法,让生成房间的大小保证在一定的范围内。
导入这些资源后,就可以正式开始制作了。
在这我为了能够标记并描述一个房间,记录了如下的内容:
- 房间中心点的位置(position)
- 房间的尺寸(size)
- 房间的类型(type)
同时为了能够简单的检测碰撞,还额外记录了矩形在X轴和Y轴上最大和最小的坐标,这样只要通过简单的比较,就可以判断两个房间是否重叠。
在选定好第一个房间之后,每一次需要生成新的房间时,我都会选择一个在设定距离内其它位置的随机点作为新的房间位置。然后还会通过我们之前导入的RandomRangeNormalDistribution库对房间的尺寸进行一定的处理,让他们的宽和高基本符合“正态分布”的曲线,这样就可以减少出现房间过于扁长或者尺寸差别过大的情况。
之后遍历生成的所有房间,利用选择排序判断房间之间是否重叠,如果检测出重叠,则调用房间脚本中的Shift方法对其进行偏移。
在这个过程中,为了方便调试,我还实现了一个不需要任何美术资源,单纯靠Unity划线的功能显示必要信息的类,这样我就可以在不需要操心其它问题的情况下,优先实现必要的功能。
选出所有合适放在地图里的房间后
将所有主房间的中心看作一个点,对这些点进行三角剖分,也就是将所有的顶点与其相邻的顶点相连,且连线之间不允许相交。这样划分出来的所有面都将是三角形,且三角形的每条边上除了顶点之外都不再有其他的点。
这时就该用到前面导入的Delaunay脚本,创建最小生成树保留结果,得到的将是一条条线段
将这些线段添加到队列中,进行删减,仅仅保留下能够保证房间联通的线段,作为最终路径。
为了让游戏内容更加丰富,我又在地图里添加一个boss房间。
先在指定范围内随机取点并生成boss房间,然后遍历其它房间,找到离boss最近的一间作为新路径的起点,boss房间作为终点,并在他们之间做出一条通路,这样就能保证boss房间就只有一条通路能够到达
最后将之前得到的所有路径都转换成符合曼哈顿距离,也就是横平竖直的路径,这样最终得到了整个地图的数据。
完成生成的步骤之后,再根据数据将美术资源排布在地图上,就可以得到一个基础地图了。而实际使用时,在地图的内部还可以额外做一些文章,比如在地图上选择一些位置添加道具或者是陷阱以及敌兵。
这次我分享了我自己对实现随机地图的一些简单尝试,不过这绝对不是唯一的方法,希望我的这期分享能够抛砖引玉,帮助你找到最合适自己的实现方式。
暂无关于此日志的评论。