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