-
Notifications
You must be signed in to change notification settings - Fork 0
/
PathCalculation.gd
120 lines (109 loc) · 3.15 KB
/
PathCalculation.gd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
extends Node2D
const DEBUG_PATHS = false
var rocks
var triangles
var ready = false
var blacklist
var paths
var thread
signal paths_updated(paths)
func _on_Game_ready():
rocks = []
for terrain in get_parent().get_parent().currentLevel.get_children():
for child in terrain.get_children():
if child.is_in_group("rock"):
rocks.append(child)
triangulate()
$PathUpdate.start()
func _draw():
if DEBUG_PATHS:
calculate()
func calculate(ignore=null):
if not ready:
return
if DEBUG_PATHS:
for rock in rocks:
draw_circle(to_local(rock.global_position), 4, Color(1,1,1,0.5))
for c in getCorners():
draw_circle(to_local(c), 6, Color(1,0,0,0.5))
var threshold = 80
paths = []
blacklist = []
for t in triangles:
var path = []
for i in range(0,3):
if DEBUG_PATHS:
draw_polyline([t[i], t[(i+1) % 3]], Color(0,1,0,0.1))
var weight = (t[i] - t[(i+1) % 3]).length()
var center = t[i] + (t[(i+1) % 3] - t[i])/2
if (center - t[(i+2)%3]).length() < threshold / 2:
blacklist.append(center)
else:
if weight > threshold and insideMargin(center, threshold / 2):
path.append(center)
if len(path) > 2:
path.append(path[0])
paths.append(path)
for path in paths:
var toRemove=[]
for point in blacklist:
for i in range(len(path)-1,-1, -1):
if (point - path[i]).length() < 10:
path.remove(i)
if len(path) == 1:
path.remove(0)
for path in paths:
for i in range(len(path)-1, -1, -1):
var n = 0
for otherPath in paths:
for otherPoint in otherPath:
if (path[i] - otherPoint).length() < 1:
n += 1
if n < 2:
path.remove(i)
for path in paths:
if len(path) == 1:
path.remove(0)
if DEBUG_PATHS:
draw_polyline(path, Color(0,0,1))
emit_signal("paths_updated", paths)
func insideMargin(point: Vector2, margin):
var corners = getCorners()
var d = margin
d = min(d, (point - corners[0]).x)
d = min(d, (point - corners[0]).y)
d = min(d, (corners[2] - point).x)
d = min(d, (corners[2] - point).y)
return d >= margin
func triangulate():
var allPoints = PoolVector2Array()
for rock in rocks:
allPoints.append(rock.global_position)
allPoints.append_array(getCorners())
var allDelaunay = Geometry.triangulate_delaunay_2d(allPoints)
var triangleArray = [];
for triple in range(0, allDelaunay.size()/3):
triangleArray.append([allDelaunay[triple*3], allDelaunay[triple*3+1], allDelaunay[triple*3+2]]);
triangles = []
for triple in triangleArray:
triangles.append([allPoints[triple[0]], allPoints[triple[1]], allPoints[triple[2]]])
ready = true
func getCorners():
var node = get_parent().get_parent().get_node("Field/CollisionShape2D")
var shape = node.shape
var corners = []
corners.append(node.to_global(shape.get_extents()*Vector2(-1,-1)))
corners.append(node.to_global(shape.get_extents()*Vector2(-1, 1)))
corners.append(node.to_global(shape.get_extents()*Vector2(1, 1)))
corners.append(node.to_global(shape.get_extents()*Vector2(1, -1)))
return corners
func _on_PathUpdate_timeout():
triangulate()
if DEBUG_PATHS:
update()
else:
thread = Thread.new()
thread.start(self, "calculate", null)
func _exit_tree():
if thread != null:
thread.wait_to_finish()