minigl 1.3.10 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  require_relative 'movement'
2
2
 
3
- module AGL
3
+ module MiniGL
4
4
  # This class represents an (optionally animated) image inside the game screen.
5
5
  class Sprite
6
6
  # The index of the current sprite in the spritesheet being drawn.
@@ -32,7 +32,7 @@ module AGL
32
32
  # image is not a spritesheet.
33
33
  # [sprite_rows] The number of rows in the spritesheet. Use +nil+ if the
34
34
  # image is not a spritesheet.
35
- def initialize x, y, img, sprite_cols = nil, sprite_rows = nil
35
+ def initialize(x, y, img, sprite_cols = nil, sprite_rows = nil)
36
36
  @x = x; @y = y
37
37
  @img =
38
38
  if sprite_cols.nil?
@@ -56,7 +56,7 @@ module AGL
56
56
  # [interval] The amount of frames between each change in the image index.
57
57
  # A frame will usually represent 1/60 second (roughly 17
58
58
  # milliseconds).
59
- def animate indices, interval
59
+ def animate(indices, interval)
60
60
  @anim_counter += 1
61
61
  if @anim_counter >= interval
62
62
  @index_index += 1
@@ -85,7 +85,7 @@ module AGL
85
85
  # its center.
86
86
  # [z_index] The z-order to draw the object. Objects with larger z-orders
87
87
  # will be drawn on top of the ones with smaller z-orders.
88
- def draw map = nil, scale_x = 1, scale_y = 1, alpha = 0xff, color = 0xffffff, angle = nil, z_index = 0
88
+ def draw(map = nil, scale_x = 1, scale_y = 1, alpha = 0xff, color = 0xffffff, angle = nil, z_index = 0)
89
89
  color = (alpha << 24) | color
90
90
  if map
91
91
  if angle
@@ -99,6 +99,15 @@ module AGL
99
99
  @img[@img_index].draw @x.round, @y.round, z_index, scale_x, scale_y, color
100
100
  end
101
101
  end
102
+
103
+ # Returns whether this sprite is visible in the given map (i.e., in the
104
+ # viewport determined by the camera of the given map). If no map is given,
105
+ # returns whether the sprite is visible on the screen.
106
+ def visible?(map = nil)
107
+ r = Rectangle.new @x, @y, @img[0].width, @img[0].height
108
+ return Rectangle.new(0, 0, G.window.width, G.window.height).intersect? r if map.nil?
109
+ map.cam.intersect? r
110
+ end
102
111
  end
103
112
 
104
113
  # This class represents an object with a set of properties and methods
@@ -128,7 +137,7 @@ module AGL
128
137
  # image is not a spritesheet.
129
138
  # [mass] The mass of the object. Details on how it is used can be found
130
139
  # in the Movement module.
131
- def initialize x, y, w, h, img, img_gap = nil, sprite_cols = nil, sprite_rows = nil, mass = 1.0
140
+ def initialize(x, y, w, h, img, img_gap = nil, sprite_cols = nil, sprite_rows = nil, mass = 1.0)
132
141
  super x, y, img, sprite_cols, sprite_rows
133
142
  @w = w; @h = h
134
143
  @img_gap =
@@ -139,7 +148,6 @@ module AGL
139
148
  end
140
149
  @mass = mass
141
150
  @speed = Vector.new 0, 0
142
- @min_speed = Vector.new 0.01, 0.01
143
151
  @max_speed = Vector.new 15, 15
144
152
  @stored_forces = Vector.new 0, 0
145
153
  end
@@ -149,7 +157,7 @@ module AGL
149
157
  #
150
158
  # Parameters:
151
159
  # [index] The image index to be set.
152
- def set_animation index
160
+ def set_animation(index)
153
161
  @anim_counter = 0
154
162
  @img_index = index
155
163
  @index_index = 0
@@ -174,7 +182,7 @@ module AGL
174
182
  # its center.
175
183
  # [z_index] The z-order to draw the object. Objects with larger z-orders
176
184
  # will be drawn on top of the ones with smaller z-orders.
177
- def draw map = nil, scale_x = 1, scale_y = 1, alpha = 0xff, color = 0xffffff, angle = nil, z_index = 0
185
+ def draw(map = nil, scale_x = 1, scale_y = 1, alpha = 0xff, color = 0xffffff, angle = nil, z_index = 0)
178
186
  color = (alpha << 24) | color
179
187
  if map
180
188
  if angle
@@ -190,6 +198,15 @@ module AGL
190
198
  @img[@img_index].draw @x.round + @img_gap.x, @y.round + @img_gap.y, z_index, scale_x, scale_y, color
191
199
  end
192
200
  end
201
+
202
+ # Returns whether this object is visible in the given map (i.e., in the
203
+ # viewport determined by the camera of the given map). If no map is given,
204
+ # returns whether the object is visible on the screen.
205
+ def visible?(map = nil)
206
+ r = Rectangle.new @x.round + @img_gap.x, @y.round + @img_gap.y, @img[0].width, @img[0].height
207
+ return Rectangle.new(0, 0, G.window.width, G.window.height).intersect? r if map.nil?
208
+ map.cam.intersect? r
209
+ end
193
210
  end
194
211
 
195
212
  # Represents a visual effect, i.e., a graphic - usually animated - that shows
@@ -222,7 +239,14 @@ module AGL
222
239
  # of the Effect object. If +nil+, it will be set to
223
240
  # <code>@indices.length * interval</code>, i.e., the exact time
224
241
  # needed for one animation cycle to complete.
225
- def initialize x, y, img, sprite_cols = nil, sprite_rows = nil, interval = 10, indices = nil, lifetime = nil
242
+ # [sound] The id of a sound to be played when the effect is created (id must
243
+ # be given in the format specified for the +Res.sound+ method).
244
+ # [sound_ext] Extension of the sound file, if a sound is given. Default is
245
+ # '.wav'.
246
+ # [sound_volume] The volume (from 0 to 1) to play the sound, if any. Default
247
+ # is 1.
248
+ def initialize(x, y, img, sprite_cols = nil, sprite_rows = nil, interval = 10, indices = nil, lifetime = nil,
249
+ sound = nil, sound_ext = '.wav', sound_volume = 1)
226
250
  super x, y, img, sprite_cols, sprite_rows
227
251
  @timer = 0
228
252
  if indices
@@ -236,6 +260,7 @@ module AGL
236
260
  else
237
261
  @lifetime = @indices.length * interval
238
262
  end
263
+ Res.sound(sound, false, sound_ext).play(sound_volume) if sound
239
264
  end
240
265
 
241
266
  # Updates the effect, animating and counting its remaining lifetime.
@@ -247,7 +272,7 @@ module AGL
247
272
  end
248
273
  end
249
274
 
250
- def draw map = nil, scale_x = 1, scale_y = 1, alpha = 0xff, color = 0xffffff, angle = nil, z_index = 0
275
+ def draw(map = nil, scale_x = 1, scale_y = 1, alpha = 0xff, color = 0xffffff, angle = nil, z_index = 0)
251
276
  super unless @dead
252
277
  end
253
278
  end
data/lib/minigl/global.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'gosu'
2
2
 
3
3
  # The main module of the library, used only as a namespace.
4
- module AGL
4
+ module MiniGL
5
5
  # This class represents a point or vector in a bidimensional space.
6
6
  class Vector
7
7
  # The x coordinate of the vector
@@ -15,7 +15,7 @@ module AGL
15
15
  # Parameters:
16
16
  # [x] The x coordinate of the vector
17
17
  # [y] The y coordinate of the vector
18
- def initialize x, y
18
+ def initialize(x = 0, y = 0)
19
19
  @x = x
20
20
  @y = y
21
21
  end
@@ -23,7 +23,7 @@ module AGL
23
23
  # Returns +true+ if both coordinates of this vector are equal to the
24
24
  # corresponding coordinates of +other_vector+, with +precision+ decimal
25
25
  # places of precision.
26
- def == other_vector, precision = 6
26
+ def ==(other_vector, precision = 6)
27
27
  @x.round(precision) == other_vector.x.round(precision) and
28
28
  @y.round(precision) == other_vector.y.round(precision)
29
29
  end
@@ -31,37 +31,37 @@ module AGL
31
31
  # Returns +true+ if at least one coordinate of this vector is different from
32
32
  # the corresponding coordinate of +other_vector+, with +precision+ decimal
33
33
  # places of precision.
34
- def != other_vector, precision = 6
34
+ def !=(other_vector, precision = 6)
35
35
  @x.round(precision) != other_vector.x.round(precision) or
36
36
  @y.round(precision) != other_vector.y.round(precision)
37
37
  end
38
38
 
39
39
  # Sums this vector with +other_vector+, i.e., sums each coordinate of this
40
40
  # vector with the corresponding coordinate of +other_vector+.
41
- def + other_vector
41
+ def +(other_vector)
42
42
  Vector.new @x + other_vector.x, @y + other_vector.y
43
43
  end
44
44
 
45
45
  # Subtracts +other_vector+ from this vector, i.e., subtracts from each
46
46
  # coordinate of this vector the corresponding coordinate of +other_vector+.
47
- def - other_vector
47
+ def -(other_vector)
48
48
  Vector.new @x - other_vector.x, @y - other_vector.y
49
49
  end
50
50
 
51
51
  # Multiplies this vector by a scalar, i.e., each coordinate is multiplied by
52
52
  # the given number.
53
- def * scalar
53
+ def *(scalar)
54
54
  Vector.new @x * scalar, @y * scalar
55
55
  end
56
56
 
57
57
  # Divides this vector by a scalar, i.e., each coordinate is divided by the
58
58
  # given number.
59
- def / scalar
59
+ def /(scalar)
60
60
  Vector.new @x / scalar.to_f, @y / scalar.to_f
61
61
  end
62
62
 
63
63
  # Returns the euclidean distance between this vector and +other_vector+.
64
- def distance other_vector
64
+ def distance(other_vector)
65
65
  dx = @x - other_vector.x
66
66
  dy = @y - other_vector.y
67
67
  Math.sqrt(dx ** 2 + dy ** 2)
@@ -69,14 +69,14 @@ module AGL
69
69
 
70
70
  # Returns a vector corresponding to the rotation of this vector around the
71
71
  # origin (0, 0) by +radians+ radians.
72
- def rotate radians
72
+ def rotate(radians)
73
73
  sin = Math.sin radians
74
74
  cos = Math.cos radians
75
75
  Vector.new cos * @x - sin * @y, sin * @x + cos * @y
76
76
  end
77
77
 
78
78
  # Rotates this vector by +radians+ radians around the origin (0, 0).
79
- def rotate! radians
79
+ def rotate!(radians)
80
80
  sin = Math.sin radians
81
81
  cos = Math.cos radians
82
82
  prev_x = @x
@@ -107,7 +107,7 @@ module AGL
107
107
  # [y] The y-coordinate of the rectangle.
108
108
  # [w] The width of the rectangle.
109
109
  # [h] The height of the rectangle.
110
- def initialize x, y, w, h
110
+ def initialize(x, y, w, h)
111
111
  @x = x; @y = y; @w = w; @h = h
112
112
  end
113
113
 
@@ -115,25 +115,69 @@ module AGL
115
115
  #
116
116
  # Parameters:
117
117
  # [r] The rectangle to check intersection with.
118
- def intersects r
118
+ def intersect?(r)
119
119
  @x < r.x + r.w && @x + @w > r.x && @y < r.y + r.h && @y + @h > r.y
120
120
  end
121
121
  end
122
122
 
123
+ # This module contains references to global objects/constants used by MiniGL.
124
+ module G
125
+ class << self
126
+ # A reference to the game window.
127
+ attr_accessor :window
128
+
129
+ # Gets or sets the value of gravity. See
130
+ # <code>GameWindow#initialize</code> for details.
131
+ attr_accessor :gravity
132
+
133
+ # Gets or sets the value of min_speed. See
134
+ # <code>GameWindow#initialize</code> for details.
135
+ attr_accessor :min_speed
136
+
137
+ # Gets or sets the value of ramp_contact_threshold. See
138
+ # <code>GameWindow#initialize</code> for details.
139
+ attr_accessor :ramp_contact_threshold
140
+
141
+ # Gets or sets the value of ramp_slip_threshold. See
142
+ # <code>GameWindow#initialize</code> for details.
143
+ attr_accessor :ramp_slip_threshold
144
+
145
+ # Gets or sets the value of kb_held_delay. See
146
+ # <code>GameWindow#initialize</code> for details.
147
+ attr_accessor :kb_held_delay
148
+
149
+ # Gets or sets the value of kb_held_interval. See
150
+ # <code>GameWindow#initialize</code> for details.
151
+ attr_accessor :kb_held_interval
152
+
153
+ # Gets or sets the value of double_click_delay. See
154
+ # <code>GameWindow#initialize</code> for details.
155
+ attr_accessor :double_click_delay
156
+ end
157
+ end
158
+
123
159
  # The main class for a MiniGL game, holds references to globally accessible
124
160
  # objects and constants.
125
- class Game
126
- # Initializes a MiniGL game. This method must be called before any feature
127
- # provided by the library can be used.
161
+ class GameWindow < Gosu::Window
162
+ # Creates a game window (initializing a game with all MiniGL features
163
+ # enabled).
128
164
  #
129
165
  # Parameters:
130
- # [window] An instance of a class which inherits from
131
- # <code>Gosu::Window</code>. This will be the game window, used
132
- # to draw everything and capture user input.
166
+ # [scr_w] Width of the window, in pixels.
167
+ # [scr_h] Height of the window, in pixels.
168
+ # [fullscreen] Whether the window must be initialized in full screen mode.
133
169
  # [gravity] A Vector object representing the horizontal and vertical
134
170
  # components of the force of gravity. Essentially, this force
135
171
  # will be applied to every object which calls +move+, from the
136
172
  # Movement module.
173
+ # [min_speed] A Vector with the minimum speed for moving objects, i.e., the
174
+ # value below which the speed will be rounded to zero.
175
+ # [ramp_contact_threshold] The maximum horizontal movement an object can
176
+ # perform in a single frame and keep contact with a
177
+ # ramp when it's above one.
178
+ # [ramp_slip_threshold] The maximum ratio between height and width of a ramp
179
+ # above which the objects will always slip down when
180
+ # trying to 'climb' that ramp.
137
181
  # [kb_held_delay] The number of frames a key must be held by the user
138
182
  # before the "held" event (that can be checked with
139
183
  # <code>KB.key_held?</code>) starts to trigger.
@@ -143,242 +187,249 @@ module AGL
143
187
  # [double_click_delay] The maximum interval, in frames, between two
144
188
  # clicks, to trigger the "double click" event
145
189
  # (checked with <code>Mouse.double_click?</code>).
146
- def self.initialize window, gravity = Vector.new(0, 1),
147
- kb_held_delay = 40, kb_held_interval = 5,
148
- double_click_delay = 8
149
- @@window = window
150
- @@gravity = gravity
151
- @@kb_held_delay = kb_held_delay
152
- @@kb_held_interval = kb_held_interval
153
- @@double_click_delay = double_click_delay
154
-
190
+ def initialize(scr_w, scr_h, fullscreen = true,
191
+ gravity = Vector.new(0, 1), min_speed = Vector.new(0.01, 0.01),
192
+ ramp_contact_threshold = 10, ramp_slip_threshold = 1.2,
193
+ kb_held_delay = 40, kb_held_interval = 5, double_click_delay = 8)
194
+ super scr_w, scr_h, fullscreen
195
+ G.window = self
196
+ G.gravity = gravity
197
+ G.min_speed = min_speed
198
+ G.ramp_contact_threshold = ramp_contact_threshold
199
+ G.ramp_slip_threshold = ramp_slip_threshold
200
+ G.kb_held_delay = kb_held_delay
201
+ G.kb_held_interval = kb_held_interval
202
+ G.double_click_delay = double_click_delay
155
203
  KB.initialize
156
204
  Mouse.initialize
157
205
  Res.initialize
158
206
  end
159
207
 
160
- # Returns a reference to the game window.
161
- def self.window; @@window; end
162
-
163
- # Returns a Vector representing the force of gravity. See +initialize+ for
164
- # details.
165
- def self.gravity; @@gravity; end
166
-
167
- # Returns the value of kb_held_delay. See +initialize+ for details.
168
- def self.kb_held_delay; @@kb_held_delay; end
169
-
170
- # Returns the value of kb_held_interval. See +initialize+ for details.
171
- def self.kb_held_interval; @@kb_held_interval; end
208
+ # Draws a rectangle with the size of the entire screen, in the given color.
209
+ #
210
+ # Parameters:
211
+ # [color] Color of the rectangle to be drawn.
212
+ def clear(color)
213
+ draw_quad 0, 0, color,
214
+ width, 0, color,
215
+ width, height, color,
216
+ 0, height, color, 0
217
+ end
172
218
 
173
- # Returns the value of double_click_delay. See +initialize+ for details.
174
- def self.double_click_delay; @@double_click_delay; end
219
+ # def toggle_fullscreen
220
+ # # TODO
221
+ # end
175
222
  end
176
223
 
177
224
  #class JSHelper
178
225
 
179
226
  # Exposes methods for controlling keyboard events.
180
- class KB
181
- # This is called by <code>Game.initialize</code>. Don't call it
182
- # explicitly.
183
- def self.initialize
184
- @@keys = [
185
- Gosu::KbUp, Gosu::KbDown,
186
- Gosu::KbReturn, Gosu::KbEscape,
187
- Gosu::KbLeftControl, Gosu::KbRightControl,
188
- Gosu::KbLeftAlt, Gosu::KbRightAlt,
189
- Gosu::KbA, Gosu::KbB, Gosu::KbC, Gosu::KbD, Gosu::KbE, Gosu::KbF,
190
- Gosu::KbG, Gosu::KbH, Gosu::KbI, Gosu::KbJ, Gosu::KbK, Gosu::KbL,
191
- Gosu::KbM, Gosu::KbN, Gosu::KbO, Gosu::KbP, Gosu::KbQ, Gosu::KbR,
192
- Gosu::KbS, Gosu::KbT, Gosu::KbU, Gosu::KbV, Gosu::KbW, Gosu::KbX,
193
- Gosu::KbY, Gosu::KbZ, Gosu::Kb1, Gosu::Kb2, Gosu::Kb3, Gosu::Kb4,
194
- Gosu::Kb5, Gosu::Kb6, Gosu::Kb7, Gosu::Kb8, Gosu::Kb9, Gosu::Kb0,
195
- Gosu::KbNumpad1, Gosu::KbNumpad2, Gosu::KbNumpad3, Gosu::KbNumpad4,
196
- Gosu::KbNumpad5, Gosu::KbNumpad6, Gosu::KbNumpad7, Gosu::KbNumpad8,
197
- Gosu::KbNumpad9, Gosu::KbNumpad0, Gosu::KbSpace, Gosu::KbBackspace,
198
- Gosu::KbDelete, Gosu::KbLeft, Gosu::KbRight, Gosu::KbHome,
199
- Gosu::KbEnd, Gosu::KbLeftShift, Gosu::KbRightShift, Gosu::KbTab,
200
- Gosu::KbBacktick, Gosu::KbMinus, Gosu::KbEqual, Gosu::KbBracketLeft,
201
- Gosu::KbBracketRight, Gosu::KbBackslash, Gosu::KbApostrophe,
202
- Gosu::KbComma, Gosu::KbPeriod, Gosu::KbSlash
203
- ]
204
- @@down = []
205
- @@prev_down = []
206
- @@held_timer = {}
207
- @@held_interval = {}
208
- end
227
+ module KB
228
+ class << self
229
+ # This is called by <code>GameWindow.initialize</code>. Don't call it
230
+ # explicitly.
231
+ def initialize
232
+ @keys = [
233
+ Gosu::KbUp, Gosu::KbDown,
234
+ Gosu::KbReturn, Gosu::KbEscape,
235
+ Gosu::KbLeftControl, Gosu::KbRightControl,
236
+ Gosu::KbLeftAlt, Gosu::KbRightAlt,
237
+ Gosu::KbA, Gosu::KbB, Gosu::KbC, Gosu::KbD, Gosu::KbE, Gosu::KbF,
238
+ Gosu::KbG, Gosu::KbH, Gosu::KbI, Gosu::KbJ, Gosu::KbK, Gosu::KbL,
239
+ Gosu::KbM, Gosu::KbN, Gosu::KbO, Gosu::KbP, Gosu::KbQ, Gosu::KbR,
240
+ Gosu::KbS, Gosu::KbT, Gosu::KbU, Gosu::KbV, Gosu::KbW, Gosu::KbX,
241
+ Gosu::KbY, Gosu::KbZ, Gosu::Kb1, Gosu::Kb2, Gosu::Kb3, Gosu::Kb4,
242
+ Gosu::Kb5, Gosu::Kb6, Gosu::Kb7, Gosu::Kb8, Gosu::Kb9, Gosu::Kb0,
243
+ Gosu::KbNumpad1, Gosu::KbNumpad2, Gosu::KbNumpad3, Gosu::KbNumpad4,
244
+ Gosu::KbNumpad5, Gosu::KbNumpad6, Gosu::KbNumpad7, Gosu::KbNumpad8,
245
+ Gosu::KbNumpad9, Gosu::KbNumpad0, Gosu::KbSpace, Gosu::KbBackspace,
246
+ Gosu::KbDelete, Gosu::KbLeft, Gosu::KbRight, Gosu::KbHome,
247
+ Gosu::KbEnd, Gosu::KbLeftShift, Gosu::KbRightShift, Gosu::KbTab,
248
+ Gosu::KbBacktick, Gosu::KbMinus, Gosu::KbEqual, Gosu::KbBracketLeft,
249
+ Gosu::KbBracketRight, Gosu::KbBackslash, Gosu::KbApostrophe,
250
+ Gosu::KbComma, Gosu::KbPeriod, Gosu::KbSlash
251
+ ]
252
+ @down = []
253
+ @prev_down = []
254
+ @held_timer = {}
255
+ @held_interval = {}
256
+ end
209
257
 
210
- # Updates the state of all keys.
211
- def self.update
212
- @@held_timer.each do |k, v|
213
- if v < Game.kb_held_delay; @@held_timer[k] += 1
214
- else
215
- @@held_interval[k] = 0
216
- @@held_timer.delete k
258
+ # Updates the state of all keys.
259
+ def update
260
+ @held_timer.each do |k, v|
261
+ if v < G.kb_held_delay; @held_timer[k] += 1
262
+ else
263
+ @held_interval[k] = 0
264
+ @held_timer.delete k
265
+ end
217
266
  end
218
- end
219
267
 
220
- @@held_interval.each do |k, v|
221
- if v < Game.kb_held_interval; @@held_interval[k] += 1
222
- else; @@held_interval[k] = 0; end
223
- end
268
+ @held_interval.each do |k, v|
269
+ if v < G.kb_held_interval; @held_interval[k] += 1
270
+ else; @held_interval[k] = 0; end
271
+ end
224
272
 
225
- @@prev_down = @@down.clone
226
- @@down.clear
227
- @@keys.each do |k|
228
- if Game.window.button_down? k
229
- @@down << k
230
- @@held_timer[k] = 0 if @@prev_down.index(k).nil?
231
- elsif @@prev_down.index(k)
232
- @@held_timer.delete k
233
- @@held_interval.delete k
273
+ @prev_down = @down.clone
274
+ @down.clear
275
+ @keys.each do |k|
276
+ if G.window.button_down? k
277
+ @down << k
278
+ @held_timer[k] = 0 if @prev_down.index(k).nil?
279
+ elsif @prev_down.index(k)
280
+ @held_timer.delete k
281
+ @held_interval.delete k
282
+ end
234
283
  end
235
284
  end
236
- end
237
285
 
238
- # Returns whether the given key is down in the current frame and was not
239
- # down in the frame before.
240
- #
241
- # Parameters:
242
- # [key] Code of the key to be checked. The available codes are <code>
243
- # Gosu::KbUp, Gosu::KbDown, Gosu::KbReturn, Gosu::KbEscape,
244
- # Gosu::KbLeftControl, Gosu::KbRightControl,
245
- # Gosu::KbLeftAlt, Gosu::KbRightAlt,
246
- # Gosu::KbA, Gosu::KbB, Gosu::KbC, Gosu::KbD, Gosu::KbE, Gosu::KbF,
247
- # Gosu::KbG, Gosu::KbH, Gosu::KbI, Gosu::KbJ, Gosu::KbK, Gosu::KbL,
248
- # Gosu::KbM, Gosu::KbN, Gosu::KbO, Gosu::KbP, Gosu::KbQ, Gosu::KbR,
249
- # Gosu::KbS, Gosu::KbT, Gosu::KbU, Gosu::KbV, Gosu::KbW, Gosu::KbX,
250
- # Gosu::KbY, Gosu::KbZ, Gosu::Kb1, Gosu::Kb2, Gosu::Kb3, Gosu::Kb4,
251
- # Gosu::Kb5, Gosu::Kb6, Gosu::Kb7, Gosu::Kb8, Gosu::Kb9, Gosu::Kb0,
252
- # Gosu::KbNumpad1, Gosu::KbNumpad2, Gosu::KbNumpad3, Gosu::KbNumpad4,
253
- # Gosu::KbNumpad5, Gosu::KbNumpad6, Gosu::KbNumpad7, Gosu::KbNumpad8,
254
- # Gosu::KbNumpad9, Gosu::KbNumpad0, Gosu::KbSpace, Gosu::KbBackspace,
255
- # Gosu::KbDelete, Gosu::KbLeft, Gosu::KbRight, Gosu::KbHome,
256
- # Gosu::KbEnd, Gosu::KbLeftShift, Gosu::KbRightShift, Gosu::KbTab,
257
- # Gosu::KbBacktick, Gosu::KbMinus, Gosu::KbEqual, Gosu::KbBracketLeft,
258
- # Gosu::KbBracketRight, Gosu::KbBackslash, Gosu::KbApostrophe,
259
- # Gosu::KbComma, Gosu::KbPeriod, Gosu::KbSlash</code>.
260
- def self.key_pressed? key
261
- @@prev_down.index(key).nil? and @@down.index(key)
262
- end
286
+ # Returns whether the given key is down in the current frame and was not
287
+ # down in the frame before.
288
+ #
289
+ # Parameters:
290
+ # [key] Code of the key to be checked. The available codes are <code>
291
+ # Gosu::KbUp, Gosu::KbDown, Gosu::KbReturn, Gosu::KbEscape,
292
+ # Gosu::KbLeftControl, Gosu::KbRightControl,
293
+ # Gosu::KbLeftAlt, Gosu::KbRightAlt,
294
+ # Gosu::KbA, Gosu::KbB, Gosu::KbC, Gosu::KbD, Gosu::KbE, Gosu::KbF,
295
+ # Gosu::KbG, Gosu::KbH, Gosu::KbI, Gosu::KbJ, Gosu::KbK, Gosu::KbL,
296
+ # Gosu::KbM, Gosu::KbN, Gosu::KbO, Gosu::KbP, Gosu::KbQ, Gosu::KbR,
297
+ # Gosu::KbS, Gosu::KbT, Gosu::KbU, Gosu::KbV, Gosu::KbW, Gosu::KbX,
298
+ # Gosu::KbY, Gosu::KbZ, Gosu::Kb1, Gosu::Kb2, Gosu::Kb3, Gosu::Kb4,
299
+ # Gosu::Kb5, Gosu::Kb6, Gosu::Kb7, Gosu::Kb8, Gosu::Kb9, Gosu::Kb0,
300
+ # Gosu::KbNumpad1, Gosu::KbNumpad2, Gosu::KbNumpad3, Gosu::KbNumpad4,
301
+ # Gosu::KbNumpad5, Gosu::KbNumpad6, Gosu::KbNumpad7, Gosu::KbNumpad8,
302
+ # Gosu::KbNumpad9, Gosu::KbNumpad0, Gosu::KbSpace, Gosu::KbBackspace,
303
+ # Gosu::KbDelete, Gosu::KbLeft, Gosu::KbRight, Gosu::KbHome,
304
+ # Gosu::KbEnd, Gosu::KbLeftShift, Gosu::KbRightShift, Gosu::KbTab,
305
+ # Gosu::KbBacktick, Gosu::KbMinus, Gosu::KbEqual, Gosu::KbBracketLeft,
306
+ # Gosu::KbBracketRight, Gosu::KbBackslash, Gosu::KbApostrophe,
307
+ # Gosu::KbComma, Gosu::KbPeriod, Gosu::KbSlash</code>.
308
+ def key_pressed?(key)
309
+ @prev_down.index(key).nil? and @down.index(key)
310
+ end
263
311
 
264
- # Returns whether the given key is down in the current frame.
265
- #
266
- # Parameters:
267
- # [key] Code of the key to be checked. See +key_pressed?+ for details.
268
- def self.key_down? key
269
- @@down.index(key)
270
- end
312
+ # Returns whether the given key is down in the current frame.
313
+ #
314
+ # Parameters:
315
+ # [key] Code of the key to be checked. See +key_pressed?+ for details.
316
+ def key_down?(key)
317
+ @down.index(key)
318
+ end
271
319
 
272
- # Returns whether the given key is not down in the current frame but was
273
- # down in the frame before.
274
- #
275
- # Parameters:
276
- # [key] Code of the key to be checked. See +key_pressed?+ for details.
277
- def self.key_released? key
278
- @@prev_down.index(key) and @@down.index(key).nil?
279
- end
320
+ # Returns whether the given key is not down in the current frame but was
321
+ # down in the frame before.
322
+ #
323
+ # Parameters:
324
+ # [key] Code of the key to be checked. See +key_pressed?+ for details.
325
+ def key_released?(key)
326
+ @prev_down.index(key) and @down.index(key).nil?
327
+ end
280
328
 
281
- # Returns whether the given key is being held down. See
282
- # <code>Game.initialize</code> for details.
283
- #
284
- # Parameters:
285
- # [key] Code of the key to be checked. See +key_pressed?+ for details.
286
- def self.key_held? key
287
- @@held_interval[key] == Game.kb_held_interval
329
+ # Returns whether the given key is being held down. See
330
+ # <code>GameWindow.initialize</code> for details.
331
+ #
332
+ # Parameters:
333
+ # [key] Code of the key to be checked. See +key_pressed?+ for details.
334
+ def key_held?(key)
335
+ @held_interval[key] == G.kb_held_interval
336
+ end
288
337
  end
289
338
  end
290
339
 
291
340
  # Exposes methods for controlling mouse events.
292
- class Mouse
293
- # This is called by <code>Game.initialize</code>. Don't call it
294
- # explicitly.
295
- def self.initialize
296
- @@down = {}
297
- @@prev_down = {}
298
- @@dbl_click = {}
299
- @@dbl_click_timer = {}
300
- end
301
-
302
- # Updates the mouse position and the state of all buttons.
303
- def self.update
304
- @@prev_down = @@down.clone
305
- @@down.clear
306
- @@dbl_click.clear
307
-
308
- @@dbl_click_timer.each do |k, v|
309
- if v < Game.double_click_delay; @@dbl_click_timer[k] += 1
310
- else; @@dbl_click_timer.delete k; end
341
+ module Mouse
342
+ class << self
343
+ # The current x-coordinate of the mouse cursor in the screen.
344
+ attr_reader :x
345
+
346
+ # The current y-coordinate of the mouse cursor in the screen.
347
+ attr_reader :y
348
+
349
+ # This is called by <code>GameWindow.initialize</code>. Don't call it
350
+ # explicitly.
351
+ def initialize
352
+ @down = {}
353
+ @prev_down = {}
354
+ @dbl_click = {}
355
+ @dbl_click_timer = {}
311
356
  end
312
357
 
313
- k1 = [Gosu::MsLeft, Gosu::MsMiddle, Gosu::MsRight]
314
- k2 = [:left, :middle, :right]
315
- for i in 0..2
316
- if Game.window.button_down? k1[i]
317
- @@down[k2[i]] = true
318
- @@dbl_click[k2[i]] = true if @@dbl_click_timer[k2[i]]
319
- @@dbl_click_timer.delete k2[i]
320
- elsif @@prev_down[k2[i]]
321
- @@dbl_click_timer[k2[i]] = 0
322
- end
323
- end
358
+ # Updates the mouse position and the state of all buttons.
359
+ def update
360
+ @prev_down = @down.clone
361
+ @down.clear
362
+ @dbl_click.clear
324
363
 
325
- @@x = Game.window.mouse_x.round
326
- @@y = Game.window.mouse_y.round
327
- end
364
+ @dbl_click_timer.each do |k, v|
365
+ if v < G.double_click_delay; @dbl_click_timer[k] += 1
366
+ else; @dbl_click_timer.delete k; end
367
+ end
328
368
 
329
- # Returns the x-coordinate of the mouse cursor in the screen.
330
- def self.x; @@x; end
369
+ k1 = [Gosu::MsLeft, Gosu::MsMiddle, Gosu::MsRight]
370
+ k2 = [:left, :middle, :right]
371
+ for i in 0..2
372
+ if G.window.button_down? k1[i]
373
+ @down[k2[i]] = true
374
+ @dbl_click[k2[i]] = true if @dbl_click_timer[k2[i]]
375
+ @dbl_click_timer.delete k2[i]
376
+ elsif @prev_down[k2[i]]
377
+ @dbl_click_timer[k2[i]] = 0
378
+ end
379
+ end
331
380
 
332
- # Returns the y-coordinate of the mouse cursor in the screen.
333
- def self.y; @@y; end
381
+ @x = G.window.mouse_x.round
382
+ @y = G.window.mouse_y.round
383
+ end
334
384
 
335
- # Returns whether the given button is down in the current frame and was
336
- # not down in the frame before.
337
- #
338
- # Parameters:
339
- # [btn] Button to be checked. Valid values are +:left+, +:middle+ and
340
- # +:right+
341
- def self.button_pressed? btn
342
- @@down[btn] and not @@prev_down[btn]
343
- end
385
+ # Returns whether the given button is down in the current frame and was
386
+ # not down in the frame before.
387
+ #
388
+ # Parameters:
389
+ # [btn] Button to be checked. Valid values are +:left+, +:middle+ and
390
+ # +:right+
391
+ def button_pressed?(btn)
392
+ @down[btn] and not @prev_down[btn]
393
+ end
344
394
 
345
- # Returns whether the given button is down in the current frame.
346
- #
347
- # Parameters:
348
- # [btn] Button to be checked. Valid values are +:left+, +:middle+ and
349
- # +:right+
350
- def self.button_down? btn
351
- @@down[btn]
352
- end
395
+ # Returns whether the given button is down in the current frame.
396
+ #
397
+ # Parameters:
398
+ # [btn] Button to be checked. Valid values are +:left+, +:middle+ and
399
+ # +:right+
400
+ def button_down?(btn)
401
+ @down[btn]
402
+ end
353
403
 
354
- # Returns whether the given button is not down in the current frame, but
355
- # was down in the frame before.
356
- #
357
- # Parameters:
358
- # [btn] Button to be checked. Valid values are +:left+, +:middle+ and
359
- # +:right+
360
- def self.button_released? btn
361
- @@prev_down[btn] and not @@down[btn]
362
- end
404
+ # Returns whether the given button is not down in the current frame, but
405
+ # was down in the frame before.
406
+ #
407
+ # Parameters:
408
+ # [btn] Button to be checked. Valid values are +:left+, +:middle+ and
409
+ # +:right+
410
+ def button_released?(btn)
411
+ @prev_down[btn] and not @down[btn]
412
+ end
363
413
 
364
- # Returns whether the given button has just been double clicked.
365
- #
366
- # Parameters:
367
- # [btn] Button to be checked. Valid values are +:left+, +:middle+ and
368
- # +:right+
369
- def self.double_click? btn
370
- @@dbl_click[btn]
371
- end
414
+ # Returns whether the given button has just been double clicked.
415
+ #
416
+ # Parameters:
417
+ # [btn] Button to be checked. Valid values are +:left+, +:middle+ and
418
+ # +:right+
419
+ def double_click?(btn)
420
+ @dbl_click[btn]
421
+ end
372
422
 
373
- # Returns whether the mouse cursor is currently inside the given area.
374
- #
375
- # Parameters:
376
- # [x] The x-coordinate of the top left corner of the area.
377
- # [y] The y-coordinate of the top left corner of the area.
378
- # [w] The width of the area.
379
- # [h] The height of the area.
380
- def self.over? x, y, w, h
381
- @@x >= x and @@x < x + w and @@y >= y and @@y < y + h
423
+ # Returns whether the mouse cursor is currently inside the given area.
424
+ #
425
+ # Parameters:
426
+ # [x] The x-coordinate of the top left corner of the area.
427
+ # [y] The y-coordinate of the top left corner of the area.
428
+ # [w] The width of the area.
429
+ # [h] The height of the area.
430
+ def over?(x, y, w, h)
431
+ @x >= x and @x < x + w and @y >= y and @y < y + h
432
+ end
382
433
  end
383
434
  end
384
435
 
@@ -393,178 +444,242 @@ module AGL
393
444
  # resource being loaded and the file name (either as string or as symbol).
394
445
  # There are default extensions for each type of resource, so the extension
395
446
  # must be specified only if the file is in a format other than the default.
396
- class Res
397
- # This is called by <code>Game.initialize</code>. Don't call it
398
- # explicitly.
399
- def self.initialize
400
- @@imgs = Hash.new
401
- @@global_imgs = Hash.new
402
- @@tilesets = Hash.new
403
- @@global_tilesets = Hash.new
404
- @@sounds = Hash.new
405
- @@global_sounds = Hash.new
406
- @@songs = Hash.new
407
- @@global_songs = Hash.new
408
- @@fonts = Hash.new
409
- @@global_fonts = Hash.new
410
- @@prefix = File.expand_path(File.dirname($0)) + '/data/'
411
- end
447
+ module Res
448
+ class << self
449
+ # Get the current prefix for searching data files. This is the directory
450
+ # under which 'img', 'sound', 'song', etc. folders are located.
451
+ attr_reader :prefix
452
+
453
+ # Gets the current path to image files (under +prefix+). Default is 'img'.
454
+ attr_reader :img_dir
455
+
456
+ # Gets the current path to tileset files (under +prefix+). Default is
457
+ # 'tileset'.
458
+ attr_reader :tileset_dir
459
+
460
+ # Gets the current path to sound files (under +prefix+). Default is 'sound'.
461
+ attr_reader :sound_dir
462
+
463
+ # Gets the current path to song files (under +prefix+). Default is 'song'.
464
+ attr_reader :song_dir
465
+
466
+ # Gets the current path to font files (under +prefix+). Default is 'font'.
467
+ attr_reader :font_dir
468
+
469
+ # Gets or sets the character that is currently being used in the +id+
470
+ # parameter of the loading methods as a folder separator. Default is '_'.
471
+ # Note that if you want to use symbols to specify paths, this separator
472
+ # should be a valid character in a Ruby symbol. On the other hand, if you
473
+ # want to use only slashes in Strings, you can specify a 'weird' character
474
+ # that won't appear in any file name.
475
+ attr_accessor :separator
476
+
477
+ # This is called by <code>GameWindow.initialize</code>. Don't call it
478
+ # explicitly.
479
+ def initialize
480
+ @imgs = {}
481
+ @global_imgs = {}
482
+ @tilesets = {}
483
+ @global_tilesets = {}
484
+ @sounds = {}
485
+ @global_sounds = {}
486
+ @songs = {}
487
+ @global_songs = {}
488
+ @fonts = {}
489
+ @global_fonts = {}
490
+
491
+ @prefix = File.expand_path(File.dirname($0)) + '/data/'
492
+ @img_dir = 'img/'
493
+ @tileset_dir = 'tileset/'
494
+ @sound_dir = 'sound/'
495
+ @song_dir = 'song/'
496
+ @font_dir = 'font/'
497
+ @separator = '_'
498
+ end
412
499
 
413
- # Get the current prefix for searching data files. This is the directory
414
- # under which 'img', 'sound', 'song', etc. folders are located.
415
- def self.prefix; @@prefix; end
500
+ # Set a custom prefix for loading resources. By default, the prefix is the
501
+ # directory of the game script. The prefix is the directory under which
502
+ # 'img', 'sound', 'song', etc. folders are located.
503
+ def prefix=(value)
504
+ value += '/' if value[-1] != '/'
505
+ @prefix = value
506
+ end
416
507
 
417
- # Set a custom prefix for loading resources. By default, the prefix is the
418
- # directory of the game script. The prefix is the directory under which
419
- # 'img', 'sound', 'song', etc. folders are located.
420
- def self.prefix= value
421
- value += '/' if value[-1] != '/'
422
- @@prefix = value
423
- end
508
+ # Sets the path to image files (under +prefix+). Default is 'img'.
509
+ def img_dir=(value)
510
+ value += '/' if value[-1] != '/'
511
+ @img_dir = value
512
+ end
424
513
 
425
- # Returns a <code>Gosu::Image</code> object.
426
- #
427
- # Parameters:
428
- # [id] A string or symbol representing the path to the image. If the file
429
- # is inside 'data/img', only the file name is needed. If it's inside
430
- # a subdirectory, the id must be prefixed by each subdirectory name
431
- # followed by an underscore. Example: to load
432
- # 'data/img/sprite/1.png', provide +:sprite_1+ or "sprite_1".
433
- # [global] Set to true if you want to keep the image in memory until the
434
- # game execution is finished. If false, the image will be
435
- # released when you call +clear+.
436
- # [tileable] Whether the image should be loaded in tileable mode, which is
437
- # proper for images that will be used as a tile, i.e., that
438
- # will be drawn repeated times, side by side, forming a
439
- # continuous composition.
440
- # [ext] The extension of the file being loaded. Specify only if it is
441
- # other than ".png".
442
- def self.img id, global = false, tileable = false, ext = ".png"
443
- if global; a = @@global_imgs; else; a = @@imgs; end
444
- return a[id] if a[id]
445
- s = @@prefix + "img/" + id.to_s.split('_').join('/') + ext
446
- img = Gosu::Image.new Game.window, s, tileable
447
- a[id] = img
448
- end
514
+ # Sets the path to tilset files (under +prefix+). Default is 'tileset'.
515
+ def tileset_dir=(value)
516
+ value += '/' if value[-1] != '/'
517
+ @tileset_dir = value
518
+ end
449
519
 
450
- # Returns an array of <code>Gosu::Image</code> objects, using the image as
451
- # a spritesheet. The image with index 0 will be the top left sprite, and
452
- # the following indices raise first from left to right and then from top
453
- # to bottom.
454
- #
455
- # Parameters:
456
- # [id] A string or symbol representing the path to the image. See +img+
457
- # for details.
458
- # [sprite_cols] Number of columns in the spritesheet.
459
- # [sprite_rows] Number of rows in the spritesheet.
460
- # [global] Set to true if you want to keep the image in memory until the
461
- # game execution is finished. If false, the image will be
462
- # released when you call +clear+.
463
- # [ext] The extension of the file being loaded. Specify only if it is
464
- # other than ".png".
465
- def self.imgs id, sprite_cols, sprite_rows, global = false, ext = ".png"
466
- if global; a = @@global_imgs; else; a = @@imgs; end
467
- return a[id] if a[id]
468
- s = @@prefix + "img/" + id.to_s.split('_').join('/') + ext
469
- imgs = Gosu::Image.load_tiles Game.window, s, -sprite_cols, -sprite_rows, false
470
- a[id] = imgs
471
- end
520
+ # Sets the path to sound files (under +prefix+). Default is 'sound'.
521
+ def sound_dir=(value)
522
+ value += '/' if value[-1] != '/'
523
+ @sound_dir = value
524
+ end
472
525
 
473
- # Returns an array of <code>Gosu::Image</code> objects, using the image as
474
- # a tileset. Works the same as +imgs+, except you must provide the tile
475
- # size instead of the number of columns and rows, and that the images will
476
- # be loaded as tileable.
477
- #
478
- # Parameters:
479
- # [id] A string or symbol representing the path to the image. It must be
480
- # specified the same way as in +img+, but the base directory is
481
- # 'data/tileset'.
482
- # [tile_width] Width of each tile, in pixels.
483
- # [tile_height] Height of each tile, in pixels.
484
- # [global] Set to true if you want to keep the image in memory until the
485
- # game execution is finished. If false, the image will be
486
- # released when you call +clear+.
487
- # [ext] The extension of the file being loaded. Specify only if it is
488
- # other than ".png".
489
- def self.tileset id, tile_width = 32, tile_height = 32, global = false, ext = ".png"
490
- if global; a = @@global_tilesets; else; a = @@tilesets; end
491
- return a[id] if a[id]
492
- s = @@prefix + "tileset/" + id.to_s.split('_').join('/') + ext
493
- tileset = Gosu::Image.load_tiles Game.window, s, tile_width, tile_height, true
494
- a[id] = tileset
495
- end
526
+ # Sets the path to song files (under +prefix+). Default is 'song'.
527
+ def song_dir=(value)
528
+ value += '/' if value[-1] != '/'
529
+ @song_dir = value
530
+ end
496
531
 
497
- # Returns a <code>Gosu::Sample</code> object. This should be used for
498
- # simple and short sound effects.
499
- #
500
- # Parameters:
501
- # [id] A string or symbol representing the path to the sound. It must be
502
- # specified the same way as in +img+, but the base directory is
503
- # 'data/sound'.
504
- # [global] Set to true if you want to keep the sound in memory until the
505
- # game execution is finished. If false, the sound will be
506
- # released when you call +clear+.
507
- # [ext] The extension of the file being loaded. Specify only if it is
508
- # other than ".wav".
509
- def self.sound id, global = false, ext = ".wav"
510
- if global; a = @@global_sounds; else; a = @@sounds; end
511
- return a[id] if a[id]
512
- s = @@prefix + "sound/" + id.to_s.split('_').join('/') + ext
513
- sound = Gosu::Sample.new Game.window, s
514
- a[id] = sound
515
- end
532
+ # Sets the path to font files (under +prefix+). Default is 'font'.
533
+ def font_dir=(value)
534
+ value += '/' if value[-1] != '/'
535
+ @font_dir = value
536
+ end
516
537
 
517
- # Returns a <code>Gosu::Song</code> object. This should be used for the
518
- # background musics of your game.
519
- #
520
- # Parameters:
521
- # [id] A string or symbol representing the path to the song. It must be
522
- # specified the same way as in +img+, but the base directory is
523
- # 'data/song'.
524
- # [global] Set to true if you want to keep the song in memory until the
525
- # game execution is finished. If false, the song will be released
526
- # when you call +clear+.
527
- # [ext] The extension of the file being loaded. Specify only if it is
528
- # other than ".ogg".
529
- def self.song id, global = false, ext = ".ogg"
530
- if global; a = @@global_songs; else; a = @@songs; end
531
- return a[id] if a[id]
532
- s = @@prefix + "song/" + id.to_s.split('_').join('/') + ext
533
- song = Gosu::Song.new Game.window, s
534
- a[id] = song
535
- end
538
+ # Returns a <code>Gosu::Image</code> object.
539
+ #
540
+ # Parameters:
541
+ # [id] A string or symbol representing the path to the image. If the file
542
+ # is inside +prefix+/+img_dir+, only the file name is needed. If it's
543
+ # inside a subdirectory of +prefix+/+img_dir+, the id must be
544
+ # prefixed by each subdirectory name followed by +separator+. Example:
545
+ # to load 'data/img/sprite/1.png', with the default values of +prefix+,
546
+ # +img_dir+ and +separator+, provide +:sprite_1+ or "sprite_1".
547
+ # [global] Set to true if you want to keep the image in memory until the
548
+ # game execution is finished. If false, the image will be
549
+ # released when you call +clear+.
550
+ # [tileable] Whether the image should be loaded in tileable mode, which is
551
+ # proper for images that will be used as a tile, i.e., that
552
+ # will be drawn repeated times, side by side, forming a
553
+ # continuous composition.
554
+ # [ext] The extension of the file being loaded. Specify only if it is
555
+ # other than '.png'.
556
+ def img(id, global = false, tileable = false, ext = '.png')
557
+ if global; a = @global_imgs; else; a = @imgs; end
558
+ return a[id] if a[id]
559
+ s = @prefix + @img_dir + id.to_s.split(@separator).join('/') + ext
560
+ img = Gosu::Image.new G.window, s, tileable
561
+ a[id] = img
562
+ end
536
563
 
537
- # Returns a <code>Gosu::Font</code> object. Fonts are needed to draw text
538
- # and used by MiniGL elements like buttons, text fields and TextHelper
539
- # objects.
540
- #
541
- # Parameters:
542
- # [id] A string or symbol representing the path to the song. It must be
543
- # specified the same way as in +img+, but the base directory is
544
- # 'data/font'.
545
- # [size] The size of the font, in pixels. This will correspond,
546
- # approximately, to the height of the tallest character when drawn.
547
- # [global] Set to true if you want to keep the font in memory until the
548
- # game execution is finished. If false, the font will be released
549
- # when you call +clear+.
550
- # [ext] The extension of the file being loaded. Specify only if it is
551
- # other than ".ttf".
552
- def self.font id, size, global = true, ext = ".ttf"
553
- if global; a = @@global_fonts; else; a = @@fonts; end
554
- id_size = "#{id}_#{size}"
555
- return a[id_size] if a[id_size]
556
- s = @@prefix + "font/" + id.to_s.split('_').join('/') + ext
557
- font = Gosu::Font.new Game.window, s, size
558
- a[id_size] = font
559
- end
564
+ # Returns an array of <code>Gosu::Image</code> objects, using the image as
565
+ # a spritesheet. The image with index 0 will be the top left sprite, and
566
+ # the following indices raise first from left to right and then from top
567
+ # to bottom.
568
+ #
569
+ # Parameters:
570
+ # [id] A string or symbol representing the path to the image. See +img+
571
+ # for details.
572
+ # [sprite_cols] Number of columns in the spritesheet.
573
+ # [sprite_rows] Number of rows in the spritesheet.
574
+ # [global] Set to true if you want to keep the image in memory until the
575
+ # game execution is finished. If false, the image will be
576
+ # released when you call +clear+.
577
+ # [ext] The extension of the file being loaded. Specify only if it is
578
+ # other than ".png".
579
+ def imgs(id, sprite_cols, sprite_rows, global = false, ext = '.png')
580
+ if global; a = @global_imgs; else; a = @imgs; end
581
+ return a[id] if a[id]
582
+ s = @prefix + @img_dir + id.to_s.split(@separator).join('/') + ext
583
+ imgs = Gosu::Image.load_tiles G.window, s, -sprite_cols, -sprite_rows, false
584
+ a[id] = imgs
585
+ end
560
586
 
561
- # Releases the memory used by all non-global resources.
562
- def self.clear
563
- @@imgs.clear
564
- @@tilesets.clear
565
- @@sounds.clear
566
- @@songs.clear
567
- @@fonts.clear
587
+ # Returns an array of <code>Gosu::Image</code> objects, using the image as
588
+ # a tileset. Works the same as +imgs+, except you must provide the tile
589
+ # size instead of the number of columns and rows, and that the images will
590
+ # be loaded as tileable.
591
+ #
592
+ # Parameters:
593
+ # [id] A string or symbol representing the path to the image. It must be
594
+ # specified the same way as in +img+, but the base directory is
595
+ # +prefix+/+tileset_dir+.
596
+ # [tile_width] Width of each tile, in pixels.
597
+ # [tile_height] Height of each tile, in pixels.
598
+ # [global] Set to true if you want to keep the image in memory until the
599
+ # game execution is finished. If false, the image will be
600
+ # released when you call +clear+.
601
+ # [ext] The extension of the file being loaded. Specify only if it is
602
+ # other than ".png".
603
+ def tileset(id, tile_width = 32, tile_height = 32, global = false, ext = '.png')
604
+ if global; a = @global_tilesets; else; a = @tilesets; end
605
+ return a[id] if a[id]
606
+ s = @prefix + @tileset_dir + id.to_s.split(@separator).join('/') + ext
607
+ tileset = Gosu::Image.load_tiles G.window, s, tile_width, tile_height, true
608
+ a[id] = tileset
609
+ end
610
+
611
+ # Returns a <code>Gosu::Sample</code> object. This should be used for
612
+ # simple and short sound effects.
613
+ #
614
+ # Parameters:
615
+ # [id] A string or symbol representing the path to the sound. It must be
616
+ # specified the same way as in +img+, but the base directory is
617
+ # +prefix+/+sound_dir+.
618
+ # [global] Set to true if you want to keep the sound in memory until the
619
+ # game execution is finished. If false, the sound will be
620
+ # released when you call +clear+.
621
+ # [ext] The extension of the file being loaded. Specify only if it is
622
+ # other than ".wav".
623
+ def sound(id, global = false, ext = '.wav')
624
+ if global; a = @global_sounds; else; a = @sounds; end
625
+ return a[id] if a[id]
626
+ s = @prefix + @sound_dir + id.to_s.split(@separator).join('/') + ext
627
+ sound = Gosu::Sample.new G.window, s
628
+ a[id] = sound
629
+ end
630
+
631
+ # Returns a <code>Gosu::Song</code> object. This should be used for the
632
+ # background musics of your game.
633
+ #
634
+ # Parameters:
635
+ # [id] A string or symbol representing the path to the song. It must be
636
+ # specified the same way as in +img+, but the base directory is
637
+ # +prefix+/+song_dir+.
638
+ # [global] Set to true if you want to keep the song in memory until the
639
+ # game execution is finished. If false, the song will be released
640
+ # when you call +clear+.
641
+ # [ext] The extension of the file being loaded. Specify only if it is
642
+ # other than ".ogg".
643
+ def song(id, global = false, ext = '.ogg')
644
+ if global; a = @global_songs; else; a = @songs; end
645
+ return a[id] if a[id]
646
+ s = @prefix + @song_dir + id.to_s.split(@separator).join('/') + ext
647
+ song = Gosu::Song.new G.window, s
648
+ a[id] = song
649
+ end
650
+
651
+ # Returns a <code>Gosu::Font</code> object. Fonts are needed to draw text
652
+ # and used by MiniGL elements like buttons, text fields and TextHelper
653
+ # objects.
654
+ #
655
+ # Parameters:
656
+ # [id] A string or symbol representing the path to the song. It must be
657
+ # specified the same way as in +img+, but the base directory is
658
+ # +prefix+/+font_dir+.
659
+ # [size] The size of the font, in pixels. This will correspond,
660
+ # approximately, to the height of the tallest character when drawn.
661
+ # [global] Set to true if you want to keep the font in memory until the
662
+ # game execution is finished. If false, the font will be released
663
+ # when you call +clear+.
664
+ # [ext] The extension of the file being loaded. Specify only if it is
665
+ # other than ".ttf".
666
+ def font(id, size, global = true, ext = '.ttf')
667
+ if global; a = @global_fonts; else; a = @fonts; end
668
+ id_size = "#{id}_#{size}"
669
+ return a[id_size] if a[id_size]
670
+ s = @prefix + @font_dir + id.to_s.split(@separator).join('/') + ext
671
+ font = Gosu::Font.new G.window, s, size
672
+ a[id_size] = font
673
+ end
674
+
675
+ # Releases the memory used by all non-global resources.
676
+ def clear
677
+ @imgs.clear
678
+ @tilesets.clear
679
+ @sounds.clear
680
+ @songs.clear
681
+ @fonts.clear
682
+ end
568
683
  end
569
684
  end
570
685
  end