minigl 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +339 -0
- data/README.md +12 -0
- data/Rakefile +7 -0
- data/data/img/image.png +0 -0
- data/lib/minigl/forms.rb +365 -0
- data/lib/minigl/game_object.rb +100 -0
- data/lib/minigl/global.rb +220 -0
- data/lib/minigl/map.rb +81 -0
- data/lib/minigl/movement.rb +290 -0
- data/lib/minigl/text.rb +94 -0
- data/lib/minigl.rb +4 -0
- data/test/game_object_tests.rb +61 -0
- data/test/map_tests.rb +57 -0
- data/test/movement_tests.rb +86 -0
- metadata +80 -0
data/lib/minigl/map.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require_relative 'global'
|
2
|
+
|
3
|
+
module AGL
|
4
|
+
class Map
|
5
|
+
attr_reader :tile_size, :size, :cam
|
6
|
+
|
7
|
+
def initialize t_w, t_h, t_x_count, t_y_count, scr_w = 800, scr_h = 600
|
8
|
+
@tile_size = Vector.new t_w, t_h
|
9
|
+
@size = Vector.new t_x_count, t_y_count
|
10
|
+
@cam = Rectangle.new 0, 0, scr_w, scr_h
|
11
|
+
@max_x = t_x_count * t_w - scr_w
|
12
|
+
@max_y = t_y_count * t_h - scr_h
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_absolute_size
|
16
|
+
Vector.new(@tile_size.x * @size.x, @tile_size.y * @size.y)
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_center
|
20
|
+
Vector.new(@tile_size.x * @size.x / 2, @tile_size.y * @size.y / 2)
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_screen_pos map_x, map_y
|
24
|
+
Vector.new(map_x * @tile_size.x - @cam.x, map_y * @tile_size.y - @cam.y)
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_map_pos scr_x, scr_y
|
28
|
+
Vector.new((scr_x + @cam.x) / @tile_size.x, (scr_y + @cam.y) / @tile_size.y)
|
29
|
+
end
|
30
|
+
|
31
|
+
def is_in_map v
|
32
|
+
v.x >= 0 && v.y >= 0 && v.x < @size.x && v.y < @size.y
|
33
|
+
end
|
34
|
+
|
35
|
+
def set_camera cam_x, cam_y
|
36
|
+
@cam.x = cam_x
|
37
|
+
@cam.y = cam_y
|
38
|
+
set_bounds
|
39
|
+
end
|
40
|
+
|
41
|
+
def move_camera x, y
|
42
|
+
@cam.x += x
|
43
|
+
@cam.y += y
|
44
|
+
set_bounds
|
45
|
+
end
|
46
|
+
|
47
|
+
def set_bounds
|
48
|
+
@cam.x = @cam.x.round
|
49
|
+
@cam.y = @cam.y.round
|
50
|
+
@cam.x = 0 if @cam.x < 0
|
51
|
+
@cam.x = @max_x if @cam.x > @max_x
|
52
|
+
@cam.y = 0 if @cam.y < 0
|
53
|
+
@cam.y = @max_y if @cam.y > @max_y
|
54
|
+
|
55
|
+
@min_vis_x = @cam.x / @tile_size.x
|
56
|
+
@min_vis_y = @cam.y / @tile_size.y
|
57
|
+
@max_vis_x = (@cam.x + @cam.w - 1) / @tile_size.x
|
58
|
+
@max_vis_y = (@cam.y + @cam.h - 1) / @tile_size.y
|
59
|
+
|
60
|
+
if @min_vis_y < 0; @min_vis_y = 0
|
61
|
+
elsif @min_vis_y > @size.y - 1; @min_vis_y = @size.y - 1; end
|
62
|
+
|
63
|
+
if @max_vis_y < 0; @max_vis_y = 0
|
64
|
+
elsif @max_vis_y > @size.y - 1; @max_vis_y = @size.y - 1; end
|
65
|
+
|
66
|
+
if @min_vis_x < 0; @min_vis_x = 0
|
67
|
+
elsif @min_vis_x > @size.x - 1; @min_vis_x = @size.x - 1; end
|
68
|
+
|
69
|
+
if @max_vis_x < 0; @max_vis_x = 0
|
70
|
+
elsif @max_vis_x > @size.x - 1; @max_vis_x = @size.x - 1; end
|
71
|
+
end
|
72
|
+
|
73
|
+
def foreach
|
74
|
+
for j in @min_vis_y..@max_vis_y
|
75
|
+
for i in @min_vis_x..@max_vis_x
|
76
|
+
yield i, j, i * @tile_size.x - @cam.x, j * @tile_size.y - @cam.y
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,290 @@
|
|
1
|
+
require_relative 'global'
|
2
|
+
|
3
|
+
module AGL
|
4
|
+
class Block
|
5
|
+
attr_reader :x, :y, :w, :h, :passable
|
6
|
+
|
7
|
+
def initialize x, y, w, h, passable
|
8
|
+
@x = x; @y = y; @w = w; @h = h
|
9
|
+
@passable = passable
|
10
|
+
end
|
11
|
+
|
12
|
+
def bounds
|
13
|
+
Rectangle.new @x, @y, @w, @h
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Ramp
|
18
|
+
def initialize x, y, w, h, left
|
19
|
+
@x = x
|
20
|
+
@y = y
|
21
|
+
@w = w
|
22
|
+
@h = h
|
23
|
+
@left = left
|
24
|
+
end
|
25
|
+
|
26
|
+
def can_collide? obj
|
27
|
+
@can_collide = (obj.speed.y >= 0 and not intersects(obj))
|
28
|
+
end
|
29
|
+
|
30
|
+
def check_intersection obj
|
31
|
+
if @can_collide and intersects obj
|
32
|
+
obj.y = get_y obj
|
33
|
+
obj.speed.y = 0
|
34
|
+
# a = @w / @h
|
35
|
+
# x = get_x(obj)
|
36
|
+
# y = get_y(obj)
|
37
|
+
# w = obj.x - x
|
38
|
+
# h = obj.y - y
|
39
|
+
# dx = w * h / (w * a + h)
|
40
|
+
# dy = dx * a
|
41
|
+
#
|
42
|
+
# obj.x -= dx
|
43
|
+
# obj.y -= dy
|
44
|
+
# obj.speed.x *= (@w / (@w + @h))
|
45
|
+
# obj.speed.y = 0
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def contact? obj
|
50
|
+
obj.x.round(6) == get_x(obj).round(6) && obj.y.round(6) == get_y(obj).round(6)
|
51
|
+
end
|
52
|
+
|
53
|
+
def intersects obj
|
54
|
+
obj.x + obj.w > @x && obj.x < @x + @w && obj.y > get_y(obj) && obj.y <= @y + @h - obj.h
|
55
|
+
end
|
56
|
+
|
57
|
+
def get_x obj
|
58
|
+
return @x + (1.0 * (@y + @h - obj.y - obj.h) * @w / @h) - obj.w if @left
|
59
|
+
@x + (1.0 * (obj.y + obj.h - @y) * @w / @h)
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_y obj
|
63
|
+
return @y - obj.h if @left && obj.x + obj.w > @x + @w
|
64
|
+
return @y + (1.0 * (@x + @w - obj.x - obj.w) * @h / @w) - obj.h if @left
|
65
|
+
return @y - obj.h if obj.x < @x
|
66
|
+
@y + (1.0 * (obj.x - @x) * @h / @w) - obj.h
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
module Movement
|
71
|
+
attr_reader :speed, :w, :h, :passable, :top, :bottom, :left, :right
|
72
|
+
attr_accessor :x, :y, :stored_forces
|
73
|
+
|
74
|
+
def bounds
|
75
|
+
Rectangle.new @x, @y, @w, @h
|
76
|
+
end
|
77
|
+
|
78
|
+
def move forces, obst, ramps
|
79
|
+
forces.x += Game.gravity.x; forces.y += Game.gravity.y
|
80
|
+
forces.x += @stored_forces.x; forces.y += @stored_forces.y
|
81
|
+
@stored_forces.x = @stored_forces.y = 0
|
82
|
+
|
83
|
+
# check_contact obst, ramps
|
84
|
+
forces.x = 0 if (forces.x < 0 and @left) or (forces.x > 0 and @right)
|
85
|
+
forces.y = 0 if (forces.y < 0 and @top) or (forces.y > 0 and @bottom)
|
86
|
+
|
87
|
+
@speed.x += forces.x; @speed.y += forces.y
|
88
|
+
@speed.x = 0 if @speed.x.abs < @min_speed.x
|
89
|
+
@speed.y = 0 if @speed.y.abs < @min_speed.y
|
90
|
+
@speed.x = (@speed.x <=> 0) * @max_speed.x if @speed.x.abs > @max_speed.x
|
91
|
+
@speed.y = (@speed.y <=> 0) * @max_speed.y if @speed.y.abs > @max_speed.y
|
92
|
+
|
93
|
+
ramps.each do |r|
|
94
|
+
r.can_collide? self
|
95
|
+
end
|
96
|
+
|
97
|
+
x = @speed.x < 0 ? @x + @speed.x : @x
|
98
|
+
y = @speed.y < 0 ? @y + @speed.y : @y
|
99
|
+
w = @w + (@speed.x < 0 ? -@speed.x : @speed.x)
|
100
|
+
h = @h + (@speed.y < 0 ? -@speed.y : @speed.y)
|
101
|
+
move_bounds = Rectangle.new x, y, w, h
|
102
|
+
coll_list = []
|
103
|
+
obst.each do |o|
|
104
|
+
coll_list << o if move_bounds.intersects o.bounds
|
105
|
+
end
|
106
|
+
|
107
|
+
if coll_list.length > 0
|
108
|
+
up = @speed.y < 0; rt = @speed.x > 0; dn = @speed.y > 0; lf = @speed.x < 0
|
109
|
+
if @speed.x == 0 || @speed.y == 0
|
110
|
+
# Ortogonal
|
111
|
+
if rt; x_lim = find_right_limit coll_list
|
112
|
+
elsif lf; x_lim = find_left_limit coll_list
|
113
|
+
elsif dn; y_lim = find_down_limit coll_list
|
114
|
+
elsif up; y_lim = find_up_limit coll_list
|
115
|
+
end
|
116
|
+
if rt && @x + @w + @speed.x > x_lim; @x = x_lim - @w; @speed.x = 0
|
117
|
+
elsif lf && @x + @speed.x < x_lim; @x = x_lim; @speed.x = 0
|
118
|
+
elsif dn && @y + @h + @speed.y > y_lim; @y = y_lim - @h; @speed.y = 0
|
119
|
+
elsif up && @y + @speed.y < y_lim; @y = y_lim; @speed.y = 0
|
120
|
+
end
|
121
|
+
else
|
122
|
+
# Diagonal
|
123
|
+
x_aim = @x + @speed.x + (rt ? @w : 0); x_lim_def = x_aim
|
124
|
+
y_aim = @y + @speed.y + (dn ? @h : 0); y_lim_def = y_aim
|
125
|
+
coll_list.each do |c|
|
126
|
+
if c.passable; x_lim = x_aim
|
127
|
+
elsif rt; x_lim = c.x
|
128
|
+
else; x_lim = c.x + c.w
|
129
|
+
end
|
130
|
+
if dn; y_lim = c.y
|
131
|
+
elsif c.passable; y_lim = y_aim
|
132
|
+
else; y_lim = c.y + c.h
|
133
|
+
end
|
134
|
+
|
135
|
+
if c.passable
|
136
|
+
y_lim_def = y_lim if dn && @y + @h <= y_lim && y_lim < y_lim_def
|
137
|
+
elsif (rt && @x + @w > x_lim) || (lf && @x < x_lim)
|
138
|
+
# Can't limit by x, will limit by y
|
139
|
+
y_lim_def = y_lim if (dn && y_lim < y_lim_def) || (up && y_lim > y_lim_def)
|
140
|
+
elsif (dn && @y + @h > y_lim) || (up && @y < y_lim)
|
141
|
+
# Can't limit by y, will limit by x
|
142
|
+
x_lim_def = x_lim if (rt && x_lim < x_lim_def) || (lf && x_lim > x_lim_def)
|
143
|
+
else
|
144
|
+
xTime = 1.0 * (x_lim - @x - (@speed.x < 0 ? 0 : @w)) / @speed.x
|
145
|
+
yTime = 1.0 * (y_lim - @y - (@speed.y < 0 ? 0 : @h)) / @speed.y
|
146
|
+
if xTime > yTime
|
147
|
+
# Will limit by x
|
148
|
+
x_lim_def = x_lim if (rt && x_lim < x_lim_def) || (lf && x_lim > x_lim_def)
|
149
|
+
elsif (dn && y_lim < y_lim_def) || (up && y_lim > y_lim_def)
|
150
|
+
y_lim_def = y_lim
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
if x_lim_def != x_aim
|
155
|
+
@speed.x = 0
|
156
|
+
if lf; @x = x_lim_def
|
157
|
+
else; @x = x_lim_def - @w
|
158
|
+
end
|
159
|
+
end
|
160
|
+
if y_lim_def != y_aim
|
161
|
+
@speed.y = 0
|
162
|
+
if up; @y = y_lim_def
|
163
|
+
else; @y = y_lim_def - @h
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
@x += @speed.x
|
169
|
+
@y += @speed.y
|
170
|
+
|
171
|
+
ramps.each do |r|
|
172
|
+
r.check_intersection self
|
173
|
+
end
|
174
|
+
check_contact obst, ramps
|
175
|
+
end
|
176
|
+
def check_contact obst, ramps
|
177
|
+
@top = @bottom = @left = @right = nil
|
178
|
+
obst.each do |o|
|
179
|
+
x2 = @x + @w; y2 = @y + @h; x2o = o.x + o.w; y2o = o.y + o.h
|
180
|
+
@right = o if !o.passable && x2.round(6) == o.x.round(6) && y2 > o.y && @y < y2o
|
181
|
+
@left = o if !o.passable && @x.round(6) == x2o.round(6) && y2 > o.y && @y < y2o
|
182
|
+
@bottom = o if y2.round(6) == o.y.round(6) && x2 > o.x && @x < x2o
|
183
|
+
@top = o if !o.passable && @y.round(6) == y2o.round(6) && x2 > o.x && @x < x2o
|
184
|
+
end
|
185
|
+
if @bottom.nil?
|
186
|
+
ramps.each do |r|
|
187
|
+
if r.contact? self
|
188
|
+
@bottom = r
|
189
|
+
break
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
def find_right_limit coll_list
|
195
|
+
limit = @x + @w + @speed.x
|
196
|
+
coll_list.each do |c|
|
197
|
+
limit = c.x if !c.passable && c.x < limit
|
198
|
+
end
|
199
|
+
limit
|
200
|
+
end
|
201
|
+
def find_left_limit coll_list
|
202
|
+
limit = @x + @speed.x
|
203
|
+
coll_list.each do |c|
|
204
|
+
limit = c.x + c.w if !c.passable && c.x + c.w > limit
|
205
|
+
end
|
206
|
+
limit
|
207
|
+
end
|
208
|
+
def find_down_limit coll_list
|
209
|
+
limit = @y + @h + @speed.y
|
210
|
+
coll_list.each do |c|
|
211
|
+
limit = c.y if c.y < limit && c.y >= @y + @h
|
212
|
+
end
|
213
|
+
limit
|
214
|
+
end
|
215
|
+
def find_up_limit coll_list
|
216
|
+
limit = @y + @speed.y
|
217
|
+
coll_list.each do |c|
|
218
|
+
limit = c.y + c.h if !c.passable && c.y + c.h > limit
|
219
|
+
end
|
220
|
+
limit
|
221
|
+
end
|
222
|
+
|
223
|
+
def move_carrying aim, speed, obstacles
|
224
|
+
x_d = aim.x - @x; y_d = aim.y - @y
|
225
|
+
distance = Math.sqrt(x_d**2 + y_d**2)
|
226
|
+
@speed.x = 1.0 * x_d * speed / distance
|
227
|
+
@speed.y = 1.0 * y_d * speed / distance
|
228
|
+
|
229
|
+
x_aim = @x + @speed.x; y_aim = @y + @speed.y
|
230
|
+
passengers = []
|
231
|
+
obstacles.each do |o|
|
232
|
+
if @x + @w > o.x && o.x + o.w > @x
|
233
|
+
foot = o.y + o.h
|
234
|
+
if foot.round(6) == @y.round(6) || @speed.y < 0 && foot < @y && foot > y_aim
|
235
|
+
passengers << o
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
if @speed.x > 0 && x_aim >= aim.x || @speed.x < 0 && x_aim <= aim.x
|
241
|
+
passengers.each do |p| p.x += aim.x - @x end
|
242
|
+
@x = aim.x; @speed.x = 0
|
243
|
+
else
|
244
|
+
passengers.each do |p| p.x += @speed.x end
|
245
|
+
@x = x_aim
|
246
|
+
end
|
247
|
+
if @speed.y > 0 && y_aim >= aim.y || @speed.y < 0 && y_aim <= aim.y
|
248
|
+
@y = aim.y; @speed.y = 0
|
249
|
+
else
|
250
|
+
@y = y_aim
|
251
|
+
end
|
252
|
+
|
253
|
+
passengers.each do |p| p.y = @y - p.h end
|
254
|
+
end
|
255
|
+
|
256
|
+
def move_free aim, speed
|
257
|
+
x_d = aim.x - @x; y_d = aim.y - @y
|
258
|
+
distance = Math.sqrt(x_d**2 + y_d**2)
|
259
|
+
@speed.x = 1.0 * x_d * speed / distance
|
260
|
+
@speed.y = 1.0 * y_d * speed / distance
|
261
|
+
|
262
|
+
if (@speed.x < 0 and @x + @speed.x <= aim.x) or (@speed.x >= 0 and @x + @speed.x >= aim.x)
|
263
|
+
@x = aim.x
|
264
|
+
@speed.x = 0
|
265
|
+
else
|
266
|
+
@x += @speed.x
|
267
|
+
end
|
268
|
+
|
269
|
+
if (@speed.y < 0 and @y + @speed.y <= aim.y) or (@speed.y >= 0 and @y + @speed.y >= aim.y)
|
270
|
+
@y = aim.y
|
271
|
+
@speed.y = 0
|
272
|
+
else
|
273
|
+
@y += @speed.y
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
def cycle points, cur_point, speed, obstacles = nil
|
278
|
+
if obstacles
|
279
|
+
move_carrying points[cur_point], speed, obstacles
|
280
|
+
else
|
281
|
+
move_free points[cur_point], speed
|
282
|
+
end
|
283
|
+
if @speed.x == 0 and @speed.y == 0
|
284
|
+
if cur_point == points.length - 1; cur_point = 0
|
285
|
+
else; cur_point += 1; end
|
286
|
+
end
|
287
|
+
cur_point
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
data/lib/minigl/text.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
module AGL
|
2
|
+
class TextHelper
|
3
|
+
def initialize font, line_spacing = 0
|
4
|
+
@font = font
|
5
|
+
@line_spacing = line_spacing
|
6
|
+
end
|
7
|
+
|
8
|
+
def write_line text, x, y, mode = :left, color = 0xffffffff
|
9
|
+
rel =
|
10
|
+
case mode
|
11
|
+
when :left then 0
|
12
|
+
when :center then 0.5
|
13
|
+
when :right then 1
|
14
|
+
else 0
|
15
|
+
end
|
16
|
+
@font.draw_rel text, x, y, 0, rel, 0, 1, 1, color
|
17
|
+
end
|
18
|
+
|
19
|
+
def write_breaking text, x, y, width, mode = :left, color = 0xffffffff
|
20
|
+
text.split("\n").each do |p|
|
21
|
+
if mode == :justified
|
22
|
+
y = write_paragraph_justified p, x, y, width, color
|
23
|
+
else
|
24
|
+
rel =
|
25
|
+
case mode
|
26
|
+
when :left then 0
|
27
|
+
when :center then 0.5
|
28
|
+
when :right then 1
|
29
|
+
else 0
|
30
|
+
end
|
31
|
+
y = write_paragraph p, x, y, width, rel, color
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def write_paragraph text, x, y, width, rel, color
|
37
|
+
line = ""
|
38
|
+
line_width = 0
|
39
|
+
text.split(' ').each do |word|
|
40
|
+
w = @font.text_width word
|
41
|
+
if line_width + w > width
|
42
|
+
@font.draw_rel line.chop, x, y, 0, rel, 0, 1, 1, color
|
43
|
+
line = ""
|
44
|
+
line_width = 0
|
45
|
+
y += @font.height + @line_spacing
|
46
|
+
end
|
47
|
+
line += "#{word} "
|
48
|
+
line_width += @font.text_width "#{word} "
|
49
|
+
end
|
50
|
+
@font.draw_rel line.chop, x, y, 0, rel, 0, 1, 1, color if not line.empty?
|
51
|
+
y + @font.height + @line_spacing
|
52
|
+
end
|
53
|
+
|
54
|
+
def write_paragraph_justified text, x, y, width, color
|
55
|
+
space_width = @font.text_width " "
|
56
|
+
spaces = [[]]
|
57
|
+
line_index = 0
|
58
|
+
new_x = x
|
59
|
+
words = text.split(' ')
|
60
|
+
words.each do |word|
|
61
|
+
w = @font.text_width word
|
62
|
+
if new_x + w > x + width
|
63
|
+
space = x + width - new_x + space_width
|
64
|
+
index = 0
|
65
|
+
while space > 0
|
66
|
+
spaces[line_index][index] += 1
|
67
|
+
space -= 1
|
68
|
+
index += 1
|
69
|
+
index = 0 if index == spaces[line_index].size - 1
|
70
|
+
end
|
71
|
+
|
72
|
+
spaces << []
|
73
|
+
line_index += 1
|
74
|
+
|
75
|
+
new_x = x
|
76
|
+
end
|
77
|
+
new_x += @font.text_width(word) + space_width
|
78
|
+
spaces[line_index] << space_width
|
79
|
+
end
|
80
|
+
|
81
|
+
index = 0
|
82
|
+
spaces.each do |line|
|
83
|
+
new_x = x
|
84
|
+
line.each do |s|
|
85
|
+
@font.draw words[index], new_x, y, 0, 1, 1, color
|
86
|
+
new_x += @font.text_width(words[index]) + s
|
87
|
+
index += 1
|
88
|
+
end
|
89
|
+
y += @font.height + @line_spacing
|
90
|
+
end
|
91
|
+
y
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/minigl.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require_relative '../lib/minigl'
|
3
|
+
include AGL
|
4
|
+
|
5
|
+
class SpriteTest < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@window = Gosu::Window.new 800, 600, false
|
8
|
+
Game.initialize @window
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_sprite_position
|
12
|
+
s = Sprite.new 10, 20, :image
|
13
|
+
assert_equal 10, s.x
|
14
|
+
assert_equal 20, s.y
|
15
|
+
s = Sprite.new -100, 200, :image
|
16
|
+
assert_equal -100, s.x
|
17
|
+
assert_equal 200, s.y
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_sprite_animation
|
21
|
+
s = Sprite.new 10, 20, :image, 3, 1
|
22
|
+
indices = [0, 1, 2]
|
23
|
+
interval = 1
|
24
|
+
3.times { s.animate indices, interval }
|
25
|
+
assert_equal 0, s.img_index
|
26
|
+
5.times { s.animate indices, interval }
|
27
|
+
assert_equal 2, s.img_index
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class GameObjectTest < Test::Unit::TestCase
|
32
|
+
def setup
|
33
|
+
@window = Gosu::Window.new 800, 600, false
|
34
|
+
Game.initialize @window
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_game_object_attributes
|
38
|
+
o = GameObject.new 10, 20, 3, 1, :image
|
39
|
+
assert_equal 10, o.x
|
40
|
+
assert_equal 20, o.y
|
41
|
+
assert_equal 3, o.w
|
42
|
+
assert_equal 1, o.h
|
43
|
+
assert_equal 0, o.speed.x
|
44
|
+
assert_equal 0, o.speed.y
|
45
|
+
assert_equal 0, o.stored_forces.x
|
46
|
+
assert_equal 0, o.stored_forces.y
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_game_object_animation
|
50
|
+
o = GameObject.new 10, 20, 3, 1, :image, nil, 3, 1
|
51
|
+
indices = [0, 1, 2]
|
52
|
+
interval = 10
|
53
|
+
5.times { o.animate indices, interval }
|
54
|
+
assert_equal 0, o.img_index
|
55
|
+
o.set_animation 0
|
56
|
+
5.times { o.animate indices, interval }
|
57
|
+
assert_equal 0, o.img_index
|
58
|
+
5.times { o.animate indices, interval }
|
59
|
+
assert_equal 1, o.img_index
|
60
|
+
end
|
61
|
+
end
|
data/test/map_tests.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require_relative '../lib/minigl'
|
3
|
+
include AGL
|
4
|
+
|
5
|
+
class MapTest < Test::Unit::TestCase
|
6
|
+
def test_map_attributes
|
7
|
+
m = Map.new 16, 16, 300, 200
|
8
|
+
assert_equal 16, m.tile_size.x
|
9
|
+
assert_equal 16, m.tile_size.y
|
10
|
+
assert_equal 300, m.size.x
|
11
|
+
assert_equal 200, m.size.y
|
12
|
+
assert_equal 0, m.cam.x
|
13
|
+
assert_equal 0, m.cam.y
|
14
|
+
m = Map.new 25, 17, 49, 133
|
15
|
+
assert_equal 25, m.tile_size.x
|
16
|
+
assert_equal 17, m.tile_size.y
|
17
|
+
assert_equal 49, m.size.x
|
18
|
+
assert_equal 133, m.size.y
|
19
|
+
assert_equal 0, m.cam.x
|
20
|
+
assert_equal 0, m.cam.y
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_absolute_size
|
24
|
+
m = Map.new 16, 16, 300, 200
|
25
|
+
v = m.get_absolute_size
|
26
|
+
assert_equal 300 * 16, v.x
|
27
|
+
assert_equal 200 * 16, v.y
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_center
|
31
|
+
m = Map.new 16, 16, 300, 200
|
32
|
+
v = m.get_center
|
33
|
+
assert_equal 300 * 16 / 2, v.x
|
34
|
+
assert_equal 200 * 16 / 2, v.y
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_screen_pos
|
38
|
+
m = Map.new 16, 16, 300, 200
|
39
|
+
v = m.get_screen_pos 8, 5
|
40
|
+
assert_equal 8 * 16, v.x
|
41
|
+
assert_equal 5 * 16, v.y
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_map_pos
|
45
|
+
m = Map.new 16, 16, 300, 200
|
46
|
+
v = m.get_map_pos 410, 300
|
47
|
+
assert_equal 25, v.x
|
48
|
+
assert_equal 18, v.y
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_in_map
|
52
|
+
m = Map.new 16, 16, 300, 200
|
53
|
+
assert m.is_in_map(Vector.new 30, 20)
|
54
|
+
assert m.is_in_map(Vector.new 299, 199)
|
55
|
+
assert !m.is_in_map(Vector.new 300, 200)
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require_relative '../lib/minigl'
|
3
|
+
include AGL
|
4
|
+
|
5
|
+
class MovingObject
|
6
|
+
include Movement
|
7
|
+
def initialize x, y, w, h
|
8
|
+
@x = x; @y = y; @w = w; @h = h
|
9
|
+
@speed = Vector.new 0, 0
|
10
|
+
@min_speed = Vector.new 0.01, 0.01
|
11
|
+
@max_speed = Vector.new 1000, 1000
|
12
|
+
@stored_forces = Vector.new 0, 0
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class MovementTest < Test::Unit::TestCase
|
17
|
+
def setup
|
18
|
+
@window = Gosu::Window.new 800, 600, false
|
19
|
+
Game.initialize @window
|
20
|
+
@obsts = [
|
21
|
+
Block.new(-1, 0, 1, 600, false),
|
22
|
+
Block.new(0, -1, 800, 1, false),
|
23
|
+
Block.new(800, 0, 1, 600, false),
|
24
|
+
Block.new(0, 600, 800, 1, false),
|
25
|
+
Block.new(280, 560, 40, 40, true)
|
26
|
+
]
|
27
|
+
@ramps = [
|
28
|
+
Ramp.new(600, 500, 200, 100, true),
|
29
|
+
Ramp.new(0, 500, 200, 100, false)
|
30
|
+
]
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_fall
|
34
|
+
o = MovingObject.new 480, 280, 40, 40
|
35
|
+
forces = Vector.new 0, 0
|
36
|
+
1000.times { o.move forces, @obsts, @ramps }
|
37
|
+
assert_equal 480, o.x
|
38
|
+
assert_equal 560, o.y
|
39
|
+
assert_equal 0, o.speed.x
|
40
|
+
assert_equal 0, o.speed.y
|
41
|
+
assert_equal @obsts[3], o.bottom
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_multiple_collision
|
45
|
+
o = MovingObject.new 750, 10, 40, 40
|
46
|
+
forces = Vector.new 50, -60
|
47
|
+
o.move forces, @obsts, @ramps
|
48
|
+
assert_equal 760, o.x
|
49
|
+
assert_equal 0, o.y
|
50
|
+
assert_equal 0, o.speed.x
|
51
|
+
assert_equal 0, o.speed.y
|
52
|
+
assert_equal @obsts[1], o.top
|
53
|
+
assert_equal @obsts[2], o.right
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_passable
|
57
|
+
o = MovingObject.new 480, 560, 40, 40
|
58
|
+
forces = Vector.new -250, 0
|
59
|
+
o.move forces, @obsts, @ramps
|
60
|
+
assert(o.x < @obsts[4].x)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_left_ramp
|
64
|
+
o = MovingObject.new 380, 560, 40, 40
|
65
|
+
forces = Vector.new 10, 0
|
66
|
+
1000.times { o.move forces, @obsts, @ramps }
|
67
|
+
assert_equal 760, o.x
|
68
|
+
assert_equal 460, o.y
|
69
|
+
assert_equal 0, o.speed.x
|
70
|
+
assert_equal 0, o.speed.y
|
71
|
+
assert_equal @obsts[2], o.right
|
72
|
+
assert_equal @ramps[0], o.bottom
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_right_ramp
|
76
|
+
o = MovingObject.new 380, 560, 40, 40
|
77
|
+
forces = Vector.new -10, 0
|
78
|
+
1000.times { o.move forces, @obsts, @ramps }
|
79
|
+
assert_equal 0, o.x
|
80
|
+
assert_equal 460, o.y
|
81
|
+
assert_equal 0, o.speed.x
|
82
|
+
assert_equal 0, o.speed.y
|
83
|
+
assert_equal @obsts[0], o.left
|
84
|
+
assert_equal @ramps[1], o.bottom
|
85
|
+
end
|
86
|
+
end
|