dxruby_sdl 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,570 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe DXRubySDL::Sprite, 'ゲームのキャラを扱う場合の基本となるクラス' do
5
+ let(:image) { DXRubySDL::Image.load(fixture_path('logo.png')) }
6
+ let(:sprite) { described_class.new(50, 150, image) }
7
+
8
+ describe '.check' do
9
+ def make_o_sprite(collision, discard = false)
10
+ s = described_class.new(0, 0)
11
+ allow(s).to receive(:===).and_return(collision)
12
+ if discard
13
+ allow(s).to receive(:shot).and_return(:discard)
14
+ else
15
+ allow(s).to receive(:shot)
16
+ end
17
+ return s
18
+ end
19
+
20
+ def make_d_sprite(discard = false)
21
+ s = described_class.new(0, 0)
22
+ if discard
23
+ allow(s).to receive(:hit).and_return(:discard)
24
+ else
25
+ allow(s).to receive(:hit)
26
+ end
27
+ return s
28
+ end
29
+
30
+ let(:o_sprites) {
31
+ Array.new(5) {
32
+ make_o_sprite(true)
33
+ }
34
+ }
35
+ let(:d_sprites) {
36
+ Array.new(5) {
37
+ make_d_sprite
38
+ }
39
+ }
40
+
41
+ subject { described_class.check(o_sprites, d_sprites) }
42
+
43
+ before do
44
+ subject
45
+ end
46
+
47
+ shared_examples 'return' do |val|
48
+ describe '戻り値' do
49
+ if val
50
+ it { should be_true }
51
+ else
52
+ it { should be_false }
53
+ end
54
+ end
55
+ end
56
+
57
+ context 'Spriteが衝突している場合' do
58
+ context 'o_sprites引数がSpriteオブジェクトの場合' do
59
+ let(:o_sprites) { make_o_sprite(true) }
60
+
61
+ specify 'o_spritesに対して#shotが呼ばれる' do
62
+ d_sprites.each do |d_sprite|
63
+ expect(o_sprites).to have_received(:shot).with(d_sprite).once
64
+ end
65
+ end
66
+
67
+ specify 'd_spritesの各要素に対して#hitが呼ばれる' do
68
+ d_sprites.each do |d_sprite|
69
+ expect(d_sprite).to have_received(:hit).with(o_sprites).once
70
+ end
71
+ end
72
+
73
+ include_examples 'return', true
74
+ end
75
+
76
+ context 'd_sprites引数がSpriteオブジェクトの場合' do
77
+ let(:d_sprites) { make_d_sprite }
78
+
79
+ specify 'o_spritesに対して#shotが呼ばれる' do
80
+ o_sprites.each do |o_sprite|
81
+ expect(o_sprite).to have_received(:shot).with(d_sprites).once
82
+ end
83
+ end
84
+
85
+ specify 'd_spritesに対して#hitが呼ばれる' do
86
+ o_sprites.each do |o_sprite|
87
+ expect(d_sprites).to have_received(:hit).with(o_sprite).once
88
+ end
89
+ end
90
+
91
+ include_examples 'return', true
92
+ end
93
+
94
+ context 'o_sprites引数がSpriteオブジェクトの配列の場合' do
95
+ specify 'o_spritesの各要素に対して#shotが呼ばれる' do
96
+ o_sprites.each do |o_sprite|
97
+ d_sprites.each do |d_sprite|
98
+ expect(o_sprite).to have_received(:shot).with(d_sprite).once
99
+ end
100
+ end
101
+ end
102
+
103
+ specify 'd_spritesの各要素に対して#hitが呼ばれる' do
104
+ d_sprites.each do |d_sprite|
105
+ o_sprites.each do |o_sprite|
106
+ expect(d_sprite).to have_received(:hit).with(o_sprite)
107
+ end
108
+ end
109
+ end
110
+
111
+ include_examples 'return', true
112
+ end
113
+
114
+ context 'o_sprites引数の#shotが:discardを返す場合' do
115
+ let(:o_sprites) {
116
+ Array.new(5) {
117
+ make_o_sprite(true, true)
118
+ }
119
+ }
120
+
121
+ specify 'o_spritesの各要素は#shotが1回だけ呼ばれる' do
122
+ o_sprites.each.with_index do |o_sprite, i|
123
+ d_sprites.each.with_index do |d_sprite, j|
124
+ if i == j
125
+ expect(o_sprite).to have_received(:shot).with(d_sprite).once
126
+ else
127
+ expect(o_sprite).not_to have_received(:shot).with(d_sprite)
128
+ end
129
+ end
130
+ end
131
+ end
132
+
133
+ specify 'd_spritesの各要素は#hitが1回だけ呼ばれる' do
134
+ o_sprites.each.with_index do |o_sprite, i|
135
+ d_sprites.each.with_index do |d_sprite, j|
136
+ if i == j
137
+ expect(d_sprite).to have_received(:hit).with(o_sprite).once
138
+ else
139
+ expect(d_sprite).not_to have_received(:hit).with(o_sprite)
140
+ end
141
+ end
142
+ end
143
+ end
144
+
145
+ include_examples 'return', true
146
+ end
147
+
148
+ context 'd_sprites引数の#hitが:discardを返す場合' do
149
+ let(:d_sprites) {
150
+ Array.new(5) {
151
+ make_d_sprite(true)
152
+ }
153
+ }
154
+
155
+ specify 'o_spritesの各要素は#shotが1回だけ呼ばれる' do
156
+ o_sprites.each.with_index do |o_sprite, i|
157
+ d_sprites.each.with_index do |d_sprite, j|
158
+ if i == j
159
+ expect(o_sprite).to have_received(:shot).with(d_sprite).once
160
+ else
161
+ expect(o_sprite).not_to have_received(:shot).with(d_sprite)
162
+ end
163
+ end
164
+ end
165
+ end
166
+
167
+ specify 'd_spritesの各要素は#hitが1回だけ呼ばれる' do
168
+ o_sprites.each.with_index do |o_sprite, i|
169
+ d_sprites.each.with_index do |d_sprite, j|
170
+ if i == j
171
+ expect(d_sprite).to have_received(:hit).with(o_sprite).once
172
+ else
173
+ expect(d_sprite).not_to have_received(:hit).with(o_sprite)
174
+ end
175
+ end
176
+ end
177
+ end
178
+
179
+ include_examples 'return', true
180
+ end
181
+ end
182
+
183
+ context 'Spriteが衝突していない場合' do
184
+ let(:o_sprites) {
185
+ Array.new(5) {
186
+ make_o_sprite(false)
187
+ }
188
+ }
189
+
190
+ specify 'o_spritesの各要素に対してSprite#shotが呼ばれない' do
191
+ o_sprites.each do |o_sprite|
192
+ expect(o_sprite).not_to have_received(:shot)
193
+ end
194
+ end
195
+
196
+ specify 'd_spritesの各要素に対してSprite#hitが呼ばれない' do
197
+ d_sprites.each do |d_sprite|
198
+ expect(d_sprite).not_to have_received(:hit)
199
+ end
200
+ end
201
+
202
+ include_examples 'return', false
203
+ end
204
+
205
+ context 'o_sprites引数やd_sprites引数に' \
206
+ 'Spriteオブジェクト以外を指定した場合' do
207
+ let(:o_sprites) {
208
+ s = double('Some Object')
209
+ allow(s).to receive(:===).and_return(true)
210
+ allow(s).to receive(:shot)
211
+ s
212
+ }
213
+ let(:d_sprites) {
214
+ s = double('Some Object')
215
+ allow(s).to receive(:hit)
216
+ s
217
+ }
218
+
219
+ describe 'o_sprites引数' do
220
+ it { expect(o_sprites).not_to have_received(:===) }
221
+ it { expect(o_sprites).not_to have_received(:shot) }
222
+ end
223
+
224
+ describe 'd_sprites引数' do
225
+ it { expect(d_sprites).not_to have_received(:hit) }
226
+ end
227
+
228
+ include_examples 'return', false
229
+ end
230
+ end
231
+
232
+ shared_context '配列内のオブジェクトのメソッドの呼び出し' do |_method|
233
+ describe ".#{_method}",
234
+ "配列内のすべてのオブジェクトの#{_method}メソッドを呼び出す" do
235
+ let(:method) { _method }
236
+
237
+ subject do
238
+ expect {
239
+ described_class.send(method, ary)
240
+ }.not_to raise_error
241
+ end
242
+
243
+ shared_context 'メソッドを呼び出す' do
244
+ context "配列内のすべてのオブジェクトに#{_method}メソッドがある場合" do
245
+ def make_sprite(i)
246
+ s = double('Sprite')
247
+ expect(s).to receive(method).once
248
+ return s
249
+ end
250
+
251
+ specify "配列内のすべてのオブジェクトの#{_method}メソッドを" \
252
+ '1回呼び出す' do
253
+ subject
254
+ end
255
+ end
256
+
257
+ context "配列内のオブジェクトの一部に#{_method}メソッドがある場合" do
258
+ def make_sprite(i)
259
+ s = double('Sprite')
260
+ if i.even?
261
+ expect(s).to receive(method).once
262
+ end
263
+ return s
264
+ end
265
+
266
+ specify "配列内の一部のオブジェクトの#{_method}メソッドを" \
267
+ '1回呼び出す' do
268
+ subject
269
+ end
270
+ end
271
+
272
+ context "配列内のオブジェクトに#{_method}メソッドがない場合" do
273
+ def make_sprite(i)
274
+ return double('Sprite')
275
+ end
276
+
277
+ specify "配列内のすべてのオブジェクトの#{_method}メソッドを" \
278
+ '呼び出さない' do
279
+ subject
280
+ end
281
+ end
282
+ end
283
+
284
+ context '引数がネストしていない配列の場合' do
285
+ let(:ary) {
286
+ 5.times.map { |i|
287
+ make_sprite(i)
288
+ }
289
+ }
290
+
291
+ include_context 'メソッドを呼び出す'
292
+ end
293
+
294
+ context '引数がネストした配列の場合' do
295
+ let(:ary) {
296
+ Array.new(5) {
297
+ 5.times.map { |i|
298
+ make_sprite(i)
299
+ }
300
+ }
301
+ }
302
+
303
+ include_context 'メソッドを呼び出す'
304
+ end
305
+ end
306
+ end
307
+
308
+ include_context '配列内のオブジェクトのメソッドの呼び出し', :update
309
+ include_context '配列内のオブジェクトのメソッドの呼び出し', :draw
310
+
311
+ describe '.clean',
312
+ '配列内のすべてのオブジェクトのvanished?メソッドを呼び出し、' \
313
+ 'trueが返ってきた要素と、もともとnilだった要素を削除する' do
314
+ subject { described_class.clean(ary) }
315
+
316
+ shared_examples 'vanished?メソッドを呼び出す' do
317
+ it '配列内のすべてのオブジェクトのvanished?メソッドを呼び出す' do
318
+ subject
319
+ ary.flatten.each do |s|
320
+ expect(s).to have_received(:vanished?).once
321
+ end
322
+ end
323
+ end
324
+
325
+ shared_context '.clean' do
326
+ context 'すべてのvanished?がtrueを返す場合' do
327
+ def make_sprite(i)
328
+ s = double('Sprite')
329
+ allow(s).to receive(:vanished?).and_return(true)
330
+ return s
331
+ end
332
+
333
+ include_examples 'vanished?メソッドを呼び出す'
334
+ it { should be_empty }
335
+ end
336
+
337
+ context '一部のvanished?がtrueを返す場合' do
338
+ def make_sprite(i)
339
+ s = double('Sprite')
340
+ if i.even?
341
+ allow(s).to receive(:vanished?).and_return(true)
342
+ else
343
+ allow(s).to receive(:vanished?).and_return(false)
344
+ end
345
+ return s
346
+ end
347
+
348
+ include_examples 'vanished?メソッドを呼び出す'
349
+
350
+ it 'vanished?がtrueのものが取り除かれた配列を返す' do
351
+ should eq(ary.flatten.reject(&:vanished?))
352
+ end
353
+ end
354
+
355
+ context '一部がnil、それ以外のvanished?がfalseを返す場合' do
356
+ def make_sprite(i)
357
+ if i.even?
358
+ s = double('Sprite')
359
+ allow(s).to receive(:vanished?).and_return(false)
360
+ return s
361
+ else
362
+ return nil
363
+ end
364
+ end
365
+
366
+ it '配列内のnilではないオブジェクトのvanished?メソッドを呼び出す' do
367
+ expect {
368
+ subject
369
+ }.not_to raise_error
370
+
371
+ ary.flatten.each do |s|
372
+ if !s.nil?
373
+ expect(s).to have_received(:vanished?).once
374
+ end
375
+ end
376
+ end
377
+
378
+ it 'nilのものが取り除かれた配列を返す' do
379
+ should eq(ary.flatten.reject(&:nil?))
380
+ end
381
+ end
382
+
383
+ context 'すべてのvanished?がfalseを返す場合' do
384
+ def make_sprite(i)
385
+ s = double('Sprite')
386
+ allow(s).to receive(:vanished?).and_return(false)
387
+ return s
388
+ end
389
+
390
+ include_examples 'vanished?メソッドを呼び出す'
391
+
392
+ it 'なにも取り除かずにフラットにした配列を返す' do
393
+ should eq(ary.flatten)
394
+ end
395
+ end
396
+ end
397
+
398
+ context '引数がネストしていない配列の場合' do
399
+ let(:ary) {
400
+ 5.times.map { |i|
401
+ make_sprite(i)
402
+ }
403
+ }
404
+
405
+ include_context '.clean'
406
+ end
407
+
408
+ context '引数がネストした配列の場合' do
409
+ let(:ary) {
410
+ Array.new(5) {
411
+ 5.times.map { |i|
412
+ make_sprite(i)
413
+ }
414
+ }
415
+ }
416
+
417
+ include_context '.clean'
418
+ end
419
+ end
420
+
421
+ describe '.new' do
422
+ subject { sprite }
423
+
424
+ shared_examples 'default' do
425
+ its(:z) { should be_nil }
426
+ its(:angle) { should be_nil }
427
+ its(:scale_x) { should be_nil }
428
+ its(:scale_y) { should be_nil }
429
+ its(:alpha) { should be_nil }
430
+ its(:blend) { should be_nil }
431
+ its(:shader) { should be_nil }
432
+ end
433
+
434
+ its(:x) { should eq(50) }
435
+ its(:y) { should eq(150) }
436
+ its(:image) { should eq(image) }
437
+ include_examples 'default'
438
+
439
+ context 'image引数を省略した場合' do
440
+ subject { described_class.new(50, 150) }
441
+
442
+ its(:x) { should eq(50) }
443
+ its(:y) { should eq(150) }
444
+ its(:image) { should be_nil }
445
+ include_examples 'default'
446
+ end
447
+
448
+ context 'y, image引数を省略した場合' do
449
+ subject { described_class.new(50) }
450
+
451
+ its(:x) { should eq(50) }
452
+ its(:y) { should eq(0) }
453
+ include_examples 'default'
454
+ end
455
+
456
+ context 'x, y, image引数を省略した場合' do
457
+ subject { described_class.new }
458
+
459
+ its(:x) { should eq(0) }
460
+ its(:y) { should eq(0) }
461
+ its(:image) { should be_nil }
462
+ include_examples 'default'
463
+ end
464
+ end
465
+
466
+ {
467
+ x: [-1, 0, 1, 100, 639, 640, 641],
468
+ y: [-1, 0, 1, 100, 479, 480, 481],
469
+ z: [-1, 0, 1, 99, 100, 101],
470
+ angle: [0, 90, 180, 260, 360],
471
+ scale_x: [10.0, 1.0, 0.5, 0, -0.5, -1.0, -10.0],
472
+ scale_y: [10.0, 1.0, 0.5, 0, -0.5, -1.0, -10.0],
473
+ center_x: [-1, 0, 1, 100, 639, 640, 641],
474
+ center_y: [-1, 0, 1, 100, 479, 480, 481],
475
+ alpha: [0, 1, 254, 255],
476
+ blend: [:alpha, :none, :add, :add2, :sub],
477
+ shader: [:shader],
478
+ image: [DXRubySDL::Image.load(fixture_path('logo.png'))],
479
+ target: [:render_target1, :render_target2],
480
+ collision: [1, [0, 0, 639, 439]],
481
+ collision_sync: [true, false],
482
+ collision_enable: [true, false],
483
+ visible: [true, false],
484
+ }.each do |method, vals|
485
+ describe "##{method}=" do
486
+ vals.each do |val|
487
+ context "#{val.inspect}を指定した場合" do
488
+ subject {
489
+ sprite.send("#{method}=".to_sym, val)
490
+ sprite.send(method)
491
+ }
492
+
493
+ it { should eq(val) }
494
+ end
495
+ end
496
+ end
497
+ end
498
+
499
+ describe '#vanish' do
500
+ describe 'レシーバ' do
501
+ subject { sprite }
502
+
503
+ context '呼び出す前' do
504
+ its(:vanished?) { should be_false }
505
+ end
506
+
507
+ context '呼び出した後' do
508
+ before do
509
+ sprite.vanish
510
+ end
511
+
512
+ its(:vanished?) { should be_true }
513
+ end
514
+ end
515
+ end
516
+
517
+ describe '#vanished?' do
518
+ subject { sprite.vanished? }
519
+
520
+ context 'Spriteが有効な場合' do
521
+ it { should be_false }
522
+ end
523
+
524
+ context 'vanishを呼び出してSpriteを無効化している場合' do
525
+ before { sprite.vanish }
526
+
527
+ it { should be_true }
528
+ end
529
+ end
530
+
531
+ describe '#check' do
532
+ let(:others) { [1, 2, 3, 4, 5] }
533
+
534
+ subject { sprite.check(others) }
535
+
536
+ before do
537
+ allow(sprite).to receive(:===) { |other|
538
+ if [1, 3, 5].include?(other)
539
+ true
540
+ else
541
+ false
542
+ end
543
+ }
544
+ end
545
+
546
+ it { should include(1, 3, 5) }
547
+ it { should have(3).items }
548
+ end
549
+
550
+ describe '#draw' do
551
+ subject do
552
+ expect {
553
+ DXRubySDL::Window.loop do
554
+ sprite.draw
555
+ SDL::Event.push(SDL::Event::Quit.new)
556
+ end
557
+ }.to raise_error(SystemExit)
558
+ end
559
+
560
+ context '左右反転' do
561
+ before do
562
+ sprite.scale_x = -1.0
563
+ end
564
+
565
+ it '描画できる' do
566
+ subject
567
+ end
568
+ end
569
+ end
570
+ end
@@ -2,11 +2,15 @@
2
2
  require 'spec_helper'
3
3
 
4
4
  describe DXRubySDL::Window do
5
- describe '.draw', 'Imageオブジェクトを描画する' do
5
+ shared_context '.draw' do
6
+ def call_draw(x, y, image, z = 0)
7
+ DXRubySDL::Window.draw(0, 0, image)
8
+ end
9
+
6
10
  subject do
7
11
  expect {
8
12
  DXRubySDL::Window.loop do
9
- DXRubySDL::Window.draw(0, 0, image)
13
+ call_draw(0, 0, image)
10
14
  SDL::Event.push(SDL::Event::Quit.new)
11
15
  end
12
16
  }.to raise_error(SystemExit)
@@ -70,9 +74,9 @@ describe DXRubySDL::Window do
70
74
  i = 0
71
75
  4.times do |y|
72
76
  2.times do |x|
73
- DXRubySDL::Window.draw(x * (images[i].width + margin),
74
- y * (images[i].height + margin),
75
- images[i])
77
+ call_draw(x * (images[i].width + margin),
78
+ y * (images[i].height + margin),
79
+ images[i])
76
80
  i += 1
77
81
  end
78
82
  end
@@ -82,4 +86,59 @@ describe DXRubySDL::Window do
82
86
  end
83
87
  end
84
88
  end
89
+
90
+ describe '.draw', 'Imageオブジェクトを描画する' do
91
+ include_context '.draw'
92
+ end
93
+
94
+ describe '.draw_ex',
95
+ '拡縮回転半透明加算合成を行ったImageオブジェクトを描画する' do
96
+ it_behaves_like '.draw' do
97
+ def call_draw(x, y, image, z = 0)
98
+ DXRubySDL::Window.draw_ex(x, y, image, z: z)
99
+ end
100
+ end
101
+
102
+ context 'hash引数を指定した場合' do
103
+ let!(:image) {
104
+ DXRubySDL::Image.load(fixture_path('logo.png'))
105
+ }
106
+ let(:hash) { {} }
107
+
108
+ subject do
109
+ expect {
110
+ DXRubySDL::Window.loop do
111
+ DXRubySDL::Window.draw_ex(320, 240, image, hash)
112
+ SDL::Event.push(SDL::Event::Quit.new)
113
+ end
114
+ }.to raise_error(SystemExit)
115
+ end
116
+
117
+ context '上下反転' do
118
+ let(:hash) { { scale_x: 1, scale_y: -1 } }
119
+
120
+ it '描画する' do
121
+ subject
122
+ end
123
+ end
124
+
125
+ context '左右反転' do
126
+ let(:hash) { { scale_x: -1, scale_y: 1 } }
127
+
128
+ it '描画する' do
129
+ subject
130
+ end
131
+ end
132
+ end
133
+
134
+ describe 'alias' do
135
+ describe '.drawEx' do
136
+ it_behaves_like '.draw' do
137
+ def call_draw(x, y, image, z = 0)
138
+ DXRubySDL::Window.drawEx(x, y, image, z: z)
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
85
144
  end
@@ -60,6 +60,22 @@ describe DXRubySDL::Window do
60
60
  end
61
61
  end
62
62
 
63
+ describe '.scale' do
64
+ subject { DXRubySDL::Window.scale }
65
+
66
+ context '初期状態' do
67
+ it { should eq(1) }
68
+ end
69
+
70
+ context '10に設定済みの場合' do
71
+ before do
72
+ DXRubySDL::Window.scale = 10
73
+ end
74
+
75
+ it { should eq(10) }
76
+ end
77
+ end
78
+
63
79
  describe '.fps=', 'FPSを設定する' do
64
80
  context '15に設定した場合' do
65
81
  let(:fps) { 15 }
@@ -85,6 +101,22 @@ describe DXRubySDL::Window do
85
101
  subject
86
102
  end
87
103
 
104
+ context '引数が空文字列の場合' do
105
+ let(:args) { [0, 0, '', font] }
106
+
107
+ it 'なにもしない' do
108
+ expect { subject }.not_to raise_error
109
+ end
110
+ end
111
+
112
+ context '引数が複数行の場合' do
113
+ let(:args) { [0, 0, "やあ\n\nこんにちは\n\nHello\n", font] }
114
+
115
+ it 'なにもしない' do
116
+ expect { subject }.not_to raise_error
117
+ end
118
+ end
119
+
88
120
  hash = { color: [255, 0, 0] }
89
121
  context "第5引数に色(#{hash.inspect})を指定した場合" do
90
122
  let(:args) { [0, 0, 'やあ', font, hash] }
File without changes
@@ -10,6 +10,10 @@ describe 'require \'dxruby\'' do
10
10
  Window
11
11
  Image
12
12
  Font
13
+ Input
14
+ Sound
15
+ SoundEffect
16
+ Sprite
13
17
  ].each do |klass_name|
14
18
  it "トップレベルに#{klass_name}が定義されている" do
15
19
  expect {