对于大多数的游戏来说,内容的消耗都是开发商非常棘手的问题,而随机生成地图的做法则大大增加了游戏的可重复性,并且可以丰富玩家的体验。最近,海外一名资深开发者在博客中分享了他做随机生成地图的方式,以下请看编译的博客内容:
  这篇博客主要解释的是一个做随机生成地图的技术,之前TinyKeepDev也进行过简略的描述,但我这里会用更多的细节和步骤来解释这个做法,总体来说,整个算法的运行方式可以用下面的gif图表示:

  生成房间
  首先,你要生成一些宽和高不同的房间,随机地放在一个圈内。TKdev的算法用了比较常见的方法随机生成房间尺寸,我认为这是一个不错的想法,因为它可以为你带来更多的参数可供使用,使用不同的宽高比例和标准偏差可以带来外观不同的副本地牢。
  你可能需要使用到的一个函数就是getRandomPointInCircle:

function getRandomPointInCircle(radius)local t = 2*math.pi*math.random()local u = math.random()+math.random()local r = nilif u > 1 then r = 2-u else r = u endreturn radius*r*math.cos(t), radius*r*math.sin(t)end

你可以在这个链接里获得更多的信息(英文版),在此之后,你就应该可以做出像下图这样的东西了:

  你需要考虑的一个非常重要的事情是,由于你(至少是概念上)在处理一个tile网格,所以你必须把所有的东西都对齐到同一个网格里,在上图的gif中tile的尺寸是4像素,意味着所有的房间位置和尺寸都必须是4的公倍数。为了做到这样,我把位置和宽高比例都放到了一个函数中,把这些数字和tile尺寸相匹配:

function roundm(n, m) return math.floor(((n + m – 1)/m))*m end— Now we can change the returned value from getRandomPointInCircle to:function getRandomPointInCircle(radius)…return roundm(radius*r*math.cos(t), tile_size),roundm(radius*r*math.sin(t), tile_size)end

分散的房间
  现在,我们可以说说分离的部分了。有很多的房间都混在了同一个地方,而且它们之间不能有重叠。TKdev使用了分离转向的做法,但我发现用一个物理引擎做起来更简单。在你增加了所有的房间之后,只要增加物理物体(solid physics body)匹配每个房间的位置、然后运行模拟,直到所有的物体都出于休眠状态。在gif里我是用平常的速度运行模拟,但当你们做不同关卡之间的模拟时,可以用更快的速度。

  这些物理物体本身并没有和tile网格相联系,但当设定了房间位置并且和随即指令放到一起的时候,你就会得到这些并不重叠的房间,而且这些房间与tile网格是匹配的,下面的gif对此进行了展示,蓝色外形是物理物体,在它们和房间之间总有一些不匹配,因为他们的位置始终是分散的。

  当你希望创造水平或者垂直分布的房间时,这样的做法可能会出现一个问题,比如我现在在做的游戏:

  游戏里的战斗都是水平向的,所以我的游戏当中大多数的房间都更更宽,但可能没有那么高。问题在于,物理引擎如何解决这些比较长的房间在一起的时候出现的冲突:

  你们可以看到的是,地牢变得非常高,这并不是理想中的状况。为了解决这个问题,我们可以一开始就把这些房间按带状分布而不是环形,这可以确保地牢本身有合适的宽高比例:

  为了在这个带状区域里随机分布,我们只要把getRandomPointInCircle函数进行改变,把分布点放到椭圆形中即可,在gif里我使用的椭圆形宽度为400,高度为20):

function getRandomPointInEllipse(ellipse_width, ellipse_height)local t = 2*math.pi*math.random()local u = math.random()+math.random()local r = nilif u > 1 then r = 2-u else r = u endreturn roundm(ellipse_width*r*math.cos(t)/2, tile_size),roundm(ellipse_height*r*math.sin(t)/2, tile_size)end

主房间
  下一步主要是解决哪些房间是主房间或者中心房间,哪些是附属房间。TKdev的方法是非常不错的,你只需要挑选超过一定宽高比阀值的房间即可,在下面的gif里,我用的阀值是1.25,也就是说,如果平均宽和高是24,那么超过宽和高30的房间都会被选择。

  三角剖分(Delaunay Triangulation)+图形
  现在,我们把所有选中房间的中间点找出来然后放到剖分程序中,你可以自己做这个过程,也可以找有经验的人分享这方面的资源。我在做游戏的时候比较幸运的是Yonaba已经做了这个过程。你们可以在界面中看到:

  在有了这些三角形之后,你随后就可以生成一个图形,这个过程可以非常简单地给你带来图形信息数据结构或者数据库。如果你没有做过,那么房间物体或者结构最好有独特的ID,这样你就可以把这些Id加到图形中,而不是来回复制。
  最小化生成树(Spanning Tree)
  在此之后,我们从图形中生成了一个最小化的生成树,需要再强调一次的是,你可以自己做也可以找有经验的人去做(前提是和你使用的同一种编程语言)。

  最小化生成树可以确保地牢中所有的主房间都是可达的,但同样将让这些房间的连接方式和此前不一样。这是很有用的,因为我们通常都不希望做一个连接太紧密的地牢,但也不希望做成不可达的孤岛。然而,我们又不希望地牢只是一个平行的路径,所以我们现在要做的就是为剖分图形增加一些边界:

  这可以增加更多的路径和循环,这会让副本地牢变得更加有趣。TKdev当时是增加了15%的边界,而我发现8-10%是更好的选择,当然,这主要取决于你希望这些副本地牢之间的连接密度是怎样的。
  走廊
  最后,我们希望为地牢增加走廊,为此,我们检查了图形中的所有节点,然后在相邻的节点之间我们可以创造直线,如果这些相邻节点排列比较平行的话,我们就可以做一个水平线。如果这些节点比较垂直,我们可以做垂直线,如果这些节点没有相邻也没有平行或者垂直,我们可以做2跳线形成L形状。
  我测试是否相邻的标准是,计算两个节点之间的中间点,然后检查中间点X或者Y的属性是否在节点的边界之内,如果在,我就可以从这个中间点创造这条线,但只能在一个轴上。

  在上图中,你们可以看到所有情况下的例子,节点62和47之间有一个平行线,60和125之间有一个垂直线,而118和119之间有一个L形线。另一个比较重要的是,这些都不是我创造的线,这些只是我正在画的,但我还在每个线的旁边创造了2个额外的线,确保每一个都能够与tile尺寸匹配,因为我希望游戏中的战士宽度和高度都至少达到3个tiles。
  不管怎么说,在这个过程之后,我们可以检查哪些并非主房间的房子与这些线冲突,有冲突的房间可以被加到任何你在用的结构中,而且它们还可以作为走廊的轮廓:
  根据你最初设定房间的尺寸和均匀度,你到这里就可以获得外观不同的副本地牢了,如果你希望让走廊变得更统一而且看起来不那么奇怪,那么你就应该把偏差做小一些,而且应该做一些检查,确保房间不至于太窄或者太宽。

  作为最后一步,我们只需要增加1个tile尺寸的网格房间不缺漏掉的部分即可,需要说的是,你其实并不需要有网格数据结构或者太花哨的东西,你可以根据tile尺寸检查每条线,并且在某些列表中增加网格分布位置即可,这就是我们增加3条线(或者更多)的原因。

  接下来,我们的随机生成地图就完成了。
  总结

  整个流程中我返回的数据结构是:一个房间列表(每个房间都只是带有独特ID的结构、x/y位置和宽高比);图形,每个节点对应一个房间id;真实的2D网格,这里的每个房间都是空的,可以指向主房间、走廊或者走廊间。有了这三个结构,我认为你可以做出任何类型的数据,然后找到在哪儿放门、敌人、物品,决定哪些房间里有BOSS等等。

原文链接:http://www.taidous.com/forum.php?mod=viewthread&tid=43609&extra=page%3D1&page=1&_dsign=241e24e4

转载于:https://www.cnblogs.com/AaronBlogs/p/7017493.html

游戏随机地图生成方法相关推荐

  1. 这些坑别踩!游戏随机地图生成开发经验分享

    当时虽然简单实现了目的,但后来自己也感到世界地图的呈现并不十分完美,恐怕也就只值95分.为了精益求精且给自己找点事做,便想对大地图的呈现方式做些微调. 之前略有瑕疵的世界地图 为何选择2D? 素材好找 ...

  2. 一个简单的2DRoguelike游戏随机地图生成思路

    首先我们要先明确一张Roguelike地图里包含的最基本元素是什么,我的理解是房间与通道.我们可以将一张地图抽象成是房间与房间通过通道来连接. 那么基于这个大前提,我的思路如下. 以图中红色格子为中心 ...

  3. [Unity]Roguelike随机地图生成(一)

    初步随机地图生成 基础房间生成 房间门的判断 基础房间生成 首先需要确定每次房间生成都是在上一个房间的哪个方向上生成,为此需要声明一个枚举值来记录上下左右四个方向 创建脚本RoomGenerator, ...

  4. 随机地图生成--自己的一次尝试

    最近照着网上的元胞自动机随机地图生成算法自己尝试着写了一下,发现效果不是很满意 local count1 = Tile_map.CheckNeighborWall(i,j)--1层墙的数量 local ...

  5. 四维图新地图坐标_一种融合双目视觉和差分卫星定位的地标地图生成方法与流程...

    本发明属于地图测绘技术领域,更为具体地讲,涉及一种融合双目视觉和差分卫星定位的地标地图生成方法. 背景技术: 地标地图是一种将地图去除冗余信息以轻量化形式存储的高精度地图,可以为智能车提供部分静态目标 ...

  6. 一种简单的随机多边形生成方法

    文章目录 搞CNN训练时候有时需要生成一些随机多变形的mask来用用,比如在分类算法中我们有时会随机将图像的一部分区域扣掉或填充为其他内容以模拟遮挡的情况.某些文章中可能会用比较规则的形状,比如矩形或 ...

  7. 《Dead Cells》的随机地图生成

    而对于平台动作(Platformer)类型的 Roguelike 来说,精妙的关卡设计显得更加重要了,于是大家也在考虑其它方式,比如预生成大量关卡模块再随机选择.整合,或者混合两种方式来做.预生成关卡 ...

  8. Java猜字母游戏——实现字母生成方法

    问题 实现猜字母游戏中的字母生成方法,即,随机生成5个不同的字母作为猜测的结果. 方案 实现generate方法,首先声明一个字符类型的数组,用于存储26个大写字母,然后声明一个boolean类型的数 ...

  9. 【饥荒】关于随机地图生成的方式

    介绍世界的生成方式 原文 我注意到,几乎没有人知道如何在饥荒mod里建立新的地图,所以我想分享我的知识.如果在任何事情上我错了,请纠正我或给我信息. 介绍世界的生成方式 世界生成的组成是 第一部分 预 ...

最新文章

  1. diy直立双足机器人_速看!近期国内外机器人资讯大汇总
  2. Puppet--用户自动化管理
  3. bt5重启网卡命令_Linux文件的常用操作命令
  4. 专访阿里云萧少聪、曹龙:一家云厂商对入局数据库做了哪些思考?
  5. 详解深度语义匹配模型DSSM和他的兄弟姐妹
  6. C/S架构和B/S架构
  7. org.jbpm.configuration.ConfigurationException: name 'default.jbpm.context'
  8. PHP操作Mysql疑问?
  9. 计算机运行一段时间黑屏,电脑运行一段时间之后间歇性黑屏,黑屏一秒钟恢复,过几秒又黑屏,是显卡问题还是cpu问题...
  10. java 生成印章_印章生成
  11. Animation动画详解
  12. IP地址冲突问题的解决方法
  13. 某试卷由26道题c语言,c语言模拟试题
  14. CET6 历年真题原词复现 核心词汇 做题技巧 听力拿分技巧汇总(这篇文章是英语四六级考试最后的版本,谢谢大家一路陪伴)
  15. Redis源码初探(1)简单动态字符串SDS
  16. mysql 微信用户昵称 emoji 完整保存
  17. (转载)(官方)UE4--图像编程----着色器开发----HLSL 交叉编译器
  18. Matlab中sym无法使用
  19. 深入理解CSS:font metrics, line-height 以及 vertical-align
  20. 服务器故障内存位置怎么确定,服务器内存故障定位方法

热门文章

  1. 小波去噪处理音频\MFCC对比
  2. 9.leetcode题目189: Rotate Array
  3. python怎么自动生成文档_用 Python 自动生成 Word 文档
  4. 程序员从普通二本毕业的真实薪资,记录一路走来的路
  5. 关于一个《十六进制转十进制》的小程序
  6. 统计学基础——负二项分布的数字特征
  7. 浅识k8s中的准入控制器
  8. OpenFeign实现降级
  9. mac系统从零开始配置若依框架后端运行环境
  10. 信息系统项目管理:项目经理担任什么样的角色?