gosling 1.0.0 → 2.0.0

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: 2e286ba691604561ac6676e60e49699cd3167587
4
- data.tar.gz: 6e2083451057aa524bed3f13012134e829a55f80
3
+ metadata.gz: ea892a020a95cbff0d56b2410eed22dcdffa0816
4
+ data.tar.gz: 9ad565fa00e58440ad245ec0ceae7479ab6c3900
5
5
  SHA512:
6
- metadata.gz: 6232f177ad08bc4869af947c3c6748c004a052d47ca92247a8d0c54910117a6c8984aa5c5d7d35edb109e31ca5281536fc52c5013928b43bdd958e5edb1c6c44
7
- data.tar.gz: 35fe442a079c785663f73640b006171c57872fe0c189bf55c9aa1146fd88c336f4cdabf52db410f3a84361fa862081dff505391c563e9f1f80e16729f1514a5f
6
+ metadata.gz: c45e93330e44318c58d2a76456d836366d7a9dc77ecd2c70ab08c1762ac6d92ca5cd20f257c367212759c03703e0387d7809ba08e88f48a3e3f7ecf8fa0ad500
7
+ data.tar.gz: 4711c9d648c83e8d26b5dfdf7b2bd7266db076500ad21c85ad8b1669fe26785efaf7294a48f6865609ee2f5d4f6b93e8256f7ac926686990cfdde2db41d308ea
data/lib/gosling/actor.rb CHANGED
@@ -3,10 +3,70 @@ require_relative 'transform.rb'
3
3
  require 'gosu'
4
4
 
5
5
  module Gosling
6
+ ##
7
+ # Actors are fundamental elements of a rendering and worldspace hierarchy. They represent the things that exist
8
+ # inside of the game world or parts of our application's user interface.
9
+ #
10
+ # A key difference between an Actor and any of its subclasses - Circle, Polygon, Sprite, and the like - is that an
11
+ # Actor is inherently intangible. By itself, it has no shape or appearance and takes up no space. If it's something you
12
+ # can see or interact with, it should probably be an instance of one of Actor's subclasses.
13
+ #
14
+ # The inheritance model is what makes an Actor by itself useful. Actors can have one or more children, which can be
15
+ # any type of Actor. Those Actors can in turn have any number of child Actors, and so on, creating a sort of tree
16
+ # structure. A parent Actor's transform is inherited by its children, so moving or rotating a parent Actor moves or
17
+ # rotates all of its children relative to its parent. And when a parent is drawn, all of its children are drawn as well
18
+ # (see #draw for exceptions).
19
+ #
20
+ # One common application of this is to use a plain Actor as a root object to which all other elements visible in the
21
+ # game world are added. As the player moves through the game world, rather than move the position of each game
22
+ # element across the screen to simulate travel, you need only move the root Actor and all other Actors will be moved
23
+ # similarly. This root actor then acts like a "stage" or "camera". For this reason, one could think of a plain Actor as
24
+ # sort of a "container" for other Actors, a way to keep them all organized and related.
25
+ #
26
+ # The behavior of inheritance can modified by setting various properties. Read on for more details.
27
+ #
6
28
  class Actor
7
29
  attr_reader :transform, :parent, :children, :window
8
- attr_accessor :is_visible, :is_tangible, :are_children_visible, :are_children_tangible, :is_mask, :color
9
30
 
31
+ ##
32
+ # If set to true, this Actor will be drawn to screen. If false, it will be skipped. The default is true.
33
+ #
34
+ attr_accessor :is_visible
35
+
36
+ ##
37
+ # If set to true, this Actor will respond to "point-in-shape" tests. If false, such tests will skip this Actor. The default
38
+ # is true.
39
+ #
40
+ attr_accessor :is_tangible
41
+
42
+ ##
43
+ # If set to true, all of this Actor's children will be drawn to screen. If false, they and their descendants will be
44
+ # skipped. The default is true.
45
+ #
46
+ attr_accessor :are_children_visible
47
+
48
+ ##
49
+ # If set to true, this Actor's children will respond to "point-in-shape" tests. If false, such tests will skip them and
50
+ # their descendants. The default is true.
51
+ #
52
+ attr_accessor :are_children_tangible
53
+
54
+ ##
55
+ # If set to true, this Actor will be treated as a "mask" for its parent regarding "point-in-shape" tests. If the point is
56
+ # in this Actor's bounds, it will act as though the point is in its parent's bounds instead of its own. The default is
57
+ # false.
58
+ #
59
+ attr_accessor :is_mask
60
+
61
+ ##
62
+ # The Gosu::Color to use when rendering this Actor.
63
+ #
64
+ attr_accessor :color
65
+
66
+ ##
67
+ # Creates a new Actor, setting all inheritance properties to their defaults and assigning a random color. Requires
68
+ # a Gosu::Window to be used when rendering.
69
+ #
10
70
  def initialize(window)
11
71
  @window = window
12
72
  @transform = Transform.new
@@ -24,17 +84,16 @@ module Gosling
24
84
  "#<#{self.class}:#{self.object_id}>"
25
85
  end
26
86
 
27
- def parent=(parent)
28
- return if parent == @parent
29
- unless parent
30
- raise Gosling::InheritanceError.new("You should use Actor.remove_child() instead of setting the parent directly.") if @parent.has_child?(self)
31
- end
32
- @parent = parent
33
- if @parent
34
- raise Gosling::InheritanceError.new("You should use Actor.add_child() instead of setting the parent directly.") unless @parent.has_child?(self)
35
- end
36
- end
37
-
87
+ ##
88
+ # Establishes a parent/child relationship between this actor and the one passed, respectively. The child Actor will
89
+ # appear relative to its parent, move as the parent moves, and draw when the parent draws.
90
+ #
91
+ # An Actor cannot be made a child of itself. Similarly, a child cannot be added to a parent if doing so would create
92
+ # a circular reference (e.g. a.add_child(b) followed by b.add_child(a)).
93
+ #
94
+ # If the child Actor already had a parent, the Actor is disassociated from its former parent before becoming
95
+ # associated with this one. An Actor can have only one parent at a time.
96
+ #
38
97
  def add_child(child)
39
98
  return if @children.include?(child)
40
99
  raise Gosling::InheritanceError.new("An Actor cannot be made a child of itself.") if child == self
@@ -49,6 +108,10 @@ module Gosling
49
108
  child.parent = self
50
109
  end
51
110
 
111
+ ##
112
+ # If the given Actor is a child of this Actor, it is disassociated from this Actor. In any case, the child Actor is
113
+ # immediately orphaned.
114
+ #
52
115
  def remove_child(child)
53
116
  return unless @children.include?(child)
54
117
 
@@ -56,94 +119,137 @@ module Gosling
56
119
  child.parent = nil
57
120
  end
58
121
 
122
+ ##
123
+ # Returns true if this Actor has the given Actor as a child.
124
+ #
59
125
  def has_child?(child)
60
126
  @children.include?(child)
61
127
  end
62
128
 
129
+ ##
130
+ # Wrapper method. Returns this Actor's x position in relative space. See Transform#translation.
131
+ #
63
132
  def x
64
- @transform.translation[0]
133
+ @transform.translation.x
65
134
  end
66
135
 
136
+ ##
137
+ # Wrapper method. Sets this Actor's x position in relative space. See Transform#translation.
138
+ #
67
139
  def x=(val)
68
- array = @transform.translation.to_a
69
- array[0] = val
70
- @transform.set_translation(Vector.elements(array))
140
+ @transform.translation = val, @transform.translation.y
71
141
  end
72
142
 
143
+ ##
144
+ # Wrapper method. Returns this Actor's y position in relative space. See Transform#translation.
145
+ #
73
146
  def y
74
- @transform.translation[1]
147
+ @transform.translation.y
75
148
  end
76
149
 
150
+ ##
151
+ # Wrapper method. Sets this Actor's y position in relative space. See Transform#translation.
152
+ #
77
153
  def y=(val)
78
- array = @transform.translation.to_a
79
- array[1] = val
80
- @transform.set_translation(Vector.elements(array))
154
+ @transform.translation = @transform.translation.x, val
81
155
  end
82
156
 
157
+ ##
158
+ # Wrapper method. Returns this Actor's position in relative space as a Snow::Vec3. See Transform#translation.
159
+ #
83
160
  def pos
84
- Vector[x, y, 0]
161
+ @transform.translation
85
162
  end
86
163
 
164
+ ##
165
+ # Wrapper method. Sets this Actor's position in relative space. See Transform#translation.
166
+ #
87
167
  def pos=(val)
88
- array = @transform.translation.to_a
89
- array[0] = val[0]
90
- array[1] = val[1]
91
- @transform.set_translation(Vector.elements(array))
168
+ @transform.translation = val
92
169
  end
93
170
 
171
+ ##
172
+ # Wrapper method. Returns the x component of the centerpoint of this Actor. See Transform#center.
173
+ #
94
174
  def center_x
95
- @transform.center[0]
175
+ @transform.center.x
96
176
  end
97
177
 
178
+ ##
179
+ # Wrapper method. Sets the x component of the centerpoint of this Actor. See Transform#center.
180
+ #
98
181
  def center_x=(val)
99
- array = @transform.center.to_a
100
- array[0] = val
101
- @transform.set_center(Vector.elements(array))
182
+ @transform.center = val, @transform.center.y
102
183
  end
103
184
 
185
+ ##
186
+ # Wrapper method. Returns the y component of the centerpoint of this Actor. See Transform#center.
187
+ #
104
188
  def center_y
105
- @transform.center[1]
189
+ @transform.center.y
106
190
  end
107
191
 
192
+ ##
193
+ # Wrapper method. Sets the y component of the centerpoint of this Actor. See Transform#center.
194
+ #
108
195
  def center_y=(val)
109
- array = @transform.center.to_a
110
- array[1] = val
111
- @transform.set_center(Vector.elements(array))
196
+ @transform.center = @transform.center.x, val
112
197
  end
113
198
 
199
+ ##
200
+ # Wrapper method. Returns the x component of the scaling of this Actor. See Transform#scale.
201
+ #
114
202
  def scale_x
115
- @transform.scale[0]
203
+ @transform.scale.x
116
204
  end
117
205
 
206
+ ##
207
+ # Wrapper method. Sets the x component of the scaling of this Actor. See Transform#scale.
208
+ #
118
209
  def scale_x=(val)
119
- array = @transform.scale.to_a
120
- array[0] = val
121
- @transform.set_scale(Vector.elements(array))
210
+ @transform.scale = val, @transform.scale.y
122
211
  end
123
212
 
213
+ ##
214
+ # Wrapper method. Returns the y component of the scaling of this Actor. See Transform#scale.
215
+ #
124
216
  def scale_y
125
- @transform.scale[1]
217
+ @transform.scale.y
126
218
  end
127
219
 
220
+ ##
221
+ # Wrapper method. Sets the y component of the scaling of this Actor. See Transform#scale.
222
+ #
128
223
  def scale_y=(val)
129
- array = @transform.scale.to_a
130
- array[1] = val
131
- @transform.set_scale(Vector.elements(array))
224
+ @transform.scale = @transform.scale.x, val
132
225
  end
133
226
 
227
+ ##
228
+ # Wrapper method. Returns this Actor's rotation in radians. See Transform#rotation.
229
+ #
134
230
  def rotation
135
231
  @transform.rotation
136
232
  end
137
233
 
234
+ ##
235
+ # Wrapper method. Sets this Actor's rotation in radians. See Transform#rotation.
236
+ #
138
237
  def rotation=(val)
139
- @transform.set_rotation(val)
140
- end
141
-
142
- def render(matrix)
143
- end
144
-
238
+ @transform.rotation = val
239
+ end
240
+
241
+ ##
242
+ # Calls #render on this Actor, drawing it to the screen if #is_visible is set to true (the default).
243
+ #
244
+ # The Actor's transforms, if any, will be applied prior to rendering. If an optional Snow::Mat3 matrix transform is
245
+ # given, the Actor will be transformed by a combination of that matrix transform and its own.
246
+ #
247
+ # If the #are_children_visible flag is set to true (the default), then this method will recursively call draw on each
248
+ # of the Actor's children, passing them the combined matrix used to render the parent. Otherwise, children will
249
+ # be skipped and not drawn.
250
+ #
145
251
  def draw(matrix = nil)
146
- matrix ||= Matrix.identity(3)
252
+ matrix ||= Snow::Mat3.new
147
253
  transform = matrix * @transform.to_matrix
148
254
  render(transform) if @is_visible
149
255
  if @are_children_visible
@@ -151,10 +257,28 @@ module Gosling
151
257
  end
152
258
  end
153
259
 
260
+ ##
261
+ # Returns false. Actors have no shape, and so no point is in their bounds. Subclasses override this method with
262
+ # shape-specific behavior.
263
+ #
154
264
  def is_point_in_bounds(point)
155
265
  false
156
266
  end
157
267
 
268
+ ##
269
+ # Given a point in global space, tests this Actor and each of its children, returning the first Actor for whom this
270
+ # point is inside its shape. Respects each Actor's transforms as well as any it may inherit from its ancestors.
271
+ # Useful for determining which Actor the user may have clicked on.
272
+ #
273
+ # If the #is_tangible flag is set to false, this Actor will not be tested. The default is true.
274
+ #
275
+ # If the #are_children_tangible flag is set to false, this Actor's children will not be tested. The default is true.
276
+ #
277
+ # If the #is_mask flag is set to true, a positive test from this Actor instead returns its parent Actor, if any. The
278
+ # default is false.
279
+ #
280
+ # If the point is not inside this Actor or any of its children (excluding any skipped Actors), nil is returned.
281
+ #
158
282
  def get_actor_at(point)
159
283
  hit = nil
160
284
  if @are_children_tangible
@@ -171,6 +295,9 @@ module Gosling
171
295
  hit
172
296
  end
173
297
 
298
+ ##
299
+ # Functions similarly to #get_actor_at, but returns a list of +all+ Actors for whom the point is inside their shape.
300
+ #
174
301
  def get_actors_at(point)
175
302
  actors = []
176
303
  if @are_children_tangible
@@ -186,50 +313,103 @@ module Gosling
186
313
  actors
187
314
  end
188
315
 
189
- def get_global_transform
190
- tf = if parent
191
- parent.get_global_transform * @transform.to_matrix
316
+ ##
317
+ # Returns a Snow::Mat3 transformation matrix combining this Actor's transforms as well as all of its ancestors.
318
+ # This matrix can be used to transform a point in this Actor's local space to its global equivalent (the geometric
319
+ # space of its root ancestor).
320
+ #
321
+ def get_global_transform(out = nil)
322
+ if parent
323
+ out ||= Snow::Mat3.new
324
+ @transform.to_matrix.multiply(parent.get_global_transform, out)
325
+ out
192
326
  else
193
327
  @transform.to_matrix
194
328
  end
195
- return tf
196
329
  end
197
330
 
331
+ ##
332
+ # Returns the global x/y position of this actor (where it is relative to its root ancestor). This value is calculated
333
+ # using the Actor's center (see Transform#center).
334
+ #
198
335
  def get_global_position
199
336
  tf = get_global_transform
200
- Transform.transform_point(tf, Vector[@transform.center[0], @transform.center[1], 0])
337
+ Transform.transform_point(tf, @transform.center)
201
338
  end
202
339
 
340
+ ##
341
+ # Wrapper method. Returns this Actor's alpha value (0-255).
342
+ #
203
343
  def alpha
204
344
  @color.alpha
205
345
  end
206
346
 
347
+ ##
348
+ # Wrapper method. Sets this Actor's alpha value (0-255).
349
+ #
207
350
  def alpha=(val)
208
351
  @color.alpha = val
209
352
  end
210
353
 
354
+ ##
355
+ # Wrapper method. Returns this Actor's red value (0-255).
356
+ #
211
357
  def red
212
358
  @color.red
213
359
  end
214
360
 
361
+ ##
362
+ # Wrapper method. Sets this Actor's red value (0-255).
363
+ #
215
364
  def red=(val)
216
365
  @color.red = val
217
366
  end
218
367
 
368
+ ##
369
+ # Wrapper method. Returns this Actor's green value (0-255).
370
+ #
219
371
  def green
220
372
  @color.green
221
373
  end
222
374
 
375
+ ##
376
+ # Wrapper method. Sets this Actor's green value (0-255).
377
+ #
223
378
  def green=(val)
224
379
  @color.green = val
225
380
  end
226
381
 
382
+ ##
383
+ # Wrapper method. Returns this Actor's blue value (0-255).
384
+ #
227
385
  def blue
228
386
  @color.blue
229
387
  end
230
388
 
389
+ ##
390
+ # Wrapper method. Sets this Actor's blue value (0-255).
391
+ #
231
392
  def blue=(val)
232
393
  @color.blue = val
233
394
  end
395
+
396
+ protected
397
+
398
+ def render(matrix)
399
+ end
400
+
401
+ ##
402
+ # Internal use only. See #add_child and #remove_child.
403
+ #
404
+ def parent=(parent)
405
+ return if parent == @parent
406
+ unless parent
407
+ raise Gosling::InheritanceError.new("You should use Actor.remove_child() instead of setting the parent directly.") if @parent.has_child?(self)
408
+ end
409
+ @parent = parent
410
+ if @parent
411
+ raise Gosling::InheritanceError.new("You should use Actor.add_child() instead of setting the parent directly.") unless @parent.has_child?(self)
412
+ end
413
+ end
234
414
  end
235
- end
415
+ end
@@ -2,26 +2,52 @@ require_relative 'actor.rb'
2
2
  require_relative 'collision.rb'
3
3
 
4
4
  module Gosling
5
+ ##
6
+ # Represents an Actor with a circular shape, defined by a mutable radius. The circle is rendered relative to the
7
+ # Circle's center (see Transform#center).
8
+ #
5
9
  class Circle < Actor
10
+ ##
11
+ # How many vertices to use when rendering circles. More vertices means more accurate rendering at the cost of
12
+ # performance.
13
+ #
6
14
  RENDER_VERTEX_COUNT = 16
7
15
 
8
16
  attr_reader :radius
9
17
 
18
+ ##
19
+ # Creates a new Circle with initial radius of zero.
20
+ #
10
21
  def initialize(window)
11
22
  super(window)
12
23
  @radius = 0
13
24
  end
14
25
 
26
+ ##
27
+ # Sets this circle's radius. Radius must be a positive integer.
28
+ #
15
29
  def radius=(val)
16
30
  raise ArgumentError.new("Circle.radius cannot be negative") if val < 0
17
31
  @radius = val
18
32
  end
19
33
 
34
+ ##
35
+ # Returns the angle's corresponding unit vector times this circle's radius.
36
+ #
20
37
  def get_point_at_angle(radians)
21
38
  raise ArgumentError.new("Expected Numeric, but received #{radians.inspect}!") unless radians.is_a?(Numeric)
22
- Vector[Math.cos(radians) * @radius, Math.sin(radians) * @radius, 0]
39
+ Snow::Vec3[Math.cos(radians) * @radius, Math.sin(radians) * @radius, 0]
23
40
  end
24
41
 
42
+ ##
43
+ # Returns true if the point is inside the Circle, false otherwise.
44
+ #
45
+ def is_point_in_bounds(point)
46
+ Collision.is_point_in_shape?(point, self)
47
+ end
48
+
49
+ private
50
+
25
51
  def render(matrix)
26
52
  local_vertices = (0...RENDER_VERTEX_COUNT).map do |i|
27
53
  get_point_at_angle(Math::PI * 2 * i / RENDER_VERTEX_COUNT)
@@ -40,9 +66,5 @@ module Gosling
40
66
  i += 1
41
67
  end
42
68
  end
43
-
44
- def is_point_in_bounds(point)
45
- Collision.is_point_in_shape?(point, self)
46
- end
47
69
  end
48
70
  end