From 6ef1fa4618e08426b874529619a66adbd3d1fcf0 Mon Sep 17 00:00:00 2001 From: Florian Merz Date: Thu, 11 Feb 2021 12:07:59 +0100 Subject: unslug ja: move --- .../tutorials/2d_breakout_game_phaser/index.html | 63 ++++++++++ .../2d_breakout_game_phaser/physics/index.html | 90 +++++++++++++ .../bounce_off_the_walls/index.html | 105 ++++++++++++++++ .../build_the_brick_field/index.html | 112 +++++++++++++++++ .../collision_detection/index.html | 132 +++++++++++++++++++ .../create_the_canvas_and_draw_on_it/index.html | 112 +++++++++++++++++ .../finishing_up/index.html | 97 ++++++++++++++ .../game_over/index.html | 86 +++++++++++++ .../2d_breakout_game_pure_javascript/index.html | 49 ++++++++ .../mouse_controls/index.html | 57 +++++++++ .../move_the_ball/index.html | 140 +++++++++++++++++++++ .../paddle_and_keyboard_controls/index.html | 128 +++++++++++++++++++ .../track_the_score_and_win/index.html | 94 ++++++++++++++ files/ja/games/tutorials/index.html | 25 ++++ 14 files changed, 1290 insertions(+) create mode 100644 files/ja/games/tutorials/2d_breakout_game_phaser/index.html create mode 100644 files/ja/games/tutorials/2d_breakout_game_phaser/physics/index.html create mode 100644 files/ja/games/tutorials/2d_breakout_game_pure_javascript/bounce_off_the_walls/index.html create mode 100644 files/ja/games/tutorials/2d_breakout_game_pure_javascript/build_the_brick_field/index.html create mode 100644 files/ja/games/tutorials/2d_breakout_game_pure_javascript/collision_detection/index.html create mode 100644 files/ja/games/tutorials/2d_breakout_game_pure_javascript/create_the_canvas_and_draw_on_it/index.html create mode 100644 files/ja/games/tutorials/2d_breakout_game_pure_javascript/finishing_up/index.html create mode 100644 files/ja/games/tutorials/2d_breakout_game_pure_javascript/game_over/index.html create mode 100644 files/ja/games/tutorials/2d_breakout_game_pure_javascript/index.html create mode 100644 files/ja/games/tutorials/2d_breakout_game_pure_javascript/mouse_controls/index.html create mode 100644 files/ja/games/tutorials/2d_breakout_game_pure_javascript/move_the_ball/index.html create mode 100644 files/ja/games/tutorials/2d_breakout_game_pure_javascript/paddle_and_keyboard_controls/index.html create mode 100644 files/ja/games/tutorials/2d_breakout_game_pure_javascript/track_the_score_and_win/index.html create mode 100644 files/ja/games/tutorials/index.html (limited to 'files/ja/games/tutorials') diff --git a/files/ja/games/tutorials/2d_breakout_game_phaser/index.html b/files/ja/games/tutorials/2d_breakout_game_phaser/index.html new file mode 100644 index 0000000000..4aecfe19b7 --- /dev/null +++ b/files/ja/games/tutorials/2d_breakout_game_phaser/index.html @@ -0,0 +1,63 @@ +--- +title: 2D breakout game using Phaser +slug: Games/Workflows/2D_breakout_game_Phaser +tags: + - 2D + - Beginner + - Canvas + - Games + - JavaScript + - NeedsTranslation + - Phaser + - TopicStub + - Tutorial +translation_of: Games/Tutorials/2D_breakout_game_Phaser +--- +
{{GamesSidebar}}
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{Next("Games/Workflows/2D_Breakout_game_Phaser/Initialize_the_framework")}}

+ +

In this step-by-step tutorial we create a simple mobile MDN Breakout game written in JavaScript, using the Phaser framework.

+ +

Every step has editable, live samples available to play with so you can see what the intermediate stages should look like. You will learn the basics of using the Phaser framework to implement fundamental game mechanics like rendering and moving images, collision detection, control machanisms, framework-specific helper functions, animations and tweens, and winning and losing states.

+ +

To get the most out of this series of articles you should already have basic to intermediate JavaScript knowledge. After working through this tutorial you should be able to build your own simple Web games with Phaser.

+ +

Gameplay screen from the game MDN Breakout created with Phaser where you can use your paddle to bounce the ball and destroy the brick field, with keeping the points and lives.

+ +

Lesson details

+ +

All the lessons — and the different versions of the MDN Breakout game we are building together — are available on GitHub:

+ +
    +
  1. Initialize the framework
  2. +
  3. Scaling
  4. +
  5. Load the assets and print them on screen
  6. +
  7. Move the ball
  8. +
  9. Physics
  10. +
  11. Bounce off the walls
  12. +
  13. Player paddle and controls
  14. +
  15. Game over
  16. +
  17. Build the brick field
  18. +
  19. Collision detection
  20. +
  21. The score
  22. +
  23. Win the game
  24. +
  25. Extra lives
  26. +
  27. Animations and tweens
  28. +
  29. Buttons
  30. +
  31. Randomizing gameplay
  32. +
+ +

As a note on learning paths — starting with pure JavaScript is the best way to get a solid knowledge of web game development. If you are not already familiar with pure JavaScript game development, we'd suggest that you first work through this series' counterpart, 2D breakout game using pure JavaScript.

+ +

After that, you can pick any framework you like and use it for your projects; we've chosen Phaser as it is a good solid framework, with a good support and community available, and a good set of plugins. Frameworks speed up development time and help take care of the boring parts, allowing you to concentrate on the fun stuff. However, frameworks are not always perfect, so if something unexpected happens or you want to write some functionality that the framework doesn't provide, you'll need some pure JavaScript knowledge.

+ +
+

Note: This series of articles can be used as material for hands-on game development workshops. You can also make use of the Gamedev Phaser Content Kit based on this tutorial if you want to give a talk about game development with Phaser.

+
+ +

Next steps

+ +

Ok, let's get started! Head to the first part of the series — Initialize the framework.

+ +

{{Next("Games/Workflows/2D_Breakout_game_Phaser/Initialize_the_framework")}}

diff --git a/files/ja/games/tutorials/2d_breakout_game_phaser/physics/index.html b/files/ja/games/tutorials/2d_breakout_game_phaser/physics/index.html new file mode 100644 index 0000000000..8ab82a8be7 --- /dev/null +++ b/files/ja/games/tutorials/2d_breakout_game_phaser/physics/index.html @@ -0,0 +1,90 @@ +--- +title: 物理演算 +slug: Games/Workflows/2D_breakout_game_Phaser/Physics +translation_of: Games/Tutorials/2D_breakout_game_Phaser/Physics +--- +
{{GamesSidebar}}
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Move_the_ball", "Games/Workflows/2D_Breakout_game_Phaser/Bounce_off_the_walls")}}

+ +
+

全 16回のゲーム開発チュートリアル の 5 回目です。 今回終了後のソースコードは Gamedev-Phaser-Content-Kit/demos/lesson05.html でご覧になれます。

+
+ +

モノ同士の衝突を正しく処理するためには、物理演算が必要になります。この文書では、Phaser での実装と、典型的な例を紹介します。

+ +

物理演算の追加

+ +

Phaser は Arcade Physics、P2、そして Ninja Physics  と、3 つの異なる物理演算エンジンを備えています。また商用プラグインとして Box2D も物理演算エンジンとして利用できます。チュートリアルで作成しているような単純なゲームでは、複雑な幾何計算を必要としません。そのような場合には Arcade Physics を利用すると良いでしょう。

+ +

まず Arcade Physics engine を初期化します。初期化は create 関数の先頭で、 physics.startSystem() メソッドを呼ぶことで行います:

+ +
game.physics.startSystem(Phaser.Physics.ARCADE);
+
+ +

標準では Phaser オブジェクトは物理演算エンジンを利用しません。そのため、create()  の末尾に次の行を追加して、ボールから物理演算エンジンを利用できるようにします:

+ +
game.physics.enable(ball, Phaser.Physics.ARCADE);
+
+ +

次にボールを動かします。次のように、create() 末尾で body 属性の持つ velocity 属性を設定します:

+ +
ball.body.velocity.set(150, 150);
+
+ +

以前作成した、更新処理の削除

+ +

update()関数から忘れずに、x と y の値の更新処理を削除しておきましょう:

+ +
function update() {
+    ball.x += 1;
+    ball.y += 1;
+}
+
+ +

以上で、物理演算エンジンを組み込むことができました。

+ +

最終的に作成されたコード

+ +

最終的に得られたコードは以下の通りです:

+ +
var ball;
+
+function preload() {
+    game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
+    game.scale.pageAlignHorizontally = true;
+    game.scale.pageAlignVertically = true;
+    game.stage.backgroundColor = '#eee';
+    game.load.image('ball', 'img/ball.png');
+}
+
+function create() {
+    game.physics.startSystem(Phaser.Physics.ARCADE);
+    ball = game.add.sprite(50, 50, 'ball');
+    game.physics.enable(ball, Phaser.Physics.ARCADE);
+    ball.body.velocity.set(150, 150);
+}
+
+function update() {
+}
+
+ +

index.html を再読み込みすると、ボールは 1 方向に進み続けます。現在、物理エンジンには重力加速度も摩擦係数も設定されていません。重力加速度を設定すれば、ボールは落下するようになります。また、摩擦係数を設定すれば、ボールが摩擦で停止するようになります。

+ +

より進んだ内容

+ +

今回扱った内容以外にもできることはたくさんあります。例えば、 ball.body.gravity.y = 100; と追加することで、ボールに影響する重力を設定できます。その結果として、ボールが重力に引かれて、落下するようになります。

+ +

このような機能はほんの一部分です。physics documentation には、物理演算に関する数多くの関数と変数が、ArcadeP2 物理演算エンジンの使用例とともに解説されています。

+ +

自分のコードと比較しよう

+ +

上記のコードや、下記のデモと比較して、どのように動作しているかを理解しましょう。

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/bjto9nj8/","","400")}}

+ +

次のステップ

+ +

次のステップでは、ボールの跳ね返り を実装します。

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Move_the_ball", "Games/Workflows/2D_Breakout_game_Phaser/Bounce_off_the_walls")}}

diff --git a/files/ja/games/tutorials/2d_breakout_game_pure_javascript/bounce_off_the_walls/index.html b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/bounce_off_the_walls/index.html new file mode 100644 index 0000000000..b8e5486a80 --- /dev/null +++ b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/bounce_off_the_walls/index.html @@ -0,0 +1,105 @@ +--- +title: ボールを壁で弾ませる +slug: Games/Workflows/2D_Breakout_game_pure_JavaScript/Bounce_off_the_walls +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Bounce_off_the_walls +--- +
{{GamesSidebar}}
+ +
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Move_the_ball", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Paddle_and_keyboard_controls")}}

+ +
+

これはゲーム開発Canvasチュートリアルの10ステップのうち3番目のステップです。このレッスンを終えたあとの完成予想のソースコードはGamedev-Canvas-workshop/lesson3.htmlで入手できます。

+
+ +

ボールが動くのを見られたのは良いことですが、画面からすぐ消えてしまっては面白くないじゃありませんか! これを解決するためにとても簡単な衝突検知 (後ほど詳しく説明します) を導入し、Canvasの四辺でボールを弾ませます。

+ +

簡単な衝突検知

+ +

衝突を検知するためにボールが壁に触っている (衝突している) か確かめ、もし触っている場合には動く方向をそれに従って変更します。

+ +

計算を簡単にするために、描画される円の半径をもつballRadiusという変数を定義しましょう。次のコードを既にどこかにある変数定義の後に追記しましょう。

+ +
var ballRadius = 10;
+ +

あわせてdrawBall()関数内のボールを描画している行も次のように更新しましょう。

+ +
ctx.arc(x, y, ballRadius, 0, Math.PI*2);
+ +

上端と下端で弾ませる

+ +

ボールを弾ませる壁は4つあります。まずは上端に注目しましょう。毎フレーム、ボールがCanvasの上端に触っているかどうか確認する必要があります。もし触っているなら、ボールの動きを反転させ、ボールが反対方向に動き、視界の範囲内に留まるようにしましす。座標系は左上端から始まることを思い出しながら考えてみれば、次のようなコードが思いつくでしょう。

+ +
if(y + dy < 0) {
+    dy = -dy;
+}
+ +

もしボールの位置のyの値が0未満だったら、符号反転させた値を設定することでy軸方向の動きの向きを変えます。もしボールが上に向かって毎フレーム2ピクセルの速さで動いていたら、今度は「上」に向かって毎フレーム-2ピクセルの速さで動く、つまり下に向かって毎フレーム2ピクセルの速さで動きます。

+ +

上記のコードは上端でボールを弾ませていました。では今度は下端について考えてみましょう。

+ +
if(y + dy > canvas.height) {
+    dy = -dy;
+}
+ +

y座標がCanvasの高さより高かったら(左上端からyの値を数えているため、上端は0で始まり下端はCanvasの高さである480ピクセルとなることを思い出してください) 、先程のようにy軸方向の動きを反転させます。

+ +

これら2つの文を合わせればコードの冗長さを減らせます。

+ +
if(y + dy > canvas.height || y + dy < 0) {
+    dy = -dy;
+}
+ +

2つの文のどちらかがtrueだったら、ボールの動きを反転させます。

+ +

左端と右端で弾ませる

+ +

上端と下端を対処したところで、左端と右端を考えてみましょう。実のところとても良く似ていて、yxで置き換えて文を繰り返すだけでよいのです。

+ +
if(x + dx > canvas.width || x + dx < 0) {
+    dx = -dx;
+}
+
+if(y + dy > canvas.height || y + dy < 0) {
+    dy = -dy;
+}
+ +

ここで上記のコードをdraw()関数の、ちょうど閉じ波括弧の前に挿入しておいてください。

+ +

まだボールが壁に隠れる!

+ +

ここであなたのコードを試してみましょう。驚くはずです。Canvasの四辺全てでボールが弾んでいます! でも別の問題がありました。ボールが壁にぶつかるとき、位置を変える少し前に壁に沈んでしまいます。

+ +

+ +

壁と円周の衝突地点を計算すべきところで、壁と円の中心の衝突地点を計算しているのがこの理由です。ボールは壁に触ったときに弾むべきで、壁に半分のめり込んだときに弾んでも仕方ありません。そこで円周を含めるために文を少し調節します。最後に追加したコードを次のように書き換えます。

+ +
if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) {
+    dx = -dx;
+}
+if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) {
+    dy = -dy;
+}
+ +

ボールの中心と辺の距離がボールの半径とちょうど等しくなったときに動く向きを変えます。半径を辺の長さから引き、もう一方では足すことで衝突検知が正しく行われたような印象が出ます。思ったとおり、壁にぶつかった時点でボールが弾むようになります。

+ +

自分のコードと比べる

+ +

もう一度、このパートを終えた後にできたコードと比べてみて、それからコードで遊んでみてください。

+ + + +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/redj37dc/","","395")}}

+ + + +
+

練習: 壁に当たるたびにボールの色をランダムに変えてみてください。

+
+ +

次のステップ

+ +

ボールが動き、かつゲームボードに留まるようになることまでこぎつけました。第4章では操作できるパドルを実装してみます。 パドルとキーボード操作を見てみましょう。

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Move_the_ball", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Paddle_and_keyboard_controls")}}

diff --git a/files/ja/games/tutorials/2d_breakout_game_pure_javascript/build_the_brick_field/index.html b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/build_the_brick_field/index.html new file mode 100644 index 0000000000..b85ae7fccf --- /dev/null +++ b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/build_the_brick_field/index.html @@ -0,0 +1,112 @@ +--- +title: ブロックのかたまりを作る +slug: Games/Workflows/2D_Breakout_game_pure_JavaScript/Build_the_brick_field +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Build_the_brick_field +--- +
{{GamesSidebar}}
+ +
{{IncludeSubnav("/ja/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Game_over", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Collision_detection")}}

+ +
+

これはゲーム開発Canvasチュートリアルの10ステップのうち6番目のステップです。このレッスンを終えたあとの完成予想のソースコードはGamedev-Canvas-workshop/lesson6.htmlで入手できます。

+
+ +

ゲームプレイ制御を修正することにより負けることができるようになります。この大きな変更により、ついにゲームらしさを感じられるようになりました。ですが、壁とパドルでボールが弾むだけではすぐに空きてしまいます。ブロック崩しで本当に必要な要素、それはボールで崩すことができるブロックです。これが今回作り込んでいく部分になります。

+ +

ブロック変数を設定する

+ +

このレッスンのおおまかな目標は、ブロックのための、2次元配列を走査する入れ子のループを使った数行のコードを書き上げることです。しかしその前に幅と高さ、行と列などといった情報を定義するいくつかの変数が必要です。自分のコードの、以前変数を宣言した場所の下に次のコードを追加してください。

+ +
var brickRowCount = 3;
+var brickColumnCount = 5;
+var brickWidth = 75;
+var brickHeight = 20;
+var brickPadding = 10;
+var brickOffsetTop = 30;
+var brickOffsetLeft = 30;
+ +

ここではブロックの行と列の数、幅と高さ、ブロックがくっつかないようにするブロック間の隙間、そしてキャンバスの端に描画されないようにするための上端、左端からの相対位置を定義しました。

+ +

1つの2次元配列で全てのブロックを記録します。2次元配列はブロックの列 (c) を含んでおり、列は行 (r) を含み、行はそれぞれのブロックが描画される画面上のx座標とy座標をもつオブジェクトを含んでいます。

+ +
var bricks = [];
+for(var c=0; c<brickColumnCount; c++) {
+    bricks[c] = [];
+    for(var r=0; r<brickRowCount; r++) {
+        bricks[c][r] = { x: 0, y: 0 };
+    }
+}
+ +

上記のコードは行と列を通してループし、新しいブロックを作ります。このブロックオブジェクトは後に衝突検出のためにも使われることを覚えておいてください。

+ +

ブロック描画ロジック

+ +

配列に含まれる全てのブロックを通してループする関数を作成し、画面上に描画しましょう。コードは次のようになります。

+ +
function drawBricks() {
+    for(var c=0; c<brickColumnCount; c++) {
+        for(var r=0; r<brickRowCount; r++) {
+            bricks[c][r].x = 0;
+            bricks[c][r].y = 0;
+            ctx.beginPath();
+            ctx.rect(0, 0, brickWidth, brickHeight);
+            ctx.fillStyle = "#0095DD";
+            ctx.fill();
+            ctx.closePath();
+        }
+    }
+}
+ +

もう一度、行と列を通してループし、それぞれのブロックのx座標とy座標を設定するとともに、1回ループを回るごとに大きさbrickWidth x brickHeightのブロックをCanvas上に描画しています。問題はそれら全てを1箇所、座標(0,0)に描画していることです。それぞれのブロックのx座標とy座標を導出する計算を一回一回のループに含める必要があります。

+ +
var brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft;
+var brickY = (r*(brickHeight+brickPadding))+brickOffsetTop;
+ +

それぞれの座標brickXbrickWidth + brickPaddingに列番号cをかけ、brickOffsetLeftをたしたものとして導出されます。brickYのロジックも同様ですが、行番号rbrickHeight、そしてbrickOffsetTopが用いられます。これで、それぞれのブロックは正しい行、列に間隔を空けて置かれ、左上端から一定の位置に描画されるようになりました。

+ +

次のようにbrickXbrickYの値を(0,0)の代わりに座標として代入するようにしたものがdrawBricks()の最終版となります。これをdrawPaddle()関数の下に追加してください。

+ +
function drawBricks() {
+    for(var c=0; c<brickColumnCount; c++) {
+        for(var r=0; r<brickRowCount; r++) {
+            var brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft;
+            var brickY = (r*(brickHeight+brickPadding))+brickOffsetTop;
+            bricks[c][r].x = brickX;
+            bricks[c][r].y = brickY;
+            ctx.beginPath();
+            ctx.rect(brickX, brickY, brickWidth, brickHeight);
+            ctx.fillStyle = "#0095DD";
+            ctx.fill();
+            ctx.closePath();
+        }
+    }
+}
+ +

ブロックを描画する

+ +

drawBricks()へ呼び出しをdraw()関数のどこかに追加して、このレッスンの仕上げとしましょう。最初のあたりの、Canvasを消去する部分とボールを描画する部分の間あたりが良いでしょう。drawBall()の呼び出しのすぐ前に次の行を追加してください。

+ +
drawBricks();
+
+ +

自分のコードと比べる

+ +

ここまででゲームは更にもう少し面白くなりました。

+ +

 

+ +

{{JSFiddleEmbed("https://jsfiddle.net/raymondjplante/Lu3vtejz/","","395")}}

+ +

 

+ +
+

練習: 行や列にあるブロックの数や位置を替えてみましょう。

+
+ +

次のステップ

+ +

というわけでついにブロックができました。でもボールはブロックに全く反応しません。第7章、衝突検知ではこれを変えます。

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Game_over", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Collision_detection")}}

diff --git a/files/ja/games/tutorials/2d_breakout_game_pure_javascript/collision_detection/index.html b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/collision_detection/index.html new file mode 100644 index 0000000000..ca89b6aaee --- /dev/null +++ b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/collision_detection/index.html @@ -0,0 +1,132 @@ +--- +title: 衝突検出 +slug: Games/Workflows/2D_Breakout_game_pure_JavaScript/Collision_detection +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Collision_detection +--- +
{{GamesSidebar}}
+ +
{{IncludeSubnav("/ja/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Build_the_brick_field", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Track_the_score_and_win")}}

+ +
+

これはゲーム開発Canvasチュートリアルの10ステップのうち7番目のステップです。このレッスンを終えたあとの完成予想のソースコードはGamedev-Canvas-workshop/lesson7.htmlで入手できます。

+
+ +

ブロックは既に画面上に現れていますが、ボールが素通りしてしまうのでは面白くありません。ボールがブロックで弾み、ブロックが壊れるように衝突検出を追加することを考えなくてはなりません。

+ +

これをどのように実装するかは私達が決められることですが、ボールが長方形に接触しているかどうか計算するというのは、Canvasには助けになる関数もないため難しいかもしれません。このチュートリアルでは最も簡単な方法をとります。ボールの中心が与えられたブロックのどれかに衝突していないか確認するのです。これは毎回完璧な結果を返すとは限りませんし、衝突検出をするにはもっと洗練された方法がありますが、基本的な概念を学ぶには十分です。

+ +

衝突検出関数

+ +

最初の第一歩として、毎フレーム描画されるたびに全てのブロックを通してループし、ひとつひとつのブロックの位置をボールの座標と比較する衝突検出関数を作成しましょう。コードがより読みやすくなるように、衝突検出のループの中でブロックオブジェクトを保存する変数bを定義します。

+ +
function collisionDetection() {
+    for(var c=0; c<brickColumnCount; c++) {
+        for(var r=0; r<brickRowCount; r++) {
+            var b = bricks[c][r];
+            // いろいろな計算
+        }
+    }
+}
+ +

もしボールの中央がブロックの1つの座標の内部だったらボールの向きを変えます。ボールの中央がブロックの内部にあるためには次の4つの命題が全て真でなければなりません。

+ + + +

コードに書き下ろしてみましょう。

+ +
function collisionDetection() {
+    for(var c=0; c<brickColumnCount; c++) {
+        for(var r=0; r<brickRowCount; r++) {
+            var b = bricks[c][r];
+            if(x > b.x && x < b.x+brickWidth && y > b.y && y < b.y+brickHeight) {
+                dy = -dy;
+            }
+        }
+    }
+}
+ +

上記のブロックを自分のコードのkeyUpHandler()関数の下に追加してください。

+ +

ブロックが当たった後に消えるようにする

+ +

上記のコードは期待したとおり動作し、ボールの向きを変えるはずです。問題はブロックがそのままとどまっているということです。ボールに既に当たったブロックを取り除く方法を考え出さなければなりません。これはそれぞれのブロックを画面上に描画したいかどうかを示す新たなパラメーターを追加することで達成できます。ブロックを初期化している部分のコードで、それぞれのブロックオブジェクトにstatusプロパティを追加しましょう。次の部分のコードをハイライトした行で示したように更新してください。

+ +
var bricks = [];
+for(var c=0; c<brickColumnCount; c++) {
+    bricks[c] = [];
+    for(var r=0; r<brickRowCount; r++) {
+        bricks[c][r] = { x: 0, y: 0, status: 1 };
+    }
+}
+ +

次に、それぞれのブロックを描画する前にstatusプロパティの値をdrawBricks()関数で確認します。もしstatus1なら描画します。でももし0ならそのブロックは既にボールに当たっていますから、これ以上画面上に描画されてほしくありません。自分のdrawBricks()関数を次のように更新してください。

+ +
function drawBricks() {
+    for(var c=0; c<brickColumnCount; c++) {
+        for(var r=0; r<brickRowCount; r++) {
+            if(bricks[c][r].status == 1) {
+                var brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft;
+                var brickY = (r*(brickHeight+brickPadding))+brickOffsetTop;
+                bricks[c][r].x = brickX;
+                bricks[c][r].y = brickY;
+                ctx.beginPath();
+                ctx.rect(brickX, brickY, brickWidth, brickHeight);
+                ctx.fillStyle = "#0095DD";
+                ctx.fill();
+                ctx.closePath();
+            }
+        }
+    }
+}
+ +

衝突検出関数で状態を追跡、更新する

+ +

ここではcollisionDetection()関数内でstatusプロパティをブロックに紐づけていきます。もしブロックがアクティブ (状態が1) なら衝突が起きるかどうか確認します。もし衝突が起きるのなら、画面上に描画されないようにそのブロックの状態を0に設定します。自分のcollisionDetection()関数を以下に示すように更新してください。

+ +
function collisionDetection() {
+    for(var c=0; c<brickColumnCount; c++) {
+        for(var r=0; r<brickRowCount; r++) {
+            var b = bricks[c][r];
+            if(b.status == 1) {
+                if(x > b.x && x < b.x+brickWidth && y > b.y && y < b.y+brickHeight) {
+                    dy = -dy;
+                    b.status = 0;
+                }
+            }
+        }
+    }
+}
+ +

衝突検出を有効にする

+ +

collisionDetection()関数への呼び出しをメインのdraw()関数に追加して仕上げとします。次の行をdraw()関数の、drawPaddle()の呼び出しのすぐ下に追加してください。

+ +
collisionDetection();
+
+ +

コードを比べる

+ +

これでボールの衝突検出がそれぞれのブロックに対してフレームごとに確認されるようになりました。ブロックを壊せるようになったのです。

+ +

 

+ +

{{JSFiddleEmbed("https://jsfiddle.net/yumetodo/kaed3hbu/","","395")}}

+ +

 

+ +
+

練習: ボールの色をブロックに当たったときに変えましょう。

+
+ +

次のステップ

+ +

着実にゴールに近づいています。では、先に進みましょう。第8章ではどのようにスコアと勝ち負けを記録するか見てみます。

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Build_the_brick_field", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Track_the_score_and_win")}}

diff --git a/files/ja/games/tutorials/2d_breakout_game_pure_javascript/create_the_canvas_and_draw_on_it/index.html b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/create_the_canvas_and_draw_on_it/index.html new file mode 100644 index 0000000000..86704e0661 --- /dev/null +++ b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/create_the_canvas_and_draw_on_it/index.html @@ -0,0 +1,112 @@ +--- +title: Canvasを作ってその上に描画する +slug: >- + Games/Workflows/2D_Breakout_game_pure_JavaScript/Create_the_Canvas_and_draw_on_it +translation_of: >- + Games/Tutorials/2D_Breakout_game_pure_JavaScript/Create_the_Canvas_and_draw_on_it +--- +
{{GamesSidebar}}
{{IncludeSubnav("/ja/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Move_the_ball")}}

+ +
+

これはゲーム開発Canvasチュートリアルの10ステップのうち1番最初のステップです。このレッスンを終えたあとの完成予想のソースコードはGamedev-Canvas-workshop/lesson1.htmlで入手できます。

+
+ +

ゲームの機能を書き始める前に、ゲーム内部を記述する基本的な構造を作る必要があります。これにはHTMLと{{htmlelement("canvas")}}要素を用います。

+ +

ゲームのHTML

+ +

ゲームは全て{{htmlelement("canvas")}}要素に描画されるため、HTML文書構造は極めて簡潔です。好きなテキストエディタを使って新しいHTML文書を作成し、適当な場所にindex.htmlとして保存してください。そして、そのHTML文書に次のコードを追加します。

+ +
<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8" />
+    <title>Gamedev Canvas Workshop</title>
+    <style>
+    	* { padding: 0; margin: 0; }
+    	canvas { background: #eee; display: block; margin: 0 auto; }
+    </style>
+</head>
+<body>
+
+<canvas id="myCanvas" width="480" height="320"></canvas>
+
+<script>
+	// JavaScriptのコードがここに入ります
+</script>
+
+</body>
+</html>
+
+ +

charset を定義し、{{htmlelement("title")}}と簡単ななCSSをヘッダに記述しました。本体には{{htmlelement("canvas")}}と{{htmlelement("script")}}要素があり、前者にはゲームを描画し、後者にはそれを制御するJavaScriptのコードを記述します。{{htmlelement("canvas")}}要素は簡単に参照を取得できるようにmyCanvasというidを持ち、幅は480ピクセル、高さは320ピクセルとしています。このチュートリアルで書く全てのJavaScriptのコードは開始の<script>と終了の</script>タグの間に配置されます。

+ +

Canvasの基本

+ +

実際に{{htmlelement("canvas")}}要素に映像を描画するために、まずはJavaScriptから要素への参照を取得しなければなりません。次のコードを開始の<script>タグのあとに追記してください。

+ +
var canvas = document.getElementById("myCanvas");
+var ctx = canvas.getContext("2d");
+ +

ここでは{{htmlelement("canvas")}}要素への参照をcanvasに保存しています。それから2D描画コンテキストを保存するためにctx変数を作成しています。2D描画コンテキストは実際にCanvasに描画するために使うツールとなります。

+ +

赤い四角形をキャンバスの上に表示するコード例を見てみましょう。下記のコードを先程記述したJavaScriptのあとに追記して、index.htmlをブラウザで読み込んでみてください。

+ +
ctx.beginPath();
+ctx.rect(20, 40, 50, 50);
+ctx.fillStyle = "#FF0000";
+ctx.fill();
+ctx.closePath();
+ +

全ての命令は{{domxref("CanvasRenderingContext2D.beginPath()","beginPath()")}}メソッドと {{domxref("CanvasRenderingContext2D.closePath()","closePath()")}}メソッドの間に記述されています。四角形を{{domxref("CanvasRenderingContext2D.rect()","rect()")}}を用いて定義しています。最初の2つの値は左上の角のキャンバス上での座標を指定し、あとの2つの値は幅と高さを指定しています。今回描画された四角形は画面の左端から20ピクセル、上端から40ピクセルの位置に幅50ピクセル、高さ50ピクセルの大きさで、正方形になっています。{{domxref("CanvasRenderingContext2D.fillStyle","fillStyle")}}プロパティは{{domxref("CanvasRenderingContext2D.fill()","fill()")}}メソッドで用いられる色 (今回は赤) を保存します。

+ +

もちろん四角形だけではありません。ここでは緑の円を描画するコードを紹介します。次のコードを自分のJavaScriptの最後に追記し、保存して再読込してみてください。

+ +
ctx.beginPath();
+ctx.arc(240, 160, 20, 0, Math.PI*2, false);
+ctx.fillStyle = "green";
+ctx.fill();
+ctx.closePath();
+ +

見て分かるとおり、{{domxref("CanvasRenderingContext2D.beginPath()","beginPath()")}}メソッドと{{domxref("CanvasRenderingContext2D.closePath()","closePath()")}}メソッドが再び用いられています。その間にこのコードで最も重要な部分、{{domxref("CanvasRenderingContext2D.arc()","arc()")}}メソッドが呼び出されています。このメソッドは6つのパラメーターを持ちます。

+ + + +

{{domxref("CanvasRenderingContext2D.fillStyle","fillStyle")}}プロパティは先程とは違う形になっています。これはCSSでそうであるように、色は16進値、色キーワード、rgba()関数、その他利用可能な色メソッドなら何でも指定することができるからです。

+ +

図形を{{domxref("CanvasRenderingContext2D.fill()","fill()")}}で塗りつぶすかわりに{{domxref("CanvasRenderingContext2D.stroke()","stroke()")}}で縁だけ色を付けることも出来ます。次のコードも自分のJavaScriptに追記してみてください。

+ +
ctx.beginPath();
+ctx.rect(160, 10, 100, 40);
+ctx.strokeStyle = "rgba(0, 0, 255, 0.5)";
+ctx.stroke();
+ctx.closePath();
+ +

上記のコードは青く縁取られたからの四角形を描画します。rgba()関数内のアルファチャネルにより青色は半透明になっています。

+ +

自分のコードと比べる

+ +

以下がJSFiddleで即実行可能な最初のレッスンのソースコード全てです。

+ +

 

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/x62h15e2/","","395")}}

+ +

 

+ +
+

練習: 与えられた図形の大きさや色を変えてみましょう。

+
+ +

次のステップ

+ +

ここまでで基本的なHTMLを組み上げcanvasに少し学習しました。それでは、第2章に進みどうやってゲーム内のボールを動かすか学びましょう。

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Move_the_ball")}}

diff --git a/files/ja/games/tutorials/2d_breakout_game_pure_javascript/finishing_up/index.html b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/finishing_up/index.html new file mode 100644 index 0000000000..7078862a9b --- /dev/null +++ b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/finishing_up/index.html @@ -0,0 +1,97 @@ +--- +title: 仕上げ +slug: Games/Workflows/2D_Breakout_game_pure_JavaScript/Finishing_up +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Finishing_up +--- +
{{GamesSidebar}}
+ +
{{IncludeSubnav("/ja/docs/Games")}}
+ +

{{Previous("Games/Workflows/2D_Breakout_game_pure_JavaScript/Mouse_controls")}}

+ +
+

これはゲーム開発Canvasチュートリアルの10ステップのうち10番目、最後のステップです。このレッスンを終えたあとの完成予想のソースコードはGamedev-Canvas-workshop/lesson10.htmlで入手できます。

+
+ +

書いたゲームのどれも常に改善の余地があります。例えば、プレイヤーに1つ以上のライフを与えることができます。1回や2回間違えてもゲームを終わらせられるようにするのです。また、描画も改善できます。

+ +

プレイヤーにライフを与える

+ +

ライフを実装するのは極めて単純です。まずは他の変数を宣言したところと同じところにライフの数を保存する変数を追加しましょう。

+ +
var lives = 3;
+ +

ライフカウンタを描画するのはスコアカウンタを描画するのとほとんど同じです。次の関数を自分のコードのdrawScore()の下に追加してください。

+ +
function drawLives() {
+    ctx.font = "16px Arial";
+    ctx.fillStyle = "#0095DD";
+    ctx.fillText("Lives: "+lives, canvas.width-65, 20);
+}
+ +

ライフがなくなるまで、ゲームをすぐ終わらせるかわりにライフの数を減らします。draw()関数内の次の2行を置き換えます。

+ +
alert("GAME OVER");
+document.location.reload();
+ +

これに以下で示すようなもう少し複雑なロジックを追加します。

+ +
lives--;
+if(!lives) {
+    alert("GAME OVER");
+    document.location.reload();
+}
+else {
+    x = canvas.width/2;
+    y = canvas.height-30;
+    dx = 2;
+    dy = -2;
+    paddleX = (canvas.width-paddleWidth)/2;
+}
+ +

ボールが画面下端に当たったときにlives変数からライフを1つひきます。もしライフが残っていなかったらゲームは負けです。まだ残っているライフがあったらボールとパドルの位置、ボールの動きがリセットされます。

+ +

ライフ表示を描画する

+ +

draw()関数内にdrawLives()への呼び出しを追加する必要があります。drawScore()の呼び出しの下に追記してください。

+ +
drawLives();
+
+ +

requestAnimationFrame()で描画を改善する

+ +

 ではゲーム機構に直結しない部分、描画に関わる部分にとりかかりましょう。{{domxref("window.requestAnimationFrame", "requestAnimationFrame")}}は今は{{domxref("windowTimers.setInterval()", "setInterval()")}}で実装している固定フレームレートよりもより良くブラウザがゲームを描画できるようにします。

+ +
setInterval(draw, 10);
+ +

これを簡単に次の行で置き換えます。

+ +
draw();
+ +

それから、draw()関数の一番下 (閉じ波括弧のすぐ前) に次の行を追加し、draw()関数が自分自身を何度も呼び出すようにします。

+ +
requestAnimationFrame(draw);
+ +

これでdraw()関数がrequestAnimationFrame()ループの中で何度も実行されるようになりましたが、固定の10ミリ秒のフレームレートではなくブラウザに制御を託しています。ブラウザはフレームレートを適切に同期し図形を必要なときだけ描画します。これは古いsetInterval()メソッドよりも効率的で滑らかなアニメーションループを生み出します。

+ +

自分のコードを比べる

+ +

これで全部です。ゲームの最終版が準備でき、プレイできる状態になりました。

+ +

 

+ +

{{JSFiddleEmbed("https://jsfiddle.net/raymondjplante/dfh2tpu1/","","395")}}

+ +

 

+ +
+

練習: ライフの数とパドルでボールが跳ねる角度を替えてみましょう。

+
+ +

ゲームクリア - 今のところは。

+ +

おめでとうございます。これで全てのレッスンを終えました。ここまでで、キャンバス操作の基本をと簡単な2Dゲームの裏にあるロジックを学んだはずです。フレームワークを学びゲーム開発を続ける良い時期です。このシリーズに対応するPhaserを使ったブロックくずしゲームデバイス回転方向を使った2D 迷路ゲームチュートリアルを見てみると良いでしょう。MDNのゲームセクションで発想やより多くの知識を探してみても良いでしょう。

+ +

また、このチュートリアルシリーズの目次を見返せます。コーディングを楽しみましょう。

+ +

{{Previous("Games/Workflows/2D_Breakout_game_pure_JavaScript/Mouse_controls")}}

diff --git a/files/ja/games/tutorials/2d_breakout_game_pure_javascript/game_over/index.html b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/game_over/index.html new file mode 100644 index 0000000000..9bd90da3cd --- /dev/null +++ b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/game_over/index.html @@ -0,0 +1,86 @@ +--- +title: ゲームオーバー +slug: Games/Workflows/2D_Breakout_game_pure_JavaScript/Game_over +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Game_over +--- +
{{GamesSidebar}}
+ +
{{IncludeSubnav("/ja/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Paddle_and_keyboard_controls", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Build_the_brick_field")}}

+ +
これはゲーム開発Canvasチュートリアルの10ステップのうち5番目のステップです。このレッスンを終えたあとの完成予想のソースコードはGamedev-Canvas-workshop/lesson5.htmlで入手できます。
+ +

ボールが壁で弾むのを見たりパドルを左右雨に動かしたりできるのは楽しいですが、そのことを除くとこのゲームは何もせず、進捗や最終目標といったものが全くありません。ゲームプレイの観点からすると、まず負けることができるようにするのが良いでしょう。ブロック崩しで負けるということの裏にある論理は簡潔です。もしパドルでボールを逃してボールが画面の下端についてしまったらゲームオーバーになるのです。

+ +

ゲームオーバーを実装する

+ +

自分のゲームにゲームオーバーを実装してみましょう。3章ではボールを壁で弾むようにしました。以下はその引用です。

+ +
if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) {
+    dx = -dx;
+}
+
+if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) {
+    dy = -dy;
+}
+ +

4辺全てでボールを弾ませるのではなく、3辺、すなわち上端と左右のみで弾むようにしましょう。底を打ったときゲームは終わりになります。2番目のif節を編集して、ボールがキャンバスの下端で衝突したときにゲームオーバー状態が発動するif else節にしましょう。ここでは簡単に、アラートメッセージを表示して、ページの再読込によりゲームを再開するだけにしましょう。

+ +

まず、 setInterval() を最初に呼び出しているところを置き換えます。

+ +

 

+ +
setInterval(draw, 10);
+ +

 

+ +

置き換え後

+ +
var interval = setInterval(draw, 10);
+ +

 

+ +

次に2番目のif節を次の内容で置き換えましょう。

+ +
if(y + dy < ballRadius) {
+    dy = -dy;
+} else if(y + dy > canvas.height-ballRadius) {
+    alert("GAME OVER");
+    document.location.reload();
+    clearInterval(interval); // Needed for Chrome to end game
+}
+ +

パドルをボールに当てる

+ +

このレッスンのしあげに、ボールとパドルの衝突検出を作り、ボールが弾んでプレイエリアに戻ってくるようにしましょう。最も簡単なやり方はボールがパドルの左端と右端の間にあるか確認することです。最後に編集したコードを今度は次のように書き換えます。

+ +
if(y + dy < ballRadius) {
+    dy = -dy;
+} else if(y + dy > canvas.height-ballRadius) {
+    if(x > paddleX && x < paddleX + paddleWidth) {
+        dy = -dy;
+    }
+    else {
+        alert("GAME OVER");
+        document.location.reload();
+    }
+}
+ +

ボールがCanvasの下端に当たっていたら、パドルにも当たっているかどうか確認します。もしパドルに当たっていたら、思ったとおりにボールは弾みます。当たらなかったら、先ほどと同じようにゲームオーバーになります。

+ +

自分のコードと比べる

+ +

自分のコードと比べられるように、実際に動くコードを以下に示します。

+ +

{{JSFiddleEmbed("https://jsfiddle.net/raymondjplante/L61c9y50/","","395")}}

+ +
+

練習: ボールがパドルに当たったときに速く動くようにしましょう。

+
+ +

次のステップ

+ +

今のところかなり順調に進歩してきていて、ゲームも負けるようになったことでもっと遊ぶ価値が感じられるようになってきました。第六章『ブロックのかたまりを作る』に進み、ボールが壊せるブロックを作りましょう。

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Paddle_and_keyboard_controls", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Build_the_brick_field")}}

diff --git a/files/ja/games/tutorials/2d_breakout_game_pure_javascript/index.html b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/index.html new file mode 100644 index 0000000000..e708967860 --- /dev/null +++ b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/index.html @@ -0,0 +1,49 @@ +--- +title: そのままのJavaScriptを使ったブロックくずしゲーム +slug: Games/Workflows/2D_Breakout_game_pure_JavaScript +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript +--- +
{{GamesSidebar}}
{{IncludeSubnav("/ja/docs/Games")}}
+ +

{{Next("Games/Workflows/2D_Breakout_game_pure_JavaScript/Create_the_Canvas_and_draw_on_it")}}

+ +

このステップ・バイ・ステップのチュートリアルでは全てJavaScriptだけで書かれた、HTML5 {{htmlelement("canvas")}}で表示できる簡単なMDN ブロックくずしゲームを作ります。

+ +

全てのステップには編集可能かつすぐに実行できるサンプルがあり、どのような過程で作るべきか確認できます。映像の描画、移動、当たり判定、操作機構、勝ち負けの状態といった基礎的なゲームの仕組みを{{htmlelement("canvas")}}要素を使って実装する基本を学びましょう。

+ +

このシリーズのほとんどの記事は理解するために初歩または中級レベルのJavaScriptの知識を必要とします。このチュートリアルを一通りこなすことで簡単なWebゲームを作れるようになるでしょう。

+ +

Gameplay screen from the game MDN Breakout where you can use your paddle to bounce the ball and destroy the brick field, with keeping the score and lives.

+ +

レッスン詳細

+ +

全てのレッスン、そしてこれから一緒に作るMDNブロック崩しゲームの各バージョンはGitHub上で入手可能です:

+ +
    +
  1. Canvasを作ってその上に描画する
  2. +
  3. ボールを動かす
  4. +
  5. ボールを壁で弾ませる
  6. +
  7. パドルとキーボード操作
  8. +
  9. ゲームオーバー
  10. +
  11. ブロックのかたまりを作る
  12. +
  13. 衝突検出
  14. +
  15. スコアと勝ち負けを記録する
  16. +
  17. マウス操作
  18. +
  19. 仕上げ
  20. +
+ +

まずはJavaScriptだけで始めるのがWebゲーム開発の確実な知識を手に入れる一番良い方法です。そのあと、自分のプロジェクトで使うフレームワークを選びましょう。フレームワークはJavaScript言語で書かれた単なるツールです。ですから、たとえフレームワークを用いて開発しようとしていてもまずはその言語を学び、手元で実際に何が起こっているか理解すると良いでしょう。フレームワークは開発速度を上げ、ゲームのとるに足らない部分を処理してくれますが、もし何かが思ったように動かないなんてことがあったらいつでもデバッグしたり、あるいは単にJavaScriptで自分なりの解を出すということもできるのです。

+ +
+

ノート: ゲームライブラリを用いた2D Webゲーム開発に興味があるのであれば、このシリーズに対応するPhaserを使ったブロックくずしゲームも参照してください。

+
+ +
+

ノート: このシリーズはゲーム開発ワークショップのハンズオンの資料として使えます。ゲーム開発全般について話すつもりならこのチュートリアルに基づいたGamedev Canvas Content Kitも利用できます。

+
+ +

次のステップ

+ +

それでは始めましょう! 最初の章、『Canvasを作ってその上に描画する』に進みます。

+ +

{{Next("Games/Workflows/2D_Breakout_game_pure_JavaScript/Create_the_Canvas_and_draw_on_it")}} 

diff --git a/files/ja/games/tutorials/2d_breakout_game_pure_javascript/mouse_controls/index.html b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/mouse_controls/index.html new file mode 100644 index 0000000000..51da95cada --- /dev/null +++ b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/mouse_controls/index.html @@ -0,0 +1,57 @@ +--- +title: マウス操作 +slug: Games/Workflows/2D_Breakout_game_pure_JavaScript/Mouse_controls +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Mouse_controls +--- +
{{GamesSidebar}}
+ +
{{IncludeSubnav("/ja/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Collision_detection", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Finishing_up")}}

+ +
+

これはゲーム開発Canvasチュートリアルの10ステップのうち9番目のステップです。このレッスンを終えたあとの完成予想のソースコードはGamedev-Canvas-workshop/lesson9.htmlで入手できます。

+
+ +

ゲーム自体は実際に完成したので、磨き上げにかかりましょう。既にキーボード操作を追加していますが、マウス操作も簡単に追加できます。

+ +

マウスの動作を監視する

+ +

マウスの操作を監視するのはキー入力を監視するのよりも簡単です。{{event("mousemove")}}イベントのリスナーさえあればよいのです。次の行を、他のイベントリスナーの近く、keyup eventのすぐ下に追記してください。

+ +
document.addEventListener("mousemove", mouseMoveHandler, false);
+ +

パドルの動きをマウスの動きと紐付ける

+ +

パドルの位置をカーソルの座標に基づいて更新することができます。次のハンドラ関数は実際にそれを行います。次の関数を自分のコードの、先程追記したコードのすぐ下に追記しましょう。

+ +
function mouseMoveHandler(e) {
+    var relativeX = e.clientX - canvas.offsetLeft;
+    if(relativeX > 0 && relativeX < canvas.width) {
+        paddleX = relativeX - paddleWidth/2;
+    }
+}
+ +

この関数ではまずビューポートの水平方向のマウスの位置 (e.clientX) からキャンバスの左端とビューポートの左端の距離 (canvas.offsetLeft) をひいてrelativeXの値を導出します。これはキャンバスの左端とマウスカーソルの距離とちょうど同じになります。もしカーソルの相対X座標が0より大きくCanvasの幅より小さいのならば、カーソルはキャンバス内にあります。また、座標paddleX (パドルの左端と紐付けられている) は、パドルの中点で対称に動くようにrelativeXの値からパドルの幅の半分をひいた値に設定されます。

+ +

パドルはマウスカーソルの位置を追うようになりますが、動きをCanvasの大きさに制限しているため、両端で消え失せてしまうようなことはありません。

+ +

自分のコードと比べる

+ +

比較用にコードの最新の状態を示します。

+ +

 

+ +

{{JSFiddleEmbed("https://jsfiddle.net/raymondjplante/vt7y5hcp/","","395")}}

+ +

 

+ +
+

練習: パドル動作の境界を調節して、Canvasの両端でもパドルの半分ではなく全体が見えるようにしてください。

+
+ +

次のステップ

+ +

最後に微調整する準備が整った、完全なゲームが完成しました。では、仕上げに入りましょう。

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Collision_detection", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Finishing_up")}}

diff --git a/files/ja/games/tutorials/2d_breakout_game_pure_javascript/move_the_ball/index.html b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/move_the_ball/index.html new file mode 100644 index 0000000000..b1a53ead12 --- /dev/null +++ b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/move_the_ball/index.html @@ -0,0 +1,140 @@ +--- +title: ボールを動かす +slug: Games/Workflows/2D_Breakout_game_pure_JavaScript/Move_the_ball +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Move_the_ball +--- +
{{GamesSidebar}}
{{IncludeSubnav("/ja/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Create_the_Canvas_and_draw_on_it", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Bounce_off_the_walls")}}

+ +
+

これはゲーム開発Canvasチュートリアルの10ステップのうち2番目のステップです。このレッスンを終えたあとの完成予想のソースコードはGamedev-Canvas-workshop/lesson2.htmlで入手できます。

+
+ +

前回のレッスンを一通りこなしてみてボールの描き方が分かりました。では今回はそれを動かしましょう。技術的には、ボールを描画し、またそれを消してからほんの少し違う位置に描画し直すという処理を毎フレームずつ行うことで動いているような印象を生み出します。ちょうど映画がどのように動くのかと同じです。

+ +

描画ループを定義する

+ +

Canvasの映像を毎フレーム、定期的に更新し続けるためには、何度も実行されるような関数を定義する必要があります。この関数には画像の位置を変えたりするために毎回違う値が与えらます。{{domxref("WindowTimers.setInterval()", "setInterval()")}}や{{domxref("window.requestAnimationFrame()", "requestAnimationFrame()")}}といったJavaScriptのタイミング関数を用いれば同じ関数を何度も実行できます。

+ +

HTMLファイル内に既に書かれているJavaScriptを最初の2行を除いて全て削除し、次のコードを追記してください。draw()関数がsetIntervalの中で10ミリ秒おきに実行されます。

+ +
function draw() {
+    // 描画コード
+}
+setInterval(draw, 10);
+ +

無限に続く setInterval の性質のため、draw()は10ミリ秒おきにずっと、あるいは私達が止めるまで呼ばれ続けます。では、ボールを描画してみましょう。draw()関数の中に下記のコードを追記してください。

+ +
ctx.beginPath();
+ctx.arc(50, 50, 10, 0, Math.PI*2);
+ctx.fillStyle = "#0095DD";
+ctx.fill();
+ctx.closePath();
+
+ +

では、書き換えたコードを試してみましょう。ボールが毎フレーム再描画されるはずです。

+ +

ボール動かす

+ +

動きがないのでボールが再描画され続けていることに気づかないはずです。動きを加えてみましょう。まず、直書きされた位置 (50,50) のかわりに xyという名の変数に開始位置を中央下端として定義し、それらを用いて円が描画される位置を定義します。

+ +

まず、xyを定義するために自分の draw()関数の上に次の2行を追加しましょう。

+ +
var x = canvas.width/2;
+var y = canvas.height-30;
+
+ +

次に、{{domxref("CanvasRenderingContext2D.arc()","arc()")}}メソッド内で変数xと変数yを使うようにdraw() 関数を書き換えましょう。次のハイライトされている行のとおりです。

+ +
function draw() {
+    ctx.beginPath();
+    ctx.arc(x, y, 10, 0, Math.PI*2);
+    ctx.fillStyle = "#0095DD";
+    ctx.fill();
+    ctx.closePath();
+}
+
+ +

ここからが大事な部分です。xyに毎フレーム描画した後に小さな値を加え、ボールが動いているように見せるのです。その小さな値をdxdyとして2、-2をそれぞれ設定しましょう。変数x、yの定義のあとに次のコードを追記してください。

+ +
var dx = 2;
+var dy = -2;
+
+ +

最後に残っていることがあります。フレームごとにxyを変数dxdyで更新して、更新されるたびにボールが新しい位置に描画されるようにするのです。次に示されている新しい2行をdraw()関数の最後に追記してください。

+ +
function draw() {
+    ctx.beginPath();
+    ctx.arc(x, y, 10, 0, Math.PI*2);
+    ctx.fillStyle = "#0095DD";
+    ctx.fill();
+    ctx.closePath();
+    x += dx;
+    y += dy;
+}
+ +

コードを保存してください。問題なく動作しますが、ボールの軌跡が残ります。

+ +

+ +

フレームの後にCanvasを消去する

+ +

前のフレームを削除せずに毎フレーム描画しているために軌跡が残ってしまいます。でも心配する必要はありません。Canvasの内容を消去するメソッド、{{domxref("CanvasRenderingContext2D.clearRect()","clearRect()")}}があります。このメソッドは4つのパラメータをとります。四角形の左上端のx、y座標と四角形の右下端のx、y座標です。この四角形で囲われた領域にある内容全てが消去されます。

+ +

次のハイライトされている新しい行をdraw()関数に追記してください。

+ +
function draw() {
+    ctx.clearRect(0, 0, canvas.width, canvas.height);
+    ctx.beginPath();
+    ctx.arc(x, y, 10, 0, Math.PI*2);
+    ctx.fillStyle = "#0095DD";
+    ctx.fill();
+    ctx.closePath();
+    x += dx;
+    y += dy;
+}
+
+ +

コードを保存してもう一度試してみてください。今度は軌跡のないボールがみえるはずです。10ミリ秒おきにキャンバスは消去され、青い円 (ボール) が指定された位置に描画され、 xyの値は次のフレームに備えて更新されます。

+ +

コードを整える

+ +

次のいくつかの記事ではdraw()関数にもっと命令を追加します。ですからdraw()関数をできるだけ簡潔にしておくのは大事なことです。ボールを描画するコードを別の関数に移しましょう。

+ +

既にあるdraw()関数を次の2つの関数で置き換えてください。

+ +
function drawBall() {
+    ctx.beginPath();
+    ctx.arc(x, y, 10, 0, Math.PI*2);
+    ctx.fillStyle = "#0095DD";
+    ctx.fill();
+    ctx.closePath();
+}
+
+function draw() {
+    ctx.clearRect(0, 0, canvas.width, canvas.height);
+    drawBall();
+    x += dx;
+    y += dy;
+}
+ +

自分のコードと比べる

+ +

この記事で組み上げた自分のコードを下のライブデモで確認したり、書き換えたりしてどのように動いているかしっかり理解しましょう。

+ +

 

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/3x5foxb1/","","395")}}

+ +

 

+ +
+

練習: 動くボールの速さや向きを変えてみましょう。

+
+ +

次のステップ

+ +

ボールを描画して動くようにしましたが、そのままCanvasの縁から消えていってしまいます。第3章ではどのようにボールを壁で弾ませるか探っていきます。

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Create_the_Canvas_and_draw_on_it", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Bounce_off_the_walls")}}

diff --git a/files/ja/games/tutorials/2d_breakout_game_pure_javascript/paddle_and_keyboard_controls/index.html b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/paddle_and_keyboard_controls/index.html new file mode 100644 index 0000000000..1602332d81 --- /dev/null +++ b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/paddle_and_keyboard_controls/index.html @@ -0,0 +1,128 @@ +--- +title: パドルとキーボード操作 +slug: Games/Workflows/2D_Breakout_game_pure_JavaScript/Paddle_and_keyboard_controls +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Paddle_and_keyboard_controls +--- +
{{GamesSidebar}}
+ +
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Bounce_off_the_walls", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Game_over")}}

+ +
+

これはゲーム開発Canvasチュートリアルの10ステップのうち4番目のステップです。このレッスンを終えたあとの完成予想のソースコードはGamedev-Canvas-workshop/lesson4.htmlで入手できます。

+
+ +

ボールは壁で自由に弾み、あなたはずっとそれを見ていることができますが、今の所何の対話要素もありません。操作できないものなんてゲームじゃありません! ですからユーザーとの対話要素、操作できるパドルを追加しましょう。

+ +

ボールにぶつかるパドルを定義する

+ +

そういうわけで、ボールに当てるパドルが必要になりました。パドルに用いるいくつかの変数を定義しましょう。次の変数を、他の変数と一緒にコードの一番上に追加してください。

+ +
var paddleHeight = 10;
+var paddleWidth = 75;
+var paddleX = (canvas.width-paddleWidth)/2;
+ +

ここではパドルの高さと幅、x軸上の開始地点を定義しています。続くコードではこれらを用いてさらなる計算が行われます。パドルを画面上に表示する関数を作成しましょう。drawBall()のすぐ下に次の関数を追加してください。

+ +
function drawPaddle() {
+    ctx.beginPath();
+    ctx.rect(paddleX, canvas.height-paddleHeight, paddleWidth, paddleHeight);
+    ctx.fillStyle = "#0095DD";
+    ctx.fill();
+    ctx.closePath();
+}
+ +

パドルを操作できるようにする

+ +

こにパドルを描画しても良いですが、ユーザーの行動に応答する必要があります。キーボード操作を実装するのです。必要なものは次のとおりです。

+ + + +

押されているボタンはこのとおり、ブーリアン値として定義、初期化できます。このコードをどこか他の変数の近くに追記してください。

+ +
var rightPressed = false;
+var leftPressed = false;
+ +

最初は制御ボタンは押されていないため、どちらにおいてもデフォルトの値はfalseです。ボタンが押されたのを検知するため、2つのイベントリスナーを設定します。JavaScriptの最後にあるsetInterval()の行のちょうど上に次のコードを追記してください。

+ +
document.addEventListener("keydown", keyDownHandler, false);
+document.addEventListener("keyup", keyUpHandler, false);
+ +

キーボードのキーのどれかに対してkeydownイベントが発火したとき (どれかが押されたとき) 、keyDownHandler()関数が実行されます。2つ目のリスナーについても同様で、(そのキーが押されなくなったき) keyupイベントはkeyUpHandler()関数を呼び出します。自分のaddEventListener()の行の下に次のコードを追記してください。

+ +
function keyDownHandler(e) {
+    if(e.key == "Right" || e.key == "ArrowRight") {
+        rightPressed = true;
+    }
+    else if(e.key == "Left" || e.key == "ArrowLeft") {
+        leftPressed = true;
+    }
+}
+
+function keyUpHandler(e) {
+    if(e.key == "Right" || e.key == "ArrowRight") {
+        rightPressed = false;
+    }
+    else if(e.key == "Left" || e.key == "ArrowLeft") {
+        leftPressed = false;
+    }
+}
+ +

キーが押されたとき、その情報は変数に保存されます。それぞれの場合で関連する変数がtrueに設定されます。キーが離されたときに変数はfalseに戻されます。

+ +

どちらの関数も変数eで表されるイベントをパラメーターとしてとります。これから有用な情報が手に入ります。keyは押されたキーについての情報を持っています。大抵のブラウザでは左右の矢印キーにそれぞれ ArrowLeftArrowRight が対応します。ただし IE/Edge に対応するために、 LeftRightも確認する必要があります。 もし左カーソルが押されたら、変数leftPressedtrueに、離されたら変数leftPressedfalseに設定されます。右カーソルと変数rightPressedについても同様です。

+ +

パドルの移動ロジック

+ +

押されているキーについての情報を保存している変数、そして関連する関数が設定されました。ではそれらを使う実際のコードに手を入れて画面上のパドルを動かしてみましょう。draw()関数の中で、各々のフレームを描画するときに左カーソルキーが押されているか、右カーソルが押されているか確認しましょう。次のようなコードになっているでしょう。

+ +
if(rightPressed) {
+    paddleX += 7;
+}
+else if(leftPressed) {
+    paddleX -= 7;
+}
+ +

左カーソルが押されていたら7ピクセル左に動き、右カーソルが押されていたら7ピクセル右に動きます。これだけでも良さそうですが、どちらかのキーを長く押し続けたらパドルがCanvasの縁から消えてしまいます。コードを次のように変えることでCanvasの境界内でのみ動くように改善できます。

+ +
if(rightPressed && paddleX < canvas.width-paddleWidth) {
+    paddleX += 7;
+}
+else if(leftPressed && paddleX > 0) {
+    paddleX -= 7;
+}
+ +

ここで用いられている位置paddleXは期待されているように左端の0と右端のcanvas.width-paddleWidth間で動きます。

+ +

上記のコード片をdraw()関数の最後、閉じ波括弧のちょうど前に追記してください。

+ +

あとはdrawPaddle()関数をdraw()関数から呼び出し、実際に画面に表示するようにすれば完了です。次の行をdraw()関数の、ちょうどdrawBall()を呼ぶ行の下に追記してください。

+ +
drawPaddle();
+
+ +

自分のコードと比べる

+ +

自分のコードと比べられる、実際に動くコードがこちらになります。

+ +

 

+ +

{{JSFiddleEmbed("https://jsfiddle.net/raymondjplante/t2udo69j/","","395")}}

+ +

 

+ +
+

練習: パドルを速く、または遅く動くようにしたり、大きさを変えたりしてみましょう。

+
+ +

次のステップ

+ +

ゲームっぽい要素を追加しましょう。今問題なのはただパドルでボールを永遠に打ち続けることしか出来ないという点です。これは第5章、ゲームオーバーでゲームの終了状態を追加することで完全に変わることになります。

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Bounce_off_the_walls", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Game_over")}}

diff --git a/files/ja/games/tutorials/2d_breakout_game_pure_javascript/track_the_score_and_win/index.html b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/track_the_score_and_win/index.html new file mode 100644 index 0000000000..44ba7aa804 --- /dev/null +++ b/files/ja/games/tutorials/2d_breakout_game_pure_javascript/track_the_score_and_win/index.html @@ -0,0 +1,94 @@ +--- +title: スコアと勝ち負けを記録する +slug: Games/Workflows/2D_Breakout_game_pure_JavaScript/Track_the_score_and_win +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Track_the_score_and_win +--- +
{{GamesSidebar}}
+ +
{{IncludeSubnav("/ja/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Collision_detection", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Mouse_controls")}}

+ +
+

これはゲーム開発Canvasチュートリアルの10ステップのうち8番目のステップです。このレッスンを終えたあとの完成予想のソースコードはGamedev-Canvas-workshop/lesson8.htmlで入手できます。

+
+ +

ブロックを崩せるのは最高ですが、より素晴らしいものにするためにユーザーが壊した全てのブロックに対してポイントを与え、合計スコアのカウントを更新し続けましょう。

+ +

スコアを数える

+ +

ゲームを通してスコアを見せることができればあとで友達に自慢することができます。スコアを記録する変数が必要です。次の行を自分のJavaScriptの他の変数のあとに追記してください。

+ +
var score = 0;
+ +

スコア表示を作成し更新するためにdrawScore()関数も必要です。次のコードをcollisionDetection()関数のあとに追加してください。

+ +
function drawScore() {
+    ctx.font = "16px Arial";
+    ctx.fillStyle = "#0095DD";
+    ctx.fillText("Score: "+score, 8, 20);
+}
+ +

文字をキャンバス上に描画するのは図形を描画するのと似ています。フォント定義はCSS出するものとちょうど同じように描きます。大きさとフォントの種類は{{domxref("CanvasRenderingContext2D.font","font()")}}メソッドで設定できます。それからフォントの色を設定するには{{domxref("CanvasRenderingContext2D.fillStyle()","fillStyle()")}}を、キャンバス上に配置される実際の文章を設定するには{{domxref("CanvasRenderingContext2D.fillText","fillText()")}}を使用してください。最初のパラメーターは文章自体です。上記のコードは現在のポイントの数を表示します。最後の2つのパラメーターは文章がキャンバス上に置かれる座標です。

+ +

ブロックに当たるたびにスコアを与えるには、衝突が検出されるたびにスコア変数を増加させる1行をcollisionDetection()関数に追加します。次のハイライトされた行を自分のコードに追加してください。

+ +
function collisionDetection() {
+    for(var c=0; c<brickColumnCount; c++) {
+        for(var r=0; r<brickRowCount; r++) {
+            var b = bricks[c][r];
+            if(b.status == 1) {
+                if(x > b.x && x < b.x+brickWidth && y > b.y && y < b.y+brickHeight) {
+                    dy = -dy;
+                    b.status = 0;
+                    score++;
+                }
+            }
+        }
+    }
+}
+ +

draw()関数からdrawScore()を呼び続けることで新しいフレームごとにスコアは最新の状態に保たれます。次の行をdraw()の中、ちょうどdrawPaddle()の呼び出しの下に追加してください。

+ +
drawScore();
+ +

全てのブロックが崩されたときに勝利を伝えるメッセージを表示する

+ +

ポイントを集め続けるという動作はうまく働きますが、永久に増やし続けることは出来ません。全てのブロックが崩されたらどうなるのでしょうか。何においてもそれこそがゲームの主目標なのですから、得られる全てのポイントが集まったときには勝利を伝えるメッセージを表示すべきです。次のハイライトされた部分を自分のcollisionDetection()関数に追記してください。

+ +
function collisionDetection() {
+    for(var c=0; c<brickColumnCount; c++) {
+        for(var r=0; r<brickRowCount; r++) {
+            var b = bricks[c][r];
+            if(b.status == 1) {
+                if(x > b.x && x < b.x+brickWidth && y > b.y && y < b.y+brickHeight) {
+                    dy = -dy;
+                    b.status = 0;
+                    score++;
+                    if(score == brickRowCount*brickColumnCount) {
+                        alert("YOU WIN, CONGRATULATIONS!");
+                        document.location.reload();
+                    }
+                }
+            }
+        }
+    }
+}
+ +

これのおかげで、全てのブロックが崩されたときにユーザーは実際にゲームに勝つことができます。ゲームにおいてはこれは非常に重要です。アラートのボタンがクリックされたらdocument.location.reload()関数はページを再読込しゲームをもう一度始めます。

+ +

自分のコードと比べる

+ +

自分のものと比べたいときのために最新のコードをいかに示します。このように見え、そして動くはずです。

+ +

{{JSFiddleEmbed("https://jsfiddle.net/raymondjplante/b3z2Lpu9/","","395")}}

+ +
+

練習: ブロックに当たるたびにより多くのポイントを追加し、ゲームの終わりに集めたポイントの数を表示するようにしましょう。

+
+ +

次のステップ

+ +

この時点でもこのゲームはかなりよく見えます。次のレッスンではマウス操作を追加することでゲームの魅力を広げます。

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Collision_detection", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Mouse_controls")}}

diff --git a/files/ja/games/tutorials/index.html b/files/ja/games/tutorials/index.html new file mode 100644 index 0000000000..9d9b5e2ff3 --- /dev/null +++ b/files/ja/games/tutorials/index.html @@ -0,0 +1,25 @@ +--- +title: Workflows for different game types +slug: Games/Workflows +tags: + - Canvas + - Games + - JavaScript + - NeedsTranslation + - TopicStub + - Web + - Workflows +translation_of: Games/Tutorials +--- +
{{GamesSidebar}}
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

This page contains articles that highlight different workflows for effectively creating different types of web games, whether you want to create a 2D or 3D game from scratch, or port a C++ or Flash game over to open web technologies.

+ +
+
2D breakout game using pure JavaScript
+
In this step-by-step tutorial you'll implement a simple breakout clone using pure JavaScript. Along the way you will learn the basics of using the {{htmlelement("canvas")}} element to implement fundamental game mechanics like rendering and moving images, collision detection, control machanisms, and winning and losing states.
+
2D breakout game using Phaser
+
In this step-by-step tutorial you'll implement the same breakout clone as the previous tutorial series, except that this time you'll do it using thePhaser HTML5 game framework. This idea here is to teach some of the fundamentals (and advantages) of working with frameworks, along with fundamental game mechanics.
+
2D maze game with device orientation
+
This tutorial shows how to create a 2D maze game using HTML5, incorporating fundamentals such as collision detection and sprite placement on a {{htmlelement("canvas")}}. This is a mobile game that uses the Device Orientation and Vibration APIs to enhance the gameplay and is built using the Phaser framework.
+
-- cgit v1.2.3-54-g00ecf