minigl 1.3.7 → 1.3.8
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 +4 -4
- data/README.md +9 -4
- data/lib/minigl/forms.rb +694 -698
- data/lib/minigl/game_object.rb +250 -255
- data/lib/minigl/global.rb +470 -470
- data/lib/minigl/map.rb +153 -155
- data/lib/minigl/movement.rb +467 -467
- data/lib/minigl/text.rb +141 -141
- data/test/game_object_tests.rb +48 -48
- data/test/iso_game.rb +27 -27
- data/test/map_tests.rb +51 -51
- data/test/movement_tests.rb +78 -78
- data/test/res_tests.rb +15 -15
- metadata +2 -2
data/lib/minigl/map.rb
CHANGED
@@ -1,47 +1,45 @@
|
|
1
1
|
require_relative 'global'
|
2
2
|
|
3
3
|
module AGL
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
# :nodoc:
|
9
|
-
|
10
|
-
# :nodoc:
|
11
|
-
MinusPiDiv4 = -Math::PI / 4
|
4
|
+
# This class provides easy control of a tile map, i.e., a map consisting of
|
5
|
+
# a grid of equally sized tiles. It also provides viewport control, through
|
6
|
+
# its camera property and methods.
|
7
|
+
class Map
|
8
|
+
Sqrt2Div2 = Math.sqrt(2) / 2 # :nodoc:
|
9
|
+
MinusPiDiv4 = -Math::PI / 4 # :nodoc:
|
12
10
|
|
13
|
-
|
14
|
-
|
11
|
+
# A Vector where x is the tile width and y is the tile height.
|
12
|
+
attr_reader :tile_size
|
15
13
|
|
16
|
-
|
17
|
-
|
14
|
+
# A Vector where x is the horizontal tile count and y the vertical count.
|
15
|
+
attr_reader :size
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
# A Rectangle representing the region of the map that is currently
|
18
|
+
# visible.
|
19
|
+
attr_reader :cam
|
22
20
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
21
|
+
# Creates a new map.
|
22
|
+
#
|
23
|
+
# Parameters:
|
24
|
+
# [t_w] The width of the tiles.
|
25
|
+
# [t_h] The height of the tiles.
|
26
|
+
# [t_x_count] The horizontal count of tiles in the map.
|
27
|
+
# [t_y_count] The vertical count of tiles in the map.
|
28
|
+
# [scr_w] Width of the viewport for the map.
|
29
|
+
# [scr_h] Height of the viewport for the map.
|
32
30
|
# [isometric] Whether to use a isometric map. By default, an ortogonal map
|
33
31
|
# is used.
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
32
|
+
# [limit_cam] Whether the camera should respect the bounds of the map
|
33
|
+
# (i.e., when given coordinates that would imply regions
|
34
|
+
# outside the map to appear in the screen, the camera would
|
35
|
+
# move to the nearest position where only the map shows up
|
36
|
+
# in the screen).
|
37
|
+
def initialize t_w, t_h, t_x_count, t_y_count, scr_w = 800, scr_h = 600, isometric = false, limit_cam = true
|
38
|
+
@tile_size = Vector.new t_w, t_h
|
39
|
+
@size = Vector.new t_x_count, t_y_count
|
40
|
+
@cam = Rectangle.new 0, 0, scr_w, scr_h
|
41
|
+
@limit_cam = limit_cam
|
42
|
+
@isometric = isometric
|
45
43
|
if isometric
|
46
44
|
initialize_isometric
|
47
45
|
elsif limit_cam
|
@@ -49,116 +47,115 @@ module AGL
|
|
49
47
|
@max_y = t_y_count * t_h - scr_h
|
50
48
|
end
|
51
49
|
set_camera 0, 0
|
52
|
-
|
50
|
+
end
|
53
51
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
52
|
+
# Returns a Vector with the total size of the map, in pixels (x for the
|
53
|
+
# width and y for the height).
|
54
|
+
def get_absolute_size
|
55
|
+
return Vector.new(@tile_size.x * @size.x, @tile_size.y * @size.y) unless @isometric
|
56
|
+
avg = (@size.x + @size.y) * 0.5
|
57
|
+
Vector.new (avg * @tile_size.x).to_i, (avg * @tile_size.y).to_i
|
58
|
+
end
|
61
59
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
60
|
+
# Returns a Vector with the coordinates of the center of the map.
|
61
|
+
def get_center
|
62
|
+
abs_size = get_absolute_size
|
63
|
+
Vector.new(abs_size.x * 0.5, abs_size.y * 0.5)
|
64
|
+
end
|
67
65
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
66
|
+
# Returns the position in the screen corresponding to the given tile
|
67
|
+
# indices.
|
68
|
+
#
|
69
|
+
# Parameters:
|
70
|
+
# [map_x] The index of the tile in the horizontal direction. It must be in
|
71
|
+
# the interval <code>0..t_x_count</code>.
|
72
|
+
# [map_y] The index of the tile in the vertical direction. It must be in
|
73
|
+
# the interval <code>0..t_y_count</code>.
|
74
|
+
def get_screen_pos map_x, map_y
|
75
|
+
return Vector.new(map_x * @tile_size.x - @cam.x, map_y * @tile_size.y - @cam.y) unless @isometric
|
76
|
+
Vector.new ((map_x - map_y - 1) * @tile_size.x * 0.5) - @cam.x + @x_offset,
|
77
|
+
((map_x + map_y) * @tile_size.y * 0.5) - @cam.y
|
78
|
+
end
|
81
79
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
80
|
+
# Returns the tile in the map that corresponds to the given position in
|
81
|
+
# the screen, as a Vector, where x is the horizontal index and y the
|
82
|
+
# vertical index.
|
83
|
+
#
|
84
|
+
# Parameters:
|
85
|
+
# [scr_x] The x-coordinate in the screen.
|
86
|
+
# [scr_y] The y-coordinate in the screen.
|
87
|
+
def get_map_pos scr_x, scr_y
|
88
|
+
return Vector.new((scr_x + @cam.x) / @tile_size.x, (scr_y + @cam.y) / @tile_size.y) unless @isometric
|
91
89
|
|
92
90
|
# Obtém a posição transformada para as coordenadas isométricas
|
93
|
-
|
94
|
-
|
95
|
-
# Depois divide pelo tamanho do quadrado para achar a posição da matriz
|
96
|
-
Vector.new((v.x * @inverse_square_size).to_i, (v.y * @inverse_square_size).to_i)
|
97
|
-
end
|
91
|
+
v = get_isometric_position scr_x, scr_y
|
98
92
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
# [v] A Vector representing the tile, with x as the horizontal index and
|
103
|
-
# y as the vertical index.
|
104
|
-
def is_in_map v
|
105
|
-
v.x >= 0 && v.y >= 0 && v.x < @size.x && v.y < @size.y
|
106
|
-
end
|
93
|
+
# Depois divide pelo tamanho do quadrado para achar a posição da matriz
|
94
|
+
Vector.new((v.x * @inverse_square_size).to_i, (v.y * @inverse_square_size).to_i)
|
95
|
+
end
|
107
96
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
@cam.y = cam_y
|
117
|
-
set_bounds
|
118
|
-
end
|
97
|
+
# Verifies whether a tile is inside the map.
|
98
|
+
#
|
99
|
+
# Parameters:
|
100
|
+
# [v] A Vector representing the tile, with x as the horizontal index and
|
101
|
+
# y as the vertical index.
|
102
|
+
def is_in_map v
|
103
|
+
v.x >= 0 && v.y >= 0 && v.x < @size.x && v.y < @size.y
|
104
|
+
end
|
119
105
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
end
|
106
|
+
# Sets the top left corner of the viewport to the given position of the
|
107
|
+
# map. Note that this is not the position in the screen.
|
108
|
+
#
|
109
|
+
# Parameters:
|
110
|
+
# [cam_x] The x-coordinate inside the map, in pixels (not a tile index).
|
111
|
+
# [cam_y] The y-coordinate inside the map, in pixels (not a tile index).
|
112
|
+
def set_camera cam_x, cam_y
|
113
|
+
@cam.x = cam_x
|
114
|
+
@cam.y = cam_y
|
115
|
+
set_bounds
|
116
|
+
end
|
132
117
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
for i in @min_vis_x..@max_vis_x
|
146
|
-
pos = get_screen_pos i, j
|
147
|
-
yield i, j, pos.x, pos.y
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
118
|
+
# Moves the viewport by the given amount of pixels.
|
119
|
+
#
|
120
|
+
# Parameters:
|
121
|
+
# [x] The amount of pixels to move horizontally. Negative values will
|
122
|
+
# cause the camera to move to the left.
|
123
|
+
# [y] The amount of pixels to move vertically. Negative values will cause
|
124
|
+
# the camera to move up.
|
125
|
+
def move_camera x, y
|
126
|
+
@cam.x += x
|
127
|
+
@cam.y += y
|
128
|
+
set_bounds
|
129
|
+
end
|
151
130
|
|
152
|
-
|
131
|
+
# Iterates through the currently visible tiles, providing the horizontal
|
132
|
+
# tile index, the vertical tile index, the x-coordinate (in pixels) and
|
133
|
+
# the y-coordinate (in pixels), of each tile, in that order, to a given
|
134
|
+
# block of code.
|
135
|
+
#
|
136
|
+
# Example:
|
137
|
+
#
|
138
|
+
# map.foreach do |i, j, x, y|
|
139
|
+
# draw_tile tiles[i][j], x, y
|
140
|
+
# end
|
141
|
+
def foreach
|
142
|
+
for j in @min_vis_y..@max_vis_y
|
143
|
+
for i in @min_vis_x..@max_vis_x
|
144
|
+
pos = get_screen_pos i, j
|
145
|
+
yield i, j, pos.x, pos.y
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
153
149
|
|
154
|
-
|
155
|
-
if @isometric
|
156
|
-
v1 = get_isometric_position(0, 0)
|
157
|
-
v2 = get_isometric_position(@cam.w - 1, 0)
|
158
|
-
v3 = get_isometric_position(@cam.w - 1, @cam.h - 1)
|
159
|
-
v4 = get_isometric_position(0, @cam.h - 1)
|
150
|
+
private
|
160
151
|
|
161
|
-
|
152
|
+
def set_bounds
|
153
|
+
if @limit_cam
|
154
|
+
if @isometric
|
155
|
+
v1 = get_isometric_position(0, 0)
|
156
|
+
v2 = get_isometric_position(@cam.w - 1, 0)
|
157
|
+
v3 = get_isometric_position(@cam.w - 1, @cam.h - 1)
|
158
|
+
v4 = get_isometric_position(0, @cam.h - 1)
|
162
159
|
if v1.x < -@max_offset
|
163
160
|
offset = -(v1.x + @max_offset)
|
164
161
|
@cam.x += offset * Sqrt2Div2
|
@@ -183,39 +180,40 @@ module AGL
|
|
183
180
|
@cam.y -= offset * Sqrt2Div2 / @tile_ratio
|
184
181
|
v4.y = @iso_abs_size.y + @max_offset
|
185
182
|
end
|
186
|
-
|
187
|
-
|
188
|
-
@min_vis_x = get_map_pos(0, 0).x
|
189
|
-
@min_vis_y = get_map_pos(@cam.w - 1, 0).y
|
190
|
-
@max_vis_x = get_map_pos(@cam.w - 1, @cam.h - 1).x
|
191
|
-
@max_vis_y = get_map_pos(0, @cam.h - 1).y
|
192
|
-
else
|
193
|
-
if @limit_cam
|
183
|
+
else
|
194
184
|
@cam.x = 0 if @cam.x < 0
|
195
185
|
@cam.x = @max_x if @cam.x > @max_x
|
196
186
|
@cam.y = 0 if @cam.y < 0
|
197
187
|
@cam.y = @max_y if @cam.y > @max_y
|
198
188
|
end
|
199
|
-
|
200
|
-
|
201
|
-
@max_vis_x = (@cam.x + @cam.w - 1) / @tile_size.x
|
202
|
-
@max_vis_y = (@cam.y + @cam.h - 1) / @tile_size.y
|
203
|
-
end
|
189
|
+
end
|
190
|
+
|
204
191
|
@cam.x = @cam.x.round
|
205
192
|
@cam.y = @cam.y.round
|
193
|
+
if @isometric
|
194
|
+
@min_vis_x = get_map_pos(0, 0).x
|
195
|
+
@min_vis_y = get_map_pos(@cam.w - 1, 0).y
|
196
|
+
@max_vis_x = get_map_pos(@cam.w - 1, @cam.h - 1).x
|
197
|
+
@max_vis_y = get_map_pos(0, @cam.h - 1).y
|
198
|
+
else
|
199
|
+
@min_vis_x = @cam.x / @tile_size.x
|
200
|
+
@min_vis_y = @cam.y / @tile_size.y
|
201
|
+
@max_vis_x = (@cam.x + @cam.w - 1) / @tile_size.x
|
202
|
+
@max_vis_y = (@cam.y + @cam.h - 1) / @tile_size.y
|
203
|
+
end
|
206
204
|
|
207
|
-
|
208
|
-
|
205
|
+
if @min_vis_y < 0; @min_vis_y = 0
|
206
|
+
elsif @min_vis_y > @size.y - 1; @min_vis_y = @size.y - 1; end
|
209
207
|
|
210
|
-
|
211
|
-
|
208
|
+
if @max_vis_y < 0; @max_vis_y = 0
|
209
|
+
elsif @max_vis_y > @size.y - 1; @max_vis_y = @size.y - 1; end
|
212
210
|
|
213
|
-
|
214
|
-
|
211
|
+
if @min_vis_x < 0; @min_vis_x = 0
|
212
|
+
elsif @min_vis_x > @size.x - 1; @min_vis_x = @size.x - 1; end
|
215
213
|
|
216
|
-
|
217
|
-
|
218
|
-
|
214
|
+
if @max_vis_x < 0; @max_vis_x = 0
|
215
|
+
elsif @max_vis_x > @size.x - 1; @max_vis_x = @size.x - 1; end
|
216
|
+
end
|
219
217
|
|
220
218
|
def initialize_isometric
|
221
219
|
@x_offset = (@size.y * 0.5 * @tile_size.x).round
|
@@ -254,5 +252,5 @@ module AGL
|
|
254
252
|
position.x -= @isometric_offset_x; position.y -= @isometric_offset_y
|
255
253
|
position
|
256
254
|
end
|
257
|
-
|
255
|
+
end
|
258
256
|
end
|
data/lib/minigl/movement.rb
CHANGED
@@ -1,471 +1,471 @@
|
|
1
1
|
require_relative 'global'
|
2
2
|
|
3
3
|
module AGL
|
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
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
4
|
+
# Represents an object with a rectangular bounding box and the +passable+
|
5
|
+
# property. It is the simplest structure that can be passed as an element of
|
6
|
+
# the +obst+ array parameter of the +move+ method.
|
7
|
+
class Block
|
8
|
+
# The x-coordinate of the top left corner of the bounding box.
|
9
|
+
attr_reader :x
|
10
|
+
|
11
|
+
# The y-coordinate of the top left corner of the bounding box.
|
12
|
+
attr_reader :y
|
13
|
+
|
14
|
+
# The width of the bounding box.
|
15
|
+
attr_reader :w
|
16
|
+
|
17
|
+
# The height of the bounding box.
|
18
|
+
attr_reader :h
|
19
|
+
|
20
|
+
# Whether a moving object can pass through this block when coming from
|
21
|
+
# below. This is a common feature of platforms in platform games.
|
22
|
+
attr_reader :passable
|
23
|
+
|
24
|
+
# Creates a new block.
|
25
|
+
#
|
26
|
+
# Parameters:
|
27
|
+
# [x] The x-coordinate of the top left corner of the bounding box.
|
28
|
+
# [y] The y-coordinate of the top left corner of the bounding box.
|
29
|
+
# [w] The width of the bounding box.
|
30
|
+
# [h] The height of the bounding box.
|
31
|
+
# [passable] Whether a moving object can pass through this block when
|
32
|
+
# coming from below. This is a common feature of platforms in platform
|
33
|
+
# games.
|
34
|
+
def initialize x, y, w, h, passable
|
35
|
+
@x = x; @y = y; @w = w; @h = h
|
36
|
+
@passable = passable
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns the bounding box of this block as a Rectangle.
|
40
|
+
def bounds
|
41
|
+
Rectangle.new @x, @y, @w, @h
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Represents a ramp, i.e., an inclined structure which allows walking over
|
46
|
+
# it while automatically going up or down. It can be imagined as a right
|
47
|
+
# triangle, with a side parallel to the x axis and another one parallel to
|
48
|
+
# the y axis. You must provide instances of this class (or derived classes)
|
49
|
+
# to the +ramps+ array parameter of the +move+ method.
|
50
|
+
class Ramp
|
51
|
+
# The x-coordinate of the top left corner of a rectangle that completely
|
52
|
+
# (and precisely) encloses the ramp (thought of as a right triangle).
|
53
|
+
attr_reader :x
|
54
|
+
|
55
|
+
# The y-coordinate of the top left corner of the rectangle described in
|
56
|
+
# the +x+ attribute.
|
57
|
+
attr_reader :y
|
58
|
+
|
59
|
+
# The width of the ramp.
|
60
|
+
attr_reader :w
|
61
|
+
|
62
|
+
# The height of the ramp.
|
63
|
+
attr_reader :h
|
64
|
+
|
65
|
+
# Whether the height of the ramp increases from left to right (decreases
|
66
|
+
# from left to right when +false+).
|
67
|
+
attr_reader :left
|
68
|
+
|
69
|
+
# Creates a new ramp.
|
70
|
+
#
|
71
|
+
# Parameters:
|
72
|
+
# [x] The x-coordinate of the top left corner of a rectangle that
|
73
|
+
# completely (and precisely) encloses the ramp (thought of as a right
|
74
|
+
# triangle).
|
75
|
+
# [y] The y-coordinate of the top left corner of the rectangle described
|
76
|
+
# above.
|
77
|
+
# [w] The width of the ramp (which corresponds to the width of the
|
78
|
+
# rectangle described above).
|
79
|
+
# [h] The height of the ramp (which corresponds to the height of the
|
80
|
+
# rectangle described above, and to the difference between the lowest
|
81
|
+
# point of the ramp, where it usually meets the floor, and the
|
82
|
+
# highest).
|
83
|
+
# [left] Whether the height of the ramp increases from left to right. Use
|
84
|
+
# +false+ for a ramp that goes down from left to right.
|
85
|
+
def initialize x, y, w, h, left
|
86
|
+
@x = x
|
87
|
+
@y = y
|
88
|
+
@w = w
|
89
|
+
@h = h
|
90
|
+
@left = left
|
91
|
+
end
|
92
|
+
|
93
|
+
# Checks if an object is in contact with this ramp (standing over it).
|
94
|
+
#
|
95
|
+
# Parameters:
|
96
|
+
# [obj] The object to check contact with. It must have the +x+, +y+, +w+
|
97
|
+
# and +h+ accessible attributes determining its bounding box.
|
98
|
+
def contact? obj
|
99
|
+
obj.x.round(6) == get_x(obj).round(6) && obj.y.round(6) == get_y(obj).round(6)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Checks if an object is intersecting this ramp (inside the corresponding
|
103
|
+
# right triangle and at the floor level or above).
|
104
|
+
#
|
105
|
+
# Parameters:
|
106
|
+
# [obj] The object to check intersection with. It must have the +x+, +y+,
|
107
|
+
# +w+ and +h+ accessible attributes determining its bounding box.
|
108
|
+
def intersects obj
|
109
|
+
obj.x + obj.w > @x && obj.x < @x + @w && obj.y > get_y(obj) && obj.y <= @y + @h - obj.h
|
110
|
+
end
|
111
|
+
|
112
|
+
# :nodoc:
|
113
|
+
def can_collide? obj
|
114
|
+
@can_collide = (obj.speed.y >= 0 and not intersects(obj))
|
115
|
+
end
|
116
|
+
|
117
|
+
def check_intersection obj
|
118
|
+
if @can_collide and intersects obj
|
119
|
+
obj.y = get_y obj
|
120
|
+
obj.speed.y = 0
|
121
|
+
# a = @w / @h
|
122
|
+
# x = get_x(obj)
|
123
|
+
# y = get_y(obj)
|
124
|
+
# w = obj.x - x
|
125
|
+
# h = obj.y - y
|
126
|
+
# dx = w * h / (w * a + h)
|
127
|
+
# dy = dx * a
|
128
|
+
#
|
129
|
+
# obj.x -= dx
|
130
|
+
# obj.y -= dy
|
131
|
+
# obj.speed.x *= (@w / (@w + @h))
|
132
|
+
# obj.speed.y = 0
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def get_x obj
|
137
|
+
return @x + (1.0 * (@y + @h - obj.y - obj.h) * @w / @h) - obj.w if @left
|
138
|
+
@x + (1.0 * (obj.y + obj.h - @y) * @w / @h)
|
139
|
+
end
|
140
|
+
|
141
|
+
def get_y obj
|
142
|
+
return @y - obj.h if @left && obj.x + obj.w > @x + @w
|
143
|
+
return @y + (1.0 * (@x + @w - obj.x - obj.w) * @h / @w) - obj.h if @left
|
144
|
+
return @y - obj.h if obj.x < @x
|
145
|
+
@y + (1.0 * (obj.x - @x) * @h / @w) - obj.h
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# This module provides objects with physical properties and methods for
|
150
|
+
# moving. It allows moving with or without collision checking (based on
|
151
|
+
# rectangular bounding boxes), including a method to behave as an elevator,
|
152
|
+
# affecting other objects' positions as it moves.
|
153
|
+
module Movement
|
154
|
+
# The mass of the object, in arbitrary units. The default value for
|
155
|
+
# GameObject instances, for example, is 1. The larger the mass (i.e., the
|
156
|
+
# heavier the object), the more intense the forces applied to the object
|
157
|
+
# have to be in order to move it.
|
158
|
+
attr_reader :mass
|
159
|
+
|
160
|
+
# A Vector with the current speed of the object (x: horizontal component,
|
161
|
+
# y: vertical component).
|
162
|
+
attr_reader :speed
|
163
|
+
|
164
|
+
# Width of the bounding box.
|
165
|
+
attr_reader :w
|
166
|
+
|
167
|
+
# Height of the bounding box.
|
168
|
+
attr_reader :h
|
169
|
+
|
170
|
+
# Whether a moving object can pass through this block when coming from
|
171
|
+
# below. This is a common feature of platforms in platform games.
|
172
|
+
attr_reader :passable
|
173
|
+
|
174
|
+
# The object that is making contact with this from above. If there's no
|
175
|
+
# contact, returns +nil+.
|
176
|
+
attr_reader :top
|
177
|
+
|
178
|
+
# The object that is making contact with this from below. If there's no
|
179
|
+
# contact, returns +nil+.
|
180
|
+
attr_reader :bottom
|
181
|
+
|
182
|
+
# The object that is making contact with this from the left. If there's no
|
183
|
+
# contact, returns +nil+.
|
184
|
+
attr_reader :left
|
185
|
+
|
186
|
+
# The object that is making contact with this from the right. If there's
|
187
|
+
# no contact, returns +nil+.
|
188
|
+
attr_reader :right
|
189
|
+
|
190
|
+
# The x-coordinate of the top left corner of the bounding box.
|
191
|
+
attr_accessor :x
|
192
|
+
|
193
|
+
# The y-coordinate of the top left corner of the bounding box.
|
194
|
+
attr_accessor :y
|
195
|
+
|
196
|
+
# A Vector with the horizontal and vertical components of a force that
|
197
|
+
# be applied in the next time +move+ is called.
|
198
|
+
attr_accessor :stored_forces
|
199
|
+
|
200
|
+
# Returns the bounding box as a Rectangle.
|
201
|
+
def bounds
|
202
|
+
Rectangle.new @x, @y, @w, @h
|
203
|
+
end
|
204
|
+
|
205
|
+
# Moves this object, based on the forces being applied to it, and
|
206
|
+
# performing collision checking.
|
207
|
+
#
|
208
|
+
# Parameters:
|
209
|
+
# [forces] A Vector where x is the horizontal component of the resulting
|
210
|
+
# force and y is the vertical component.
|
211
|
+
# [obst] An array of obstacles to be considered in the collision checking.
|
212
|
+
# Obstacles must be instances of Block (or derived classes), or
|
213
|
+
# objects that <code>include Movement</code>.
|
214
|
+
# [ramps] An array of ramps to be considered in the collision checking.
|
215
|
+
# Ramps must be instances of Ramp (or derived classes).
|
216
|
+
def move forces, obst, ramps
|
217
|
+
forces.x += Game.gravity.x; forces.y += Game.gravity.y
|
218
|
+
forces.x += @stored_forces.x; forces.y += @stored_forces.y
|
219
|
+
@stored_forces.x = @stored_forces.y = 0
|
220
|
+
|
221
|
+
# check_contact obst, ramps
|
222
|
+
forces.x = 0 if (forces.x < 0 and @left) or (forces.x > 0 and @right)
|
223
|
+
forces.y = 0 if (forces.y < 0 and @top) or (forces.y > 0 and @bottom)
|
224
|
+
|
225
|
+
@speed.x += forces.x / @mass; @speed.y += forces.y / @mass
|
226
|
+
@speed.x = 0 if @speed.x.abs < @min_speed.x
|
227
|
+
@speed.y = 0 if @speed.y.abs < @min_speed.y
|
228
|
+
@speed.x = (@speed.x <=> 0) * @max_speed.x if @speed.x.abs > @max_speed.x
|
229
|
+
@speed.y = (@speed.y <=> 0) * @max_speed.y if @speed.y.abs > @max_speed.y
|
230
|
+
|
231
|
+
ramps.each do |r|
|
232
|
+
r.can_collide? self
|
233
|
+
end
|
234
|
+
|
235
|
+
x = @speed.x < 0 ? @x + @speed.x : @x
|
236
|
+
y = @speed.y < 0 ? @y + @speed.y : @y
|
237
|
+
w = @w + (@speed.x < 0 ? -@speed.x : @speed.x)
|
238
|
+
h = @h + (@speed.y < 0 ? -@speed.y : @speed.y)
|
239
|
+
move_bounds = Rectangle.new x, y, w, h
|
240
|
+
coll_list = []
|
241
|
+
obst.each do |o|
|
242
|
+
coll_list << o if move_bounds.intersects o.bounds
|
243
|
+
end
|
244
|
+
|
245
|
+
if coll_list.length > 0
|
246
|
+
up = @speed.y < 0; rt = @speed.x > 0; dn = @speed.y > 0; lf = @speed.x < 0
|
247
|
+
if @speed.x == 0 || @speed.y == 0
|
248
|
+
# Ortogonal
|
249
|
+
if rt; x_lim = find_right_limit coll_list
|
250
|
+
elsif lf; x_lim = find_left_limit coll_list
|
251
|
+
elsif dn; y_lim = find_down_limit coll_list
|
252
|
+
elsif up; y_lim = find_up_limit coll_list
|
253
|
+
end
|
254
|
+
if rt && @x + @w + @speed.x > x_lim; @x = x_lim - @w; @speed.x = 0
|
255
|
+
elsif lf && @x + @speed.x < x_lim; @x = x_lim; @speed.x = 0
|
256
|
+
elsif dn && @y + @h + @speed.y > y_lim; @y = y_lim - @h; @speed.y = 0
|
257
|
+
elsif up && @y + @speed.y < y_lim; @y = y_lim; @speed.y = 0
|
258
|
+
end
|
259
|
+
else
|
260
|
+
# Diagonal
|
261
|
+
x_aim = @x + @speed.x + (rt ? @w : 0); x_lim_def = x_aim
|
262
|
+
y_aim = @y + @speed.y + (dn ? @h : 0); y_lim_def = y_aim
|
263
|
+
coll_list.each do |c|
|
264
|
+
if c.passable; x_lim = x_aim
|
265
|
+
elsif rt; x_lim = c.x
|
266
|
+
else; x_lim = c.x + c.w
|
267
|
+
end
|
268
|
+
if dn; y_lim = c.y
|
269
|
+
elsif c.passable; y_lim = y_aim
|
270
|
+
else; y_lim = c.y + c.h
|
271
|
+
end
|
272
|
+
|
273
|
+
if c.passable
|
274
|
+
y_lim_def = y_lim if dn && @y + @h <= y_lim && y_lim < y_lim_def
|
275
|
+
elsif (rt && @x + @w > x_lim) || (lf && @x < x_lim)
|
276
|
+
# Can't limit by x, will limit by y
|
277
|
+
y_lim_def = y_lim if (dn && y_lim < y_lim_def) || (up && y_lim > y_lim_def)
|
278
|
+
elsif (dn && @y + @h > y_lim) || (up && @y < y_lim)
|
279
|
+
# Can't limit by y, will limit by x
|
280
|
+
x_lim_def = x_lim if (rt && x_lim < x_lim_def) || (lf && x_lim > x_lim_def)
|
281
|
+
else
|
282
|
+
x_time = 1.0 * (x_lim - @x - (@speed.x < 0 ? 0 : @w)) / @speed.x
|
283
|
+
y_time = 1.0 * (y_lim - @y - (@speed.y < 0 ? 0 : @h)) / @speed.y
|
284
|
+
if x_time > y_time
|
285
|
+
# Will limit by x
|
286
|
+
x_lim_def = x_lim if (rt && x_lim < x_lim_def) || (lf && x_lim > x_lim_def)
|
287
|
+
elsif (dn && y_lim < y_lim_def) || (up && y_lim > y_lim_def)
|
288
|
+
y_lim_def = y_lim
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
if x_lim_def != x_aim
|
293
|
+
@speed.x = 0
|
294
|
+
if lf; @x = x_lim_def
|
295
|
+
else; @x = x_lim_def - @w
|
296
|
+
end
|
297
|
+
end
|
298
|
+
if y_lim_def != y_aim
|
299
|
+
@speed.y = 0
|
300
|
+
if up; @y = y_lim_def
|
301
|
+
else; @y = y_lim_def - @h
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
@x += @speed.x
|
307
|
+
@y += @speed.y
|
308
|
+
|
309
|
+
ramps.each do |r|
|
310
|
+
r.check_intersection self
|
311
|
+
end
|
312
|
+
check_contact obst, ramps
|
313
|
+
end
|
314
|
+
|
315
|
+
# Moves this object as an elevator (i.e., potentially carrying other
|
316
|
+
# objects) towards a given point.
|
317
|
+
#
|
318
|
+
# Parameters:
|
319
|
+
# [aim] A Vector specifying where the object will move to.
|
320
|
+
# [speed] The constant speed at which the object will move. This must be
|
321
|
+
# provided as a scalar, not a vector.
|
322
|
+
# [obstacles] An array of obstacles to be considered in the collision
|
323
|
+
# checking, and carried along when colliding from above.
|
324
|
+
# Obstacles must be instances of Block (or derived classes),
|
325
|
+
# or objects that <code>include Movement</code>.
|
326
|
+
def move_carrying aim, speed, obstacles
|
327
|
+
x_d = aim.x - @x; y_d = aim.y - @y
|
328
|
+
distance = Math.sqrt(x_d**2 + y_d**2)
|
329
|
+
@speed.x = 1.0 * x_d * speed / distance
|
330
|
+
@speed.y = 1.0 * y_d * speed / distance
|
331
|
+
|
332
|
+
x_aim = @x + @speed.x; y_aim = @y + @speed.y
|
333
|
+
passengers = []
|
334
|
+
obstacles.each do |o|
|
335
|
+
if @x + @w > o.x && o.x + o.w > @x
|
336
|
+
foot = o.y + o.h
|
337
|
+
if foot.round(6) == @y.round(6) || @speed.y < 0 && foot < @y && foot > y_aim
|
338
|
+
passengers << o
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
if @speed.x > 0 && x_aim >= aim.x || @speed.x < 0 && x_aim <= aim.x
|
344
|
+
passengers.each do |p| p.x += aim.x - @x end
|
345
|
+
@x = aim.x; @speed.x = 0
|
346
|
+
else
|
347
|
+
passengers.each do |p| p.x += @speed.x end
|
348
|
+
@x = x_aim
|
349
|
+
end
|
350
|
+
if @speed.y > 0 && y_aim >= aim.y || @speed.y < 0 && y_aim <= aim.y
|
351
|
+
@y = aim.y; @speed.y = 0
|
352
|
+
else
|
353
|
+
@y = y_aim
|
354
|
+
end
|
355
|
+
|
356
|
+
passengers.each do |p| p.y = @y - p.h end
|
357
|
+
end
|
358
|
+
|
359
|
+
# Moves this object, without performing any collision checking, towards
|
360
|
+
# the specified point.
|
361
|
+
#
|
362
|
+
# Parameters:
|
363
|
+
# [aim] A Vector specifying where the object will move to.
|
364
|
+
# [speed] The constant speed at which the object will move. This must be
|
365
|
+
# provided as a scalar, not a vector.
|
366
|
+
def move_free aim, speed
|
367
|
+
x_d = aim.x - @x; y_d = aim.y - @y
|
368
|
+
distance = Math.sqrt(x_d**2 + y_d**2)
|
369
|
+
@speed.x = 1.0 * x_d * speed / distance
|
370
|
+
@speed.y = 1.0 * y_d * speed / distance
|
371
|
+
|
372
|
+
if (@speed.x < 0 and @x + @speed.x <= aim.x) or (@speed.x >= 0 and @x + @speed.x >= aim.x)
|
373
|
+
@x = aim.x
|
374
|
+
@speed.x = 0
|
375
|
+
else
|
376
|
+
@x += @speed.x
|
377
|
+
end
|
378
|
+
|
379
|
+
if (@speed.y < 0 and @y + @speed.y <= aim.y) or (@speed.y >= 0 and @y + @speed.y >= aim.y)
|
380
|
+
@y = aim.y
|
381
|
+
@speed.y = 0
|
382
|
+
else
|
383
|
+
@y += @speed.y
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
# Causes the object to move in cycles across multiple given points (the
|
388
|
+
# method must be called repeatedly, and it returns the value that must be
|
389
|
+
# provided to +cur_point+ after the first call). If obstacles are
|
390
|
+
# provided, it will behave as an elevator (as in +move_carrying+).
|
391
|
+
#
|
392
|
+
# Parameters:
|
393
|
+
# [points] An array of Vectors representing the path that the object will
|
394
|
+
# perform.
|
395
|
+
# [cur_point] The index of the point in the path that the object is
|
396
|
+
# currently moving to. In the first call, it is a good idea to
|
397
|
+
# provide 0, while in the subsequent calls, you must provide
|
398
|
+
# the return value of this method.
|
399
|
+
# [speed] The constant speed at which the object will move. This must be
|
400
|
+
# provided as a scalar, not a vector.
|
401
|
+
# [obstacles] An array of obstacles to be considered in the collision
|
402
|
+
# checking, and carried along when colliding from above.
|
403
|
+
# Obstacles must be instances of Block (or derived classes),
|
404
|
+
# or objects that <code>include Movement</code>.
|
405
|
+
def cycle points, cur_point, speed, obstacles = nil
|
406
|
+
if obstacles
|
407
|
+
move_carrying points[cur_point], speed, obstacles
|
408
|
+
else
|
409
|
+
move_free points[cur_point], speed
|
410
|
+
end
|
411
|
+
if @speed.x == 0 and @speed.y == 0
|
412
|
+
if cur_point == points.length - 1; cur_point = 0
|
413
|
+
else; cur_point += 1; end
|
414
|
+
end
|
415
|
+
cur_point
|
416
|
+
end
|
417
|
+
|
418
|
+
private
|
419
|
+
|
420
|
+
def check_contact obst, ramps
|
421
|
+
@top = @bottom = @left = @right = nil
|
422
|
+
obst.each do |o|
|
423
|
+
x2 = @x + @w; y2 = @y + @h; x2o = o.x + o.w; y2o = o.y + o.h
|
424
|
+
@right = o if !o.passable && x2.round(6) == o.x.round(6) && y2 > o.y && @y < y2o
|
425
|
+
@left = o if !o.passable && @x.round(6) == x2o.round(6) && y2 > o.y && @y < y2o
|
426
|
+
@bottom = o if y2.round(6) == o.y.round(6) && x2 > o.x && @x < x2o
|
427
|
+
@top = o if !o.passable && @y.round(6) == y2o.round(6) && x2 > o.x && @x < x2o
|
428
|
+
end
|
429
|
+
if @bottom.nil?
|
430
|
+
ramps.each do |r|
|
431
|
+
if r.contact? self
|
432
|
+
@bottom = r
|
433
|
+
break
|
434
|
+
end
|
435
|
+
end
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
def find_right_limit coll_list
|
440
|
+
limit = @x + @w + @speed.x
|
441
|
+
coll_list.each do |c|
|
442
|
+
limit = c.x if !c.passable && c.x < limit
|
443
|
+
end
|
444
|
+
limit
|
445
|
+
end
|
446
|
+
|
447
|
+
def find_left_limit coll_list
|
448
|
+
limit = @x + @speed.x
|
449
|
+
coll_list.each do |c|
|
450
|
+
limit = c.x + c.w if !c.passable && c.x + c.w > limit
|
451
|
+
end
|
452
|
+
limit
|
453
|
+
end
|
454
|
+
|
455
|
+
def find_down_limit coll_list
|
456
|
+
limit = @y + @h + @speed.y
|
457
|
+
coll_list.each do |c|
|
458
|
+
limit = c.y if c.y < limit && c.y >= @y + @h
|
459
|
+
end
|
460
|
+
limit
|
461
|
+
end
|
462
|
+
|
463
|
+
def find_up_limit coll_list
|
464
|
+
limit = @y + @speed.y
|
465
|
+
coll_list.each do |c|
|
466
|
+
limit = c.y + c.h if !c.passable && c.y + c.h > limit
|
467
|
+
end
|
468
|
+
limit
|
469
|
+
end
|
470
|
+
end
|
471
471
|
end
|