使用GDScript(godot)生成仿杀戮尖塔地图
使用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)生成仿杀戮尖塔地图的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 量化投资作业的R实现——收益率相关图形绘
- 下一篇: 202007 软件市场分析