minigl 2.2.3 → 2.2.4
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/LICENSE +19 -19
- data/README.md +35 -35
- data/Rakefile +11 -11
- data/lib/minigl.rb +4 -4
- data/lib/minigl/forms.rb +1486 -1485
- data/lib/minigl/game_object.rb +379 -379
- data/lib/minigl/global.rb +729 -729
- data/lib/minigl/map.rb +261 -256
- data/lib/minigl/movement.rb +585 -585
- data/lib/minigl/text.rb +190 -190
- data/test/data/img/barbg.svg +73 -73
- data/test/data/img/barfg.svg +106 -106
- data/test/data/img/square.svg +66 -66
- data/test/data/img/square2.svg +66 -66
- data/test/data/img/square3.svg +76 -76
- data/test/data/img/tile1.svg +66 -66
- data/test/data/img/tile2.svg +66 -66
- data/test/game.rb +150 -150
- data/test/game_object_tests.rb +108 -108
- data/test/iso_game.rb +39 -39
- data/test/map_tests.rb +57 -57
- data/test/mov_game.rb +76 -76
- data/test/movement_tests.rb +86 -86
- data/test/res_tests.rb +45 -45
- data/test/vector_tests.rb +55 -55
- metadata +23 -23
data/lib/minigl/map.rb
CHANGED
@@ -1,256 +1,261 @@
|
|
1
|
-
require_relative 'global'
|
2
|
-
|
3
|
-
module MiniGL
|
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
|
-
|
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
|
-
@cam.
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
@cam.
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
@cam.
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
@min_vis_x =
|
200
|
-
@min_vis_y = @cam.
|
201
|
-
@max_vis_x = (@cam.
|
202
|
-
@max_vis_y = (
|
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
|
-
position
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
1
|
+
require_relative 'global'
|
2
|
+
|
3
|
+
module MiniGL
|
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
|
+
# When working with +GameObject+, +Sprite+ and +Effect+ inside a +Map+, you
|
8
|
+
# should provide the map instance as parameter to the +draw+ method of these;
|
9
|
+
# when using Gosu's +Image+, you'll need to manually subtract the coordinates
|
10
|
+
# of the camera from the position of the image, like this:
|
11
|
+
# <code>img.draw(x - map.cam.x, y - map.cam.y, z)</code>
|
12
|
+
class Map
|
13
|
+
SQRT_2_DIV_2 = Math.sqrt(2) / 2 # :nodoc:
|
14
|
+
MINUS_PI_DIV_4 = -Math::PI / 4 # :nodoc:
|
15
|
+
|
16
|
+
# A Vector where x is the tile width and y is the tile height.
|
17
|
+
attr_reader :tile_size
|
18
|
+
|
19
|
+
# A Vector where x is the horizontal tile count and y the vertical count.
|
20
|
+
attr_reader :size
|
21
|
+
|
22
|
+
# A Rectangle representing the region of the map that is currently
|
23
|
+
# visible.
|
24
|
+
attr_reader :cam
|
25
|
+
|
26
|
+
# Creates a new map.
|
27
|
+
#
|
28
|
+
# Parameters:
|
29
|
+
# [t_w] The width of the tiles.
|
30
|
+
# [t_h] The height of the tiles.
|
31
|
+
# [t_x_count] The horizontal count of tiles in the map.
|
32
|
+
# [t_y_count] The vertical count of tiles in the map.
|
33
|
+
# [scr_w] Width of the viewport for the map.
|
34
|
+
# [scr_h] Height of the viewport for the map.
|
35
|
+
# [isometric] Whether to use a isometric map. By default, an ortogonal map
|
36
|
+
# is used.
|
37
|
+
# [limit_cam] Whether the camera should respect the bounds of the map
|
38
|
+
# (i.e., when given coordinates that would imply regions
|
39
|
+
# outside the map to appear in the screen, the camera would
|
40
|
+
# move to the nearest position where only the map shows up
|
41
|
+
# in the screen).
|
42
|
+
def initialize(t_w, t_h, t_x_count, t_y_count, scr_w = 800, scr_h = 600, isometric = false, limit_cam = true)
|
43
|
+
@tile_size = Vector.new t_w, t_h
|
44
|
+
@size = Vector.new t_x_count, t_y_count
|
45
|
+
@cam = Rectangle.new 0, 0, scr_w, scr_h
|
46
|
+
@limit_cam = limit_cam
|
47
|
+
@isometric = isometric
|
48
|
+
if isometric
|
49
|
+
initialize_isometric
|
50
|
+
elsif limit_cam
|
51
|
+
@max_x = t_x_count * t_w - scr_w
|
52
|
+
@max_y = t_y_count * t_h - scr_h
|
53
|
+
end
|
54
|
+
set_camera 0, 0
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns a Vector with the total size of the map, in pixels (x for the
|
58
|
+
# width and y for the height).
|
59
|
+
def get_absolute_size
|
60
|
+
return Vector.new(@tile_size.x * @size.x, @tile_size.y * @size.y) unless @isometric
|
61
|
+
avg = (@size.x + @size.y) * 0.5
|
62
|
+
Vector.new (avg * @tile_size.x).to_i, (avg * @tile_size.y).to_i
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns a Vector with the coordinates of the center of the map.
|
66
|
+
def get_center
|
67
|
+
abs_size = get_absolute_size
|
68
|
+
Vector.new(abs_size.x * 0.5, abs_size.y * 0.5)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Returns the position in the screen corresponding to the given tile
|
72
|
+
# indices.
|
73
|
+
#
|
74
|
+
# Parameters:
|
75
|
+
# [map_x] The index of the tile in the horizontal direction. It must be in
|
76
|
+
# the interval <code>0..t_x_count</code>.
|
77
|
+
# [map_y] The index of the tile in the vertical direction. It must be in
|
78
|
+
# the interval <code>0..t_y_count</code>.
|
79
|
+
def get_screen_pos(map_x, map_y)
|
80
|
+
return Vector.new(map_x * @tile_size.x - @cam.x, map_y * @tile_size.y - @cam.y) unless @isometric
|
81
|
+
Vector.new ((map_x - map_y - 1) * @tile_size.x * 0.5) - @cam.x + @x_offset,
|
82
|
+
((map_x + map_y) * @tile_size.y * 0.5) - @cam.y
|
83
|
+
end
|
84
|
+
|
85
|
+
# Returns the tile in the map that corresponds to the given position in
|
86
|
+
# the screen, as a Vector, where x is the horizontal index and y the
|
87
|
+
# vertical index.
|
88
|
+
#
|
89
|
+
# Parameters:
|
90
|
+
# [scr_x] The x-coordinate in the screen.
|
91
|
+
# [scr_y] The y-coordinate in the screen.
|
92
|
+
def get_map_pos(scr_x, scr_y)
|
93
|
+
return Vector.new((scr_x + @cam.x) / @tile_size.x, (scr_y + @cam.y) / @tile_size.y) unless @isometric
|
94
|
+
|
95
|
+
# Gets the position transformed to isometric coordinates
|
96
|
+
v = get_isometric_position scr_x, scr_y
|
97
|
+
|
98
|
+
# divides by the square size to find the position in the matrix
|
99
|
+
Vector.new((v.x * @inverse_square_size).to_i, (v.y * @inverse_square_size).to_i)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Verifies whether a tile is inside the map.
|
103
|
+
#
|
104
|
+
# Parameters:
|
105
|
+
# [v] A Vector representing the tile, with x as the horizontal index and
|
106
|
+
# y as the vertical index.
|
107
|
+
def is_in_map(v)
|
108
|
+
v.x >= 0 && v.y >= 0 && v.x < @size.x && v.y < @size.y
|
109
|
+
end
|
110
|
+
|
111
|
+
# Sets the top left corner of the viewport to the given position of the
|
112
|
+
# map. Note that this is not the position in the screen.
|
113
|
+
#
|
114
|
+
# Parameters:
|
115
|
+
# [cam_x] The x-coordinate inside the map, in pixels (not a tile index).
|
116
|
+
# [cam_y] The y-coordinate inside the map, in pixels (not a tile index).
|
117
|
+
def set_camera(cam_x, cam_y)
|
118
|
+
@cam.x = cam_x
|
119
|
+
@cam.y = cam_y
|
120
|
+
set_bounds
|
121
|
+
end
|
122
|
+
|
123
|
+
# Moves the viewport by the given amount of pixels.
|
124
|
+
#
|
125
|
+
# Parameters:
|
126
|
+
# [x] The amount of pixels to move horizontally. Negative values will
|
127
|
+
# cause the camera to move to the left.
|
128
|
+
# [y] The amount of pixels to move vertically. Negative values will cause
|
129
|
+
# the camera to move up.
|
130
|
+
def move_camera(x, y)
|
131
|
+
@cam.x += x
|
132
|
+
@cam.y += y
|
133
|
+
set_bounds
|
134
|
+
end
|
135
|
+
|
136
|
+
# Iterates through the currently visible tiles, providing the horizontal
|
137
|
+
# tile index, the vertical tile index, the x-coordinate (in pixels) and
|
138
|
+
# the y-coordinate (in pixels), of each tile, in that order, to a given
|
139
|
+
# block of code.
|
140
|
+
#
|
141
|
+
# Example:
|
142
|
+
#
|
143
|
+
# map.foreach do |i, j, x, y|
|
144
|
+
# draw_tile tiles[i][j], x, y
|
145
|
+
# end
|
146
|
+
def foreach
|
147
|
+
for j in @min_vis_y..@max_vis_y
|
148
|
+
for i in @min_vis_x..@max_vis_x
|
149
|
+
pos = get_screen_pos i, j
|
150
|
+
yield i, j, pos.x, pos.y
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
private
|
156
|
+
|
157
|
+
def set_bounds
|
158
|
+
if @limit_cam
|
159
|
+
if @isometric
|
160
|
+
v1 = get_isometric_position(0, 0)
|
161
|
+
v2 = get_isometric_position(@cam.w - 1, 0)
|
162
|
+
v3 = get_isometric_position(@cam.w - 1, @cam.h - 1)
|
163
|
+
v4 = get_isometric_position(0, @cam.h - 1)
|
164
|
+
if v1.x < -@max_offset
|
165
|
+
offset = -(v1.x + @max_offset)
|
166
|
+
@cam.x += offset * SQRT_2_DIV_2
|
167
|
+
@cam.y += offset * SQRT_2_DIV_2 / @tile_ratio
|
168
|
+
v1.x = -@max_offset
|
169
|
+
end
|
170
|
+
if v2.y < -@max_offset
|
171
|
+
offset = -(v2.y + @max_offset)
|
172
|
+
@cam.x -= offset * SQRT_2_DIV_2
|
173
|
+
@cam.y += offset * SQRT_2_DIV_2 / @tile_ratio
|
174
|
+
v2.y = -@max_offset
|
175
|
+
end
|
176
|
+
if v3.x > @iso_abs_size.x + @max_offset
|
177
|
+
offset = v3.x - @iso_abs_size.x - @max_offset
|
178
|
+
@cam.x -= offset * SQRT_2_DIV_2
|
179
|
+
@cam.y -= offset * SQRT_2_DIV_2 / @tile_ratio
|
180
|
+
v3.x = @iso_abs_size.x + @max_offset
|
181
|
+
end
|
182
|
+
if v4.y > @iso_abs_size.y + @max_offset
|
183
|
+
offset = v4.y - @iso_abs_size.y - @max_offset
|
184
|
+
@cam.x += offset * SQRT_2_DIV_2
|
185
|
+
@cam.y -= offset * SQRT_2_DIV_2 / @tile_ratio
|
186
|
+
v4.y = @iso_abs_size.y + @max_offset
|
187
|
+
end
|
188
|
+
else
|
189
|
+
@cam.x = @max_x if @cam.x > @max_x
|
190
|
+
@cam.x = 0 if @cam.x < 0
|
191
|
+
@cam.y = @max_y if @cam.y > @max_y
|
192
|
+
@cam.y = 0 if @cam.y < 0
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
@cam.x = @cam.x.round
|
197
|
+
@cam.y = @cam.y.round
|
198
|
+
if @isometric
|
199
|
+
@min_vis_x = get_map_pos(0, 0).x
|
200
|
+
@min_vis_y = get_map_pos(@cam.w - 1, 0).y
|
201
|
+
@max_vis_x = get_map_pos(@cam.w - 1, @cam.h - 1).x
|
202
|
+
@max_vis_y = get_map_pos(0, @cam.h - 1).y
|
203
|
+
else
|
204
|
+
@min_vis_x = @cam.x / @tile_size.x
|
205
|
+
@min_vis_y = @cam.y / @tile_size.y
|
206
|
+
@max_vis_x = (@cam.x + @cam.w - 1) / @tile_size.x
|
207
|
+
@max_vis_y = (@cam.y + @cam.h - 1) / @tile_size.y
|
208
|
+
end
|
209
|
+
|
210
|
+
if @min_vis_y < 0; @min_vis_y = 0
|
211
|
+
elsif @min_vis_y > @size.y - 1; @min_vis_y = @size.y - 1; end
|
212
|
+
|
213
|
+
if @max_vis_y < 0; @max_vis_y = 0
|
214
|
+
elsif @max_vis_y > @size.y - 1; @max_vis_y = @size.y - 1; end
|
215
|
+
|
216
|
+
if @min_vis_x < 0; @min_vis_x = 0
|
217
|
+
elsif @min_vis_x > @size.x - 1; @min_vis_x = @size.x - 1; end
|
218
|
+
|
219
|
+
if @max_vis_x < 0; @max_vis_x = 0
|
220
|
+
elsif @max_vis_x > @size.x - 1; @max_vis_x = @size.x - 1; end
|
221
|
+
end
|
222
|
+
|
223
|
+
def initialize_isometric
|
224
|
+
@x_offset = (@size.y * 0.5 * @tile_size.x).round
|
225
|
+
@tile_ratio = @tile_size.x.to_f / @tile_size.y
|
226
|
+
square_size = @tile_size.x * SQRT_2_DIV_2
|
227
|
+
@inverse_square_size = 1 / square_size
|
228
|
+
@iso_abs_size = Vector.new(square_size * @size.x, square_size * @size.y)
|
229
|
+
a = (@size.x + @size.y) * 0.5 * @tile_size.x
|
230
|
+
@isometric_offset_x = (a - square_size * @size.x) * 0.5
|
231
|
+
@isometric_offset_y = (a - square_size * @size.y) * 0.5
|
232
|
+
if @limit_cam
|
233
|
+
actual_cam_h = @cam.h * @tile_ratio
|
234
|
+
@max_offset = actual_cam_h < @cam.w ? actual_cam_h : @cam.w
|
235
|
+
@max_offset *= SQRT_2_DIV_2
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def get_isometric_position(scr_x, scr_y)
|
240
|
+
# Gets the position relative to the center of the map
|
241
|
+
center = get_center
|
242
|
+
position = Vector.new scr_x + @cam.x - center.x, scr_y + @cam.y - center.y
|
243
|
+
|
244
|
+
# Multiplies by tile_ratio to get square tiles
|
245
|
+
position.y *= @tile_ratio
|
246
|
+
|
247
|
+
# Moves the center of the map accordingly
|
248
|
+
center.y *= @tile_ratio
|
249
|
+
|
250
|
+
# Rotates the position -45 degrees
|
251
|
+
position.rotate! MINUS_PI_DIV_4
|
252
|
+
|
253
|
+
# Returns the reference to the center of the map
|
254
|
+
position += center
|
255
|
+
|
256
|
+
# Returns to the corner of the screen
|
257
|
+
position.x -= @isometric_offset_x; position.y -= @isometric_offset_y
|
258
|
+
position
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|