minigl 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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