本文是针对 CS61B 学习的 proj 2 的部分内容的笔记。通过本文可以学习到怎么生成地牢游戏用的洞穴地图和房间走廊地图,主要讲解元胞自动机,房间走廊的暴力生成算法,房间(矩形)范围碰撞检测算法,简单(暴力)的路径生成算法,Prim 求解最小生成树连通房间算法。


成品

Josh 做的例子是这样的:

首先是模仿 Josh 的版本做的矩形房间和通道的版本:具体做法也很简单很暴力。

然后还有一个做的地牢的基于洞穴的版本大致这样(地图应该调平滑点洞穴减少直线的路)。

基本方案是使用 Cellular Automata 演变,然后用某种策略联通不联通的洞穴。(设计多种可走路径才比较趣味)。

实际上如果对这类游戏感兴趣,可以做一种先生成房间,然后在房间里面做 cave 这种的,这样可能更好玩一些。

讲解从 Cave 开始讲,之后在讲怎么做 josh 的版本。


Cellular Automata

请学习元胞自动机的基本思路,这里摘录一下:

1.每个元胞都依赖其邻居而引发下一个时刻状态的更新。

2. 几个显而易见的应用:(特殊模型的理解性难搞,相似模型才方便用)生命游戏:指定某种规则让 Cell 生长或死亡。澳洲火灾:指定树木火和空地,编写地生树树生火的依概率转变的元胞自动机。其中树生火可以认为是外界火激励(雷电,烟头)。

3. 邻居分布有:摩尔型 Moor 和 冯诺依曼型 Von 和其他类型

要点是:

一次更新全部更新 (全局更新,并行性质)。

边界条件就是涉及倒边界的时候他的邻居取谁,有固定型,周期型,绝热型和映射型这四种。固定就是指定一个值。周期就是回到整个世界的另一边。绝热是取自己。映射是指定取某个地方的。

不废话了。。。好像没有什么好摘录的。

对于初始化的世界,我们可以采用随机的方法。

了解元胞自动机理论可以编写一些地板和墙壁相互转换的规则,比如扩大墙壁堆和扩大墙壁范围的规则(floor 的邻居的墙数超过一定程度就变成墙),清除空心墙的规则(floor 的邻居的墙数为8一定程度就变成墙)。

尝试不同的参数,最终用的方案经过多次演变之后得到一个洞穴地图:

尽管已经很不错了,但是可以发现有一些没有连通起来的洞穴,必须把他们连接起来。


Prim 建路打通

Prim 算法本来是建立 最小生成树/支撑树 的。

这里复习一下,用来打通地图的不联通的域。请复习 dijkstra,prim 和 kruskal 算法(复习成果能看明白下面的文段)。

Kruskal 是边的贪心,每次选一条最短的边(对边集排序的优先队列即可),然后不成环地(使用并查集)接入支撑树。

Prim 算法则是 Dijkstra 的变形和 Kruskal 的无需判环改进。

回想 Dijkstra 的过程,其贪心决策是基于单源点到达目前点的距离,松弛操作也是基于这个原则,每次从 visited 取最小代价的加入 done,然后去松弛其他 visited 和 unvisited 节点。

回顾最小生成树解决的问题是是 Spanning Tree 的总权重,第一个是取松弛源点的时候是从整个支撑树的集合里面随意取的,然后贪心地遍历能连接两个集合的边,这里实际上是两个集合(done 和 unvisited)笛卡尔积的遍历,找最短边的过程。这也是为什么说 Prim 是 Kruskal 的无需判环的改进,因为他实际上还是对边贪心)。Dijkstra 的优化要快速取得贪心的当前 unvisited 里最短路径节点使用 PriorityQueue 优化,Prim 的时空复杂度和 Dijkstra 是一样的。其正确性可以通过这样的归纳法想到:首先起始一个点, visited 点集必然是一颗最小生成树。然后每次都保证添加的边是 visited 这个点集所有点中到 unvisited 中最短的那条(相当于整个集合重权重的增量最小),所以更新后的 visited 点集也必定是一颗对节点们来说最小生成树。本质上和 kruskal 是一样的,只是通过划分集合来防止成环而已,而kruskal只需要排序一次,prim就要用优先队列动态排序。

不过我们不需要做一个最小生成树的决策,所以实际是就简单地建路而已,有兴趣的话可以用发言人的距离来做最小生成树建路。

简单的一种建路方案:

由于在地图里并不是直接对节点进行最短路或者支撑树的操作,实际的节点是一堆代表房间或者墙壁的 Tiles 。

如果我们想要建立一个图的结构,涉及边的构造问题,就算是真的求支撑树或者最短路,也必须要先弄一幅图出来,但是实际上要建这一个底图并不简单,首先我们不能直接搞一个全连接的图,这样后面的算法就算不过来,就涉及到哪些节点连接起来的问题。如果了解拓扑学,我们知道研究曲面的时候可以用三角剖分(Triangulation)来研究,有限元分析里离散建模也常用这种多边形的方法,图形学里就更加是采用多边形来画立体图形的。这里有一种方法 Delaunay Triangulation 可以对点集建立一个基于三角形的图。这个暂且不讲了,如果我们要模拟 Josh 的示例结果,说不定会用上这个算法来建立路径。

首先我们指定地区发言人(或者是房间发言人)作为一个洞穴的代表(用来作为建路的起点和终点),这个房间发言人就依据遍历顺序取房间的左下角好了。

为了简单起见,建路简单模仿这个过程好了,依据区域发言人离最左下角的曼哈顿距离来决定哪两个非联通区域需要建一条路。

先遍历地图,找到地区发言人之后加入到子图中,然后用一个循环从优先队列取两个发言人来,用某个随机决定左右上下的方案建设一条路。(其实优先队列都不用, 只需要一次排序就行的事情。。。)

我采用的随机化方案如下:

具体就是每次决定是向 x 前进还是向 y 前进。不走迂回的路减少代码量。

运行结果:

可以发现原来很多的墙壁的地方又被打通了,看上去洞穴的那种很多连在一起的感觉没有了,实际上这里可以做一部小洞穴全部填成墙的操作保留更多的墙壁完整性,这一点则需要在找到非连通洞穴的时候顺带进行一个计数,如果数量小于某个 threshold 就全部填了,粗暴的做法可能使用更多的内存和运行时间,这里暂时就不研究下去了。


边界墙上开门思路

我这个普通版洞穴地牢设计的是四周都是墙,所以只需要确定一个方向(l,r,t,b)然后遍历对应的那条边随便找一个就行了。

如果是单行的墙,直接开一个门即可,如果是多行的(比如右下角),我限定一个 loop 最多上限次数(防止全部都是多行墙导致死循环)然后再跳出来去打穿这个开一条路给门用。

开路这个直接确定方向后沿用前面 Prim 调用的那个随机选方向开路的方案的 helper 就行了。


权重放置

更多时候需要根据地图上点的特性决定放置某些东西(包括门和宝物陷阱自动寻路AI怪物等),需要对地图建立某种评分机制。为了方便我们可以沿用 Cellular Automata 的思路根据摩尔邻居或者冯诺依曼邻居以及扩展摩尔邻居等来对某些特性评分。

和用卷积核滤波器求相关度相似。

比如要找比较角落(靠近墙)的地方,就求某个邻居墙阈值之上比较高分的点。要找路的话则是墙和地板某种比例范围的,如果是洞穴则是全是地板。具体细节可以通过理论推导也可以编程时调参,具体我们写到这里再回来补充。

这里对全是地板的地方,我们可以补充一个元胞自动机的规则,采用某个大范围的扩展摩尔型邻居,如果邻居中墙的个数过少,我们就建立一些墙,并且下一个循环仍然会扩充墙和地板,这样能避免自动机多次迭代只剩下大片空地的问题。

这个时候都累死了,但是我实际上不想用这个 Cave 的方案,因为他不好看哈哈。josh 的房间和 hallway 做得挺好看的,我决定要来模仿这个!


矩形重叠检测

我们来研究 josh 的示例里面的 room base, 事实上在他的 lab proj 讲解视频里野没有具体说 implementation 的方面,就是讲了一下 hallway 的一些建议。我于是建立一个基本思路就是先生成 rooms,再生成 hallway(也是延续用我的这个 Cave 的思路了,因为实在是懒得思考其他思路的实现。其实我野参考了一些博主,见参考连接的一些先生成 迷宫 再挖 出 rooms 的方案,但是就是懒得去学迷宫的算法,希望之后补上)

为了 room 的运算和传参方便,定义 Rectangle 类

第一步是生成 no overlap 的房间。836. 矩形重叠 - 力扣(LeetCode) (leetcode-cn.com),这个算法概要就是高中的线性规划问题里计算 overlap 的可行域有没有面积。和判断两个水平、垂直线段是否 overlap 是一个道理的。

当然我野参考了一些游戏(主要是 indienova 的参考资料)源码怎么生成的,他有一种是用物理引擎自己的碰撞算法来分离房间(

CS61B project 2 示例图的地牢地图房间走廊地图生成洞穴地图生成方法相关推荐

  1. Unity Tilemap动态生成2d地图

    Unity Tilemap动态生成2d地图 (参考链接) rule tile 动态生成地图:https://blog.csdn.net/mkr67n/article/details/108340749 ...

  2. java地图完整项目-地图找房(基于百度地图-MongoDB)

    1.BMapGLLib库 网址: GitHub - huiyan-fe/BMapGLLib: 百度地图JSAPI GL版JavaScript开源工具库 该库相关辅助功能可通过点击上述网址进行查看! 2 ...

  3. echarts地图文字重叠解决方案_Echarts扩展地图文字位置错乱的问题

    最近在弄echarts 因为要用到扩展地图,所以在官网下载了相应的json文件 ,引入之后发现文字位置错乱 于是查找网上资料 发现 textFixed : { '大洋洲' : [265, 0], }, ...

  4. DOTA无法加载服务器指定的地图,Dota2自定义地图工具怎么安装_Dota2自定义地图工具常见问题处理方法...

    Dota 2 创意工坊工具的早期测试(Alpha)版本已经发布,如果你有新奇的想法可以使用工具开发制作自己的地图,为Dota 2再添砖瓦. 如果是抱着"玩"的心态小编建议就不要下载 ...

  5. gps两点距离 php,PHP应用:PHP计算百度地图两个GPS坐标之间距离的方法

    <PHP应用:PHP计算百度地图两个GPS坐标之间距离的方法>要点: 本文介绍了PHP应用:PHP计算百度地图两个GPS坐标之间距离的方法,希望对您有用.如果有疑问,可以联系我们. 本文实 ...

  6. 织梦html地图插件,织梦dede网站地图xml生成插件(图文教程)

    织梦网站地图xml生成插件描述 1.utf8 和 gbk 有齐2种编码插件文件 2.根据自己程序编码选择对应插件,上传模块,安装,使用 3.可同时生成5种地图文件 sitemap.html  site ...

  7. 【百度地图API】百度API卫星图使用方法和卫星图对比工具

    百度地图API推出卫星图接口也有一个月啦~ 本文除了介绍如何使用百度地图API来操作卫星图外,还顺带制作了个卫星图对比工具. 一.百度地图API卫星图 调用百度卫星图有两种方式,一是地图类型控件,一是 ...

  8. 【“零起点”--百度地图手机SDK】如何添加地图图层+按钮事件+水平垂直布局?...

    摘要:我们在这一章将学习到如何通过按钮事件来控制地图图层(交通流量图,卫星图)的显示,以及如何对android应用进行水平和垂直布局. -------------------------------- ...

  9. 百度地图API快速调用,一键生成百度地图

    对于在网站或者网页之内插入百度地图插件,可能很多编程技术人员都知道如何来做,但是做起来所花费的时间都比较长,那么下面跟大家分享一下如何快速调用百度地图API,一件生成百度地图的方法,这种方法适用于任何 ...

  10. 百度地图android wear,Android SDK | 百度地图API SDK

    个性化地图 自v3.7.0起,支持使用个性化地图模板,改变底图颜色和样式. 支持设置8大类地图元素的颜色和可见性,包含大地.水系.草地.高速.普通道路.铁路.地铁,poi. 效果示例: 个性化地图元素 ...

最新文章

  1. CentOS6.8下安装Docker
  2. 注塑机摆放间距多少合适_红木家具之间正确的摆放距离
  3. Solr配置与简单Demo[转]
  4. linux显示没有网卡
  5. Linux ln指令
  6. NSTimer不准确与GCDTimer详解
  7. php openssl加密数据长度,PHP使用openssl解密数据(用mcrypt加密)
  8. 94年的博士后又拿到了这个金奖!原来是他的学弟
  9. 使用SQL视图和存储过程限制和监视SQL Server数据访问
  10. DeepMind提出训练网络新方法,快速找到最佳超参数和模型
  11. 【廖雪峰官方网站/Java教程】泛型
  12. Lightroom Classic 教程,如何将照片从 Lightroom 移至Ps,在 Ps 中为照片添加文本?
  13. 人人视频android资源比ios多,人人视频
  14. 001数据类型-字面值-运算规则
  15. sendgrid_电子邮件即服务第2部分:Sendgrid,Mailgun和邮戳
  16. java并发编程艺术——基础篇
  17. python最小二乘拟合圆_点云球面最小二乘拟合的python实现
  18. linux hudson svn,Hudson Maven SVN快速搭建持续集成环境
  19. UCF HSPT 2021 A . Minimum Excluded String (mex)
  20. 网页子窗口iframe的用法

热门文章

  1. ODL(OpenDayLight)Yang UI界面下发流表(ODL+mininet)
  2. WiFi探针的原理与安全
  3. 下肢外骨骼机器人开发技术综述
  4. DOORS vs DNG
  5. Matlab 蒙特卡洛求解三门问题
  6. mc服务器资源包在什么文件夹,资源包
  7. R语言导入TXT数据,最简单明了!!!
  8. Linux 使用shell命令复制文件
  9. 红轴和茶轴哪个声音大 红轴和茶轴哪个适合打字
  10. 【TencentOS tiny学习】源码分析(6)——互斥锁