【伪教程】如何生成一个地牢?
scratch吧
全部回复
仅看楼主
吧务
level 15
遧傂鼝 楼主
先上效果图:
要说明的是,本篇介绍的只是地牢生成的基本思路,示例还有很大的优化空间,也不排除有bug。后面会留下一些问题供大家思考[滑稽]
本篇重在讲解思路,具体脚本方面涉及较少,所以称之为伪教程。主要是希望各位理解算法的思想,自己写出符合自己风格的脚本。
实在不会写的话,可以在我阿儿法营的小号里找到示例文件。搜索作者:天火XO即可
2022年07月04日 04点07分 1
吧务
level 15
遧傂鼝 楼主
首先梳理一下思路。我们想要实现的效果是生成一个地牢。显然,它需要一个起点房间(以绿色表示)和一个终点房间(以红色表示),以及若干普通房间,这些房间必须相互连接;起点房间最好在正中央,而终点房间离起点越远越好——最好让玩家能够探索到尽可能多的房间;终点房间只能由唯一的一个门进入;房间最好不要挤作一团,否则玩家会因为一直在一小片区域逗留而失去探索感,很快感到烦躁。
那么,该如何解决这么多难题呢?
让我们把问题拆解一下,首先来试着实现相互连通的房间。第一步自然是在正中央生成一个起点房间。
然后,考虑到玩家是从起点开始,一个房间接着一个房间一直走下去,直到到达终点。按照这个思路,我们可以让需要生成的房间随机选定在上一个房间的上下左右4个方向的其中之一。
2022年07月04日 04点07分 2
吧务
level 15
遧傂鼝 楼主
不过,这样一来显然会遇到在选定的方向已经生成了房间的情况:
这时有两种方法。
一种是枚举出所有情况。但由于周围存在其它房间的情况一共有16种——
无房间相邻:1种;
1个房间相邻:4种;
2个房间相邻:6种;
3个房间相邻:4种;
4个房间相邻:1种。
这样显然非常繁琐。于是出现了第二种方法:在选定方向后判断一次该方向是否存在房间,如果存在则生成失败,重新尝试一次生成;如果不存在,那么就生成房间。这种方法一定程度上牺牲了效率,但是在可接受范围内。
这样一直进行下去,直到碰到边缘。碰到边缘后,直接将最后一个房间设置为终点。我们会发现,终点房间必定只会连接到单独的一个房间(想想是为什么!)。
看上去我们已经解决了问题的第一部分——
2022年07月04日 04点07分 3
吧务
level 15
遧傂鼝 楼主
——吗?在一些情况下这样的算法就足够了;但在另一些情况下,我们会发现,房间不断生成,直到走进了死胡同——在生成最后一个房间后,这个房间四周都已经存在了其它房间。于是按照之前的方式,房间生成无法再进行下去,陷入了死循环。
为了避免出现死循环,我们需要再回想一下玩家在地牢里走进死胡同后会做的事:原路返回。按照这个思路,我们每生成一个房间,就在列表里记录下这个房间的位置;一旦遇到死胡同,就回到上一个房间,直到走出死胡同,然后继续尝试生成房间。
至此,问题的第一部分才算得到了解决。
2022年07月04日 04点07分 4
吧务
level 15
遧傂鼝 楼主
接下来是第二部分:避免房间过度拥挤。在一些情况下,我们会发现我们得到了这样的地牢:
房间太拥挤怎么办?自然是删除掉那些多余的房间。但我们必须小心,不要制造出不与地牢主体相连的房间。很自然地,我们会想到,当一个房间周围8个位置都存在房间时,删除掉它肯定是稳妥的。但执行删除过后,依然剩下了不少。
2022年07月04日 04点07分 5
吧务
level 15
遧傂鼝 楼主
这时候,联想一下你玩过的地牢探索类游戏——比如以撒的结合。以撒的结合会通过生成一些大房间来避免房间数过多或过于拥挤,我们可以参考一下,将这些相邻的4个房间合并为一个2*2的大房间。为了避免生成过大的房间或者异形房间,需要建立一个大房间位置的标准(这里是用左上角房间的位置),来判断某个房间是否可以作为大房间的一部分。这样可以确保我们生成的大房间都是2*2的。
2022年07月04日 04点07分 6
@遧傂鼝 这里忘记说明一点:起点和终点必定是小房间。所以在判断完是否可以作为大房间左上角后还需要再判断一下房间类型,然后再决定是否合并房间
2022年07月04日 04点07分
吧务
level 15
遧傂鼝 楼主
最后是一些局限性:
第一,我们会发现有些时候地牢缺少岔路。
该如何生成更多的岔路呢?(提示:逆用生成终点时的算法)
第二,地牢半径较大时,房间数会很悬殊。
该如何保证地牢房间数稳定在某个值附近呢?(提示:用更多方式合并房间)
第三,大房间永远优先生成在左上角,导致某些房间组合形式无法出现。
该如何避免呢?(提示:调整大房间生成概率)
2022年07月04日 04点07分 7
level 11
水块备战中考大吧没了,悲 :/
来支持下未来的新吧主
2022年07月05日 00点07分 8
level 12
支持[太开心]
2022年07月06日 07点07分 9
1