-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathcollide.moon
More file actions
201 lines (156 loc) · 3.86 KB
/
collide.moon
File metadata and controls
201 lines (156 loc) · 3.86 KB
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
-- collision stuff
import rectangle, setColor, getColor from love.graphics
import rad, atan2, cos, sin from math
export *
class List
new: => @clear!
_node: (item) =>
error "list already contains item: " .. tostring item if @nodes[item]
n = { value: item }
@nodes[item] = n
n
_insert_after: (node, after_node) =>
nxt = after_node.next
node.prev = after_node
node.next = nxt
after_node.next = node
nxt.prev = node
_remove: (node) =>
node.prev.next = node.next
node.next.prev = node.prev
remove: (item) =>
n = @nodes[item]
if n
@nodes[item] = nil
@_remove n
true
clear: =>
@front = { next: nil }
@back = { prev: @front }
@front.next = @back
@nodes = {}
push: (item) =>
n = @_node item
@_insert_after n, @back.prev
shift: (item) =>
n = @_node item
@_insert_after n, @front
each: =>
coroutine.wrap ->
curr = @front.next
while curr != @back
coroutine.yield curr.value
curr = curr.next
class Vec2d
base = self.__base
self.__base.__index = (name) =>
if name == "x"
self[1]
elseif name == "y"
self[2]
else
base[name]
self.from_angle = (deg) ->
theta = rad deg
Vec2d cos(theta), sin(theta)
angle: =>
math.deg atan2 self[2], self[1]
new: (x=0, y=0) =>
self[1] = x
self[2] = y
len: =>
n = self[1]^2 + self[2]^2
return 0 if n == 0
math.sqrt n
left: => return self[1] < 0
right: => return self[1] > 0
normalized: =>
len = @len!
if len == 0
Vec2d!
else
Vec2d self[1] / len, self[2] / len
__mul: (other) =>
if type(other) == "number"
Vec2d self[1] * other, self[2] * other
__add: (other) =>
Vec2d self[1] + other[1], self[2] + other[2]
__sub: (other) =>
Vec2d self[1] - other[1], self[2] - other[2]
__tostring: =>
("vec2d<%f, %f>")\format self[1], self[2]
class Box
self.from_pt = (x1, y1, x2, y2) ->
Box x1, y1, x2 - x1, y2 - y1
new: (@x, @y, @w, @h) =>
unpack: => @x, @y, @w, @h
unpack2: => @x, @y, @x + @w, @y + @h
set_pos: (@x, @y) =>
move: (x, y) =>
@x += x
@y += y
center: =>
@x + @w / 2, @y + @h / 2
touches_pt: (x, y) =>
x1, y1, x2, y2 = @unpack2!
x > x1 and x < x2 and y > y1 and y < y2
touches_box: (o) =>
x1, y1, x2, y2 = @unpack2!
ox1, oy1, ox2, oy2 = o\unpack2!
return false if x2 <= ox1
return false if x1 >= ox2
return false if y2 <= oy1
return false if y1 >= oy2
true
-- is self left of box
left_of: (box) =>
self.x < box.x
draw: (color=nil) =>
setColor color if color
rectangle "fill", @unpack!
__tostring: =>
("box<(%d, %d), (%d, %d)>")\format @unpack!
hash_pt = (x,y) ->
tostring(x)..":"..tostring(y)
class SetList
new: => @contains = {}
add: (item) =>
return if @contains[item]
@contains[item] = true
self[#self+1] = item
class UniformGrid
new: (@cell_size=10) =>
@buckets = {}
add: (box) =>
for bucket, key in @buckets_for_box box, true
table.insert bucket, box
get_candidates: (query) =>
with SetList!
for bucket in @buckets_for_box query
for box in *bucket
\add box
bucket_for_pt: (x,y, insert=false) =>
x = math.floor x / @cell_size
y = math.floor y / @cell_size
key = hash_pt x, y
b = @buckets[key]
if not b and insert
b = {}
@buckets[key] = b
b, key
buckets_for_box: (box, insert=false) =>
coroutine.wrap ->
x1, y1, x2, y2 = box\unpack2!
x, y = x1, y1
while x < x2 + @cell_size
y = y1
while y < y2 + @cell_size
b, k = @bucket_for_pt x, y, insert
coroutine.yield b, k if b
y += @cell_size
x += @cell_size
if __test == true
import p from require "moon"
g = UniformGrid 100
g\add Box 90, 0, 20, 20
-- p g\get_candidates Box 0,0, 1,1