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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 01d773ef32ca54ed13e397c386708830e7731e8e
4
- data.tar.gz: 810ff8899be10ec787147090c539ac0d7608f603
3
+ metadata.gz: d75703110c27893ced02abaa49767ac4137d1b34
4
+ data.tar.gz: c376306e0d0a7838ebae01863302a418408ce840
5
5
  SHA512:
6
- metadata.gz: 25128512170f5275e48a8baec43555ab0307f246703cde5eeb55a5d2d4a52ffa9dbc055d5bb7933786eac9c7f00e289c03d8acb982d1aed514482127ebe8f952
7
- data.tar.gz: 7e0a5f25b732eaba12c1156e471ea7e1cff6a68774e09be3f3d6e29fbb43903f67420b7aabab0f08640467e34ef24a7a1226d7d05a8f26f17f0c9eaf701db7d1
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.5**
24
+ **Version 1.2.6**
25
25
 
26
- * Added support for "invisible" buttons (for associating actions with clicks
27
- in screen areas).
28
- * Exposed `Button`'s `click` method and `TextField`'s `focus` and `unfocus`
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
@@ -5,3 +5,7 @@ Rake::TestTask.new do |t|
5
5
  t.test_files = FileList['test/*_tests.rb']
6
6
  t.verbose = true
7
7
  end
8
+
9
+ task :doc do |t|
10
+ sh "rdoc lib/minigl/*.rb"
11
+ end
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
- def initialize x, y, font, img, cursor_img = nil, margin_x = 0, margin_y = 0, max_length = 100, active = false,
94
- text = "", text_color = 0, selection_color = 0
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'-=/[]\\,.;\"_+?{}|<>:!@#$%6&*()"
132
- end
133
-
134
- def text= value
135
- @text = value[0...max_length]
136
- @nodes.clear; @nodes << (@x + @margin_x)
137
- x = @nodes[0]
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)
@@ -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
- attr_accessor :x, :y, :w, :h
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 = @@global_sounds; else; a = @@sounds; end
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
- # def self.text id
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
- attr_reader :tile_size, :size, :cam
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
@@ -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
- attr_reader :x, :y, :w, :h, :passable
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
- attr_reader :speed, :w, :h, :passable, :top, :bottom, :left, :right
72
- attr_accessor :x, :y, :stored_forces
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, false, 15, 5) {}
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.5
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-06 00:00:00.000000000 Z
11
+ date: 2014-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gosu