gosling 2.3.0 → 2.3.2

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