使用GDScript(godot)生成仿杀戮尖塔地图

代码如下:需要中文增强版才可以运行

extends Node2Dexport (PackedScene) var Ballvar 被连接数 = {}  # 每个怪物被下层怪物连接的数量 最多为2
var 连接1 = {}  # 第一次连接的上层怪物位置
var 连接2 = {} # 第二次连接的上层怪物位置
var 怪物数量 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0]  # 每层怪物的数量
var 总层数 =8  # 总层数
var 怪物坐标行 = {}  # 存储随机处理后的怪物行坐标
var 怪物坐标列 = {}  # 存储随机处理后的怪物列坐标func _ready():生成怪物()位置调整()画地图()func 生成怪物():for i  in range(总层数):怪物数量[i] = 生成随机数(4,6)  # 生成每层怪物的数量 4 5 6if i>0 :首尾连接(i)   第一次连接(i)第二次连接(i)func 首尾连接(层数):# 将下层最外侧的怪和上层最外层的怪相连连接1[Vector2(层数,1)] = 1连接1[Vector2(层数,怪物数量[层数])] = 怪物数量[层数-1]被连接数[Vector2(层数-1,1)] = 1被连接数[Vector2(层数-1,怪物数量[层数-1])] = 1passfunc 第一次连接 (层数):var 当前位置 = 1  # 上层怪物的位置指针,从1开始var 待连接点 = 怪物数量[层数] - 2var 上层未连接点 = 怪物数量[层数 - 1] - 2var 本层未连接点 = 怪物数量[层数]  - 2for i in range(待连接点):#默认可选位置为2,既当前位置和下一位置var 可选位置 = 2# 如果本层未连接点<上层未连接点,则上层指针+1if 本层未连接点 < 上层未连接点:当前位置 = 当前位置 + 1上层未连接点 =上层未连接点 -1 # 如果指针已经指向上层最后一个怪,则可选位置为1,因为没有下一个怪可以选了     if i + 2 + 1 >= 怪物数量[层数] and 当前位置 == 怪物数量[层数 - 1]:可选位置 =1# 本层倒数第三个怪,不能连接上层最后一个怪  if i + 2 + 2 == 怪物数量[层数] and 当前位置 ==  怪物数量[层数 - 1] -1: 可选位置 = 1  # 如果r为0 则连接当前指针 如果r 为1 则连接下一指针var r = 生成随机数(0,可选位置-1)连接1[Vector2(层数, 2 + i)] = 当前位置 + rvar n = 读取字典(被连接数,Vector2(层数 - 1, 当前位置 + r))被连接数[Vector2(层数 - 1, 当前位置 + r)] = n + 1#如果上层指针所指的怪已经有两个连接,则强制指针+1if 被连接数[Vector2(层数 - 1, 当前位置 + r)] == 2 : r = r + 1当前位置 = 当前位置 + r上层未连接点 = 上层未连接点 - r本层未连接点 = 本层未连接点 - 1func 第二次连接 (层数):for i in range(1 ,怪物数量[层数]+1):# 将当前节点所连接的上层怪物位置作为指针var 连接1位置 = 连接1[Vector2(层数, i)]# 查看该指针前后位置的情况var 后一位置 = 连接1位置 + 1var 前一位置 = 连接1位置 - 1if 后一位置 > 怪物数量[层数-1]:后一位置 = 怪物数量[层数-1]var 已连接 = 0# 先判断该右边的点是否可连接if 是否可连接(层数, 后一位置, i,1):var n = 读取字典(被连接数,Vector2(层数 - 1 , 后一位置))if n == 0:连接2[Vector2(层数, i)] = 后一位置被连接数[Vector2(层数 - 1 , 后一位置)] = n + 1已连接 = 1elif n == 1 :var r = 生成随机数(0,3)if r == 0:连接2[Vector2(层数, i)] = 后一位置被连接数[Vector2(层数 - 1 , 后一位置)]= n + 1已连接 = 1# 如果右边没有产生连接,则再判断左边的点if    已连接 == 0:if 是否可连接(层数, 前一位置, i,2):var n = 读取字典(被连接数,Vector2(层数 - 1 , 前一位置))if n == 0:连接2[Vector2(层数, i)] = 前一位置被连接数[Vector2(层数 - 1 , 前一位置)] = n + 1已连接 = 1elif n == 1 :var r = 生成随机数(0,2)if r == 0:连接2[Vector2(层数, i)] = 前一位置被连接数[Vector2(层数 - 1 , 前一位置)]= n + 1已连接 = 1func 是否可连接(层数, 上层位置, 本层位置, 方向):var 可连接 = truevar n = 读取字典(连接1,Vector2(层数 , 本层位置))# 已经连接过了,不可连接if n == 上层位置:可连接 = false#方向1,向右查找 先找右边再找左边 如果加一个随机来决定先左或先右会更好if 方向 == 1:n = 读取字典(连接1,Vector2(层数 , 本层位置+1))# 构成了交叉,不可连接if n == 上层位置 - 1 :可连接 = falseelse: #方向2,向左查找# 构成了交叉,不可连接n = 读取字典(连接2,Vector2(层数 , 本层位置-1))if n == 上层位置 + 1 :可连接 = falsen = 读取字典(连接1,Vector2(层数 , 本层位置-1))# 构成了交叉,不可连接if n == 上层位置 + 1 : 可连接 = false  return 可连接func 读取字典(字典,key):if 字典.has(key):return 字典[key]else:return 0func 画怪物(x,y):var new_ball = Ball.instance()new_ball.position = Vector2(x,y) add_child(new_ball)func 画地图():for i  in range(总层数):for l  in range(1,怪物数量[i]+1):画怪物(怪物坐标列[Vector2(i,l)],怪物坐标行[Vector2(i,l)])passfunc 位置调整():for i in range(0,总层数):for l  in range(1,怪物数量[i]+1):var 间隔 = (450 / (怪物数量[i])) as int怪物坐标行[Vector2(i,l)] = i * 80 + 40 + 生成随机数(0,40)怪物坐标列[Vector2(i,l)] =  间隔 * l + 生成随机数(0,30) - 30func _on_Node2D_draw():for i  in range(1,总层数):for l  in range(1,怪物数量[i]+1):var n = 读取字典(连接1,Vector2(i,l))if  n > 0:var x1 = 怪物坐标列[Vector2(i,l)]var y1 = 怪物坐标行[Vector2(i,l)]var x2 = 怪物坐标列[Vector2(i-1,n)]var y2 = 怪物坐标行[Vector2(i-1,n)]draw_line(Vector2(x1,y1),Vector2(x2,y2),Color.blue)for l  in range(1,怪物数量[i]+1):var n = 读取字典(连接2,Vector2(i,l))if  n > 0:var x1 = 怪物坐标列[Vector2(i,l)]var y1 = 怪物坐标行[Vector2(i,l)]var x2 = 怪物坐标列[Vector2(i-1,n)]var y2 = 怪物坐标行[Vector2(i-1,n)]                draw_line(Vector2(x1,y1),Vector2(x2,y2),Color.blue)     func 生成随机数(左边界,右边界):randomize()var r = rand_range(左边界, 右边界+1) as intreturn r

算法思路:

杀戮尖塔的地图,下层最外层的点会和上层最外层的点相连.

所有下层点点都会至少连接一个上层点,但最多只能连接两个上层点,而每个上层点也最多被两个下层点连接,且连线不能交叉

而下面的连法都是错误的.



那么如何实现正确的连接呢,我采用了两次连接的方式:
第一次连接:保证除两侧的(两侧的下层点已经和上层两侧的对应点连接了)下层点,所有的其他下层点都连接到一个上层点.。
但不保证所有的上层点都被连接到。

首先在上层定义一个指针位置,第一个待连接点可以在该指针或下一位置中随机选择一个连接。

如果选择了原指针位置,则指针不变。
如果选择了下一位置,则指针+1
但同时,如果上层该点已经有两个连接点,因为杀戮尖塔每个上层点最多连接2个下层点,所有此时指针位置也会强制+1

下一个待连接点同理:

但这种连接算法在面对上下层点的数量相差较大是有问题的。

我们可以发现,无论后续采用什么连接方式,都无法保证上层的3个未连接点被下层连接了。

所以需要对原算法进行修正,加入对上下层点数量的判断。

首先,指针依然是指向第一个节点。
然后判断上下层待连接点的数量。
如果上层的数量>下层的数量,则指针+1
以此类推(其实这里可以用数学的方法推断出什么情况下必须+1,什么情况下不需要,但形状会不太自然)



还有一种连接形状也是错误的

可以看出,倒数第二点已经没有可以连接的选择了。
避免的方式就是禁止下层倒数第三个点和上层最后一个点连接。

至此第一次连接完毕。所有的下层点都保证了和上层至少一个点连接。
但上层的点还有未被连接的,所有要进行第二次连接:


第二次连接,会依次查找下层每个连接点所连接的上层点左右两侧的点。
我设定的是先查找右边的点
如果该点还没有被任何下层点连接,则进行连接。
如果该点已经被连接,但连接数未满2,则有概率进行连接。
这个概率的大小会影响最终地图的复杂度。
查完右边再查左边。
此外,因为第二次连接存在交叉的可能,还需要一个计算连接是否交叉的算法
可以看上边的代码。

使用GDScript(godot)生成仿杀戮尖塔地图相关推荐

  1. 在Godot中制作杀戮尖塔的箭头

    杀戮尖塔的卡牌箭头 杀戮尖塔里面使用卡牌时的箭头是这样的: 贝塞尔曲线 箭头的形态非常符合贝塞尔曲线. PS 中的钢笔工具就是用的贝塞尔曲线: 如图,一条贝塞尔曲线需要用四个点来确定,一个起点,一个终 ...

  2. 写一个杀戮尖塔存档修改器

    软件及源码下载 1. 前言 之前杀戮尖塔打折了,然后 买了这个游戏,游戏很好玩,所以我简单研究了一下游戏.游戏是java写的,那么几乎可以看到他的完整源码了. 这个软件前前后后我差不多我写了一周了.所 ...

  3. 杀戮尖塔用java也打不开_《杀戮尖塔》创意工坊使用指南以及mod推荐

    <杀戮尖塔>的创意工坊可谓是重新为这个游戏赋予了新的使命,而国内玩家想要游玩创意工坊的mod需要下载许多基础mod,但是很多人都不知道该下哪一种,导致mod不能玩,下面小编就将带来< ...

  4. 修改jar中的class:杀戮尖塔修改教程

    缘起 作为一只程序猿,游戏自然是标配.自从入了杀戮尖塔的坑,几年来陆陆续续玩了几百小时.然而steam上的成就至今没刷完,发牌员和各路小怪次次都在针对我.在第nn{n^n}nn次死于通往进阶20的三层 ...

  5. 【Unity】类杀戮尖塔手牌系统实现(初始卡组、随机抽牌、卡牌绘制)

    制作初始卡组 在DontDestroyOnLoad 的物体下挂不会被销毁的Global脚本,用于跨场景调用玩家当前手牌 制作ScriptableObject类型的卡资源,这样策划可以直接在Unity编 ...

  6. STEAM 97%好评,体验堪比《杀戮尖塔》,为什么玩家说这是2020年上半年最超值的游戏?

    当我们感叹<怪物火车>优秀地继承并创新了类<杀戮尖塔>的Roguelike DBG(卡牌构筑游戏,Deck Building Game)玩法时,或许不会想到在短短一个月后,又有 ...

  7. 如何用高德地图定位生成二维码_OSM地图本地发布如何生成各省市矢量地图

    1.缘起 2.问题 3.分析 4.生成自定义地区矢量瓦片 4.1.启动docker 4.2.启动postGIS容器 4.3.设置不清理上次的结果 4.4.删除默认切图范围 4.5.修改切图层级和范围 ...

  8. 杀戮尖塔是用java_杀戮尖塔修改class文件图文教程 杀戮尖塔怎么改class

    杀戮尖塔中玩家们可以单独来修改class文件,来在游戏中得到想要的状态.下面给大家带来杀戮尖塔修改class文件图文教程,感兴趣的玩家可以试一下. 杀戮尖塔修改class文件图文教程 从网上看到有两种 ...

  9. JAVA启动杀怒尖塔_杀戮尖塔如何修改class 杀戮尖塔修改class文件方法步骤图解

    杀戮尖塔如何修改class?相信小伙伴们一定很好奇,修改class文件可以在游戏中得到想要的状态,下面小编为大家带来了杀戮尖塔修改class文件方法步骤图解,感兴趣的小伙伴赶紧跟着小编一起来看看吧. ...

最新文章

  1. 帅爆了!3个月0基础转型头条数据分析师,他做对了什么?
  2. stm32固件库assert_param()
  3. linux mint视频,Linux Mint 20.1 beta 发布,新增免费视频播放器
  4. 探秘HDFS —— 发展历史、核心概念、架构、工作机制 (上)| 博文精选
  5. 李开复离职后谷歌将在中国消亡
  6. 学习索引结构的一些案例——Jeff Dean在SystemML会议上发布的论文(中)
  7. java后台发送请求并获取返回值(续)
  8. hibernate 继承映射(二)
  9. Java笔记(十七) 异步任务执行服务
  10. API的 Signature(签名)Token(令牌) 认证
  11. 通过源码成功启动odoo 10.0
  12. dmg文件转换iso ultraiso_Ultraiso软盘如何制作U盘启动盘
  13. LPC2478时钟模块详解
  14. 如何将UCI数据集转换成Matlab可用格式
  15. 芯烨 Xprinter XP-DT108A 打印机驱动
  16. 连接网络打印机报错0x000003e3
  17. GP技术的展望——道生一,一生二
  18. Ubuntu20与win10共享文件夹
  19. 云中网络的隔离:GRE、VXLAN
  20. 为什么梦里常有视觉和听觉,却没有痛觉和嗅觉?

热门文章

  1. 【多模态】多模态摘要简述
  2. 易想团购 注入 user.php,易想购物(easethink)存在sql注入漏洞,附利用测试POC
  3. 基于51单片机的智能花盆测控(温湿度、光照)【仿真资料-126】
  4. java 调用弗雷_JAVA API(一)String类和StringBuffer类
  5. pybind11学习 | 面向对象编程
  6. 手机不能打电话没有信号无服务器,手机没信号也能拨打电话?不知道了吧!
  7. Pr零基础入门指南笔记一——项目、序列、预设
  8. 使用源码部署CITA(Ubuntu18.0.4 | VMware)
  9. Meta拟裁撤Instagram伦敦员工 其余人将调往美国---转自百度新闻|财联社
  10. 【XAI】Comment: Graphical Models, Causality and Intervention