dxruby_sdl 0.0.4 → 0.0.5

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.
@@ -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 {