gosling 2.3.0 → 2.3.2

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.
data/lib/gosling/utils.rb CHANGED
@@ -1,20 +1,20 @@
1
- ##
2
- # Raises an ArgumentError unless the object is of the specified type.
3
- #
4
- def type_check(obj, type)
5
- raise ArgumentError.new("Expected #{type}, but received #{obj.inspect}!") unless obj.is_a?(type)
6
- end
7
-
8
- ##
9
- # Raises an ArgumentError unless the object is one of the listed types.
10
- #
11
- def types_check(obj, *types)
12
- raise ArgumentError.new("Expected one of #{types.inspect}, but received #{obj.inspect}!") unless types.any? { |type| obj.is_a?(type) }
13
- end
14
-
15
- ##
16
- # Raises an ArgumentError unless the object is truthy.
17
- #
18
- def boolean_check(obj)
19
- raise ArgumentError.new("Expected true or false, but received #{obj.inspect}!") unless [true, false].include?(obj)
20
- end
1
+ ##
2
+ # Raises an ArgumentError unless the object is of the specified type.
3
+ #
4
+ def type_check(obj, type)
5
+ raise ArgumentError.new("Expected #{type}, but received #{obj.inspect}!") unless obj.is_a?(type)
6
+ end
7
+
8
+ ##
9
+ # Raises an ArgumentError unless the object is one of the listed types.
10
+ #
11
+ def types_check(obj, *types)
12
+ raise ArgumentError.new("Expected one of #{types.inspect}, but received #{obj.inspect}!") unless types.any? { |type| obj.is_a?(type) }
13
+ end
14
+
15
+ ##
16
+ # Raises an ArgumentError unless the object is truthy.
17
+ #
18
+ def boolean_check(obj)
19
+ raise ArgumentError.new("Expected true or false, but received #{obj.inspect}!") unless [true, false].include?(obj)
20
+ end
@@ -1,21 +1,21 @@
1
- require_relative 'object_cache.rb'
2
-
3
- class VectorCache
4
- include Singleton
5
- include ObjectCache
6
-
7
- def initialize
8
- @cache = {}
9
- end
10
-
11
- protected
12
-
13
- def create
14
- Snow::Vec3.new
15
- end
16
-
17
- def reset(vector)
18
- type_check(vector, Snow::Vec3)
19
- vector.set(0, 0, 0)
20
- end
21
- end
1
+ require_relative 'object_cache.rb'
2
+
3
+ class VectorCache
4
+ include Singleton
5
+ include ObjectCache
6
+
7
+ def initialize
8
+ @cache = {}
9
+ end
10
+
11
+ protected
12
+
13
+ def create
14
+ Snow::Vec3.new
15
+ end
16
+
17
+ def reset(vector)
18
+ type_check(vector, Snow::Vec3)
19
+ vector.set(0, 0, 0)
20
+ end
21
+ end
@@ -1,7 +1,7 @@
1
- #--
2
- # MAJOR version when you make incompatible changes,
3
- # MINOR version when you add functionality in a backwards-compatible manner, and
4
- # PATCH version when you make backwards-compatible bug fixes.
5
- module Gosling
6
- VERSION = '2.3.0'
7
- end
1
+ #--
2
+ # MAJOR version when you make incompatible changes,
3
+ # MINOR version when you add functionality in a backwards-compatible manner, and
4
+ # PATCH version when you make backwards-compatible bug fixes.
5
+ module Gosling
6
+ VERSION = '2.3.2'
7
+ end
data/spec/actor_spec.rb CHANGED
@@ -1,628 +1,628 @@
1
- module Gosling
2
- class Actor
3
- public :render
4
- end
5
- end
6
-
7
- describe Gosling::Actor do
8
- before(:all) do
9
- @window = Gosu::Window.new(640, 480, false)
10
- @read_only_actor = Gosling::Actor.new(@window)
11
- @parent = Gosling::Actor.new(@window)
12
- @child = Gosling::Actor.new(@window)
13
- end
14
-
15
- describe '#new' do
16
- it 'requires a Gosu::Window' do
17
- expect { Gosling::Actor.new(@window) }.not_to raise_error
18
- expect { Gosling::Actor.new() }.to raise_error(ArgumentError)
19
- end
20
- end
21
-
22
- it 'has a transform' do
23
- expect(@read_only_actor).to be_kind_of(Gosling::Transformable)
24
- end
25
-
26
- it 'can have a parent' do
27
- expect { @read_only_actor.parent }.not_to raise_error
28
- end
29
-
30
- it "does not initialize with a parent" do
31
- expect(@read_only_actor.parent).to be == nil
32
- end
33
-
34
- describe '#add_child' do
35
- it "creates a two-way parent/child link" do
36
- @parent.add_child(@child)
37
- expect(@parent.has_child?(@child)).to be true
38
- expect(@child.parent).to be == @parent
39
- end
40
- end
41
-
42
- describe '#remove_child' do
43
- it "severs the two-way parent/child link" do
44
- @parent.add_child(@child)
45
- @parent.remove_child(@child)
46
- expect(@parent.has_child?(@child)).to be false
47
- expect(@child.parent).to be == nil
48
- end
49
- end
50
-
51
- it 'has a list of children' do
52
- expect(@read_only_actor.children).to be_instance_of(Array)
53
- end
54
-
55
- it "starts with no children" do
56
- expect(@read_only_actor.children.empty?).to be true
57
- end
58
-
59
- it "knows if it has a particular child or not" do
60
- expect(@read_only_actor.has_child?(Gosling::Actor.new(@window))).to be false
61
- end
62
-
63
- it "will never add any of its ancestors as children" do
64
- @parent.add_child(@child)
65
- expect { @child.add_child(@parent) }.to raise_error(Gosling::InheritanceError)
66
- end
67
-
68
- it "will not add itself as its own child" do
69
- expect { @child.add_child(@child) }.to raise_error(Gosling::InheritanceError)
70
- end
71
-
72
- context "when given a child" do
73
- before do
74
- @parent.add_child(@child)
75
- end
76
-
77
- it "it forms a two-way link with that child" do
78
- expect(@parent.has_child?(@child)).to be true
79
- expect(@child.parent).to be == @parent
80
- end
81
-
82
- it "cannot be given the same child more than once" do
83
- @parent.add_child(@child)
84
- expect(@parent.children.length).to be == 1
85
- end
86
-
87
- context "and then the child is removed" do
88
- before do
89
- @parent.remove_child(@child)
90
- end
91
-
92
- it "the parent/child link is broken" do
93
- expect(@parent.has_child?(@child)).to be false
94
- expect(@child.parent).to be == nil
95
- end
96
- end
97
-
98
- context 'and then adopted by another actor' do
99
- it 'automatically breaks the old child/parent link' do
100
- parent2 = Gosling::Actor.new(@window)
101
- parent2.add_child(@child)
102
- expect(@parent.has_child?(@child)).to be false
103
- expect(@child.parent).to be == parent2
104
- end
105
- end
106
- end
107
-
108
- it 'has a visibility flag' do
109
- actor = Gosling::Actor.new(@window)
110
- actor.is_visible = true
111
- expect(actor.is_visible).to be true
112
- actor.is_visible = false
113
- expect(actor.is_visible).to be false
114
- end
115
-
116
- it 'has a children visibility flag' do
117
- actor = Gosling::Actor.new(@window)
118
- actor.are_children_visible = true
119
- expect(actor.are_children_visible).to be true
120
- actor.are_children_visible = false
121
- expect(actor.are_children_visible).to be false
122
- end
123
-
124
- it 'has a tangible flag' do
125
- actor = Gosling::Actor.new(@window)
126
- actor.is_tangible = true
127
- expect(actor.is_tangible).to be true
128
- actor.is_tangible = false
129
- expect(actor.is_tangible).to be false
130
- end
131
-
132
- it 'has a children tangibile flag' do
133
- actor = Gosling::Actor.new(@window)
134
- actor.are_children_tangible = true
135
- expect(actor.are_children_tangible).to be true
136
- actor.are_children_tangible = false
137
- expect(actor.are_children_tangible).to be false
138
- end
139
-
140
- it 'has a mask flag' do
141
- actor = Gosling::Actor.new(@window)
142
- actor.is_mask = true
143
- expect(actor.is_mask).to be true
144
- actor.is_mask = false
145
- expect(actor.is_mask).to be false
146
- end
147
-
148
- describe '#render' do
149
- it 'the method exists' do
150
- expect { @read_only_actor.render(Snow::Mat3.new) }.not_to raise_error
151
- end
152
- end
153
-
154
- describe '#draw' do
155
- before(:all) do
156
- @draw_actor = Gosling::Actor.new(@window)
157
- @mat = Snow::Mat3.new
158
- end
159
-
160
- context 'when visible' do
161
- it 'calls render on itself' do
162
- @draw_actor.is_visible = true
163
- expect(@draw_actor).to receive(:render).with(@mat).once
164
- @draw_actor.draw(@mat)
165
- end
166
- end
167
-
168
- context 'when not visible' do
169
- it 'does not call render on itself' do
170
- @draw_actor.is_visible = false
171
- expect(@draw_actor).not_to receive(:render)
172
- @draw_actor.draw(@mat)
173
- end
174
- end
175
-
176
- context 'with children' do
177
- before(:all) do
178
- @child1 = Gosling::Actor.new(@window)
179
- @child2 = Gosling::Actor.new(@window)
180
- @draw_actor.add_child(@child1)
181
- @draw_actor.add_child(@child2)
182
- end
183
-
184
- context 'when are_children_visible is false' do
185
- it 'draws itself, but not its children' do
186
- @draw_actor.are_children_visible = false
187
- expect(@child1).not_to receive(:draw)
188
- expect(@child2).not_to receive(:draw)
189
- @draw_actor.draw(@mat)
190
- @draw_actor.are_children_visible = true
191
- end
192
- end
193
-
194
- it 'calls draw on each of its children' do
195
- expect(@child1).to receive(:draw).with(@mat).once
196
- expect(@child2).to receive(:draw).with(@mat).once
197
- @draw_actor.draw(@mat)
198
- end
199
-
200
- it 'passes its children a comprehensive transformation matrix' do
201
- parameter_mat = Snow::Mat3[
202
- 1, 0, 10,
203
- 0, 1, 20,
204
- 0, 0, 1
205
- ]
206
- self_mat = Snow::Mat3[
207
- 2, 0, 0,
208
- 0, 3, 0,
209
- 0, 0, 1
210
- ]
211
- result_mat = self_mat * parameter_mat
212
-
213
- allow(@draw_actor).to receive(:to_matrix).and_return(self_mat)
214
-
215
- expect(@child1).to receive(:draw).with(result_mat).once
216
- expect(@child2).to receive(:draw).with(result_mat).once
217
- @draw_actor.draw(parameter_mat)
218
- end
219
-
220
- after(:all) do
221
- @draw_actor.children.each { |child| @draw_actor.remove_child(@child) }
222
- end
223
- end
224
- end
225
-
226
- describe '#is_point_in_bounds' do
227
- it 'returns false' do
228
- expect(@read_only_actor.is_point_in_bounds(Snow::Vec3[0,0,1])).to be false
229
- end
230
- end
231
-
232
- describe '#get_actor_at' do
233
- before(:all) do
234
- @parent = Gosling::Actor.new(@window)
235
- end
236
-
237
- context 'when tangible is false' do
238
- it 'returns nil even if hit' do
239
- @parent.is_tangible = false
240
- allow(@parent).to receive(:is_point_in_bounds).and_return(true)
241
- expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == nil
242
- @parent.is_tangible = true
243
- end
244
- end
245
-
246
- context 'with no children' do
247
- it 'returns itself if the point is within its bounds' do
248
- allow(@parent).to receive(:is_point_in_bounds).and_return(true)
249
- expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @parent
250
- end
251
-
252
- it 'returns nil if point is not within its bounds' do
253
- allow(@parent).to receive(:is_point_in_bounds).and_return(false)
254
- expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == nil
255
- end
256
- end
257
-
258
- context 'with two children' do
259
- before(:all) do
260
- @child1 = Gosling::Actor.new(@window)
261
- @child2 = Gosling::Actor.new(@window)
262
- @parent.add_child(@child1)
263
- @parent.add_child(@child2)
264
- end
265
-
266
- context 'when the children are not tangible' do
267
- it 'does not hit test any children' do
268
- @parent.are_children_tangible = false
269
- allow(@parent).to receive(:is_point_in_bounds).and_return(false, true)
270
- allow(@child1).to receive(:is_point_in_bounds).and_return(true)
271
- allow(@child2).to receive(:is_point_in_bounds).and_return(true)
272
-
273
- expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == nil
274
- expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @parent
275
- @parent.are_children_tangible = true
276
- end
277
- end
278
-
279
- it "returns the second child if such is hit" do
280
- allow(@parent).to receive(:is_point_in_bounds).and_return(false, true, false, true)
281
- allow(@child1).to receive(:is_point_in_bounds).and_return(false, false, true, true)
282
- allow(@child2).to receive(:is_point_in_bounds).and_return(true)
283
-
284
- 4.times { expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @child2 }
285
- end
286
-
287
- it "returns the first child if the second was not hit" do
288
- allow(@parent).to receive(:is_point_in_bounds).and_return(false, true)
289
- allow(@child1).to receive(:is_point_in_bounds).and_return(true)
290
- allow(@child2).to receive(:is_point_in_bounds).and_return(false)
291
-
292
- 2.times { expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @child1 }
293
- end
294
-
295
- it "returns itself if neither child was hit" do
296
- allow(@parent).to receive(:is_point_in_bounds).and_return(true)
297
- allow(@child1).to receive(:is_point_in_bounds).and_return(false)
298
- allow(@child2).to receive(:is_point_in_bounds).and_return(false)
299
-
300
- expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @parent
301
- end
302
-
303
- it 'returns nil if point is not within it or its children' do
304
- allow(@parent).to receive(:is_point_in_bounds).and_return(false)
305
- allow(@child1).to receive(:is_point_in_bounds).and_return(false)
306
- allow(@child2).to receive(:is_point_in_bounds).and_return(false)
307
-
308
- expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == nil
309
- end
310
-
311
- context 'with a mask child' do
312
- it 'returns the parent if the child is hit' do
313
- @child1.is_mask = true
314
- allow(@parent).to receive(:is_point_in_bounds).and_return(false)
315
- allow(@child1).to receive(:is_point_in_bounds).and_return(true)
316
- allow(@child2).to receive(:is_point_in_bounds).and_return(false)
317
-
318
- expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @parent
319
- @child1.is_mask = false
320
- end
321
- end
322
-
323
- after(:all) do
324
- @parent.children.each { |child| @parent.remove_child(child) }
325
- end
326
- end
327
- end
328
-
329
- describe '#get_actors_at' do
330
- before(:all) do
331
- @parent = Gosling::Actor.new(@window)
332
- end
333
-
334
- context 'when tangible is false' do
335
- it 'returns an empty array even if hit' do
336
- @parent.is_tangible = false
337
- allow(@parent).to receive(:is_point_in_bounds).and_return(true)
338
- expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be_empty
339
- @parent.is_tangible = true
340
- end
341
- end
342
-
343
- context 'with no children' do
344
- it 'returns an array containing itself if the point is within its bounds' do
345
- allow(@parent).to receive(:is_point_in_bounds).and_return(true)
346
- expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
347
- end
348
-
349
- it 'returns an empty array if point is not within its bounds' do
350
- allow(@parent).to receive(:is_point_in_bounds).and_return(false)
351
- expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be_empty
352
- end
353
- end
354
-
355
- context 'with two children' do
356
- before(:all) do
357
- @child1 = Gosling::Actor.new(@window)
358
- @child2 = Gosling::Actor.new(@window)
359
- @parent.add_child(@child1)
360
- @parent.add_child(@child2)
361
- end
362
-
363
- context 'when the children are not tangible' do
364
- it 'ignores the children' do
365
- @parent.are_children_tangible = false
366
- allow(@parent).to receive(:is_point_in_bounds).and_return(false, true)
367
- allow(@child1).to receive(:is_point_in_bounds).and_return(true)
368
- allow(@child2).to receive(:is_point_in_bounds).and_return(true, false)
369
-
370
- expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == []
371
- expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
372
- @parent.are_children_tangible = true
373
- end
374
- end
375
-
376
- it "returns an array containing all actors hit" do
377
- allow(@parent).to receive(:is_point_in_bounds).and_return(false, true, false, true, false, true, false, true)
378
- allow(@child1).to receive(:is_point_in_bounds).and_return(false, false, true, true, false, false, true, true)
379
- allow(@child2).to receive(:is_point_in_bounds).and_return(false, false, false, false, true, true, true, true)
380
-
381
- expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == []
382
- expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
383
- expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child1]
384
- expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child1, @parent]
385
- expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child2]
386
- expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child2, @parent]
387
- expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child2, @child1]
388
- expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child2, @child1, @parent]
389
- end
390
-
391
- context 'with a mask child' do
392
- before(:all) do
393
- @child1.is_mask = true
394
- end
395
-
396
- it 'returns the parent if the child is hit' do
397
- allow(@parent).to receive(:is_point_in_bounds).and_return(false)
398
- allow(@child1).to receive(:is_point_in_bounds).and_return(true)
399
- allow(@child2).to receive(:is_point_in_bounds).and_return(false)
400
-
401
- expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
402
- end
403
-
404
- it 'returns the parent only once if both children are masks and are hit' do
405
- @child2.is_mask = true
406
- allow(@parent).to receive(:is_point_in_bounds).and_return(false)
407
- allow(@child1).to receive(:is_point_in_bounds).and_return(true)
408
- allow(@child2).to receive(:is_point_in_bounds).and_return(true)
409
-
410
- expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
411
- @child2.is_mask = false
412
- end
413
-
414
- it 'returns the parent only once if both parent and child are hit' do
415
- allow(@parent).to receive(:is_point_in_bounds).and_return(true)
416
- allow(@child1).to receive(:is_point_in_bounds).and_return(true)
417
- allow(@child2).to receive(:is_point_in_bounds).and_return(false)
418
-
419
- expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
420
- end
421
-
422
- after(:all) do
423
- @child1.is_mask = false
424
- end
425
- end
426
-
427
- after(:all) do
428
- @parent.children.each { |child| @parent.remove_child(child) }
429
- end
430
- end
431
- end
432
-
433
- describe '#get_global_transform' do
434
- it 'returns a 3x3 matrix' do
435
- result = @parent.get_global_transform
436
- expect(result).to be_instance_of(Snow::Mat3)
437
- end
438
-
439
- it 'is a composite of its own transform plus all of its ancestors' do
440
- centered_view = Gosling::Actor.new(@window)
441
- centered_view.center_x = 10
442
- centered_view.center_y = 2
443
-
444
- scaled_view = Gosling::Actor.new(@window)
445
- scaled_view.scale_x = 3
446
- scaled_view.scale_y = 2
447
-
448
- rotated_view = Gosling::Actor.new(@window)
449
- rotated_view.rotation = Math::PI / 4
450
-
451
- translated_view = Gosling::Actor.new(@window)
452
- translated_view.x = -50
453
- translated_view.y = 10
454
-
455
- centered_view.add_child(scaled_view)
456
- scaled_view.add_child(rotated_view)
457
- rotated_view.add_child(translated_view)
458
- translated_view.add_child(@parent)
459
-
460
- expected = @parent.to_matrix * translated_view.to_matrix * rotated_view.to_matrix * scaled_view.to_matrix * centered_view.to_matrix
461
-
462
- result = @parent.get_global_transform
463
- expect(result).to be == expected
464
-
465
- translated_view.remove_child(@parent)
466
- end
467
- end
468
-
469
- describe '#get_global_position' do
470
- it 'returns a 3d vector' do
471
- result = @parent.get_global_position
472
- expect(result).to be_instance_of(Snow::Vec3)
473
- end
474
-
475
- context 'with a long ancestry' do
476
- before do
477
- @parent.x = 0
478
- @parent.y = 0
479
- @parent.center_x = 0
480
- @parent.center_y = 0
481
- @parent.scale_x = 1
482
- @parent.scale_y = 1
483
- @parent.rotation = 0
484
-
485
- centered_view = Gosling::Actor.new(@window)
486
- centered_view.center_x = 10
487
- centered_view.center_y = 2
488
-
489
- scaled_view = Gosling::Actor.new(@window)
490
- scaled_view.scale_x = 3
491
- scaled_view.scale_y = 2
492
-
493
- rotated_view = Gosling::Actor.new(@window)
494
- rotated_view.rotation = Math::PI / 2
495
-
496
- translated_view = Gosling::Actor.new(@window)
497
- translated_view.x = -50
498
- translated_view.y = 10
499
-
500
- centered_view.add_child(scaled_view)
501
- scaled_view.add_child(rotated_view)
502
- rotated_view.add_child(translated_view)
503
- translated_view.add_child(@parent)
504
-
505
- @ancestry = [
506
- centered_view,
507
- scaled_view,
508
- rotated_view,
509
- translated_view,
510
- @parent
511
- ]
512
- end
513
-
514
- it 'respects all ancestors' do
515
- result = @parent.get_global_position
516
- expect(result).to be == Snow::Vec3[(0 + 10) * 3 - 10, (0 - 50) * -2 - 2, 0]
517
- end
518
-
519
- after do
520
- @ancestry.each { |actor| actor.parent.remove_child(actor) if actor.parent }
521
- end
522
- end
523
- end
524
-
525
- describe '#alpha' do
526
- it 'returns the alpha (transparency) value' do
527
- expect(@parent.alpha).to be_kind_of(Numeric)
528
- end
529
-
530
- it 'sets the alpha (transparency) value' do
531
- actor = Gosling::Actor.new(@window)
532
-
533
- actor.alpha = 128
534
- expect(actor.alpha).to be == 128
535
- end
536
-
537
- it 'forces numeric values to be between 0 and 255' do
538
- actor = Gosling::Actor.new(@window)
539
-
540
- actor.alpha = -128
541
- expect(actor.alpha).to be == 0
542
- actor.alpha = -1
543
- expect(actor.alpha).to be == 0
544
- actor.alpha = 256
545
- expect(actor.alpha).to be == 255
546
- actor.alpha = 1024
547
- expect(actor.alpha).to be == 255
548
- end
549
- end
550
-
551
- describe '#red' do
552
- it 'returns the red value' do
553
- expect(@parent.red).to be_kind_of(Numeric)
554
- end
555
-
556
- it 'sets the red value' do
557
- actor = Gosling::Actor.new(@window)
558
-
559
- actor.red = 128
560
- expect(actor.red).to be == 128
561
- end
562
-
563
- it 'forces numeric values to be between 0 and 255' do
564
- actor = Gosling::Actor.new(@window)
565
-
566
- actor.red = -128
567
- expect(actor.red).to be == 0
568
- actor.red = -1
569
- expect(actor.red).to be == 0
570
- actor.red = 256
571
- expect(actor.red).to be == 255
572
- actor.red = 1024
573
- expect(actor.red).to be == 255
574
- end
575
- end
576
-
577
- describe '#green' do
578
- it 'returns the green value' do
579
- expect(@parent.green).to be_kind_of(Numeric)
580
- end
581
-
582
- it 'sets the green value' do
583
- actor = Gosling::Actor.new(@window)
584
-
585
- actor.green = 128
586
- expect(actor.green).to be == 128
587
- end
588
-
589
- it 'forces numeric values to be between 0 and 255' do
590
- actor = Gosling::Actor.new(@window)
591
-
592
- actor.green = -128
593
- expect(actor.green).to be == 0
594
- actor.green = -1
595
- expect(actor.green).to be == 0
596
- actor.green = 256
597
- expect(actor.green).to be == 255
598
- actor.green = 1024
599
- expect(actor.green).to be == 255
600
- end
601
- end
602
-
603
- describe '#blue' do
604
- it 'returns the blue value' do
605
- expect(@parent.blue).to be_kind_of(Numeric)
606
- end
607
-
608
- it 'sets the blue value' do
609
- actor = Gosling::Actor.new(@window)
610
-
611
- actor.blue = 128
612
- expect(actor.blue).to be == 128
613
- end
614
-
615
- it 'forces numeric values to be between 0 and 255' do
616
- actor = Gosling::Actor.new(@window)
617
-
618
- actor.blue = -128
619
- expect(actor.blue).to be == 0
620
- actor.blue = -1
621
- expect(actor.blue).to be == 0
622
- actor.blue = 256
623
- expect(actor.blue).to be == 255
624
- actor.blue = 1024
625
- expect(actor.blue).to be == 255
626
- end
627
- end
1
+ module Gosling
2
+ class Actor
3
+ public :render
4
+ end
5
+ end
6
+
7
+ describe Gosling::Actor do
8
+ before(:all) do
9
+ @window = Gosu::Window.new(640, 480, false)
10
+ @read_only_actor = Gosling::Actor.new(@window)
11
+ @parent = Gosling::Actor.new(@window)
12
+ @child = Gosling::Actor.new(@window)
13
+ end
14
+
15
+ describe '#new' do
16
+ it 'requires a Gosu::Window' do
17
+ expect { Gosling::Actor.new(@window) }.not_to raise_error
18
+ expect { Gosling::Actor.new() }.to raise_error(ArgumentError)
19
+ end
20
+ end
21
+
22
+ it 'has a transform' do
23
+ expect(@read_only_actor).to be_kind_of(Gosling::Transformable)
24
+ end
25
+
26
+ it 'can have a parent' do
27
+ expect { @read_only_actor.parent }.not_to raise_error
28
+ end
29
+
30
+ it "does not initialize with a parent" do
31
+ expect(@read_only_actor.parent).to be == nil
32
+ end
33
+
34
+ describe '#add_child' do
35
+ it "creates a two-way parent/child link" do
36
+ @parent.add_child(@child)
37
+ expect(@parent.has_child?(@child)).to be true
38
+ expect(@child.parent).to be == @parent
39
+ end
40
+ end
41
+
42
+ describe '#remove_child' do
43
+ it "severs the two-way parent/child link" do
44
+ @parent.add_child(@child)
45
+ @parent.remove_child(@child)
46
+ expect(@parent.has_child?(@child)).to be false
47
+ expect(@child.parent).to be == nil
48
+ end
49
+ end
50
+
51
+ it 'has a list of children' do
52
+ expect(@read_only_actor.children).to be_instance_of(Array)
53
+ end
54
+
55
+ it "starts with no children" do
56
+ expect(@read_only_actor.children.empty?).to be true
57
+ end
58
+
59
+ it "knows if it has a particular child or not" do
60
+ expect(@read_only_actor.has_child?(Gosling::Actor.new(@window))).to be false
61
+ end
62
+
63
+ it "will never add any of its ancestors as children" do
64
+ @parent.add_child(@child)
65
+ expect { @child.add_child(@parent) }.to raise_error(Gosling::InheritanceError)
66
+ end
67
+
68
+ it "will not add itself as its own child" do
69
+ expect { @child.add_child(@child) }.to raise_error(Gosling::InheritanceError)
70
+ end
71
+
72
+ context "when given a child" do
73
+ before do
74
+ @parent.add_child(@child)
75
+ end
76
+
77
+ it "it forms a two-way link with that child" do
78
+ expect(@parent.has_child?(@child)).to be true
79
+ expect(@child.parent).to be == @parent
80
+ end
81
+
82
+ it "cannot be given the same child more than once" do
83
+ @parent.add_child(@child)
84
+ expect(@parent.children.length).to be == 1
85
+ end
86
+
87
+ context "and then the child is removed" do
88
+ before do
89
+ @parent.remove_child(@child)
90
+ end
91
+
92
+ it "the parent/child link is broken" do
93
+ expect(@parent.has_child?(@child)).to be false
94
+ expect(@child.parent).to be == nil
95
+ end
96
+ end
97
+
98
+ context 'and then adopted by another actor' do
99
+ it 'automatically breaks the old child/parent link' do
100
+ parent2 = Gosling::Actor.new(@window)
101
+ parent2.add_child(@child)
102
+ expect(@parent.has_child?(@child)).to be false
103
+ expect(@child.parent).to be == parent2
104
+ end
105
+ end
106
+ end
107
+
108
+ it 'has a visibility flag' do
109
+ actor = Gosling::Actor.new(@window)
110
+ actor.is_visible = true
111
+ expect(actor.is_visible).to be true
112
+ actor.is_visible = false
113
+ expect(actor.is_visible).to be false
114
+ end
115
+
116
+ it 'has a children visibility flag' do
117
+ actor = Gosling::Actor.new(@window)
118
+ actor.are_children_visible = true
119
+ expect(actor.are_children_visible).to be true
120
+ actor.are_children_visible = false
121
+ expect(actor.are_children_visible).to be false
122
+ end
123
+
124
+ it 'has a tangible flag' do
125
+ actor = Gosling::Actor.new(@window)
126
+ actor.is_tangible = true
127
+ expect(actor.is_tangible).to be true
128
+ actor.is_tangible = false
129
+ expect(actor.is_tangible).to be false
130
+ end
131
+
132
+ it 'has a children tangibile flag' do
133
+ actor = Gosling::Actor.new(@window)
134
+ actor.are_children_tangible = true
135
+ expect(actor.are_children_tangible).to be true
136
+ actor.are_children_tangible = false
137
+ expect(actor.are_children_tangible).to be false
138
+ end
139
+
140
+ it 'has a mask flag' do
141
+ actor = Gosling::Actor.new(@window)
142
+ actor.is_mask = true
143
+ expect(actor.is_mask).to be true
144
+ actor.is_mask = false
145
+ expect(actor.is_mask).to be false
146
+ end
147
+
148
+ describe '#render' do
149
+ it 'the method exists' do
150
+ expect { @read_only_actor.render(Snow::Mat3.new) }.not_to raise_error
151
+ end
152
+ end
153
+
154
+ describe '#draw' do
155
+ before(:all) do
156
+ @draw_actor = Gosling::Actor.new(@window)
157
+ @mat = Snow::Mat3.new
158
+ end
159
+
160
+ context 'when visible' do
161
+ it 'calls render on itself' do
162
+ @draw_actor.is_visible = true
163
+ expect(@draw_actor).to receive(:render).with(@mat).once
164
+ @draw_actor.draw(@mat)
165
+ end
166
+ end
167
+
168
+ context 'when not visible' do
169
+ it 'does not call render on itself' do
170
+ @draw_actor.is_visible = false
171
+ expect(@draw_actor).not_to receive(:render)
172
+ @draw_actor.draw(@mat)
173
+ end
174
+ end
175
+
176
+ context 'with children' do
177
+ before(:all) do
178
+ @child1 = Gosling::Actor.new(@window)
179
+ @child2 = Gosling::Actor.new(@window)
180
+ @draw_actor.add_child(@child1)
181
+ @draw_actor.add_child(@child2)
182
+ end
183
+
184
+ context 'when are_children_visible is false' do
185
+ it 'draws itself, but not its children' do
186
+ @draw_actor.are_children_visible = false
187
+ expect(@child1).not_to receive(:draw)
188
+ expect(@child2).not_to receive(:draw)
189
+ @draw_actor.draw(@mat)
190
+ @draw_actor.are_children_visible = true
191
+ end
192
+ end
193
+
194
+ it 'calls draw on each of its children' do
195
+ expect(@child1).to receive(:draw).with(@mat).once
196
+ expect(@child2).to receive(:draw).with(@mat).once
197
+ @draw_actor.draw(@mat)
198
+ end
199
+
200
+ it 'passes its children a comprehensive transformation matrix' do
201
+ parameter_mat = Snow::Mat3[
202
+ 1, 0, 10,
203
+ 0, 1, 20,
204
+ 0, 0, 1
205
+ ]
206
+ self_mat = Snow::Mat3[
207
+ 2, 0, 0,
208
+ 0, 3, 0,
209
+ 0, 0, 1
210
+ ]
211
+ result_mat = self_mat * parameter_mat
212
+
213
+ allow(@draw_actor).to receive(:to_matrix).and_return(self_mat)
214
+
215
+ expect(@child1).to receive(:draw).with(result_mat).once
216
+ expect(@child2).to receive(:draw).with(result_mat).once
217
+ @draw_actor.draw(parameter_mat)
218
+ end
219
+
220
+ after(:all) do
221
+ @draw_actor.children.each { |child| @draw_actor.remove_child(@child) }
222
+ end
223
+ end
224
+ end
225
+
226
+ describe '#is_point_in_bounds' do
227
+ it 'returns false' do
228
+ expect(@read_only_actor.is_point_in_bounds(Snow::Vec3[0,0,1])).to be false
229
+ end
230
+ end
231
+
232
+ describe '#get_actor_at' do
233
+ before(:all) do
234
+ @parent = Gosling::Actor.new(@window)
235
+ end
236
+
237
+ context 'when tangible is false' do
238
+ it 'returns nil even if hit' do
239
+ @parent.is_tangible = false
240
+ allow(@parent).to receive(:is_point_in_bounds).and_return(true)
241
+ expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == nil
242
+ @parent.is_tangible = true
243
+ end
244
+ end
245
+
246
+ context 'with no children' do
247
+ it 'returns itself if the point is within its bounds' do
248
+ allow(@parent).to receive(:is_point_in_bounds).and_return(true)
249
+ expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @parent
250
+ end
251
+
252
+ it 'returns nil if point is not within its bounds' do
253
+ allow(@parent).to receive(:is_point_in_bounds).and_return(false)
254
+ expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == nil
255
+ end
256
+ end
257
+
258
+ context 'with two children' do
259
+ before(:all) do
260
+ @child1 = Gosling::Actor.new(@window)
261
+ @child2 = Gosling::Actor.new(@window)
262
+ @parent.add_child(@child1)
263
+ @parent.add_child(@child2)
264
+ end
265
+
266
+ context 'when the children are not tangible' do
267
+ it 'does not hit test any children' do
268
+ @parent.are_children_tangible = false
269
+ allow(@parent).to receive(:is_point_in_bounds).and_return(false, true)
270
+ allow(@child1).to receive(:is_point_in_bounds).and_return(true)
271
+ allow(@child2).to receive(:is_point_in_bounds).and_return(true)
272
+
273
+ expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == nil
274
+ expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @parent
275
+ @parent.are_children_tangible = true
276
+ end
277
+ end
278
+
279
+ it "returns the second child if such is hit" do
280
+ allow(@parent).to receive(:is_point_in_bounds).and_return(false, true, false, true)
281
+ allow(@child1).to receive(:is_point_in_bounds).and_return(false, false, true, true)
282
+ allow(@child2).to receive(:is_point_in_bounds).and_return(true)
283
+
284
+ 4.times { expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @child2 }
285
+ end
286
+
287
+ it "returns the first child if the second was not hit" do
288
+ allow(@parent).to receive(:is_point_in_bounds).and_return(false, true)
289
+ allow(@child1).to receive(:is_point_in_bounds).and_return(true)
290
+ allow(@child2).to receive(:is_point_in_bounds).and_return(false)
291
+
292
+ 2.times { expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @child1 }
293
+ end
294
+
295
+ it "returns itself if neither child was hit" do
296
+ allow(@parent).to receive(:is_point_in_bounds).and_return(true)
297
+ allow(@child1).to receive(:is_point_in_bounds).and_return(false)
298
+ allow(@child2).to receive(:is_point_in_bounds).and_return(false)
299
+
300
+ expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @parent
301
+ end
302
+
303
+ it 'returns nil if point is not within it or its children' do
304
+ allow(@parent).to receive(:is_point_in_bounds).and_return(false)
305
+ allow(@child1).to receive(:is_point_in_bounds).and_return(false)
306
+ allow(@child2).to receive(:is_point_in_bounds).and_return(false)
307
+
308
+ expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == nil
309
+ end
310
+
311
+ context 'with a mask child' do
312
+ it 'returns the parent if the child is hit' do
313
+ @child1.is_mask = true
314
+ allow(@parent).to receive(:is_point_in_bounds).and_return(false)
315
+ allow(@child1).to receive(:is_point_in_bounds).and_return(true)
316
+ allow(@child2).to receive(:is_point_in_bounds).and_return(false)
317
+
318
+ expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @parent
319
+ @child1.is_mask = false
320
+ end
321
+ end
322
+
323
+ after(:all) do
324
+ @parent.children.each { |child| @parent.remove_child(child) }
325
+ end
326
+ end
327
+ end
328
+
329
+ describe '#get_actors_at' do
330
+ before(:all) do
331
+ @parent = Gosling::Actor.new(@window)
332
+ end
333
+
334
+ context 'when tangible is false' do
335
+ it 'returns an empty array even if hit' do
336
+ @parent.is_tangible = false
337
+ allow(@parent).to receive(:is_point_in_bounds).and_return(true)
338
+ expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be_empty
339
+ @parent.is_tangible = true
340
+ end
341
+ end
342
+
343
+ context 'with no children' do
344
+ it 'returns an array containing itself if the point is within its bounds' do
345
+ allow(@parent).to receive(:is_point_in_bounds).and_return(true)
346
+ expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
347
+ end
348
+
349
+ it 'returns an empty array if point is not within its bounds' do
350
+ allow(@parent).to receive(:is_point_in_bounds).and_return(false)
351
+ expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be_empty
352
+ end
353
+ end
354
+
355
+ context 'with two children' do
356
+ before(:all) do
357
+ @child1 = Gosling::Actor.new(@window)
358
+ @child2 = Gosling::Actor.new(@window)
359
+ @parent.add_child(@child1)
360
+ @parent.add_child(@child2)
361
+ end
362
+
363
+ context 'when the children are not tangible' do
364
+ it 'ignores the children' do
365
+ @parent.are_children_tangible = false
366
+ allow(@parent).to receive(:is_point_in_bounds).and_return(false, true)
367
+ allow(@child1).to receive(:is_point_in_bounds).and_return(true)
368
+ allow(@child2).to receive(:is_point_in_bounds).and_return(true, false)
369
+
370
+ expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == []
371
+ expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
372
+ @parent.are_children_tangible = true
373
+ end
374
+ end
375
+
376
+ it "returns an array containing all actors hit" do
377
+ allow(@parent).to receive(:is_point_in_bounds).and_return(false, true, false, true, false, true, false, true)
378
+ allow(@child1).to receive(:is_point_in_bounds).and_return(false, false, true, true, false, false, true, true)
379
+ allow(@child2).to receive(:is_point_in_bounds).and_return(false, false, false, false, true, true, true, true)
380
+
381
+ expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == []
382
+ expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
383
+ expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child1]
384
+ expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child1, @parent]
385
+ expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child2]
386
+ expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child2, @parent]
387
+ expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child2, @child1]
388
+ expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child2, @child1, @parent]
389
+ end
390
+
391
+ context 'with a mask child' do
392
+ before(:all) do
393
+ @child1.is_mask = true
394
+ end
395
+
396
+ it 'returns the parent if the child is hit' do
397
+ allow(@parent).to receive(:is_point_in_bounds).and_return(false)
398
+ allow(@child1).to receive(:is_point_in_bounds).and_return(true)
399
+ allow(@child2).to receive(:is_point_in_bounds).and_return(false)
400
+
401
+ expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
402
+ end
403
+
404
+ it 'returns the parent only once if both children are masks and are hit' do
405
+ @child2.is_mask = true
406
+ allow(@parent).to receive(:is_point_in_bounds).and_return(false)
407
+ allow(@child1).to receive(:is_point_in_bounds).and_return(true)
408
+ allow(@child2).to receive(:is_point_in_bounds).and_return(true)
409
+
410
+ expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
411
+ @child2.is_mask = false
412
+ end
413
+
414
+ it 'returns the parent only once if both parent and child are hit' do
415
+ allow(@parent).to receive(:is_point_in_bounds).and_return(true)
416
+ allow(@child1).to receive(:is_point_in_bounds).and_return(true)
417
+ allow(@child2).to receive(:is_point_in_bounds).and_return(false)
418
+
419
+ expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
420
+ end
421
+
422
+ after(:all) do
423
+ @child1.is_mask = false
424
+ end
425
+ end
426
+
427
+ after(:all) do
428
+ @parent.children.each { |child| @parent.remove_child(child) }
429
+ end
430
+ end
431
+ end
432
+
433
+ describe '#get_global_transform' do
434
+ it 'returns a 3x3 matrix' do
435
+ result = @parent.get_global_transform
436
+ expect(result).to be_instance_of(Snow::Mat3)
437
+ end
438
+
439
+ it 'is a composite of its own transform plus all of its ancestors' do
440
+ centered_view = Gosling::Actor.new(@window)
441
+ centered_view.center_x = 10
442
+ centered_view.center_y = 2
443
+
444
+ scaled_view = Gosling::Actor.new(@window)
445
+ scaled_view.scale_x = 3
446
+ scaled_view.scale_y = 2
447
+
448
+ rotated_view = Gosling::Actor.new(@window)
449
+ rotated_view.rotation = Math::PI / 4
450
+
451
+ translated_view = Gosling::Actor.new(@window)
452
+ translated_view.x = -50
453
+ translated_view.y = 10
454
+
455
+ centered_view.add_child(scaled_view)
456
+ scaled_view.add_child(rotated_view)
457
+ rotated_view.add_child(translated_view)
458
+ translated_view.add_child(@parent)
459
+
460
+ expected = @parent.to_matrix * translated_view.to_matrix * rotated_view.to_matrix * scaled_view.to_matrix * centered_view.to_matrix
461
+
462
+ result = @parent.get_global_transform
463
+ expect(result).to be == expected
464
+
465
+ translated_view.remove_child(@parent)
466
+ end
467
+ end
468
+
469
+ describe '#get_global_position' do
470
+ it 'returns a 3d vector' do
471
+ result = @parent.get_global_position
472
+ expect(result).to be_instance_of(Snow::Vec3)
473
+ end
474
+
475
+ context 'with a long ancestry' do
476
+ before do
477
+ @parent.x = 0
478
+ @parent.y = 0
479
+ @parent.center_x = 0
480
+ @parent.center_y = 0
481
+ @parent.scale_x = 1
482
+ @parent.scale_y = 1
483
+ @parent.rotation = 0
484
+
485
+ centered_view = Gosling::Actor.new(@window)
486
+ centered_view.center_x = 10
487
+ centered_view.center_y = 2
488
+
489
+ scaled_view = Gosling::Actor.new(@window)
490
+ scaled_view.scale_x = 3
491
+ scaled_view.scale_y = 2
492
+
493
+ rotated_view = Gosling::Actor.new(@window)
494
+ rotated_view.rotation = Math::PI / 2
495
+
496
+ translated_view = Gosling::Actor.new(@window)
497
+ translated_view.x = -50
498
+ translated_view.y = 10
499
+
500
+ centered_view.add_child(scaled_view)
501
+ scaled_view.add_child(rotated_view)
502
+ rotated_view.add_child(translated_view)
503
+ translated_view.add_child(@parent)
504
+
505
+ @ancestry = [
506
+ centered_view,
507
+ scaled_view,
508
+ rotated_view,
509
+ translated_view,
510
+ @parent
511
+ ]
512
+ end
513
+
514
+ it 'respects all ancestors' do
515
+ result = @parent.get_global_position
516
+ expect(result).to be == Snow::Vec3[(0 + 10) * 3 - 10, (0 - 50) * -2 - 2, 0]
517
+ end
518
+
519
+ after do
520
+ @ancestry.each { |actor| actor.parent.remove_child(actor) if actor.parent }
521
+ end
522
+ end
523
+ end
524
+
525
+ describe '#alpha' do
526
+ it 'returns the alpha (transparency) value' do
527
+ expect(@parent.alpha).to be_kind_of(Numeric)
528
+ end
529
+
530
+ it 'sets the alpha (transparency) value' do
531
+ actor = Gosling::Actor.new(@window)
532
+
533
+ actor.alpha = 128
534
+ expect(actor.alpha).to be == 128
535
+ end
536
+
537
+ it 'forces numeric values to be between 0 and 255' do
538
+ actor = Gosling::Actor.new(@window)
539
+
540
+ actor.alpha = -128
541
+ expect(actor.alpha).to be == 0
542
+ actor.alpha = -1
543
+ expect(actor.alpha).to be == 0
544
+ actor.alpha = 256
545
+ expect(actor.alpha).to be == 255
546
+ actor.alpha = 1024
547
+ expect(actor.alpha).to be == 255
548
+ end
549
+ end
550
+
551
+ describe '#red' do
552
+ it 'returns the red value' do
553
+ expect(@parent.red).to be_kind_of(Numeric)
554
+ end
555
+
556
+ it 'sets the red value' do
557
+ actor = Gosling::Actor.new(@window)
558
+
559
+ actor.red = 128
560
+ expect(actor.red).to be == 128
561
+ end
562
+
563
+ it 'forces numeric values to be between 0 and 255' do
564
+ actor = Gosling::Actor.new(@window)
565
+
566
+ actor.red = -128
567
+ expect(actor.red).to be == 0
568
+ actor.red = -1
569
+ expect(actor.red).to be == 0
570
+ actor.red = 256
571
+ expect(actor.red).to be == 255
572
+ actor.red = 1024
573
+ expect(actor.red).to be == 255
574
+ end
575
+ end
576
+
577
+ describe '#green' do
578
+ it 'returns the green value' do
579
+ expect(@parent.green).to be_kind_of(Numeric)
580
+ end
581
+
582
+ it 'sets the green value' do
583
+ actor = Gosling::Actor.new(@window)
584
+
585
+ actor.green = 128
586
+ expect(actor.green).to be == 128
587
+ end
588
+
589
+ it 'forces numeric values to be between 0 and 255' do
590
+ actor = Gosling::Actor.new(@window)
591
+
592
+ actor.green = -128
593
+ expect(actor.green).to be == 0
594
+ actor.green = -1
595
+ expect(actor.green).to be == 0
596
+ actor.green = 256
597
+ expect(actor.green).to be == 255
598
+ actor.green = 1024
599
+ expect(actor.green).to be == 255
600
+ end
601
+ end
602
+
603
+ describe '#blue' do
604
+ it 'returns the blue value' do
605
+ expect(@parent.blue).to be_kind_of(Numeric)
606
+ end
607
+
608
+ it 'sets the blue value' do
609
+ actor = Gosling::Actor.new(@window)
610
+
611
+ actor.blue = 128
612
+ expect(actor.blue).to be == 128
613
+ end
614
+
615
+ it 'forces numeric values to be between 0 and 255' do
616
+ actor = Gosling::Actor.new(@window)
617
+
618
+ actor.blue = -128
619
+ expect(actor.blue).to be == 0
620
+ actor.blue = -1
621
+ expect(actor.blue).to be == 0
622
+ actor.blue = 256
623
+ expect(actor.blue).to be == 255
624
+ actor.blue = 1024
625
+ expect(actor.blue).to be == 255
626
+ end
627
+ end
628
628
  end