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.
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
@@ -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,4 @@
1
+ require_relative 'minigl/game_object'
2
+ require_relative 'minigl/map'
3
+ require_relative 'minigl/text'
4
+ require_relative 'minigl/forms'
@@ -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