minigl 1.3.3 → 1.3.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/README.md +16 -7
- data/lib/minigl/global.rb +76 -67
- data/lib/minigl/map.rb +154 -42
- data/test/game_object_tests.rb +6 -4
- data/test/iso_game.rb +40 -0
- data/test/res_tests.rb +3 -2
- metadata +4 -9
- data/data/font/font1.ttf +0 -0
- data/data/img/btn.png +0 -0
- data/data/img/check.png +0 -0
- data/data/img/image.png +0 -0
- data/data/img/img1.png +0 -0
- data/data/img/text.png +0 -0
- data/data/tileset/tileset1.png +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2d4aee75d7720a8a267a10b165430543f95768f
|
4
|
+
data.tar.gz: 6f5617de1e50714495a7f9e2f86213c33b7a8fb3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f27a68517fb4284d1cf04c07e1c50402150915abc683432ef410c7c71ce2aba12bb951941a5a14e0a50372e155312812d97065c90f308b4c8aadbcb533d264fb
|
7
|
+
data.tar.gz: 7282c90ab81911f85445f54af4cd32e0ebd99f920fc346768c364028faddd913d04698db13aa73c9571d82b1dd70cffaf0fdf397960c9e079f1cf4968a874118
|
data/README.md
CHANGED
@@ -4,6 +4,7 @@ MiniGL is a minimal **2D Game** Library, available as a Ruby gem, and built on
|
|
4
4
|
top of the [Gosu](http://www.libgosu.org/) gem.
|
5
5
|
|
6
6
|
It provides the following features:
|
7
|
+
|
7
8
|
* Resource management (images, sounds, ...)
|
8
9
|
* Input manipulation (keyboard, mouse, ...)
|
9
10
|
* UI (text, buttons, text fields, ...)
|
@@ -13,6 +14,15 @@ It provides the following features:
|
|
13
14
|
More functionalities are coming. Feel free to contribute! You can send feedback
|
14
15
|
to victordavidsantos@gmail.com.
|
15
16
|
|
17
|
+
## Installing
|
18
|
+
|
19
|
+
MiniGL was built on top of the Gosu gem, version 0.7.50. This gem has its own
|
20
|
+
dependencies for compiling extensions. Visit
|
21
|
+
[this page](https://github.com/jlnr/gosu/wiki/Getting-Started-on-Linux) for
|
22
|
+
details.
|
23
|
+
|
24
|
+
After installing Gosu, you can just `gem install minigl`.
|
25
|
+
|
16
26
|
Please note:
|
17
27
|
|
18
28
|
* The test package is not complete! Most of the functionality
|
@@ -22,11 +32,10 @@ this [working game example](https://github.com/victords/aventura-do-saber).
|
|
22
32
|
* An auxiliary, tutorial-like documentation is under construction
|
23
33
|
[here](https://github.com/victords/minigl/wiki).
|
24
34
|
|
25
|
-
**Version 1.3.
|
26
|
-
|
27
|
-
* Added `mass` attribute to the GameObject class and Movement module.
|
28
|
-
* Added readers for the attributes of `Ramp`.
|
29
|
-
* Added z-index support to all drawing functions.
|
35
|
+
**Version 1.3.4**
|
30
36
|
|
31
|
-
|
32
|
-
|
37
|
+
* Fixed issue when running the game from a directory other than the directory
|
38
|
+
of the game script.
|
39
|
+
* Added `prefix=` method to `Res`, allowing specification of the prefix for
|
40
|
+
the 'data' directory.
|
41
|
+
* Added the `limit_cam` and `isometric` options to the `Map` class.
|
data/lib/minigl/global.rb
CHANGED
@@ -5,24 +5,24 @@ module AGL
|
|
5
5
|
# A Struct with two attributes, x and y (in this order), representing a point
|
6
6
|
# in a bidimensional space.
|
7
7
|
Vector = Struct.new :x, :y
|
8
|
-
|
8
|
+
|
9
9
|
# This class represents a rectangle by its x and y coordinates and width and
|
10
10
|
# height.
|
11
11
|
class Rectangle
|
12
12
|
# The x-coordinate of the rectangle.
|
13
13
|
attr_accessor :x
|
14
|
-
|
14
|
+
|
15
15
|
# The y-coordinate of the rectangle.
|
16
16
|
attr_accessor :y
|
17
|
-
|
17
|
+
|
18
18
|
# The width of the rectangle.
|
19
19
|
attr_accessor :w
|
20
|
-
|
20
|
+
|
21
21
|
# The height of the rectangle.
|
22
22
|
attr_accessor :h
|
23
|
-
|
23
|
+
|
24
24
|
# Creates a new rectangle.
|
25
|
-
#
|
25
|
+
#
|
26
26
|
# Parameters:
|
27
27
|
# [x] The x-coordinate of the rectangle.
|
28
28
|
# [y] The y-coordinate of the rectangle.
|
@@ -31,22 +31,22 @@ module AGL
|
|
31
31
|
def initialize x, y, w, h
|
32
32
|
@x = x; @y = y; @w = w; @h = h
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
# Returns whether this rectangle intersects another.
|
36
|
-
#
|
36
|
+
#
|
37
37
|
# Parameters:
|
38
38
|
# [r] The rectangle to check intersection with.
|
39
39
|
def intersects r
|
40
40
|
@x < r.x + r.w && @x + @w > r.x && @y < r.y + r.h && @y + @h > r.y
|
41
41
|
end
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
# The main class for a MiniGL game, holds references to globally accessible
|
45
45
|
# objects and constants.
|
46
46
|
class Game
|
47
47
|
# Initializes a MiniGL game. This method must be called before any feature
|
48
48
|
# provided by the library can be used.
|
49
|
-
#
|
49
|
+
#
|
50
50
|
# Parameters:
|
51
51
|
# [window] An instance of a class which inherits from
|
52
52
|
# <code>Gosu::Window</code>. This will be the game window, used
|
@@ -72,31 +72,31 @@ module AGL
|
|
72
72
|
@@kb_held_delay = kb_held_delay
|
73
73
|
@@kb_held_interval = kb_held_interval
|
74
74
|
@@double_click_delay = double_click_delay
|
75
|
-
|
75
|
+
|
76
76
|
KB.initialize
|
77
77
|
Mouse.initialize
|
78
78
|
Res.initialize
|
79
79
|
end
|
80
|
-
|
80
|
+
|
81
81
|
# Returns a reference to the game window.
|
82
82
|
def self.window; @@window; end
|
83
|
-
|
83
|
+
|
84
84
|
# Returns a Vector representing the force of gravity. See +initialize+ for
|
85
85
|
# details.
|
86
86
|
def self.gravity; @@gravity; end
|
87
|
-
|
87
|
+
|
88
88
|
# Returns the value of kb_held_delay. See +initialize+ for details.
|
89
89
|
def self.kb_held_delay; @@kb_held_delay; end
|
90
|
-
|
90
|
+
|
91
91
|
# Returns the value of kb_held_interval. See +initialize+ for details.
|
92
92
|
def self.kb_held_interval; @@kb_held_interval; end
|
93
|
-
|
93
|
+
|
94
94
|
# Returns the value of double_click_delay. See +initialize+ for details.
|
95
95
|
def self.double_click_delay; @@double_click_delay; end
|
96
96
|
end
|
97
|
-
|
97
|
+
|
98
98
|
#class JSHelper
|
99
|
-
|
99
|
+
|
100
100
|
# Exposes methods for controlling keyboard events.
|
101
101
|
class KB
|
102
102
|
# This is called by <code>Game.initialize</code>. Don't call it
|
@@ -127,7 +127,7 @@ module AGL
|
|
127
127
|
@@held_timer = {}
|
128
128
|
@@held_interval = {}
|
129
129
|
end
|
130
|
-
|
130
|
+
|
131
131
|
# Updates the state of all keys.
|
132
132
|
def self.update
|
133
133
|
@@held_timer.each do |k, v|
|
@@ -137,12 +137,12 @@ module AGL
|
|
137
137
|
@@held_timer.delete k
|
138
138
|
end
|
139
139
|
end
|
140
|
-
|
140
|
+
|
141
141
|
@@held_interval.each do |k, v|
|
142
142
|
if v < Game.kb_held_interval; @@held_interval[k] += 1
|
143
143
|
else; @@held_interval[k] = 0; end
|
144
144
|
end
|
145
|
-
|
145
|
+
|
146
146
|
@@prev_down = @@down.clone
|
147
147
|
@@down.clear
|
148
148
|
@@keys.each do |k|
|
@@ -155,10 +155,10 @@ module AGL
|
|
155
155
|
end
|
156
156
|
end
|
157
157
|
end
|
158
|
-
|
158
|
+
|
159
159
|
# Returns whether the given key is down in the current frame and was not
|
160
160
|
# down in the frame before.
|
161
|
-
#
|
161
|
+
#
|
162
162
|
# Parameters:
|
163
163
|
# [key] Code of the key to be checked. The available codes are <code>
|
164
164
|
# Gosu::KbUp, Gosu::KbDown, Gosu::KbReturn, Gosu::KbEscape,
|
@@ -181,34 +181,34 @@ module AGL
|
|
181
181
|
def self.key_pressed? key
|
182
182
|
@@prev_down.index(key).nil? and @@down.index(key)
|
183
183
|
end
|
184
|
-
|
184
|
+
|
185
185
|
# Returns whether the given key is down in the current frame.
|
186
|
-
#
|
186
|
+
#
|
187
187
|
# Parameters:
|
188
188
|
# [key] Code of the key to be checked. See +key_pressed?+ for details.
|
189
189
|
def self.key_down? key
|
190
190
|
@@down.index(key)
|
191
191
|
end
|
192
|
-
|
192
|
+
|
193
193
|
# Returns whether the given key is not down in the current frame but was
|
194
194
|
# down in the frame before.
|
195
|
-
#
|
195
|
+
#
|
196
196
|
# Parameters:
|
197
197
|
# [key] Code of the key to be checked. See +key_pressed?+ for details.
|
198
198
|
def self.key_released? key
|
199
199
|
@@prev_down.index(key) and @@down.index(key).nil?
|
200
200
|
end
|
201
|
-
|
201
|
+
|
202
202
|
# Returns whether the given key is being held down. See
|
203
203
|
# <code>Game.initialize</code> for details.
|
204
|
-
#
|
204
|
+
#
|
205
205
|
# Parameters:
|
206
206
|
# [key] Code of the key to be checked. See +key_pressed?+ for details.
|
207
207
|
def self.key_held? key
|
208
208
|
@@held_interval[key] == Game.kb_held_interval
|
209
209
|
end
|
210
210
|
end
|
211
|
-
|
211
|
+
|
212
212
|
# Exposes methods for controlling mouse events.
|
213
213
|
class Mouse
|
214
214
|
# This is called by <code>Game.initialize</code>. Don't call it
|
@@ -219,18 +219,18 @@ module AGL
|
|
219
219
|
@@dbl_click = {}
|
220
220
|
@@dbl_click_timer = {}
|
221
221
|
end
|
222
|
-
|
222
|
+
|
223
223
|
# Updates the mouse position and the state of all buttons.
|
224
224
|
def self.update
|
225
225
|
@@prev_down = @@down.clone
|
226
226
|
@@down.clear
|
227
227
|
@@dbl_click.clear
|
228
|
-
|
228
|
+
|
229
229
|
@@dbl_click_timer.each do |k, v|
|
230
230
|
if v < Game.double_click_delay; @@dbl_click_timer[k] += 1
|
231
231
|
else; @@dbl_click_timer.delete k; end
|
232
232
|
end
|
233
|
-
|
233
|
+
|
234
234
|
k1 = [Gosu::MsLeft, Gosu::MsMiddle, Gosu::MsRight]
|
235
235
|
k2 = [:left, :middle, :right]
|
236
236
|
for i in 0..2
|
@@ -242,57 +242,57 @@ module AGL
|
|
242
242
|
@@dbl_click_timer[k2[i]] = 0
|
243
243
|
end
|
244
244
|
end
|
245
|
-
|
245
|
+
|
246
246
|
@@x = Game.window.mouse_x.round
|
247
247
|
@@y = Game.window.mouse_y.round
|
248
248
|
end
|
249
|
-
|
249
|
+
|
250
250
|
# Returns the x-coordinate of the mouse cursor in the screen.
|
251
251
|
def self.x; @@x; end
|
252
|
-
|
252
|
+
|
253
253
|
# Returns the y-coordinate of the mouse cursor in the screen.
|
254
254
|
def self.y; @@y; end
|
255
|
-
|
255
|
+
|
256
256
|
# Returns whether the given button is down in the current frame and was
|
257
257
|
# not down in the frame before.
|
258
|
-
#
|
258
|
+
#
|
259
259
|
# Parameters:
|
260
260
|
# [btn] Button to be checked. Valid values are +:left+, +:middle+ and
|
261
261
|
# +:right+
|
262
262
|
def self.button_pressed? btn
|
263
263
|
@@down[btn] and not @@prev_down[btn]
|
264
264
|
end
|
265
|
-
|
265
|
+
|
266
266
|
# Returns whether the given button is down in the current frame.
|
267
|
-
#
|
267
|
+
#
|
268
268
|
# Parameters:
|
269
269
|
# [btn] Button to be checked. Valid values are +:left+, +:middle+ and
|
270
270
|
# +:right+
|
271
271
|
def self.button_down? btn
|
272
272
|
@@down[btn]
|
273
273
|
end
|
274
|
-
|
274
|
+
|
275
275
|
# Returns whether the given button is not down in the current frame, but
|
276
276
|
# was down in the frame before.
|
277
|
-
#
|
277
|
+
#
|
278
278
|
# Parameters:
|
279
279
|
# [btn] Button to be checked. Valid values are +:left+, +:middle+ and
|
280
280
|
# +:right+
|
281
281
|
def self.button_released? btn
|
282
282
|
@@prev_down[btn] and not @@down[btn]
|
283
283
|
end
|
284
|
-
|
284
|
+
|
285
285
|
# Returns whether the given button has just been double clicked.
|
286
|
-
#
|
286
|
+
#
|
287
287
|
# Parameters:
|
288
288
|
# [btn] Button to be checked. Valid values are +:left+, +:middle+ and
|
289
289
|
# +:right+
|
290
290
|
def self.double_click? btn
|
291
291
|
@@dbl_click[btn]
|
292
292
|
end
|
293
|
-
|
293
|
+
|
294
294
|
# Returns whether the mouse cursor is currently inside the given area.
|
295
|
-
#
|
295
|
+
#
|
296
296
|
# Parameters:
|
297
297
|
# [x] The x-coordinate of the top left corner of the area.
|
298
298
|
# [y] The y-coordinate of the top left corner of the area.
|
@@ -302,7 +302,7 @@ module AGL
|
|
302
302
|
@@x >= x and @@x < x + w and @@y >= y and @@y < y + h
|
303
303
|
end
|
304
304
|
end
|
305
|
-
|
305
|
+
|
306
306
|
# This class is responsible for resource management. It keeps references to
|
307
307
|
# all loaded resources until a call to +clear+ is made. Resources can be
|
308
308
|
# loaded as global, so that their references won't be removed even when
|
@@ -328,10 +328,19 @@ module AGL
|
|
328
328
|
@@global_songs = Hash.new
|
329
329
|
@@fonts = Hash.new
|
330
330
|
@@global_fonts = Hash.new
|
331
|
-
|
332
|
-
|
331
|
+
@@prefix = File.expand_path(File.dirname($0)) + '/'
|
332
|
+
puts @@prefix
|
333
|
+
end
|
334
|
+
|
335
|
+
# Set a custom prefix for loading resources. By default, the prefix is the
|
336
|
+
# directory of the game script.
|
337
|
+
def self.prefix= value
|
338
|
+
value += '/' if value[-1] != '/'
|
339
|
+
@@prefix = value
|
340
|
+
end
|
341
|
+
|
333
342
|
# Returns a <code>Gosu::Image</code> object.
|
334
|
-
#
|
343
|
+
#
|
335
344
|
# Parameters:
|
336
345
|
# [id] A string or symbol representing the path to the image. If the file
|
337
346
|
# is inside 'data/img', only the file name is needed. If it's inside
|
@@ -350,16 +359,16 @@ module AGL
|
|
350
359
|
def self.img id, global = false, tileable = false, ext = ".png"
|
351
360
|
if global; a = @@global_imgs; else; a = @@imgs; end
|
352
361
|
return a[id] if a[id]
|
353
|
-
s = "data/img/" + id.to_s.split('_').join('/') + ext
|
362
|
+
s = @@prefix + "data/img/" + id.to_s.split('_').join('/') + ext
|
354
363
|
img = Gosu::Image.new Game.window, s, tileable
|
355
364
|
a[id] = img
|
356
365
|
end
|
357
|
-
|
366
|
+
|
358
367
|
# Returns an array of <code>Gosu::Image</code> objects, using the image as
|
359
368
|
# a spritesheet. The image with index 0 will be the top left sprite, and
|
360
369
|
# the following indices raise first from left to right and then from top
|
361
370
|
# to bottom.
|
362
|
-
#
|
371
|
+
#
|
363
372
|
# Parameters:
|
364
373
|
# [id] A string or symbol representing the path to the image. See +img+
|
365
374
|
# for details.
|
@@ -373,16 +382,16 @@ module AGL
|
|
373
382
|
def self.imgs id, sprite_cols, sprite_rows, global = false, ext = ".png"
|
374
383
|
if global; a = @@global_imgs; else; a = @@imgs; end
|
375
384
|
return a[id] if a[id]
|
376
|
-
s = "data/img/" + id.to_s.split('_').join('/') + ext
|
385
|
+
s = @@prefix + "data/img/" + id.to_s.split('_').join('/') + ext
|
377
386
|
imgs = Gosu::Image.load_tiles Game.window, s, -sprite_cols, -sprite_rows, false
|
378
387
|
a[id] = imgs
|
379
388
|
end
|
380
|
-
|
389
|
+
|
381
390
|
# Returns an array of <code>Gosu::Image</code> objects, using the image as
|
382
391
|
# a tileset. Works the same as +imgs+, except you must provide the tile
|
383
392
|
# size instead of the number of columns and rows, and that the images will
|
384
393
|
# be loaded as tileable.
|
385
|
-
#
|
394
|
+
#
|
386
395
|
# Parameters:
|
387
396
|
# [id] A string or symbol representing the path to the image. It must be
|
388
397
|
# specified the same way as in +img+, but the base directory is
|
@@ -397,14 +406,14 @@ module AGL
|
|
397
406
|
def self.tileset id, tile_width = 32, tile_height = 32, global = false, ext = ".png"
|
398
407
|
if global; a = @@global_tilesets; else; a = @@tilesets; end
|
399
408
|
return a[id] if a[id]
|
400
|
-
s = "data/tileset/" + id.to_s.split('_').join('/') + ext
|
409
|
+
s = @@prefix + "data/tileset/" + id.to_s.split('_').join('/') + ext
|
401
410
|
tileset = Gosu::Image.load_tiles Game.window, s, tile_width, tile_height, true
|
402
411
|
a[id] = tileset
|
403
412
|
end
|
404
|
-
|
413
|
+
|
405
414
|
# Returns a <code>Gosu::Sample</code> object. This should be used for
|
406
415
|
# simple and short sound effects.
|
407
|
-
#
|
416
|
+
#
|
408
417
|
# Parameters:
|
409
418
|
# [id] A string or symbol representing the path to the sound. It must be
|
410
419
|
# specified the same way as in +img+, but the base directory is
|
@@ -417,14 +426,14 @@ module AGL
|
|
417
426
|
def self.sound id, global = false, ext = ".wav"
|
418
427
|
if global; a = @@global_sounds; else; a = @@sounds; end
|
419
428
|
return a[id] if a[id]
|
420
|
-
s = "data/sound/" + id.to_s.split('_').join('/') + ext
|
429
|
+
s = @@prefix + "data/sound/" + id.to_s.split('_').join('/') + ext
|
421
430
|
sound = Gosu::Sample.new Game.window, s
|
422
431
|
a[id] = sound
|
423
432
|
end
|
424
|
-
|
433
|
+
|
425
434
|
# Returns a <code>Gosu::Song</code> object. This should be used for the
|
426
435
|
# background musics of your game.
|
427
|
-
#
|
436
|
+
#
|
428
437
|
# Parameters:
|
429
438
|
# [id] A string or symbol representing the path to the song. It must be
|
430
439
|
# specified the same way as in +img+, but the base directory is
|
@@ -437,15 +446,15 @@ module AGL
|
|
437
446
|
def self.song id, global = false, ext = ".ogg"
|
438
447
|
if global; a = @@global_songs; else; a = @@songs; end
|
439
448
|
return a[id] if a[id]
|
440
|
-
s = "data/song/" + id.to_s.split('_').join('/') + ext
|
449
|
+
s = @@prefix + "data/song/" + id.to_s.split('_').join('/') + ext
|
441
450
|
song = Gosu::Song.new Game.window, s
|
442
451
|
a[id] = song
|
443
452
|
end
|
444
|
-
|
453
|
+
|
445
454
|
# Returns a <code>Gosu::Font</code> object. Fonts are needed to draw text
|
446
455
|
# and used by MiniGL elements like buttons, text fields and TextHelper
|
447
456
|
# objects.
|
448
|
-
#
|
457
|
+
#
|
449
458
|
# Parameters:
|
450
459
|
# [id] A string or symbol representing the path to the song. It must be
|
451
460
|
# specified the same way as in +img+, but the base directory is
|
@@ -461,11 +470,11 @@ module AGL
|
|
461
470
|
if global; a = @@global_fonts; else; a = @@fonts; end
|
462
471
|
id_size = "#{id}_#{size}"
|
463
472
|
return a[id_size] if a[id_size]
|
464
|
-
s = "data/font/" + id.to_s.split('_').join('/') + ext
|
473
|
+
s = @@prefix + "data/font/" + id.to_s.split('_').join('/') + ext
|
465
474
|
font = Gosu::Font.new Game.window, s, size
|
466
475
|
a[id_size] = font
|
467
476
|
end
|
468
|
-
|
477
|
+
|
469
478
|
# Releases the memory used by all non-global resources.
|
470
479
|
def self.clear
|
471
480
|
@@imgs.clear
|
data/lib/minigl/map.rb
CHANGED
@@ -7,16 +7,16 @@ module AGL
|
|
7
7
|
class Map
|
8
8
|
# A Vector where x is the tile width and y is the tile height.
|
9
9
|
attr_reader :tile_size
|
10
|
-
|
10
|
+
|
11
11
|
# A Vector where x is the horizontal tile count and y the vertical count.
|
12
12
|
attr_reader :size
|
13
|
-
|
13
|
+
|
14
14
|
# A Rectangle representing the region of the map that is currently
|
15
15
|
# visible.
|
16
16
|
attr_reader :cam
|
17
|
-
|
17
|
+
|
18
18
|
# Creates a new map.
|
19
|
-
#
|
19
|
+
#
|
20
20
|
# Parameters:
|
21
21
|
# [t_w] The width of the tiles.
|
22
22
|
# [t_h] The height of the tiles.
|
@@ -24,60 +24,85 @@ module AGL
|
|
24
24
|
# [t_y_count] The vertical count of tiles in the map.
|
25
25
|
# [scr_w] Width of the viewport for the map.
|
26
26
|
# [scr_h] Height of the viewport for the map.
|
27
|
-
|
27
|
+
# [isometric] Whether to use a isometric map. By default, an ortogonal map
|
28
|
+
# is used.
|
29
|
+
# [limit_cam] Whether the camera should respect the bounds of the map
|
30
|
+
# (i.e., when given coordinates that would imply regions
|
31
|
+
# outside the map to appear in the screen, the camera would
|
32
|
+
# move to the nearest position where only the map shows up
|
33
|
+
# in the screen).
|
34
|
+
def initialize t_w, t_h, t_x_count, t_y_count, scr_w = 800, scr_h = 600, isometric = false, limit_cam = true
|
28
35
|
@tile_size = Vector.new t_w, t_h
|
29
36
|
@size = Vector.new t_x_count, t_y_count
|
30
37
|
@cam = Rectangle.new 0, 0, scr_w, scr_h
|
31
|
-
@
|
32
|
-
@
|
38
|
+
@limit_cam = limit_cam
|
39
|
+
@isometric = isometric
|
40
|
+
if isometric
|
41
|
+
initialize_isometric
|
42
|
+
elsif limit_cam
|
43
|
+
@max_x = t_x_count * t_w - scr_w
|
44
|
+
@max_y = t_y_count * t_h - scr_h
|
45
|
+
end
|
46
|
+
set_camera 0, 0
|
33
47
|
end
|
34
|
-
|
48
|
+
|
35
49
|
# Returns a Vector with the total size of the map, in pixels (x for the
|
36
50
|
# width and y for the height).
|
37
51
|
def get_absolute_size
|
38
|
-
Vector.new(@tile_size.x * @size.x, @tile_size.y * @size.y)
|
52
|
+
return Vector.new(@tile_size.x * @size.x, @tile_size.y * @size.y) unless @isometric
|
53
|
+
avg = (@size.x + @size.y) * 0.5
|
54
|
+
Vector.new (avg * @tile_size.x).to_i, (avg * @tile_size.y).to_i
|
39
55
|
end
|
40
|
-
|
56
|
+
|
41
57
|
# Returns a Vector with the coordinates of the center of the map.
|
42
58
|
def get_center
|
43
|
-
|
59
|
+
abs_size = get_absolute_size
|
60
|
+
Vector.new(abs_size.x * 0.5, abs_size.y * 0.5)
|
44
61
|
end
|
45
|
-
|
62
|
+
|
46
63
|
# Returns the position in the screen corresponding to the given tile
|
47
64
|
# indices.
|
48
|
-
#
|
65
|
+
#
|
49
66
|
# Parameters:
|
50
67
|
# [map_x] The index of the tile in the horizontal direction. It must be in
|
51
68
|
# the interval <code>0..t_x_count</code>.
|
52
69
|
# [map_y] The index of the tile in the vertical direction. It must be in
|
53
70
|
# the interval <code>0..t_y_count</code>.
|
54
71
|
def get_screen_pos map_x, map_y
|
55
|
-
Vector.new(map_x * @tile_size.x - @cam.x, map_y * @tile_size.y - @cam.y)
|
72
|
+
return Vector.new(map_x * @tile_size.x - @cam.x, map_y * @tile_size.y - @cam.y) unless @isometric
|
73
|
+
Vector.new ((map_x - map_y - 1) * @tile_size.x * 0.5) - @cam.x + @x_offset,
|
74
|
+
((map_x + map_y) * @tile_size.y * 0.5) - @cam.y
|
56
75
|
end
|
57
|
-
|
76
|
+
|
58
77
|
# Returns the tile in the map that corresponds to the given position in
|
59
78
|
# the screen, as a Vector, where x is the horizontal index and y the
|
60
79
|
# vertical index.
|
61
|
-
#
|
80
|
+
#
|
62
81
|
# Parameters:
|
63
82
|
# [scr_x] The x-coordinate in the screen.
|
64
83
|
# [scr_y] The y-coordinate in the screen.
|
65
84
|
def get_map_pos scr_x, scr_y
|
66
|
-
Vector.new((scr_x + @cam.x) / @tile_size.x, (scr_y + @cam.y) / @tile_size.y)
|
85
|
+
return Vector.new((scr_x + @cam.x) / @tile_size.x, (scr_y + @cam.y) / @tile_size.y) unless @isometric
|
86
|
+
|
87
|
+
# Obtém a posição transformada para as coordenadas isométricas
|
88
|
+
v = get_isometric_position scr_x, scr_y
|
89
|
+
|
90
|
+
# Depois divide pelo tamanho do quadrado para achar a posição da matriz
|
91
|
+
Vector.new((v.x * @inverse_square_size).to_i, (v.y * @inverse_square_size).to_i)
|
67
92
|
end
|
68
|
-
|
93
|
+
|
69
94
|
# Verifies whether a tile is inside the map.
|
70
|
-
#
|
95
|
+
#
|
71
96
|
# Parameters:
|
72
97
|
# [v] A Vector representing the tile, with x as the horizontal index and
|
73
98
|
# y as the vertical index.
|
74
99
|
def is_in_map v
|
75
100
|
v.x >= 0 && v.y >= 0 && v.x < @size.x && v.y < @size.y
|
76
101
|
end
|
77
|
-
|
102
|
+
|
78
103
|
# Sets the top left corner of the viewport to the given position of the
|
79
104
|
# map. Note that this is not the position in the screen.
|
80
|
-
#
|
105
|
+
#
|
81
106
|
# Parameters:
|
82
107
|
# [cam_x] The x-coordinate inside the map, in pixels (not a tile index).
|
83
108
|
# [cam_y] The y-coordinate inside the map, in pixels (not a tile index).
|
@@ -86,9 +111,9 @@ module AGL
|
|
86
111
|
@cam.y = cam_y
|
87
112
|
set_bounds
|
88
113
|
end
|
89
|
-
|
114
|
+
|
90
115
|
# Moves the viewport by the given amount of pixels.
|
91
|
-
#
|
116
|
+
#
|
92
117
|
# Parameters:
|
93
118
|
# [x] The amount of pixels to move horizontally. Negative values will
|
94
119
|
# cause the camera to move to the left.
|
@@ -99,7 +124,7 @@ module AGL
|
|
99
124
|
@cam.y += y
|
100
125
|
set_bounds
|
101
126
|
end
|
102
|
-
|
127
|
+
|
103
128
|
# Iterates through the currently visible tiles, providing the horizontal
|
104
129
|
# tile index, the vertical tile index, the x-coordinate (in pixels) and
|
105
130
|
# the y-coordinate (in pixels), of each tile, in that order, to a given
|
@@ -113,37 +138,124 @@ module AGL
|
|
113
138
|
def foreach
|
114
139
|
for j in @min_vis_y..@max_vis_y
|
115
140
|
for i in @min_vis_x..@max_vis_x
|
116
|
-
|
141
|
+
pos = get_screen_pos i, j
|
142
|
+
yield i, j, pos.x, pos.y
|
117
143
|
end
|
118
144
|
end
|
119
145
|
end
|
120
|
-
|
146
|
+
|
121
147
|
private
|
122
|
-
|
148
|
+
Sqrt2Div2 = Math.sqrt(2) / 2
|
149
|
+
MinusPiDiv4 = -Math::PI / 4
|
150
|
+
|
123
151
|
def set_bounds
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
152
|
+
if @isometric
|
153
|
+
v1 = get_isometric_position(0, 0)
|
154
|
+
v2 = get_isometric_position(@cam.w - 1, 0)
|
155
|
+
v3 = get_isometric_position(@cam.w - 1, @cam.h - 1)
|
156
|
+
v4 = get_isometric_position(0, @cam.h - 1)
|
157
|
+
|
158
|
+
if @limit_cam
|
159
|
+
if v1.x < -@max_offset
|
160
|
+
offset = -(v1.x + @max_offset)
|
161
|
+
@cam.x += offset * Sqrt2Div2
|
162
|
+
@cam.y += offset * Sqrt2Div2 / @tile_ratio
|
163
|
+
v1.x = -@max_offset
|
164
|
+
end
|
165
|
+
if v2.y < -@max_offset
|
166
|
+
offset = -(v2.y + @max_offset)
|
167
|
+
@cam.x -= offset * Sqrt2Div2
|
168
|
+
@cam.y += offset * Sqrt2Div2 / @tile_ratio
|
169
|
+
v2.y = -@max_offset
|
170
|
+
end
|
171
|
+
if v3.x > @iso_abs_size.x + @max_offset
|
172
|
+
offset = v3.x - @iso_abs_size.x - @max_offset
|
173
|
+
@cam.x -= offset * Sqrt2Div2
|
174
|
+
@cam.y -= offset * Sqrt2Div2 / @tile_ratio
|
175
|
+
v3.x = @iso_abs_size.x + @max_offset
|
176
|
+
end
|
177
|
+
if v4.y > @iso_abs_size.y + @max_offset
|
178
|
+
offset = v4.y - @iso_abs_size.y - @max_offset
|
179
|
+
@cam.x += offset * Sqrt2Div2
|
180
|
+
@cam.y -= offset * Sqrt2Div2 / @tile_ratio
|
181
|
+
v4.y = @iso_abs_size.y + @max_offset
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
@min_vis_x = get_map_pos(0, 0).x
|
186
|
+
@min_vis_y = get_map_pos(@cam.w - 1, 0).y
|
187
|
+
@max_vis_x = get_map_pos(@cam.w - 1, @cam.h - 1).x
|
188
|
+
@max_vis_y = get_map_pos(0, @cam.h - 1).y
|
189
|
+
else
|
190
|
+
if @limit_cam
|
191
|
+
@cam.x = 0 if @cam.x < 0
|
192
|
+
@cam.x = @max_x if @cam.x > @max_x
|
193
|
+
@cam.y = 0 if @cam.y < 0
|
194
|
+
@cam.y = @max_y if @cam.y > @max_y
|
195
|
+
end
|
196
|
+
@min_vis_x = @cam.x / @tile_size.x
|
197
|
+
@min_vis_y = @cam.y / @tile_size.y
|
198
|
+
@max_vis_x = (@cam.x + @cam.w - 1) / @tile_size.x
|
199
|
+
@max_vis_y = (@cam.y + @cam.h - 1) / @tile_size.y
|
200
|
+
end
|
201
|
+
@cam.x = @cam.x.round
|
202
|
+
@cam.y = @cam.y.round
|
203
|
+
|
136
204
|
if @min_vis_y < 0; @min_vis_y = 0
|
137
205
|
elsif @min_vis_y > @size.y - 1; @min_vis_y = @size.y - 1; end
|
138
|
-
|
206
|
+
|
139
207
|
if @max_vis_y < 0; @max_vis_y = 0
|
140
208
|
elsif @max_vis_y > @size.y - 1; @max_vis_y = @size.y - 1; end
|
141
|
-
|
209
|
+
|
142
210
|
if @min_vis_x < 0; @min_vis_x = 0
|
143
211
|
elsif @min_vis_x > @size.x - 1; @min_vis_x = @size.x - 1; end
|
144
|
-
|
212
|
+
|
145
213
|
if @max_vis_x < 0; @max_vis_x = 0
|
146
214
|
elsif @max_vis_x > @size.x - 1; @max_vis_x = @size.x - 1; end
|
147
215
|
end
|
216
|
+
|
217
|
+
def initialize_isometric
|
218
|
+
@x_offset = (@size.y * 0.5 * @tile_size.x).round
|
219
|
+
@tile_ratio = @tile_size.x.to_f / @tile_size.y
|
220
|
+
square_size = @tile_size.x * Sqrt2Div2
|
221
|
+
@inverse_square_size = 1 / square_size
|
222
|
+
@iso_abs_size = Vector.new(square_size * @size.x, square_size * @size.y)
|
223
|
+
a = (@size.x + @size.y) * 0.5 * @tile_size.x
|
224
|
+
@isometric_offset_x = (a - square_size * @size.x) * 0.5
|
225
|
+
@isometric_offset_y = (a - square_size * @size.y) * 0.5
|
226
|
+
if @limit_cam
|
227
|
+
actual_cam_h = @cam.h * @tile_ratio
|
228
|
+
@max_offset = actual_cam_h < @cam.w ? actual_cam_h : @cam.w
|
229
|
+
@max_offset *= Sqrt2Div2
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def get_isometric_position scr_x, scr_y
|
234
|
+
# Escreve a posição em relação a origem (no centro do mapa)
|
235
|
+
center = get_center
|
236
|
+
position = Vector.new scr_x + @cam.x - center.x, scr_y + @cam.y - center.y
|
237
|
+
|
238
|
+
# Multiplica por tile_ratio para obter tiles quadrados
|
239
|
+
position.y *= @tile_ratio
|
240
|
+
|
241
|
+
# O centro do mapa também é deslocado
|
242
|
+
center.y *= @tile_ratio
|
243
|
+
|
244
|
+
# Rotaciona o vetor posição -45°
|
245
|
+
position = rotate position, MinusPiDiv4
|
246
|
+
|
247
|
+
# Retorna a referência da posição para o canto da tela
|
248
|
+
position.x += center.x; position.y += center.y
|
249
|
+
|
250
|
+
# O mapa quadrado está centralizado no centro do losango, precisa retornar ao canto da tela
|
251
|
+
position.x -= @isometric_offset_x; position.y -= @isometric_offset_y
|
252
|
+
position
|
253
|
+
end
|
254
|
+
|
255
|
+
def rotate v, angle
|
256
|
+
sin = Math.sin angle
|
257
|
+
cos = Math.cos angle
|
258
|
+
Vector.new cos * v.x - sin * v.y, sin * v.x + cos * v.y
|
259
|
+
end
|
148
260
|
end
|
149
261
|
end
|
data/test/game_object_tests.rb
CHANGED
@@ -6,8 +6,9 @@ class SpriteTest < Test::Unit::TestCase
|
|
6
6
|
def setup
|
7
7
|
@window = Gosu::Window.new 800, 600, false
|
8
8
|
Game.initialize @window
|
9
|
+
Res.prefix = File.expand_path(File.dirname(__FILE__))
|
9
10
|
end
|
10
|
-
|
11
|
+
|
11
12
|
def test_sprite_position
|
12
13
|
s = Sprite.new 10, 20, :image
|
13
14
|
assert_equal 10, s.x
|
@@ -16,7 +17,7 @@ class SpriteTest < Test::Unit::TestCase
|
|
16
17
|
assert_equal -100, s.x
|
17
18
|
assert_equal 200, s.y
|
18
19
|
end
|
19
|
-
|
20
|
+
|
20
21
|
def test_sprite_animation
|
21
22
|
s = Sprite.new 10, 20, :image, 3, 1
|
22
23
|
indices = [0, 1, 2]
|
@@ -32,8 +33,9 @@ class GameObjectTest < Test::Unit::TestCase
|
|
32
33
|
def setup
|
33
34
|
@window = Gosu::Window.new 800, 600, false
|
34
35
|
Game.initialize @window
|
36
|
+
Res.prefix = File.expand_path(File.dirname(__FILE__))
|
35
37
|
end
|
36
|
-
|
38
|
+
|
37
39
|
def test_game_object_attributes
|
38
40
|
o = GameObject.new 10, 20, 3, 1, :image
|
39
41
|
assert_equal 10, o.x
|
@@ -45,7 +47,7 @@ class GameObjectTest < Test::Unit::TestCase
|
|
45
47
|
assert_equal 0, o.stored_forces.x
|
46
48
|
assert_equal 0, o.stored_forces.y
|
47
49
|
end
|
48
|
-
|
50
|
+
|
49
51
|
def test_game_object_animation
|
50
52
|
o = GameObject.new 10, 20, 3, 1, :image, nil, 3, 1
|
51
53
|
indices = [0, 1, 2]
|
data/test/iso_game.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require_relative '../lib/minigl'
|
2
|
+
include AGL
|
3
|
+
|
4
|
+
class MyGame < Gosu::Window
|
5
|
+
def initialize
|
6
|
+
super 800, 600, false
|
7
|
+
Game.initialize self
|
8
|
+
|
9
|
+
@tile1 = Res.img :tile2
|
10
|
+
@tile2 = Res.img :tile2b
|
11
|
+
@map = Map.new 25, 17, 200, 200, 800, 600, true
|
12
|
+
@p = Vector.new -1, -1
|
13
|
+
end
|
14
|
+
|
15
|
+
def needs_cursor?
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
def update
|
20
|
+
KB.update
|
21
|
+
Mouse.update
|
22
|
+
p = @map.get_map_pos Mouse.x, Mouse.y
|
23
|
+
@p = p if @map.is_in_map p
|
24
|
+
|
25
|
+
@map.move_camera 0, -5 if KB.key_down? Gosu::KbUp
|
26
|
+
@map.move_camera 5, 0 if KB.key_down? Gosu::KbRight
|
27
|
+
@map.move_camera 0, 5 if KB.key_down? Gosu::KbDown
|
28
|
+
@map.move_camera -5, 0 if KB.key_down? Gosu::KbLeft
|
29
|
+
@map.set_camera 0, 0 if KB.key_down? Gosu::KbReturn
|
30
|
+
end
|
31
|
+
|
32
|
+
def draw
|
33
|
+
@map.foreach do |i, j, x, y|
|
34
|
+
if i == @p.x and j == @p.y; @tile2.draw x, y, 0
|
35
|
+
else; @tile1.draw x, y, 0; end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
MyGame.new.show
|
data/test/res_tests.rb
CHANGED
@@ -2,12 +2,13 @@ require 'test/unit'
|
|
2
2
|
require_relative '../lib/minigl'
|
3
3
|
include AGL
|
4
4
|
|
5
|
-
class
|
5
|
+
class ResTest < Test::Unit::TestCase
|
6
6
|
def setup
|
7
7
|
@window = Gosu::Window.new 800, 600, false
|
8
8
|
Game.initialize @window
|
9
|
+
Res.prefix = File.expand_path(File.dirname(__FILE__))
|
9
10
|
end
|
10
|
-
|
11
|
+
|
11
12
|
def test_tileset
|
12
13
|
t1 = Res.tileset :tileset1
|
13
14
|
assert_equal 9, t1.length
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: minigl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Victor David Santos
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gosu
|
@@ -39,13 +39,6 @@ files:
|
|
39
39
|
- LICENSE
|
40
40
|
- README.md
|
41
41
|
- Rakefile
|
42
|
-
- data/font/font1.ttf
|
43
|
-
- data/img/btn.png
|
44
|
-
- data/img/check.png
|
45
|
-
- data/img/image.png
|
46
|
-
- data/img/img1.png
|
47
|
-
- data/img/text.png
|
48
|
-
- data/tileset/tileset1.png
|
49
42
|
- lib/minigl.rb
|
50
43
|
- lib/minigl/forms.rb
|
51
44
|
- lib/minigl/game_object.rb
|
@@ -55,6 +48,7 @@ files:
|
|
55
48
|
- lib/minigl/text.rb
|
56
49
|
- test/game.rb
|
57
50
|
- test/game_object_tests.rb
|
51
|
+
- test/iso_game.rb
|
58
52
|
- test/map_tests.rb
|
59
53
|
- test/movement_tests.rb
|
60
54
|
- test/res_tests.rb
|
@@ -86,5 +80,6 @@ test_files:
|
|
86
80
|
- test/movement_tests.rb
|
87
81
|
- test/map_tests.rb
|
88
82
|
- test/game.rb
|
83
|
+
- test/iso_game.rb
|
89
84
|
- test/res_tests.rb
|
90
85
|
- test/game_object_tests.rb
|
data/data/font/font1.ttf
DELETED
Binary file
|
data/data/img/btn.png
DELETED
Binary file
|
data/data/img/check.png
DELETED
Binary file
|
data/data/img/image.png
DELETED
Binary file
|
data/data/img/img1.png
DELETED
Binary file
|
data/data/img/text.png
DELETED
Binary file
|
data/data/tileset/tileset1.png
DELETED
Binary file
|