aka gravity ninja golf
1extends Node2D
2
3var polyinner: PackedVector2Array
4var colyinner: PackedColorArray
5var polyouter: PackedVector2Array
6var colyouter: PackedColorArray
7var BOUNDS: Rect2
8
9
10func initialize(fg: Color, bounds: Rect2):
11 colyinner = []
12 colyinner.resize(11 + 14 + 2)
13 colyinner.fill(fg)
14
15 colyouter = []
16 colyouter.resize(23 + 19 + 2)
17 colyouter.fill(fg)
18 BOUNDS = bounds
19 sketch()
20
21func sketch():
22 polyinner = genring(genpolygon(11, 14.0, 1.0), genpolygon(14, 28.0, 1.1))
23 polyouter = genring(genpolygon(19, 50.0, 1.3), genpolygon(23, 62.0, 1.5))
24 queue_redraw()
25
26func _draw():
27 for dx in [-1, 0, 1]:
28 for dy in [-1, 0, 1]:
29 draw_polygon(offsetpoly(polyouter, dx, dy), colyouter)
30 draw_polygon(offsetpoly(polyinner, dx, dy), colyinner)
31
32func offsetpoly(a: PackedVector2Array, dx: int, dy: int) -> PackedVector2Array:
33 if dx == 0 && dy == 0: return a
34 var offset = Vector2.ZERO
35 offset.x = dx * BOUNDS.size.x
36 offset.y = dy * BOUNDS.size.y
37 var res: PackedVector2Array = []
38 res.resize(a.size())
39 for i in range(a.size()):
40 res[i] = a[i] + offset
41 return res
42
43## genring takes an [param inner] polygon and an [param outer] polygon, and concatenates them so that
44## they form a polygon with the inner polygon cut out from the outer polygon. doesn't do any checks
45## to make sure that the polygon actually tesselates, but it does pick the best point in the inner polygon
46## to connect to the first point from the outer polygon
47func genring(inner: PackedVector2Array, outer: PackedVector2Array) -> PackedVector2Array:
48 var res: PackedVector2Array = []
49 res.resize(inner.size() + outer.size() + 2)
50 for i in range(outer.size()):
51 res[i] = outer[i]
52 var fouter = outer[0]
53 res[outer.size()] = fouter
54 var bi: int = -1
55 var best: float = 100000.0
56 for j in range(inner.size()):
57 var nl = (fouter - inner[j]).length()
58 if nl < best:
59 best = nl
60 bi = j
61 var os = outer.size() + 1
62 for j in range(inner.size()):
63 var idx = (inner.size() - j + bi) % inner.size()
64 res[os + j] = inner[idx]
65 res[os + inner.size()] = inner[bi]
66 return res
67
68## genpolygon generates a (nonconvex polygon) with [param n] vertices, and the given [param radius]
69## and [param deviation]
70func genpolygon(n: int, radius: float, deviation: float) -> PackedVector2Array:
71 var rads = []
72 rads.resize(n)
73 var rots = []
74 rots.resize(n)
75 var rsum = 0
76 for i in range(n):
77 rads[i] = randfn(radius, deviation)
78 rots[i] = rsum + randf() + .2
79 rsum = rots[i]
80 var poly = PackedVector2Array()
81 poly.resize(n)
82 var randrot = randf() * TAU
83 for i in range(n):
84 poly[i] = Vector2(rads[i], 0).rotated(rots[i] / rsum * TAU + randrot)
85 return poly