minigl 1.2.5 → 1.2.6
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 +4 -5
- data/Rakefile +4 -0
- data/lib/minigl/forms.rb +154 -36
- data/lib/minigl/game_object.rb +93 -3
- data/lib/minigl/global.rb +221 -6
- data/lib/minigl/map.rb +61 -1
- data/lib/minigl/movement.rb +158 -16
- data/lib/minigl/text.rb +40 -2
- data/test/game.rb +4 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d75703110c27893ced02abaa49767ac4137d1b34
|
4
|
+
data.tar.gz: c376306e0d0a7838ebae01863302a418408ce840
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 221538181848507fc1b079eb9ac34d3c80f4740070641e2a1bfaef34ebe34effce282f36680082c4c6d2051eb9261f48af4b4d25a1428ad913c89cbba1694cad
|
7
|
+
data.tar.gz: e0f31296045813f211981db2c5c46a8b0fa0a044642072749d9396c14810739f5f6667d5a029d437497217bb605f8fb9cdb2e9302297e4e3bdb6293a98ecb2c0
|
data/README.md
CHANGED
@@ -21,9 +21,8 @@ this [working game example](https://github.com/victords/aventura-do-saber).
|
|
21
21
|
* The [documentation](https://github.com/victords/minigl/wiki) is under
|
22
22
|
construction.
|
23
23
|
|
24
|
-
**Version 1.2.
|
24
|
+
**Version 1.2.6**
|
25
25
|
|
26
|
-
* Added support for
|
27
|
-
|
28
|
-
*
|
29
|
-
methods.
|
26
|
+
* Added support for character restriction in `TextField`.
|
27
|
+
* Added `set_position` method to `Button` and `TextField`.
|
28
|
+
* Added RDoc documentation.
|
data/Rakefile
CHANGED
data/lib/minigl/forms.rb
CHANGED
@@ -1,7 +1,34 @@
|
|
1
1
|
require_relative 'global'
|
2
2
|
|
3
3
|
module AGL
|
4
|
+
# This class represents a button.
|
4
5
|
class Button
|
6
|
+
# Creates a button.
|
7
|
+
# Parameters:
|
8
|
+
# [x] The x-coordinate where the button will be drawn in the screen.
|
9
|
+
# [y] The y-coordinate where the button will be drawn in the screen.
|
10
|
+
# [font] The <code>Gosu::Font</code> object that will be used to draw the
|
11
|
+
# button text.
|
12
|
+
# [text] The button text. Can be +nil+ or empty.
|
13
|
+
# [img] A spritesheet containing three images in a column, representing,
|
14
|
+
# from top to bottom, the default state, the hover state (when the
|
15
|
+
# mouse is over the button) and the pressed state (when the mouse
|
16
|
+
# button is down and the cursor is over the button). If +nil+, the
|
17
|
+
# +width+ and +height+ parameters must be provided.
|
18
|
+
# [text_color] Color of the button text, in hexadecimal RRGGBB format.
|
19
|
+
# [center] Whether the button text should be centered in its area (the
|
20
|
+
# area is defined by the image size, when an image is given, or
|
21
|
+
# by the +width+ and +height+ parameters, otherwise).
|
22
|
+
# [margin_x] The x offset, from the button x-coordinate, to draw the text.
|
23
|
+
# This parameter is used only if +center+ is false.
|
24
|
+
# [margin_y] The y offset, from the button y-coordinate, to draw the text.
|
25
|
+
# This parameter is used only if +center+ is false.
|
26
|
+
# [width] Width of the button clickable area. This parameter is used only
|
27
|
+
# if +img+ is +nil+.
|
28
|
+
# [height] Height of the button clickable area. This parameter is used
|
29
|
+
# only if +img+ is +nil+.
|
30
|
+
# [action] The block of code executed when the button is clicked (or by
|
31
|
+
# calling the +click+ method).
|
5
32
|
def initialize x, y, font, text, img, text_color = 0, center = true, margin_x = 0, margin_y = 0, width = nil, height = nil, &action
|
6
33
|
@x = x
|
7
34
|
@y = y
|
@@ -30,7 +57,9 @@ module AGL
|
|
30
57
|
@state = :up
|
31
58
|
@img_index = 0
|
32
59
|
end
|
33
|
-
|
60
|
+
|
61
|
+
# Updates the button, checking the mouse movement and buttons to define
|
62
|
+
# the button state.
|
34
63
|
def update
|
35
64
|
mouse_over = Mouse.over? @x, @y, @w, @h
|
36
65
|
mouse_press = Mouse.button_pressed? :left
|
@@ -69,10 +98,32 @@ module AGL
|
|
69
98
|
end
|
70
99
|
end
|
71
100
|
|
101
|
+
# Executes the button click action.
|
72
102
|
def click
|
73
103
|
@action.call
|
74
104
|
end
|
75
105
|
|
106
|
+
# Sets the position of the button in the screen.
|
107
|
+
# Parameters:
|
108
|
+
# [x] The new x-coordinate for the button.
|
109
|
+
# [y] The new y-coordinate for the button.
|
110
|
+
def set_position x, y
|
111
|
+
d_x = x - @x
|
112
|
+
d_y = y - @y
|
113
|
+
@x = x; @y = y
|
114
|
+
if @center
|
115
|
+
@text_x = x + @w / 2
|
116
|
+
@text_y = y + @h / 2
|
117
|
+
else
|
118
|
+
@text_x += d_x
|
119
|
+
@text_y += d_y
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Draws the button in the screen.
|
124
|
+
# Parameters:
|
125
|
+
# [alpha] The opacity with which the button will be drawn. Allowed values
|
126
|
+
# vary between 0 (fully transparent) and 255 (fully opaque).
|
76
127
|
def draw alpha = 0xff
|
77
128
|
color = (alpha << 24) | 0xffffff
|
78
129
|
text_color = (alpha << 24) | @text_color
|
@@ -87,11 +138,42 @@ module AGL
|
|
87
138
|
end
|
88
139
|
end
|
89
140
|
|
141
|
+
# This class represents a text field (input).
|
90
142
|
class TextField
|
143
|
+
# The current text inside the text field.
|
91
144
|
attr_reader :text
|
92
145
|
|
93
|
-
|
94
|
-
|
146
|
+
# Creates a new text field.
|
147
|
+
# Parameters:
|
148
|
+
# [x] The x-coordinate where the text field will be drawn in the screen.
|
149
|
+
# [y] The y-coordinate where the text field will be drawn in the screen.
|
150
|
+
# [font] The <code>Gosu::Font</code> object that will be used to draw the
|
151
|
+
# text inside the field.
|
152
|
+
# [img] The image of the text field. For a good result, you would likely
|
153
|
+
# want something like a rectangle, horizontally wide, vertically
|
154
|
+
# short, and with a color that contrasts with the +text_color+.
|
155
|
+
# [cursor_img] An image for the blinking cursor that stands in the point
|
156
|
+
# where text will be inserted. If +nil+, a simple black line
|
157
|
+
# will be drawn instead.
|
158
|
+
# [text_color] Color of the button text, in hexadecimal RRGGBB format.
|
159
|
+
# [margin_x] The x offset, from the field x-coordinate, to draw the text.
|
160
|
+
# [margin_y] The y offset, from the field y-coordinate, to draw the text.
|
161
|
+
# [max_length] The maximum length of the text inside the field.
|
162
|
+
# [active] Whether the text field must be focused by default. If +false+,
|
163
|
+
# focus can be granted by clicking inside the text field or by
|
164
|
+
# calling the +focus+ method.
|
165
|
+
# [text] The starting text. Must not be +nil+.
|
166
|
+
# [allowed_chars] A string containing all characters that can be typed
|
167
|
+
# inside the text field. The complete set of supported
|
168
|
+
# characters is given by the string
|
169
|
+
# <code>"abcdefghijklmnopqrstuvwxyz1234567890 ABCDEFGHIJKLMNOPQRSTUVWXYZ'-=/[]\\\\,.;\"_+?{}|<>:!@#$%¨&*()"</code>.
|
170
|
+
# [text_color] The color with which the text will be drawn, in hexadecimal
|
171
|
+
# RRGGBB format.
|
172
|
+
# [selection_color] The color of the rectangle highlighting selected text,
|
173
|
+
# in hexadecimal RRGGBB format. The rectangle will
|
174
|
+
# always be drawn with 50% of opacity.
|
175
|
+
def initialize x, y, font, img, cursor_img = nil, margin_x = 0, margin_y = 0, max_length = 100, active = false, text = "",
|
176
|
+
allowed_chars = nil, text_color = 0, selection_color = 0
|
95
177
|
@x = x
|
96
178
|
@y = y
|
97
179
|
@font = font
|
@@ -128,41 +210,16 @@ module AGL
|
|
128
210
|
Gosu::KbBracketRight, Gosu::KbBackslash, Gosu::KbApostrophe,
|
129
211
|
Gosu::KbComma, Gosu::KbPeriod, Gosu::KbSlash
|
130
212
|
]
|
131
|
-
@chars = "abcdefghijklmnopqrstuvwxyz1234567890 ABCDEFGHIJKLMNOPQRSTUVWXYZ'-=/[]\\,.;\"_+?{}
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
for char in @text
|
139
|
-
x += @font.text_width char
|
140
|
-
@nodes << x
|
141
|
-
end
|
142
|
-
@cur_node = @nodes.size - 1
|
143
|
-
@anchor1 = nil
|
144
|
-
@anchor2 = nil
|
145
|
-
set_cursor_visible
|
146
|
-
end
|
147
|
-
|
148
|
-
def selected_text
|
149
|
-
return "" if @anchor2.nil?
|
150
|
-
min = @anchor1 < @anchor2 ? @anchor1 : @anchor2
|
151
|
-
max = min == @anchor1 ? @anchor2 : @anchor1
|
152
|
-
@text[min..max]
|
153
|
-
end
|
154
|
-
|
155
|
-
def focus
|
156
|
-
@active = true
|
157
|
-
end
|
158
|
-
|
159
|
-
def unfocus
|
160
|
-
@anchor1 = @anchor2 = nil
|
161
|
-
@cursor_visible = false
|
162
|
-
@cursor_timer = 0
|
163
|
-
@active = false
|
213
|
+
@chars = "abcdefghijklmnopqrstuvwxyz1234567890 ABCDEFGHIJKLMNOPQRSTUVWXYZ'-=/[]\\,.;\"_+?{}|<>:!@#$%¨&*()"
|
214
|
+
@allowed_chars =
|
215
|
+
if allowed_chars
|
216
|
+
allowed_chars
|
217
|
+
else
|
218
|
+
@chars
|
219
|
+
end
|
164
220
|
end
|
165
221
|
|
222
|
+
# Updates the text field, checking for mouse events and keyboard input.
|
166
223
|
def update
|
167
224
|
################################ Mouse ################################
|
168
225
|
if Mouse.over? @x, @y, @w, @h
|
@@ -321,6 +378,66 @@ module AGL
|
|
321
378
|
end
|
322
379
|
end
|
323
380
|
|
381
|
+
# Sets the text of the text field to the specified value.
|
382
|
+
# Parameters:
|
383
|
+
# [value] The new text to be set. If it's longer than the +max_length+
|
384
|
+
# parameter used in the constructor, it will be truncated to
|
385
|
+
# +max_length+ characters.
|
386
|
+
def text= value
|
387
|
+
@text = value[0...max_length]
|
388
|
+
@nodes.clear; @nodes << (@x + @margin_x)
|
389
|
+
x = @nodes[0]
|
390
|
+
for char in @text
|
391
|
+
x += @font.text_width char
|
392
|
+
@nodes << x
|
393
|
+
end
|
394
|
+
@cur_node = @nodes.size - 1
|
395
|
+
@anchor1 = nil
|
396
|
+
@anchor2 = nil
|
397
|
+
set_cursor_visible
|
398
|
+
end
|
399
|
+
|
400
|
+
# Returns the currently selected text.
|
401
|
+
def selected_text
|
402
|
+
return "" if @anchor2.nil?
|
403
|
+
min = @anchor1 < @anchor2 ? @anchor1 : @anchor2
|
404
|
+
max = min == @anchor1 ? @anchor2 : @anchor1
|
405
|
+
@text[min..max]
|
406
|
+
end
|
407
|
+
|
408
|
+
# Grants focus to the text field, so that it allows keyboard input.
|
409
|
+
def focus
|
410
|
+
@active = true
|
411
|
+
end
|
412
|
+
|
413
|
+
# Removes focus from the text field, so that no keyboard input will be
|
414
|
+
# accepted.
|
415
|
+
def unfocus
|
416
|
+
@anchor1 = @anchor2 = nil
|
417
|
+
@cursor_visible = false
|
418
|
+
@cursor_timer = 0
|
419
|
+
@active = false
|
420
|
+
end
|
421
|
+
|
422
|
+
# Sets the position of the text field in the screen.
|
423
|
+
# Parameters:
|
424
|
+
# [x] The new x-coordinate for the text field.
|
425
|
+
# [y] The new y-coordinate for the text field.
|
426
|
+
def set_position x, y
|
427
|
+
d_x = x - @x
|
428
|
+
d_y = y - @y
|
429
|
+
@x = x; @y = y
|
430
|
+
@text_x += d_x
|
431
|
+
@text_y += d_y
|
432
|
+
@nodes.map! do |n|
|
433
|
+
n + d_x
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
# Draws the text field in the screen.
|
438
|
+
# Parameters:
|
439
|
+
# [alpha] The opacity with which the text field will be drawn. Allowed
|
440
|
+
# values vary between 0 (fully transparent) and 255 (fully opaque).
|
324
441
|
def draw alpha = 0xff
|
325
442
|
color = (alpha << 24) | 0xffffff
|
326
443
|
text_color = (alpha << 24) | @text_color
|
@@ -371,6 +488,7 @@ module AGL
|
|
371
488
|
end
|
372
489
|
|
373
490
|
def insert_char char
|
491
|
+
return unless @allowed_chars.index char
|
374
492
|
if @text.length < @max_length
|
375
493
|
@text.insert @cur_node, char
|
376
494
|
@nodes.insert @cur_node + 1, @nodes[@cur_node] + @font.text_width(char)
|
data/lib/minigl/game_object.rb
CHANGED
@@ -1,10 +1,34 @@
|
|
1
1
|
require_relative 'movement'
|
2
2
|
|
3
3
|
module AGL
|
4
|
+
# This class represents an (optionally animated) image inside the game screen.
|
4
5
|
class Sprite
|
6
|
+
# The index of the current sprite in the spritesheet being drawn.
|
5
7
|
attr_reader :img_index
|
6
|
-
attr_accessor :x, :y
|
7
8
|
|
9
|
+
# The x-coordinate of the image in the screen.
|
10
|
+
attr_accessor :x
|
11
|
+
|
12
|
+
# The y-coordinate of the image in the screen.
|
13
|
+
attr_accessor :y
|
14
|
+
|
15
|
+
# Creates a new sprite.
|
16
|
+
# Parameters:
|
17
|
+
# [x] The x-coordinate where the sprite will be drawn in the screen.
|
18
|
+
# [y] The y-coordinate where the sprite will be drawn in the screen.
|
19
|
+
# [img] The path to a PNG image or spritesheet, following the MiniGL
|
20
|
+
# convention: images must be inside a 'data/img' directory, relative
|
21
|
+
# to the code file, and you must only provide the file name, without
|
22
|
+
# extension, in this case. If the image is inside a subdirectory of
|
23
|
+
# 'data/img', you must prefix the file name with each subdirectory
|
24
|
+
# name, followed by an underscore (so the file and directories names
|
25
|
+
# must not contain underscores). For example, if your image is
|
26
|
+
# 'data/img/sprite/1.png', you must provide <code>"sprite_1"</code>
|
27
|
+
# or +:sprite_1+.
|
28
|
+
# [sprite_cols] The number of columns in the spritesheet. Use +nil+ if the
|
29
|
+
# image is not a spritesheet.
|
30
|
+
# [sprite_rows] The number of rows in the spritesheet. Use +nil+ if the
|
31
|
+
# image is not a spritesheet.
|
8
32
|
def initialize x, y, img, sprite_cols = nil, sprite_rows = nil
|
9
33
|
@x = x; @y = y
|
10
34
|
@img =
|
@@ -18,6 +42,16 @@ module AGL
|
|
18
42
|
@index_index = 0
|
19
43
|
end
|
20
44
|
|
45
|
+
# Performs time checking to update the image index according to the
|
46
|
+
# sequence of indices and the interval.
|
47
|
+
# Parameters:
|
48
|
+
# [indices] The sequence of image indices used in the animation. The
|
49
|
+
# indices are determined from left to right, and from top to
|
50
|
+
# bottom, inside the spritesheet. All indices must be in the
|
51
|
+
# interval <code>0..(sprite_cols * sprite_rows)</code>.
|
52
|
+
# [interval] The amount of frames between each change in the image index.
|
53
|
+
# A frame will usually represent 1/60 second (roughly 17
|
54
|
+
# milliseconds).
|
21
55
|
def animate indices, interval
|
22
56
|
@anim_counter += 1
|
23
57
|
if @anim_counter >= interval
|
@@ -28,6 +62,22 @@ module AGL
|
|
28
62
|
end
|
29
63
|
end
|
30
64
|
|
65
|
+
# Draws the sprite in the screen
|
66
|
+
# Parameters:
|
67
|
+
# [map] A Map object, relative to which the sprite will be drawn (the x
|
68
|
+
# and y coordinates of the sprite will be changed according to the
|
69
|
+
# position of the camera).
|
70
|
+
# [scale_x] A scale factor to be applied horizontally to the image.
|
71
|
+
# [scale_y] A scale factor to be applied vertically to the image.
|
72
|
+
# [alpha] The opacity with which the image will be drawn. Valid values
|
73
|
+
# vary from 0 (fully transparent) to 255 (fully opaque).
|
74
|
+
# [color] A color filter to apply to the image. A white (0xffffff) filter
|
75
|
+
# will keep all colors unchanged, while a black (0x000000) filter
|
76
|
+
# will turn all colors to black. A red (0xff0000) filter will keep
|
77
|
+
# reddish colors with slight or no change, whereas bluish colors
|
78
|
+
# will be darkened, for example.
|
79
|
+
# [angle] A rotation, in degrees, to be applied to the image, relative to
|
80
|
+
# its center.
|
31
81
|
def draw map = nil, scale_x = 1, scale_y = 1, alpha = 0xff, color = 0xffffff, angle = nil
|
32
82
|
color = (alpha << 24) | color
|
33
83
|
if map
|
@@ -43,10 +93,29 @@ module AGL
|
|
43
93
|
end
|
44
94
|
end
|
45
95
|
end
|
46
|
-
|
96
|
+
|
97
|
+
# This class represents an object with a set of properties and methods
|
98
|
+
# commonly used in games. It defines an object with a rectangular bounding
|
99
|
+
# box, and having all the attributes required for using the Movement module.
|
47
100
|
class GameObject < Sprite
|
48
101
|
include Movement
|
49
102
|
|
103
|
+
# Creates a new game object.
|
104
|
+
# Parameters:
|
105
|
+
# [x] The x-coordinate of the object's bounding box.
|
106
|
+
# [y] The y-coordinate of the object's bounding box.
|
107
|
+
# [w] The width of the object's bounding box.
|
108
|
+
# [h] The height of the object's bounding box.
|
109
|
+
# [img] The image or spritesheet for the object.
|
110
|
+
# [img_gap] A Vector object representing the difference between the top
|
111
|
+
# left corner of the bounding box and the coordinates of the
|
112
|
+
# image. For example, an object with <code>x = 100</code>,
|
113
|
+
# <code>y = 50</code> and <code>img_gap = Vector.new(-5, -5)</code>
|
114
|
+
# will be drawn at position (95, 45) of the screen.
|
115
|
+
# [sprite_cols] The number of columns in the spritesheet. Use +nil+ if the
|
116
|
+
# image is not a spritesheet.
|
117
|
+
# [sprite_rows] The number of rows in the spritesheet. Use +nil+ if the
|
118
|
+
# image is not a spritesheet.
|
50
119
|
def initialize x, y, w, h, img, img_gap = nil, sprite_cols = nil, sprite_rows = nil
|
51
120
|
super x, y, img, sprite_cols, sprite_rows
|
52
121
|
@w = w; @h = h
|
@@ -62,17 +131,37 @@ module AGL
|
|
62
131
|
@stored_forces = Vector.new 0, 0
|
63
132
|
end
|
64
133
|
|
134
|
+
# Resets the animation timer and immediately changes the image index to
|
135
|
+
# the specified value.
|
136
|
+
# Parameters:
|
137
|
+
# [index] The image index to be set.
|
65
138
|
def set_animation index
|
66
139
|
@anim_counter = 0
|
67
140
|
@img_index = index
|
68
141
|
@index_index = 0
|
69
142
|
end
|
70
143
|
|
71
|
-
def is_visible map
|
144
|
+
def is_visible map # :nodoc:
|
72
145
|
return map.cam.intersects @active_bounds if @active_bounds
|
73
146
|
false
|
74
147
|
end
|
75
148
|
|
149
|
+
# Draws the game object in the screen.
|
150
|
+
# Parameters:
|
151
|
+
# [map] A Map object, relative to which the object will be drawn (the x
|
152
|
+
# and y coordinates of the image will be changed according to the
|
153
|
+
# position of the camera).
|
154
|
+
# [scale_x] A scale factor to be applied horizontally to the image.
|
155
|
+
# [scale_y] A scale factor to be applied vertically to the image.
|
156
|
+
# [alpha] The opacity with which the image will be drawn. Valid values
|
157
|
+
# vary from 0 (fully transparent) to 255 (fully opaque).
|
158
|
+
# [color] A color filter to apply to the image. A white (0xffffff) filter
|
159
|
+
# will keep all colors unchanged, while a black (0x000000) filter
|
160
|
+
# will turn all colors to black. A red (0xff0000) filter will keep
|
161
|
+
# reddish colors with slight or no change, whereas bluish colors
|
162
|
+
# will be darkened, for example.
|
163
|
+
# [angle] A rotation, in degrees, to be applied to the image, relative to
|
164
|
+
# its center.
|
76
165
|
def draw map = nil, scale_x = 1, scale_y = 1, alpha = 0xff, color = 0xffffff, angle = nil
|
77
166
|
color = (alpha << 24) | color
|
78
167
|
if map
|
@@ -91,6 +180,7 @@ module AGL
|
|
91
180
|
end
|
92
181
|
end
|
93
182
|
|
183
|
+
# :nodoc: all
|
94
184
|
class Effect < Sprite
|
95
185
|
def initialize x, y, life_time, img, sprite_cols = nil, sprite_rows = nil, indices = nil, interval = 1
|
96
186
|
super x, y, img, sprite_cols, sprite_rows
|
data/lib/minigl/global.rb
CHANGED
@@ -1,21 +1,66 @@
|
|
1
1
|
require 'gosu'
|
2
2
|
|
3
|
+
# The main module of the library, used only as a namespace.
|
3
4
|
module AGL
|
5
|
+
# A Struct with two attributes, x and y (in this order), representing a point
|
6
|
+
# in a bidimensional space.
|
4
7
|
Vector = Struct.new :x, :y
|
5
8
|
|
9
|
+
# This class represents a rectangle by its x and y coordinates and width and
|
10
|
+
# height.
|
6
11
|
class Rectangle
|
7
|
-
|
12
|
+
# The x-coordinate of the rectangle.
|
13
|
+
attr_accessor :x
|
8
14
|
|
15
|
+
# The y-coordinate of the rectangle.
|
16
|
+
attr_accessor :y
|
17
|
+
|
18
|
+
# The width of the rectangle.
|
19
|
+
attr_accessor :w
|
20
|
+
|
21
|
+
# The height of the rectangle.
|
22
|
+
attr_accessor :h
|
23
|
+
|
24
|
+
# Creates a new rectangle.
|
25
|
+
# Parameters:
|
26
|
+
# [x] The x-coordinate of the rectangle.
|
27
|
+
# [y] The y-coordinate of the rectangle.
|
28
|
+
# [w] The width of the rectangle.
|
29
|
+
# [h] The height of the rectangle.
|
9
30
|
def initialize x, y, w, h
|
10
31
|
@x = x; @y = y; @w = w; @h = h
|
11
32
|
end
|
12
33
|
|
34
|
+
# Returns whether this rectangle intersects another.
|
35
|
+
# Parameters:
|
36
|
+
# [r] The rectangle to check intersection with.
|
13
37
|
def intersects r
|
14
38
|
@x < r.x + r.w && @x + @w > r.x && @y < r.y + r.h && @y + @h > r.y
|
15
39
|
end
|
16
40
|
end
|
17
41
|
|
42
|
+
# The main class for a MiniGL game, holds references to globally accessible
|
43
|
+
# objects and constants.
|
18
44
|
class Game
|
45
|
+
# Initializes a MiniGL game. This method must be called before any feature
|
46
|
+
# provided by the library can be used.
|
47
|
+
# Parameters:
|
48
|
+
# [window] An instance of a class which inherits from
|
49
|
+
# <code>Gosu::Window</code>. This will be the game window, used
|
50
|
+
# to draw everything and capture user input.
|
51
|
+
# [gravity] A Vector object representing the horizontal and vertical
|
52
|
+
# components of the force of gravity. Essentially, this force
|
53
|
+
# will be applied to every object which calls +move+, from the
|
54
|
+
# Movement module.
|
55
|
+
# [kb_held_delay] The number of frames a key must be held by the user
|
56
|
+
# before the "held" event (that can be checked with
|
57
|
+
# <code>KB.key_held?</code>) starts to trigger.
|
58
|
+
# [kb_held_interval] The interval, in frames, between each triggering of
|
59
|
+
# the "held" event, after the key has been held for
|
60
|
+
# more than +kb_held_delay+ frames.
|
61
|
+
# [double_click_delay] The maximum interval, in frames, between two
|
62
|
+
# clicks, to trigger the "double click" event
|
63
|
+
# (checked with <code>Mouse.double_click?</code>).
|
19
64
|
def self.initialize window, gravity = Vector.new(0, 1),
|
20
65
|
kb_held_delay = 40, kb_held_interval = 5,
|
21
66
|
double_click_delay = 8
|
@@ -30,16 +75,29 @@ module AGL
|
|
30
75
|
Res.initialize
|
31
76
|
end
|
32
77
|
|
78
|
+
# Returns a reference to the game window.
|
33
79
|
def self.window; @@window; end
|
80
|
+
|
81
|
+
# Returns a Vector representing the force of gravity. See +initialize+ for
|
82
|
+
# details.
|
34
83
|
def self.gravity; @@gravity; end
|
84
|
+
|
85
|
+
# Returns the value of kb_held_delay. See +initialize+ for details.
|
35
86
|
def self.kb_held_delay; @@kb_held_delay; end
|
87
|
+
|
88
|
+
# Returns the value of kb_held_interval. See +initialize+ for details.
|
36
89
|
def self.kb_held_interval; @@kb_held_interval; end
|
90
|
+
|
91
|
+
# Returns the value of double_click_delay. See +initialize+ for details.
|
37
92
|
def self.double_click_delay; @@double_click_delay; end
|
38
93
|
end
|
39
94
|
|
40
95
|
#class JSHelper
|
41
96
|
|
97
|
+
# Exposes methods for controlling keyboard events.
|
42
98
|
class KB
|
99
|
+
# This is called by <code>Game.initialize</code>. Don't call it
|
100
|
+
# explicitly.
|
43
101
|
def self.initialize
|
44
102
|
@@keys = [
|
45
103
|
Gosu::KbUp, Gosu::KbDown,
|
@@ -66,6 +124,7 @@ module AGL
|
|
66
124
|
@@held_interval = {}
|
67
125
|
end
|
68
126
|
|
127
|
+
# Updates the state of all keys.
|
69
128
|
def self.update
|
70
129
|
@@held_timer.each do |k, v|
|
71
130
|
if v < Game.kb_held_delay; @@held_timer[k] += 1
|
@@ -93,24 +152,58 @@ module AGL
|
|
93
152
|
end
|
94
153
|
end
|
95
154
|
|
155
|
+
# Returns whether the given key is down in the current frame and was not
|
156
|
+
# down in the frame before.
|
157
|
+
# Parameters:
|
158
|
+
# [key] Code of the key to be checked. The available codes are <code>
|
159
|
+
# Gosu::KbUp, Gosu::KbDown, Gosu::KbReturn, Gosu::KbEscape,
|
160
|
+
# Gosu::KbLeftControl, Gosu::KbRightControl,
|
161
|
+
# Gosu::KbA, Gosu::KbB, Gosu::KbC, Gosu::KbD, Gosu::KbE, Gosu::KbF,
|
162
|
+
# Gosu::KbG, Gosu::KbH, Gosu::KbI, Gosu::KbJ, Gosu::KbK, Gosu::KbL,
|
163
|
+
# Gosu::KbM, Gosu::KbN, Gosu::KbO, Gosu::KbP, Gosu::KbQ, Gosu::KbR,
|
164
|
+
# Gosu::KbS, Gosu::KbT, Gosu::KbU, Gosu::KbV, Gosu::KbW, Gosu::KbX,
|
165
|
+
# Gosu::KbY, Gosu::KbZ, Gosu::Kb1, Gosu::Kb2, Gosu::Kb3, Gosu::Kb4,
|
166
|
+
# Gosu::Kb5, Gosu::Kb6, Gosu::Kb7, Gosu::Kb8, Gosu::Kb9, Gosu::Kb0,
|
167
|
+
# Gosu::KbNumpad1, Gosu::KbNumpad2, Gosu::KbNumpad3, Gosu::KbNumpad4,
|
168
|
+
# Gosu::KbNumpad5, Gosu::KbNumpad6, Gosu::KbNumpad7, Gosu::KbNumpad8,
|
169
|
+
# Gosu::KbNumpad9, Gosu::KbNumpad0, Gosu::KbSpace, Gosu::KbBackspace,
|
170
|
+
# Gosu::KbDelete, Gosu::KbLeft, Gosu::KbRight, Gosu::KbHome,
|
171
|
+
# Gosu::KbEnd, Gosu::KbLeftShift, Gosu::KbRightShift,
|
172
|
+
# Gosu::KbBacktick, Gosu::KbMinus, Gosu::KbEqual, Gosu::KbBracketLeft,
|
173
|
+
# Gosu::KbBracketRight, Gosu::KbBackslash, Gosu::KbApostrophe,
|
174
|
+
# Gosu::KbComma, Gosu::KbPeriod, Gosu::KbSlash</code>.
|
96
175
|
def self.key_pressed? key
|
97
176
|
@@prev_down.index(key).nil? and @@down.index(key)
|
98
177
|
end
|
99
178
|
|
179
|
+
# Returns whether the given key is down in the current frame.
|
180
|
+
# Parameters:
|
181
|
+
# [key] Code of the key to be checked. See +key_pressed?+ for details.
|
100
182
|
def self.key_down? key
|
101
183
|
@@down.index(key)
|
102
184
|
end
|
103
185
|
|
186
|
+
# Returns whether the given key is not down in the current frame but was
|
187
|
+
# down in the frame before.
|
188
|
+
# Parameters:
|
189
|
+
# [key] Code of the key to be checked. See +key_pressed?+ for details.
|
104
190
|
def self.key_released? key
|
105
191
|
@@prev_down.index(key) and @@down.index(key).nil?
|
106
192
|
end
|
107
193
|
|
194
|
+
# Returns whether the given key is being held down. See
|
195
|
+
# <code>Game.initialize</code> for details.
|
196
|
+
# Parameters:
|
197
|
+
# [key] Code of the key to be checked. See +key_pressed?+ for details.
|
108
198
|
def self.key_held? key
|
109
199
|
@@held_interval[key] == Game.kb_held_interval
|
110
200
|
end
|
111
201
|
end
|
112
202
|
|
203
|
+
# Exposes methods for controlling mouse events.
|
113
204
|
class Mouse
|
205
|
+
# This is called by <code>Game.initialize</code>. Don't call it
|
206
|
+
# explicitly.
|
114
207
|
def self.initialize
|
115
208
|
@@down = {}
|
116
209
|
@@prev_down = {}
|
@@ -118,6 +211,7 @@ module AGL
|
|
118
211
|
@@dbl_click_timer = {}
|
119
212
|
end
|
120
213
|
|
214
|
+
# Updates the mouse position and the state of all buttons.
|
121
215
|
def self.update
|
122
216
|
@@prev_down = @@down.clone
|
123
217
|
@@down.clear
|
@@ -144,31 +238,71 @@ module AGL
|
|
144
238
|
@@y = Game.window.mouse_y.round
|
145
239
|
end
|
146
240
|
|
241
|
+
# Returns the x-coordinate of the mouse cursor in the screen.
|
147
242
|
def self.x; @@x; end
|
243
|
+
|
244
|
+
# Returns the y-coordinate of the mouse cursor in the screen.
|
148
245
|
def self.y; @@y; end
|
149
246
|
|
247
|
+
# Returns whether the given button is down in the current frame and was
|
248
|
+
# not down in the frame before.
|
249
|
+
# Parameters:
|
250
|
+
# [btn] Button to be checked. Valid values are +:left+, +:middle+ and
|
251
|
+
# +:right+
|
150
252
|
def self.button_pressed? btn
|
151
253
|
@@down[btn] and not @@prev_down[btn]
|
152
254
|
end
|
153
255
|
|
256
|
+
# Returns whether the given button is down in the current frame.
|
257
|
+
# Parameters:
|
258
|
+
# [btn] Button to be checked. Valid values are +:left+, +:middle+ and
|
259
|
+
# +:right+
|
154
260
|
def self.button_down? btn
|
155
261
|
@@down[btn]
|
156
262
|
end
|
157
263
|
|
264
|
+
# Returns whether the given button is not down in the current frame, but
|
265
|
+
# was down in the frame before.
|
266
|
+
# Parameters:
|
267
|
+
# [btn] Button to be checked. Valid values are +:left+, +:middle+ and
|
268
|
+
# +:right+
|
158
269
|
def self.button_released? btn
|
159
270
|
@@prev_down[btn] and not @@down[btn]
|
160
271
|
end
|
161
272
|
|
273
|
+
# Returns whether the given button has just been double clicked.
|
274
|
+
# Parameters:
|
275
|
+
# [btn] Button to be checked. Valid values are +:left+, +:middle+ and
|
276
|
+
# +:right+
|
162
277
|
def self.double_click? btn
|
163
278
|
@@dbl_click[btn]
|
164
279
|
end
|
165
280
|
|
281
|
+
# Returns whether the mouse cursor is currently inside the given area.
|
282
|
+
# Parameters:
|
283
|
+
# [x] The x-coordinate of the top left corner of the area.
|
284
|
+
# [y] The y-coordinate of the top left corner of the area.
|
285
|
+
# [w] The width of the area.
|
286
|
+
# [h] The height of the area.
|
166
287
|
def self.over? x, y, w, h
|
167
288
|
@@x >= x and @@x < x + w and @@y >= y and @@y < y + h
|
168
289
|
end
|
169
290
|
end
|
170
291
|
|
292
|
+
# This class is responsible for resource management. It keeps references to
|
293
|
+
# all loaded resources until a call to +clear+ is made. Resources can be
|
294
|
+
# loaded as global, so that their references won't be removed even when
|
295
|
+
# +clear+ is called.
|
296
|
+
#
|
297
|
+
# It also provides an easier syntax for loading resources, assuming a
|
298
|
+
# particular folder structure. All resources must be inside subdirectories
|
299
|
+
# of a 'data' directory, so that you will only need to specify the type of
|
300
|
+
# resource being loaded and the file name (either as string or as symbol).
|
301
|
+
# There are default extensions for each type of resource, so the extension
|
302
|
+
# must be specified only if the file is in a format other than the default.
|
171
303
|
class Res
|
304
|
+
# This is called by <code>Game.initialize</code>. Don't call it
|
305
|
+
# explicitly.
|
172
306
|
def self.initialize
|
173
307
|
@@imgs = Hash.new
|
174
308
|
@@global_imgs = Hash.new
|
@@ -176,10 +310,28 @@ module AGL
|
|
176
310
|
@@global_tilesets = Hash.new
|
177
311
|
@@sounds = Hash.new
|
178
312
|
@@global_sounds = Hash.new
|
313
|
+
@@songs = Hash.new
|
314
|
+
@@global_songs = Hash.new
|
179
315
|
@@fonts = Hash.new
|
180
316
|
@@global_fonts = Hash.new
|
181
317
|
end
|
182
318
|
|
319
|
+
# Returns a <code>Gosu::Image</code> object.
|
320
|
+
# Parameters:
|
321
|
+
# [id] A string or symbol representing the path to the image. If the file
|
322
|
+
# is inside 'data/img', only the file name is needed. If it's inside
|
323
|
+
# a subdirectory, the id must be prefixed by each subdirectory name
|
324
|
+
# followed by an underscore. Example: to load
|
325
|
+
# 'data/img/sprite/1.png', provide +:sprite_1+ or "sprite_1".
|
326
|
+
# [global] Set to true if you want to keep the image in memory until the
|
327
|
+
# game execution is finished. If false, the image will be
|
328
|
+
# released when you call +clear+.
|
329
|
+
# [tileable] Whether the image should be loaded in tileable mode, which is
|
330
|
+
# proper for images that will be used as a tile, i.e., that
|
331
|
+
# will be drawn repeated times, side by side, forming a
|
332
|
+
# continuous composition.
|
333
|
+
# [ext] The extension of the file being loaded. Specify only if it is
|
334
|
+
# other than ".png".
|
183
335
|
def self.img id, global = false, tileable = false, ext = ".png"
|
184
336
|
if global; a = @@global_imgs; else; a = @@imgs; end
|
185
337
|
return a[id] if a[id]
|
@@ -188,6 +340,20 @@ module AGL
|
|
188
340
|
a[id] = img
|
189
341
|
end
|
190
342
|
|
343
|
+
# Returns an array of <code>Gosu::Image</code> objects, using the image as
|
344
|
+
# a spritesheet. The image with index 0 will be the top left sprite, and
|
345
|
+
# the following indices raise first from left to right and then from top
|
346
|
+
# to bottom.
|
347
|
+
# Parameters:
|
348
|
+
# [id] A string or symbol representing the path to the image. See +img+
|
349
|
+
# for details.
|
350
|
+
# [sprite_cols] Number of columns in the spritesheet.
|
351
|
+
# [sprite_rows] Number of rows in the spritesheet.
|
352
|
+
# [global] Set to true if you want to keep the image in memory until the
|
353
|
+
# game execution is finished. If false, the image will be
|
354
|
+
# released when you call +clear+.
|
355
|
+
# [ext] The extension of the file being loaded. Specify only if it is
|
356
|
+
# other than ".png".
|
191
357
|
def self.imgs id, sprite_cols, sprite_rows, global = false, ext = ".png"
|
192
358
|
if global; a = @@global_imgs; else; a = @@imgs; end
|
193
359
|
return a[id] if a[id]
|
@@ -196,6 +362,21 @@ module AGL
|
|
196
362
|
a[id] = imgs
|
197
363
|
end
|
198
364
|
|
365
|
+
# Returns an array of <code>Gosu::Image</code> objects, using the image as
|
366
|
+
# a tileset. Works the same as +imgs+, except you must provide the tile
|
367
|
+
# size instead of the number of columns and rows, and that the images will
|
368
|
+
# be loaded as tileable.
|
369
|
+
# Parameters:
|
370
|
+
# [id] A string or symbol representing the path to the image. It must be
|
371
|
+
# specified the same way as in +img+, but the base directory is
|
372
|
+
# 'data/tileset'.
|
373
|
+
# [tile_width] Width of each tile, in pixels.
|
374
|
+
# [tile_height] Height of each tile, in pixels.
|
375
|
+
# [global] Set to true if you want to keep the image in memory until the
|
376
|
+
# game execution is finished. If false, the image will be
|
377
|
+
# released when you call +clear+.
|
378
|
+
# [ext] The extension of the file being loaded. Specify only if it is
|
379
|
+
# other than ".png".
|
199
380
|
def self.tileset id, tile_width = 32, tile_height = 32, global = false, ext = ".png"
|
200
381
|
if global; a = @@global_tilesets; else; a = @@tilesets; end
|
201
382
|
return a[id] if a[id]
|
@@ -204,6 +385,17 @@ module AGL
|
|
204
385
|
a[id] = tileset
|
205
386
|
end
|
206
387
|
|
388
|
+
# Returns a <code>Gosu::Sample</code> object. This should be used for
|
389
|
+
# simple and short sound effects.
|
390
|
+
# Parameters:
|
391
|
+
# [id] A string or symbol representing the path to the sound. It must be
|
392
|
+
# specified the same way as in +img+, but the base directory is
|
393
|
+
# 'data/sound'.
|
394
|
+
# [global] Set to true if you want to keep the sound in memory until the
|
395
|
+
# game execution is finished. If false, the sound will be
|
396
|
+
# released when you call +clear+.
|
397
|
+
# [ext] The extension of the file being loaded. Specify only if it is
|
398
|
+
# other than ".wav".
|
207
399
|
def self.sound id, global = false, ext = ".wav"
|
208
400
|
if global; a = @@global_sounds; else; a = @@sounds; end
|
209
401
|
return a[id] if a[id]
|
@@ -212,14 +404,39 @@ module AGL
|
|
212
404
|
a[id] = sound
|
213
405
|
end
|
214
406
|
|
407
|
+
# Returns a <code>Gosu::Song</code> object. This should be used for the
|
408
|
+
# background musics of your game.
|
409
|
+
# Parameters:
|
410
|
+
# [id] A string or symbol representing the path to the song. It must be
|
411
|
+
# specified the same way as in +img+, but the base directory is
|
412
|
+
# 'data/song'.
|
413
|
+
# [global] Set to true if you want to keep the song in memory until the
|
414
|
+
# game execution is finished. If false, the song will be released
|
415
|
+
# when you call +clear+.
|
416
|
+
# [ext] The extension of the file being loaded. Specify only if it is
|
417
|
+
# other than ".ogg".
|
215
418
|
def self.song id, global = false, ext = ".ogg"
|
216
|
-
if global; a = @@
|
419
|
+
if global; a = @@global_songs; else; a = @@songs; end
|
217
420
|
return a[id] if a[id]
|
218
421
|
s = "data/song/" + id.to_s.split('_').join('/') + ext
|
219
422
|
song = Gosu::Song.new Game.window, s
|
220
423
|
a[id] = song
|
221
424
|
end
|
222
425
|
|
426
|
+
# Returns a <code>Gosu::Font</code> object. Fonts are needed to draw text
|
427
|
+
# and used by MiniGL elements like buttons, text fields and TextHelper
|
428
|
+
# objects.
|
429
|
+
# Parameters:
|
430
|
+
# [id] A string or symbol representing the path to the song. It must be
|
431
|
+
# specified the same way as in +img+, but the base directory is
|
432
|
+
# 'data/font'.
|
433
|
+
# [size] The size of the font, in pixels. This will correspond,
|
434
|
+
# approximately, to the height of the tallest character when drawn.
|
435
|
+
# [global] Set to true if you want to keep the font in memory until the
|
436
|
+
# game execution is finished. If false, the font will be released
|
437
|
+
# when you call +clear+.
|
438
|
+
# [ext] The extension of the file being loaded. Specify only if it is
|
439
|
+
# other than ".ttf".
|
223
440
|
def self.font id, size, global = true, ext = ".ttf"
|
224
441
|
if global; a = @@global_fonts; else; a = @@fonts; end
|
225
442
|
id_size = "#{id}_#{size}"
|
@@ -229,14 +446,12 @@ module AGL
|
|
229
446
|
a[id_size] = font
|
230
447
|
end
|
231
448
|
|
232
|
-
#
|
233
|
-
# G.texts[G.lang][id.to_sym]
|
234
|
-
# end
|
235
|
-
|
449
|
+
# Releases the memory used by all non-global resources.
|
236
450
|
def self.clear
|
237
451
|
@@imgs.clear
|
238
452
|
@@tilesets.clear
|
239
453
|
@@sounds.clear
|
454
|
+
@@songs.clear
|
240
455
|
@@fonts.clear
|
241
456
|
end
|
242
457
|
end
|
data/lib/minigl/map.rb
CHANGED
@@ -1,9 +1,28 @@
|
|
1
1
|
require_relative 'global'
|
2
2
|
|
3
3
|
module AGL
|
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.
|
4
7
|
class Map
|
5
|
-
|
8
|
+
# A Vector where x is the tile width and y is the tile height.
|
9
|
+
attr_reader :tile_size
|
6
10
|
|
11
|
+
# A Vector where x is the horizontal tile count and y the vertical count.
|
12
|
+
attr_reader :size
|
13
|
+
|
14
|
+
# A Rectangle representing the region of the map that is currently
|
15
|
+
# visible.
|
16
|
+
attr_reader :cam
|
17
|
+
|
18
|
+
# Creates a new map.
|
19
|
+
# Parameters:
|
20
|
+
# [t_w] The width of the tiles.
|
21
|
+
# [t_h] The height of the tiles.
|
22
|
+
# [t_x_count] The horizontal count of tiles in the map.
|
23
|
+
# [t_y_count] The vertical count of tiles in the map.
|
24
|
+
# [scr_w] Width of the viewport for the map.
|
25
|
+
# [scr_h] Height of the viewport for the map.
|
7
26
|
def initialize t_w, t_h, t_x_count, t_y_count, scr_w = 800, scr_h = 600
|
8
27
|
@tile_size = Vector.new t_w, t_h
|
9
28
|
@size = Vector.new t_x_count, t_y_count
|
@@ -12,38 +31,79 @@ module AGL
|
|
12
31
|
@max_y = t_y_count * t_h - scr_h
|
13
32
|
end
|
14
33
|
|
34
|
+
# Returns a Vector with the total size of the map, in pixels (x for the
|
35
|
+
# width and y for the height).
|
15
36
|
def get_absolute_size
|
16
37
|
Vector.new(@tile_size.x * @size.x, @tile_size.y * @size.y)
|
17
38
|
end
|
18
39
|
|
40
|
+
# Returns a Vector with the coordinates of the center of the map.
|
19
41
|
def get_center
|
20
42
|
Vector.new(@tile_size.x * @size.x / 2, @tile_size.y * @size.y / 2)
|
21
43
|
end
|
22
44
|
|
45
|
+
# Returns the position in the screen corresponding to the given tile
|
46
|
+
# indices.
|
47
|
+
# Parameters:
|
48
|
+
# [map_x] The index of the tile in the horizontal direction. It must be in
|
49
|
+
# the interval <code>0..t_x_count</code>.
|
50
|
+
# [map_y] The index of the tile in the vertical direction. It must be in
|
51
|
+
# the interval <code>0..t_y_count</code>.
|
23
52
|
def get_screen_pos map_x, map_y
|
24
53
|
Vector.new(map_x * @tile_size.x - @cam.x, map_y * @tile_size.y - @cam.y)
|
25
54
|
end
|
26
55
|
|
56
|
+
# Returns the tile in the map that corresponds to the given position in
|
57
|
+
# the screen, as a Vector, where x is the horizontal index and y the
|
58
|
+
# vertical index.
|
59
|
+
# Parameters:
|
60
|
+
# [scr_x] The x-coordinate in the screen.
|
61
|
+
# [scr_y] The y-coordinate in the screen.
|
27
62
|
def get_map_pos scr_x, scr_y
|
28
63
|
Vector.new((scr_x + @cam.x) / @tile_size.x, (scr_y + @cam.y) / @tile_size.y)
|
29
64
|
end
|
30
65
|
|
66
|
+
# Verifies whether a tile is inside the map.
|
67
|
+
# Parameters:
|
68
|
+
# [v] A Vector representing the tile, with x as the horizontal index and
|
69
|
+
# y as the vertical index.
|
31
70
|
def is_in_map v
|
32
71
|
v.x >= 0 && v.y >= 0 && v.x < @size.x && v.y < @size.y
|
33
72
|
end
|
34
73
|
|
74
|
+
# Sets the top left corner of the viewport to the given position of the
|
75
|
+
# map. Note that this is not the position in the screen.
|
76
|
+
# Parameters:
|
77
|
+
# [cam_x] The x-coordinate inside the map, in pixels (not a tile index).
|
78
|
+
# [cam_y] The y-coordinate inside the map, in pixels (not a tile index).
|
35
79
|
def set_camera cam_x, cam_y
|
36
80
|
@cam.x = cam_x
|
37
81
|
@cam.y = cam_y
|
38
82
|
set_bounds
|
39
83
|
end
|
40
84
|
|
85
|
+
# Moves the viewport by the given amount of pixels.
|
86
|
+
# Parameters:
|
87
|
+
# [x] The amount of pixels to move horizontally. Negative values will
|
88
|
+
# cause the camera to move to the left.
|
89
|
+
# [y] The amount of pixels to move vertically. Negative values will cause
|
90
|
+
# the camera to move up.
|
41
91
|
def move_camera x, y
|
42
92
|
@cam.x += x
|
43
93
|
@cam.y += y
|
44
94
|
set_bounds
|
45
95
|
end
|
46
96
|
|
97
|
+
# Iterates through the currently visible tiles, providing the horizontal
|
98
|
+
# tile index, the vertical tile index, the x-coordinate (in pixels) and
|
99
|
+
# the y-coordinate (in pixels), of each tile, in that order, to a given
|
100
|
+
# block of code.
|
101
|
+
#
|
102
|
+
# Example:
|
103
|
+
#
|
104
|
+
# map.foreach do |i, j, x, y|
|
105
|
+
# draw_tile tiles[i][j], x, y
|
106
|
+
# end
|
47
107
|
def foreach
|
48
108
|
for j in @min_vis_y..@max_vis_y
|
49
109
|
for i in @min_vis_x..@max_vis_x
|
data/lib/minigl/movement.rb
CHANGED
@@ -1,20 +1,67 @@
|
|
1
1
|
require_relative 'global'
|
2
2
|
|
3
3
|
module AGL
|
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.
|
4
7
|
class Block
|
5
|
-
|
8
|
+
# The x-coordinate of the top left corner of the bounding box.
|
9
|
+
attr_reader :x
|
6
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
|
+
# Parameters:
|
26
|
+
# [x] The x-coordinate of the top left corner of the bounding box.
|
27
|
+
# [y] The y-coordinate of the top left corner of the bounding box.
|
28
|
+
# [w] The width of the bounding box.
|
29
|
+
# [h] The height of the bounding box.
|
30
|
+
# [passable] Whether a moving object can pass through this block when
|
31
|
+
# coming from below. This is a common feature of platforms in platform
|
32
|
+
# games.
|
7
33
|
def initialize x, y, w, h, passable
|
8
34
|
@x = x; @y = y; @w = w; @h = h
|
9
35
|
@passable = passable
|
10
36
|
end
|
11
37
|
|
38
|
+
# Returns the bounding box of this block as a Rectangle.
|
12
39
|
def bounds
|
13
40
|
Rectangle.new @x, @y, @w, @h
|
14
41
|
end
|
15
42
|
end
|
16
43
|
|
44
|
+
# Represents a ramp, i.e., an inclined structure which allows walking over
|
45
|
+
# it while automatically going up or down. It can be imagined as a right
|
46
|
+
# triangle, with a side parallel to the x axis and another one parallel to
|
47
|
+
# the y axis. You must provide instances of this class (or derived classes)
|
48
|
+
# to the +ramps+ array parameter of the +move+ method.
|
17
49
|
class Ramp
|
50
|
+
# Creates a new ramp.
|
51
|
+
# Parameters:
|
52
|
+
# [x] The x-coordinate of the top left corner of a rectangle that
|
53
|
+
# completely (and precisely) encloses the ramp (thought of as a right
|
54
|
+
# triangle).
|
55
|
+
# [y] The y-coordinate of the top left corner of the rectangle described
|
56
|
+
# above.
|
57
|
+
# [w] The width of the ramp (which corresponds to the width of the
|
58
|
+
# rectangle described above).
|
59
|
+
# [h] The height of the ramp (which corresponds to the height of the
|
60
|
+
# rectangle described above, and to the difference between the lowest
|
61
|
+
# point of the ramp, where it usually meets the floor, and the
|
62
|
+
# highest).
|
63
|
+
# [left] Whether the height of the ramp increases from left to right. Use
|
64
|
+
# +false+ for a ramp that goes down from left to right.
|
18
65
|
def initialize x, y, w, h, left
|
19
66
|
@x = x
|
20
67
|
@y = y
|
@@ -23,6 +70,24 @@ module AGL
|
|
23
70
|
@left = left
|
24
71
|
end
|
25
72
|
|
73
|
+
# Checks if an object is in contact with this ramp (standing over it).
|
74
|
+
# Parameters:
|
75
|
+
# [obj] The object to check contact with. It must have the +x+, +y+, +w+
|
76
|
+
# and +h+ accessible attributes determining its bounding box.
|
77
|
+
def contact? obj
|
78
|
+
obj.x.round(6) == get_x(obj).round(6) && obj.y.round(6) == get_y(obj).round(6)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Checks if an object is intersecting this ramp (inside the corresponding
|
82
|
+
# right triangle and at the floor level or above).
|
83
|
+
# Parameters:
|
84
|
+
# [obj] The object to check intersection with. It must have the +x+, +y+,
|
85
|
+
# +w+ and +h+ accessible attributes determining its bounding box.
|
86
|
+
def intersects obj
|
87
|
+
obj.x + obj.w > @x && obj.x < @x + @w && obj.y > get_y(obj) && obj.y <= @y + @h - obj.h
|
88
|
+
end
|
89
|
+
|
90
|
+
# :nodoc:
|
26
91
|
def can_collide? obj
|
27
92
|
@can_collide = (obj.speed.y >= 0 and not intersects(obj))
|
28
93
|
end
|
@@ -46,14 +111,6 @@ module AGL
|
|
46
111
|
end
|
47
112
|
end
|
48
113
|
|
49
|
-
def contact? obj
|
50
|
-
obj.x.round(6) == get_x(obj).round(6) && obj.y.round(6) == get_y(obj).round(6)
|
51
|
-
end
|
52
|
-
|
53
|
-
def intersects obj
|
54
|
-
obj.x + obj.w > @x && obj.x < @x + @w && obj.y > get_y(obj) && obj.y <= @y + @h - obj.h
|
55
|
-
end
|
56
|
-
|
57
114
|
def get_x obj
|
58
115
|
return @x + (1.0 * (@y + @h - obj.y - obj.h) * @w / @h) - obj.w if @left
|
59
116
|
@x + (1.0 * (obj.y + obj.h - @y) * @w / @h)
|
@@ -67,14 +124,66 @@ module AGL
|
|
67
124
|
end
|
68
125
|
end
|
69
126
|
|
127
|
+
# This module provides objects with physical properties and methods for
|
128
|
+
# moving. It allows moving with or without collision checking (based on
|
129
|
+
# rectangular bounding boxes), including a method to behave as an elevator,
|
130
|
+
# affecting other objects' positions as it moves.
|
70
131
|
module Movement
|
71
|
-
|
72
|
-
|
73
|
-
|
132
|
+
# A Vector with the current speed of the object (x: horizontal component,
|
133
|
+
# y: vertical component).
|
134
|
+
attr_reader :speed
|
135
|
+
|
136
|
+
# Width of the bounding box.
|
137
|
+
attr_reader :w
|
138
|
+
|
139
|
+
# Height of the bounding box.
|
140
|
+
attr_reader :h
|
141
|
+
|
142
|
+
# Whether a moving object can pass through this block when coming from
|
143
|
+
# below. This is a common feature of platforms in platform games.
|
144
|
+
attr_reader :passable
|
145
|
+
|
146
|
+
# The object that is making contact with this from above. If there's no
|
147
|
+
# contact, returns +nil+.
|
148
|
+
attr_reader :top
|
149
|
+
|
150
|
+
# The object that is making contact with this from below. If there's no
|
151
|
+
# contact, returns +nil+.
|
152
|
+
attr_reader :bottom
|
153
|
+
|
154
|
+
# The object that is making contact with this from the left. If there's no
|
155
|
+
# contact, returns +nil+.
|
156
|
+
attr_reader :left
|
157
|
+
|
158
|
+
# The object that is making contact with this from the right. If there's
|
159
|
+
# no contact, returns +nil+.
|
160
|
+
attr_reader :right
|
161
|
+
|
162
|
+
# The x-coordinate of the top left corner of the bounding box.
|
163
|
+
attr_accessor :x
|
164
|
+
|
165
|
+
# The y-coordinate of the top left corner of the bounding box.
|
166
|
+
attr_accessor :y
|
167
|
+
|
168
|
+
# A Vector with the horizontal and vertical components of a force that
|
169
|
+
# be applied in the next time +move+ is called.
|
170
|
+
attr_accessor :stored_forces
|
171
|
+
|
172
|
+
# Returns the bounding box as a Rectangle.
|
74
173
|
def bounds
|
75
174
|
Rectangle.new @x, @y, @w, @h
|
76
175
|
end
|
77
|
-
|
176
|
+
|
177
|
+
# Moves this object, based on the forces being applied to it, and
|
178
|
+
# performing collision checking.
|
179
|
+
# Parameters:
|
180
|
+
# [forces] A Vector where x is the horizontal component of the resulting
|
181
|
+
# force and y is the vertical component.
|
182
|
+
# [obst] An array of obstacles to be considered in the collision checking.
|
183
|
+
# Obstacles must be instances of Block (or derived classes), or
|
184
|
+
# objects that <code>include Movement</code>.
|
185
|
+
# [ramps] An array of ramps to be considered in the collision checking.
|
186
|
+
# Ramps must be instances of Ramp (or derived classes).
|
78
187
|
def move forces, obst, ramps
|
79
188
|
forces.x += Game.gravity.x; forces.y += Game.gravity.y
|
80
189
|
forces.x += @stored_forces.x; forces.y += @stored_forces.y
|
@@ -173,7 +282,17 @@ module AGL
|
|
173
282
|
end
|
174
283
|
check_contact obst, ramps
|
175
284
|
end
|
176
|
-
|
285
|
+
|
286
|
+
# Moves this object as an elevator (i.e., potentially carrying other
|
287
|
+
# objects) towards a given point.
|
288
|
+
# Parameters:
|
289
|
+
# [aim] A Vector specifying where the object will move to.
|
290
|
+
# [speed] The constant speed at which the object will move. This must be
|
291
|
+
# provided as a scalar, not a vector.
|
292
|
+
# [obstacles] An array of obstacles to be considered in the collision
|
293
|
+
# checking, and carried along when colliding from above.
|
294
|
+
# Obstacles must be instances of Block (or derived classes),
|
295
|
+
# or objects that <code>include Movement</code>.
|
177
296
|
def move_carrying aim, speed, obstacles
|
178
297
|
x_d = aim.x - @x; y_d = aim.y - @y
|
179
298
|
distance = Math.sqrt(x_d**2 + y_d**2)
|
@@ -206,7 +325,13 @@ module AGL
|
|
206
325
|
|
207
326
|
passengers.each do |p| p.y = @y - p.h end
|
208
327
|
end
|
209
|
-
|
328
|
+
|
329
|
+
# Moves this object, without performing any collision checking, towards
|
330
|
+
# the specified point.
|
331
|
+
# Parameters:
|
332
|
+
# [aim] A Vector specifying where the object will move to.
|
333
|
+
# [speed] The constant speed at which the object will move. This must be
|
334
|
+
# provided as a scalar, not a vector.
|
210
335
|
def move_free aim, speed
|
211
336
|
x_d = aim.x - @x; y_d = aim.y - @y
|
212
337
|
distance = Math.sqrt(x_d**2 + y_d**2)
|
@@ -227,7 +352,24 @@ module AGL
|
|
227
352
|
@y += @speed.y
|
228
353
|
end
|
229
354
|
end
|
230
|
-
|
355
|
+
|
356
|
+
# Causes the object to move in cycles across multiple given points (the
|
357
|
+
# method must be called repeatedly, and it returns the value that must be
|
358
|
+
# provided to +cur_point+ after the first call). If obstacles are
|
359
|
+
# provided, it will behave as an elevator (as in +move_carrying+).
|
360
|
+
# Parameters:
|
361
|
+
# [points] An array of Vectors representing the path that the object will
|
362
|
+
# perform.
|
363
|
+
# [cur_point] The index of the point in the path that the object is
|
364
|
+
# currently moving to. In the first call, it is a good idea to
|
365
|
+
# provide 0, while in the subsequent calls, you must provide
|
366
|
+
# the return value of this method.
|
367
|
+
# [speed] The constant speed at which the object will move. This must be
|
368
|
+
# provided as a scalar, not a vector.
|
369
|
+
# [obstacles] An array of obstacles to be considered in the collision
|
370
|
+
# checking, and carried along when colliding from above.
|
371
|
+
# Obstacles must be instances of Block (or derived classes),
|
372
|
+
# or objects that <code>include Movement</code>.
|
231
373
|
def cycle points, cur_point, speed, obstacles = nil
|
232
374
|
if obstacles
|
233
375
|
move_carrying points[cur_point], speed, obstacles
|
data/lib/minigl/text.rb
CHANGED
@@ -1,10 +1,32 @@
|
|
1
1
|
module AGL
|
2
|
+
# This class provides methods for easily drawing one or multiple lines of
|
3
|
+
# text, with control over the text alignment and coloring.
|
2
4
|
class TextHelper
|
5
|
+
# Creates a TextHelper.
|
6
|
+
# Parameters:
|
7
|
+
# [font] A <code>Gosu::Font</code> that will be used to draw the text.
|
8
|
+
# [line_spacing] When drawing multiple lines, the distance, in pixels,
|
9
|
+
# between each line.
|
3
10
|
def initialize font, line_spacing = 0
|
4
11
|
@font = font
|
5
12
|
@line_spacing = line_spacing
|
6
13
|
end
|
7
|
-
|
14
|
+
|
15
|
+
# Draws a single line of text.
|
16
|
+
# Parameters:
|
17
|
+
# [text] The text to be drawn. No line breaks are allowed.
|
18
|
+
# [x] The horizontal reference for drawing the text. If +mode+ is +:left+,
|
19
|
+
# all text will be drawn from this point to the right; if +mode+ is
|
20
|
+
# +:right+, all text will be drawn from this point to the left; and if
|
21
|
+
# +mode+ is +:center+, the text will be equally distributed to the
|
22
|
+
# left and to the right of this point.
|
23
|
+
# [y] The vertical reference for drawing the text. All text will be drawn
|
24
|
+
# from this point down.
|
25
|
+
# [mode] The alignment of the text. Valid values are +:left+, +:right+ and
|
26
|
+
# +:center+.
|
27
|
+
# [color] The color of the text, in hexadecimal RRGGBB format.
|
28
|
+
# [alpha] The opacity of the text. Valid values vary from 0 (fully
|
29
|
+
# transparent) to 255 (fully opaque).
|
8
30
|
def write_line text, x, y, mode = :left, color = 0, alpha = 0xff
|
9
31
|
color = (alpha << 24) | color
|
10
32
|
rel =
|
@@ -16,7 +38,23 @@ module AGL
|
|
16
38
|
end
|
17
39
|
@font.draw_rel text, x, y, 0, rel, 0, 1, 1, color
|
18
40
|
end
|
19
|
-
|
41
|
+
|
42
|
+
# Draws text, breaking lines when needed and when explicitly caused by the
|
43
|
+
# "\n" character.
|
44
|
+
# Parameters:
|
45
|
+
# [text] The text to be drawn. Line breaks are allowed.
|
46
|
+
# [x] The horizontal reference for drawing the text. Works like in
|
47
|
+
# +write_line+ for the +:left+, +:right+ and +:center+ modes. For the
|
48
|
+
# +:justified+ mode, works the same as for +:left+.
|
49
|
+
# [y] The vertical reference for drawing the text. All text will be drawn
|
50
|
+
# from this point down.
|
51
|
+
# [width] The maximum width for the lines of text. Line is broken when
|
52
|
+
# this width is exceeded.
|
53
|
+
# [mode] The alignment of the text. Valid values are +:left+, +:right+,
|
54
|
+
# +:center+ and +:justified+.
|
55
|
+
# [color] The color of the text, in hexadecimal RRGGBB format.
|
56
|
+
# [alpha] The opacity of the text. Valid values vary from 0 (fully
|
57
|
+
# transparent) to 255 (fully opaque).
|
20
58
|
def write_breaking text, x, y, width, mode = :left, color = 0, alpha = 0xff
|
21
59
|
color = (alpha << 24) | color
|
22
60
|
text.split("\n").each do |p|
|
data/test/game.rb
CHANGED
@@ -11,8 +11,8 @@ class MyGame < Gosu::Window
|
|
11
11
|
|
12
12
|
@font = Res.font :font1, 20
|
13
13
|
@writer = TextHelper.new @font, 5
|
14
|
-
@btn = Button.new(10, 560, @font, "Test", :btn, 0x008000
|
15
|
-
@txt = TextField.new 10, 520, @font, :text, nil, 15, 5, 16, false, "", 0, 0x0000ff
|
14
|
+
@btn = Button.new(10, 560, @font, "Test", :btn, 0x008000) {}
|
15
|
+
@txt = TextField.new 10, 520, @font, :text, nil, 15, 5, 16, false, "", nil, 0, 0x0000ff
|
16
16
|
end
|
17
17
|
|
18
18
|
def needs_cursor?
|
@@ -25,6 +25,8 @@ class MyGame < Gosu::Window
|
|
25
25
|
@obj1.x += 1 if KB.key_down? Gosu::KbRight
|
26
26
|
@obj1.y += 1 if KB.key_held? Gosu::KbDown
|
27
27
|
@obj1.x -= 1 if KB.key_down? Gosu::KbLeft
|
28
|
+
@btn.set_position rand(700), rand(550) if KB.key_pressed? Gosu::KbSpace
|
29
|
+
@txt.set_position rand(700), rand(550) if KB.key_pressed? Gosu::KbReturn
|
28
30
|
|
29
31
|
Mouse.update
|
30
32
|
if Mouse.double_click? :left
|
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.2.
|
4
|
+
version: 1.2.6
|
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-07-
|
11
|
+
date: 2014-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gosu
|