質問編集履歴

1

ソースコードと該当コードを抜き出しました

2019/09/03 06:04

投稿

programing_you
programing_you

スコア12

test CHANGED
File without changes
test CHANGED
@@ -8,6 +8,782 @@
8
8
 
9
9
 
10
10
 
11
+ ```targetcode
12
+
13
+ //6,7行目
14
+
15
+ x: 0,
16
+
17
+ y: 0
18
+
19
+
20
+
21
+ //10行目
22
+
23
+ initialize: function() {
24
+
25
+
26
+
27
+   //32行目
28
+
29
+    render: function() {
30
+
31
+ ```
32
+
33
+
34
+
11
35
  参考URL
12
36
 
13
37
  「 https://codepen.io/unlikenesses/pen/JKENom 」
38
+
39
+
40
+
41
+ ```JavaScript
42
+
43
+ var app = app || {};
44
+
45
+
46
+
47
+ app.Block = Backbone.Model.extend({
48
+
49
+
50
+
51
+ defaults: {
52
+
53
+ x: 0,
54
+
55
+ y: 0
56
+
57
+ },
58
+
59
+
60
+
61
+ initialize: function() {
62
+
63
+ var shape = this.get('shape');
64
+
65
+ this.set('width', shape[0].length);
66
+
67
+ this.set('height', shape.length);
68
+
69
+ }
70
+
71
+
72
+
73
+ });
74
+
75
+
76
+
77
+ app.Board = Backbone.Collection.extend({
78
+
79
+
80
+
81
+ model: app.Block
82
+
83
+
84
+
85
+ });
86
+
87
+
88
+
89
+ app.BlockView = Backbone.View.extend({
90
+
91
+
92
+
93
+ initialize: function() {
94
+
95
+ var self = this;
96
+
97
+ this.render();
98
+
99
+ this.model.on('change', _.bind(this.render, this));
100
+
101
+ },
102
+
103
+
104
+
105
+ render: function() {
106
+
107
+ this.clearCanvas();
108
+
109
+ var self = this;
110
+
111
+ var shape = this.model.get('shape');
112
+
113
+ var x_pos = this.model.get('x') * app.blockSize;
114
+
115
+ var y_pos = this.model.get('y') * app.blockSize;
116
+
117
+ for (var y = 0; y < shape.length; y++) {
118
+
119
+ var row = shape[y];
120
+
121
+ for (var x = 0; x < row.length; x++) {
122
+
123
+ if (row[x] == 1) {
124
+
125
+ self.stamp(x_pos + (x * app.blockSize), y_pos + (y * app.blockSize));
126
+
127
+ }
128
+
129
+ }
130
+
131
+ }
132
+
133
+ app.events.trigger('blockRendered');
134
+
135
+ return this;
136
+
137
+ },
138
+
139
+
140
+
141
+ clearCanvas: function() {
142
+
143
+ app.context.clearRect(0, 0, app.canvas.width, app.canvas.height);
144
+
145
+
146
+
147
+ },
148
+
149
+
150
+
151
+ stamp: function(x, y) {
152
+
153
+ app.context.beginPath();
154
+
155
+ app.context.rect(x, y, app.blockSize, app.blockSize);
156
+
157
+ app.context.lineWidth = 1;
158
+
159
+ app.context.strokeStyle = 'white';
160
+
161
+ app.context.stroke();
162
+
163
+ }
164
+
165
+
166
+
167
+ });
168
+
169
+
170
+
171
+ app.BoardView = Backbone.View.extend({
172
+
173
+
174
+
175
+ el: $('canvas'),
176
+
177
+
178
+
179
+ paused: false,
180
+
181
+
182
+
183
+ muted: false,
184
+
185
+
186
+
187
+ gameOver: false,
188
+
189
+
190
+
191
+ /* Initialize board view */
192
+
193
+ initialize: function() {
194
+
195
+ gridView = new app.GridView();
196
+
197
+ if (!app.logging) {
198
+
199
+ var gridWidth = $('#gridContainer').width();
200
+
201
+ var boardWidth = $('#board').width();
202
+
203
+ $('#gridContainer').hide();
204
+
205
+ $('#board').width(boardWidth - gridWidth - 60);
206
+
207
+ }
208
+
209
+ this.collection = new app.Board(app.blocks);
210
+
211
+ gridView.clearGrid();
212
+
213
+ gridView.logGrid();
214
+
215
+ $(document).on('keydown', $.proxy(this.keyAction, this)); // http://stackoverflow.com/a/13379556/519497
216
+
217
+ app.events.on('pause', this.pause, this);
218
+
219
+ app.events.on('mute', this.mute, this);
220
+
221
+ app.events.on('blockRendered', gridView.drawGrid, this);
222
+
223
+ this.start();
224
+
225
+ },
226
+
227
+
228
+
229
+ /* Set up interval */
230
+
231
+ start: function() {
232
+
233
+ var self = this;
234
+
235
+ clearInterval(app.interval);
236
+
237
+ app.interval = setInterval(function() {
238
+
239
+ self.descend();
240
+
241
+ self.render();
242
+
243
+ }, 800);
244
+
245
+ },
246
+
247
+
248
+
249
+ /* Render board */
250
+
251
+ render: function() {
252
+
253
+ this.collection.each(function(model) {
254
+
255
+ var blockView = new app.BlockView({
256
+
257
+ model: model
258
+
259
+ });
260
+
261
+ }, this);
262
+
263
+ },
264
+
265
+
266
+
267
+ /* Behaviour for when a block has landed */
268
+
269
+ blockLanded: function(block) {
270
+
271
+ this.updateGrid();
272
+
273
+ this.checkGameOver(block);
274
+
275
+ this.checkCompleteRows();
276
+
277
+ this.clearCollection();
278
+
279
+ this.spawnNewBlock();
280
+
281
+ },
282
+
283
+
284
+
285
+ /* Clear colletion of current block */
286
+
287
+ clearCollection: function() {
288
+
289
+ this.collection.reset();
290
+
291
+ },
292
+
293
+
294
+
295
+ /* Create a new block at random and add to collection */
296
+
297
+ spawnNewBlock: function() {
298
+
299
+ var shapePos = _.random(app.shapes.length - 1);
300
+
301
+ this.collection.add([app.shapes[shapePos]]);
302
+
303
+ },
304
+
305
+
306
+
307
+ /* Dispatch key commands */
308
+
309
+ keyAction: function(e) {
310
+
311
+ var code = e.keyCode || e.which;
312
+
313
+ if (!this.paused) {
314
+
315
+ if (code == 37) {
316
+
317
+ this.moveLeft();
318
+
319
+ } else if (code == 39) {
320
+
321
+ this.moveRight();
322
+
323
+ } else if (code == 40) {
324
+
325
+ this.moveDown();
326
+
327
+ } else if (code == 38) {
328
+
329
+ this.rotate();
330
+
331
+ }
332
+
333
+ }
334
+
335
+ if (code == 80) {
336
+
337
+ this.pause();
338
+
339
+ }
340
+
341
+ if (code == 78) {
342
+
343
+ this.newGame();
344
+
345
+ }
346
+
347
+ if (code == 77) {
348
+
349
+ this.mute();
350
+
351
+ }
352
+
353
+ },
354
+
355
+
356
+
357
+ /* Pause or unpause game */
358
+
359
+ pause: function() {
360
+
361
+ this.paused = !this.paused;
362
+
363
+ if (this.paused) {
364
+
365
+ $('#pause').html('Unpause (p)');
366
+
367
+ $('#message').html('Paused.')
368
+
369
+ clearInterval(app.interval);
370
+
371
+ } else {
372
+
373
+ $('#pause').html('Pause (p)');
374
+
375
+ $('#message').html('');
376
+
377
+ this.start();
378
+
379
+ }
380
+
381
+ },
382
+
383
+
384
+
385
+ /* Toggle mute */
386
+
387
+ mute: function() {
388
+
389
+ this.muted = !this.muted;
390
+
391
+ if (this.muted) {
392
+
393
+ $('#mute').html('Unmute (m)');
394
+
395
+ } else {
396
+
397
+ $('#mute').html('Mute (m)');
398
+
399
+ }
400
+
401
+ },
402
+
403
+
404
+
405
+ /* Add a landed block to the underlying grid */
406
+
407
+ updateGrid: function() {
408
+
409
+ this.collection.each(function(model) {
410
+
411
+ gridView.updateGrid(model)
412
+
413
+ gridView.logGrid();
414
+
415
+ }, this);
416
+
417
+ },
418
+
419
+
420
+
421
+ checkGameOver: function(block) {
422
+
423
+ var blockY = block.get('y');
424
+
425
+ if (blockY <= 0) {
426
+
427
+ this.gameOver();
428
+
429
+ }
430
+
431
+ },
432
+
433
+
434
+
435
+ gameOver: function() {
436
+
437
+ gridView.drawGrid();
438
+
439
+ this.playAudio('gameOver');
440
+
441
+ clearInterval(app.interval);
442
+
443
+ $('#message').html('GAME OVER!')
444
+
445
+ },
446
+
447
+
448
+
449
+ playAudio: function(key) {
450
+
451
+ if (!this.muted) {
452
+
453
+ var player = new Audio();
454
+
455
+ player.src = jsfxr(app.sounds[key]);
456
+
457
+ player.play();
458
+
459
+ }
460
+
461
+ },
462
+
463
+
464
+
465
+ newGame: function() {
466
+
467
+ this.start();
468
+
469
+ this.playAudio('newGame');
470
+
471
+ $('#message').html('');
472
+
473
+ this.collection.reset();
474
+
475
+ gridView.clearGrid();
476
+
477
+ gridView.drawGrid();
478
+
479
+ gridView.logGrid();
480
+
481
+ this.spawnNewBlock();
482
+
483
+ },
484
+
485
+
486
+
487
+ /* Check to see if any rows are full */
488
+
489
+ checkCompleteRows: function() {
490
+
491
+ var completeRows = [];
492
+
493
+ for (var y = 0; y < app.grid.length; y++) {
494
+
495
+ var row = app.grid[y];
496
+
497
+ var complete = true;
498
+
499
+ for (var x = 0; x < row.length; x++) {
500
+
501
+ if (row[x] != 1) {
502
+
503
+ complete = false;
504
+
505
+ }
506
+
507
+ }
508
+
509
+ if (complete) {
510
+
511
+ completeRows.push(y);
512
+
513
+ }
514
+
515
+ }
516
+
517
+ if (completeRows.length > 0) {
518
+
519
+ this.clearCompleteRows(completeRows);
520
+
521
+ } else {
522
+
523
+ this.playAudio('land');
524
+
525
+ }
526
+
527
+ },
528
+
529
+
530
+
531
+ /* Clear any complete rows from the grid and add a new clean row to the top */
532
+
533
+ clearCompleteRows: function(completeRows) {
534
+
535
+ this.playAudio('completeRow');
536
+
537
+ for (var i = 0; i < completeRows.length; i++) {
538
+
539
+ var rowIndex = completeRows[i];
540
+
541
+ app.grid.splice(rowIndex, 1);
542
+
543
+ var row = [];
544
+
545
+ for (var x = 0; x < app.width; x++) {
546
+
547
+ row.push(0);
548
+
549
+ }
550
+
551
+ app.grid.unshift(row);
552
+
553
+ }
554
+
555
+ gridView.logGrid();
556
+
557
+ },
558
+
559
+
560
+
561
+ /* Move a block left on keyboard input */
562
+
563
+ moveLeft: function() {
564
+
565
+ var self = this;
566
+
567
+ this.collection.each(function(model) {
568
+
569
+ var newX = model.get('x') - 1;
570
+
571
+ if (model.get('x') > 0 && self.shapeFits(model.get('shape'), newX, model.get('y'))) {
572
+
573
+ model.set('x', newX);
574
+
575
+ self.playAudio('bluhp');
576
+
577
+ }
578
+
579
+ });
580
+
581
+ },
582
+
583
+
584
+
585
+ /* Move a block right on keyboard input */
586
+
587
+ moveRight: function() {
588
+
589
+ var self = this;
590
+
591
+ this.collection.each(function(model) {
592
+
593
+ var newX = model.get('x') + 1;
594
+
595
+ if (model.get('x') + model.get('width') < app.width && self.shapeFits(model.get('shape'), newX, model.get('y'))) {
596
+
597
+ model.set('x', newX);
598
+
599
+ self.playAudio('bluhp');
600
+
601
+ }
602
+
603
+ });
604
+
605
+ },
606
+
607
+
608
+
609
+ /* Move a block down on keyboard input */
610
+
611
+ moveDown: function() {
612
+
613
+ var self = this;
614
+
615
+ this.collection.each(function(model) {
616
+
617
+ var newY = model.get('y') + 1;
618
+
619
+ if (model.get('y') + model.get('height') < app.height && self.shapeFits(model.get('shape'), model.get('x'), newY)) {
620
+
621
+ model.set('y', newY);
622
+
623
+ self.playAudio('bluhp');
624
+
625
+ }
626
+
627
+ });
628
+
629
+ },
630
+
631
+
632
+
633
+ /* Automatically move a block down one step */
634
+
635
+ descend: function() {
636
+
637
+ var self = this;
638
+
639
+ this.collection.each(function(model) {
640
+
641
+ if (model.get('y') + model.get('height') < app.height && self.shapeFits(model.get('shape'), model.get('x'), model.get('y') + 1)) {
642
+
643
+ model.set('y', model.get('y') + 1);
644
+
645
+ } else {
646
+
647
+ self.blockLanded(model);
648
+
649
+ }
650
+
651
+ });
652
+
653
+ },
654
+
655
+
656
+
657
+ /* Check if a given shape is within the bounds of the play area */
658
+
659
+ shapeWithinBounds: function(shape, x, y) {
660
+
661
+ if (x < 0) {
662
+
663
+ return false;
664
+
665
+ }
666
+
667
+ if (x + shape[0].length > app.width) {
668
+
669
+ return false;
670
+
671
+ }
672
+
673
+ return true;
674
+
675
+ },
676
+
677
+
678
+
679
+ /* Check if a shape fits in the play area and with the other blocks */
680
+
681
+ rotatedShapeFits: function(shape, x, y) {
682
+
683
+ return this.shapeFits(shape, x, y) && this.shapeWithinBounds(shape, x, y);
684
+
685
+ },
686
+
687
+
688
+
689
+ /* Rotate a block */
690
+
691
+ rotate: function() {
692
+
693
+ var self = this;
694
+
695
+ this.collection.each(function(model) {
696
+
697
+ // Method 1: (from http://stackoverflow.com/a/34164786)
698
+
699
+ // Transpose the shape matrix (from http://stackoverflow.com/a/17428779):
700
+
701
+ var transposed = _.zip.apply(_, model.get('shape'));
702
+
703
+ var reversed = transposed.reverse();
704
+
705
+ if (self.rotatedShapeFits(reversed, model.get('x'), model.get('y'))) {
706
+
707
+ model.set('shape', reversed);
708
+
709
+ var shape = model.get('shape');
710
+
711
+ model.set('width', shape[0].length);
712
+
713
+ model.set('height', shape.length);
714
+
715
+ self.playAudio('bluhp');
716
+
717
+ }
718
+
719
+ });
720
+
721
+ },
722
+
723
+
724
+
725
+ /* Check if a block collides with landed blocks */
726
+
727
+ shapeFits: function(shape, shapeX, shapeY) {
728
+
729
+ for (var y = 0; y < shape.length; y++) {
730
+
731
+ var row = shape[y];
732
+
733
+ for (var x = 0; x < row.length; x++) {
734
+
735
+ if (row[x] == 1) {
736
+
737
+ var checkX = shapeX + x;
738
+
739
+ var checkY = shapeY + y;
740
+
741
+ if (app.grid[checkY][checkX] == 1) {
742
+
743
+ return false;
744
+
745
+ }
746
+
747
+ }
748
+
749
+ }
750
+
751
+ }
752
+
753
+ return true;
754
+
755
+ }
756
+
757
+ });
758
+
759
+
760
+
761
+ app.ControlsView = Backbone.View.extend({
762
+
763
+
764
+
765
+ el: $('#controls'),
766
+
767
+
768
+
769
+ events: {
770
+
771
+ 'click #pause': 'pause',
772
+
773
+ 'click #mute': 'mute',
774
+
775
+ },
776
+
777
+
778
+
779
+ pause: function() {
780
+
781
+ app.events.trigger('pause');
782
+
783
+ }
784
+
785
+
786
+
787
+ //コードが長いので割愛します
788
+
789
+ ```