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