recursal/MDN huggingface dataset:
物理演算
====

* « 前のページ (en-US)
* 次のページ » (en-US)

これは、Gamedev Phaser チュートリアルの 16 ステップ中、 **5 ステップ目**になります。このレッスンを終えた後のソースコードは Gamedev-Phaser-Content-Kit/demos/lesson05.html で見ることができます。

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

物理演算の追加
-------

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

まず最初に、ゲーム内の Arcade Physics エンジンを初期化しましょう。以下のように、`create` 関数の最初に `physics.startSystem()` メソッドを追加します（関数内の最初の行にします）。


```js
game.physics.startSystem(Phaser.Physics.ARCADE);
```


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


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


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


```js
ball.body.velocity.set(150, 150);
```

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

`update()` 関数から `x` と `y` に値を追加する古いメソッドを削除することを忘れないでください。


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


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

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

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


```js
let 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 には、物理演算に関する数多くの関数と変数が、 Arcade と P2 物理演算エンジンの使用例とともに解説されています。

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

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

次のステップ
------

次のステップでは、壁でボールを跳ね返す (en-US)を実装します。

* « 前のページ (en-US)
* 次のページ » (en-US)
仕上げ
===

* « 前のページ

これは、ゲーム開発キャンバスチュートリアル の 10 ステップ中 **10 ステップ目、最後のステップ**になります。このレッスンを終えた後のソースコードは、Gamedev-Canvas-workshop/lesson10.htmlで見ることができます。

私たちが書くゲームには、常に改良の余地があります。例えば、プレイヤーに複数の人生を提供することができます。 1 人または 2 人がミスをしても、ゲームを完了させることができるのです。また、コードのレンダリングを改善することもできます。

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

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


```js
let lives = 3;
```


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


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


すぐにゲームを終了するのではなく、ライフがなくなるまでライフを減らしていきます。また、プレイヤーが次のライフで始めるときに、ボールとパドルの位置をリセットすることができます。そこで、 `draw()` 関数の中で、以下の 3 行を置き換えてください。


```js
alert("GAME OVER");
document.location.reload();
clearInterval(interval); // クロームがゲームを終了するのに必要
```


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


```js
lives--;
if (!lives) {
  alert("GAME OVER");
  document.location.reload();
  clearInterval(interval); // クロームがゲームを終了するのに必要
} else {
  x = canvas.width / 2;
  y = canvas.height - 30;
  dx = 2;
  dy = -2;
  paddleX = (canvas.width - paddleWidth) / 2;
}
```


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

### ライフ表示を描画する

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


```js
drawLives();
```

requestAnimationFrame()で描画を改善する
-------------------------------

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


```js
const interval = setInterval(draw, 10);
```


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


```js
draw();
```


そして、それぞれのインスタンスを削除します。


```js
clearInterval(interval); // クロームがゲームを終了するのに必要
```


次に、 `draw()` 関数の一番下（中括弧を閉じる直前）に、以下の行を追加します。これは、 `draw()` 関数が何度も繰り返し呼び出されるようにするためのものです。


```js
requestAnimationFrame(draw);
```


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

自分のコードを比べる
----------

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

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

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

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

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

* « 前のページ
ゲームオーバー
=======

* « 前のページ
* 次のページ »

これは、ゲーム開発キャンバスチュートリアル の 10 ステップ中 **5 ステップ目**になります。このレッスンを終えた後のソースコードは、Gamedev-Canvas-workshop/lesson5.htmlで見ることができます。

ボールが壁に当たって跳ねているのを見たり、パドルを移動させたりできるのは楽しいのですが、それ以外は何もせず、ゲームの進行や最終目標がありません。ゲームプレイの観点からは、負けることがあってもいいのではないでしょうか。ブロック崩しで負ける理屈は簡単です。パドルでボールを飛ばして画面の下端へ到達させたらゲームオーバーです。

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

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


```js
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()` を最初に呼び出しているところを置き換えます。


```js
setInterval(draw, 10);
```


置き換えるとこうなります。


```js
const interval = setInterval(draw, 10);
```


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


```js
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
}
```

パドルをボールに当てる
-----------

このレッスンの最後に、ボールとパドルの間に何らかの衝突判定を作成し、ボールがパドルで跳ねてプレイエリアに戻れるようにします。最も簡単なのは、ボールの中心がパドルの左端と右端の間にあるかどうかをチェックすることです。最後に修正したコードを再び以下のように更新してください。


```js
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();
    clearInterval(interval);
  }
}
```


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

自分のコードと比べる
----------

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

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

次のステップ
------

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

* « 前のページ
* 次のページ »
マウス操作
=====

* « 前のページ
* 次のページ »

これは、ゲーム開発キャンバスチュートリアル の 10 ステップ中 **9 ステップ目**になります。このレッスンを終えた後のソースコードは、Gamedev-Canvas-workshop/lesson9.htmlで見ることができます。

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

マウスの動作を監視する
-----------

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


```js
document.addEventListener("mousemove", mouseMoveHandler, false);
```

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

ポインターの座標に基づいてパドルの位置を更新することができます。以下のハンドラー関数がまさにそれを行うものです。以下の関数を、前に追加した行の下に、あなたのコードに追加してください。


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


この値は、ビューポート内のマウスの水平位置 (`e.clientX`) からキャンバスの左端とビューポートの左端間の距離 (`canvas.offsetLeft`) を引いたもので、実質的にこれはキャンバス左端からマウスポインターまでの距離と等しくなっています。ポインタの相対 X 位置が 0 より大きく、キャンバスの幅よりも小さい場合、ポインタはキャンバスの境界内にあり、`paddleX` 位置（パドルの左端に固定）は `relativeX` 値からパドルの幅の半分を引いた値に設定され、実際の移動はパドルの中央に対して相対的に行われることになります。

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

自分のコードと比べる
----------

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

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

次のステップ
------

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

* « 前のページ
* 次のページ »
スコアと勝ち負けを記録する
=============

* « 前のページ
* 次のページ »

これは、ゲーム開発キャンバスチュートリアル の 10 ステップ中 **8 ステップ目**になります。このレッスンを終えた後のソースコードは、Gamedev-Canvas-workshop/lesson8.htmlで見ることができます。

レンガを破壊するのはとてもクールですが、ユーザーがレンガにぶつかるごとにこの点を与え、その合計点をカウントしていくことで、さらに素晴らしいゲームになります。

スコアを数える
-------

ゲーム中に自分のスコアを見ることができれば、最終的には友達を感動させることができます。スコアを記録するための変数が必要です。 JavaScript に以下のように、残りの変数の後に追加してください。


```js
let score = 0;
```


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


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


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

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


```js
function collisionDetection() {
  for (let c = 0; c < brickColumnCount; c++) {
    for (let r = 0; r < brickRowCount; r++) {
      const 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++;
        }
      }
    }
  }
}
```


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


```js
drawScore();
```

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

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


```js
function collisionDetection() {
  for (let c = 0; c < brickColumnCount; c++) {
    for (let r = 0; r < brickRowCount; r++) {
      const 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();
            clearInterval(interval); // Needed for Chrome to end game
          }
        }
      }
    }
  }
}
```


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

自分のコードと比べる
----------

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

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

次のステップ
------

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

* « 前のページ
* 次のページ »
ボールを壁で跳ね返させる
============

* « 前のページ
* 次のページ »

これは、ゲーム開発キャンバスチュートリアル の 10 ステップ中 **3 ステップ目**になります。このレッスンを終えた後のソースコードは、Gamedev-Canvas-workshop/lesson3.htmlで見ることができます。

ボールが移動するのを見るのは楽しいですが、すばやく画面の内側へ消えてしまうので、ボールの楽しみが半減してしまいます。この問題を解決するために、とても簡単な衝突判定（詳しくは後ほど説明します）を実装して、ボールをキャンバスの 4 つの辺で跳ね返らせるようにしましょう。

簡単な衝突検出
-------

衝突を検出するために、ボールが壁に触れているか（衝突しているか）どうかをチェックし、触れていればそれに応じてボールの移動方向を変更します。

計算を簡単にするために、描画された円の半径を保持し、計算に使用する `ballRadius` という変数を定義しましょう。これをコードに追加してください。既存の変数宣言の下のどこかです。


```js
const ballRadius = 10;
```


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


```js
ctx.arc(x, y, ballRadius, 0, Math.PI \* 2);
```

### 上端と下端で跳ね返させる

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


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


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

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


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


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

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


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


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

### 左端と右端で跳ね返させる

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


```js
if (x + dx > canvas.width || x + dx < 0) {
  dx = -dx;
}

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


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

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

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

![](/ja/docs/Games/Tutorials/2D_Breakout_game_pure_JavaScript/Bounce_off_the_walls/ball-in-wall.png)

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


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


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

自分のコードと比べる
----------

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

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

次のステップ
------

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

* « 前のページ
* 次のページ »
キャンバスを作ってその上に描画する
=================

* « 前のページ
* 次のページ »

これは、ゲーム開発キャンバスチュートリアル の 10 ステップ中 **1 ステップ目**になります。このレッスンを終えた後のソースコードは、Gamedev-Canvas-workshop/lesson1.htmlで見ることができます。

ゲームの機能を書き始める前に、ゲームを内部でレンダリングするための基本的な構造を作成する必要があります。これは、HTML と `<canvas>` 要素を使用して行うことができます。

ゲームの HTML
---------

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


```html
<!doctype html>
<html lang="en-US">
  <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` を定義し、 `<title>` と簡単なな CSS をヘッダーに記述しました。本体には `<canvas>` と `<script>` 要素があり、前者にはゲームを描画し、後者にはそれを制御する JavaScript のコードを記述します。 `<canvas>` 要素は簡単に参照を取得できるように `id` を `myCanvas` とし、幅は 480 ピクセル、高さは 320 ピクセルとしています。このチュートリアルで書くすべての JavaScript のコードは開始の `<script>` と終了の `</script>` タグの間に配置されます。

キャンバスの基本
--------

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


```js
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");
```


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

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


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


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

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


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


見て分かるとおり、 `beginPath()` メソッドと `closePath()` メソッドが再び用いられています。その間にこのコードで最も重要な部分、 `arc()` メソッドが呼び出されています。このメソッドは 6 つの引数を持ちます。

* 円の中心の `x`、`y` 座標
* 円の半径
* 開始角度と終了角度 (円を描く始める時点の角度と描き終えたあとの角度をラジアンで)
* 描く方向 (時計回りは `false` で、既定値。反時計回りは `true`。) この最後の引数は省略可能です。

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

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


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


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

自分のコードと比べる
----------

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

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

次のステップ
------

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

* « 前のページ
* 次のページ »
ブロックのかたまりを作る
============

* « 前のページ
* 次のページ »

これは、ゲーム開発キャンバスチュートリアル の 10 ステップ中 **6 ステップ目**になります。このレッスンを終えた後のソースコードは、Gamedev-Canvas-workshop/lesson6.htmlで見ることができます。

ゲームプレイの仕組みを修正した結果、負けることができるようになりました。これは、ゲームがようやくゲームらしくなってきたという意味で、とてもいいことです。しかし、壁やパドルでボールを跳ね返すだけでは、すぐに飽きられてしまいます。ブロック崩しに必要なのは、ボールでレンガを破壊すること。

ブロック変数を設定する
-----------

このレッスンの全体的な目的は、二次元配列で動作する入れ子ループを使用して、レンガのコードをいくつかレンダリングすることです。しかし、最初の段階では、レンガの幅や高さ、行や列などの情報を定義するために、いくつかの変数を設定する必要があります。次の行を、あらかじめプログラムで宣言しておいた変数の下に追加してください。


```js
const brickRowCount = 3;
const brickColumnCount = 5;
const brickWidth = 75;
const brickHeight = 20;
const brickPadding = 10;
const brickOffsetTop = 30;
const brickOffsetLeft = 30;
```


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

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


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


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

ブロック描画ロジック
----------

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


```js
function drawBricks() {
  for (let c = 0; c < brickColumnCount; c++) {
    for (let 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` のブロックをキャンバス上に描画しています。問題はそれら全てを 1 箇所、座標 `(0,0)` に描画していることです。それぞれのブロックの `x` 座標と `y` 座標を導出する計算を一回一回のループに含める必要があります。


```js
const brickX = c \* (brickWidth + brickPadding) + brickOffsetLeft;
const brickY = r \* (brickHeight + brickPadding) + brickOffsetTop;
```


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

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


```js
function drawBricks() {
  for (let c = 0; c < brickColumnCount; c++) {
    for (let r = 0; r < brickRowCount; r++) {
      const brickX = c \* (brickWidth + brickPadding) + brickOffsetLeft;
      const 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()` 関数のどこかに追加して、このレッスンの仕上げとしましょう。最初のあたりの、キャンバスを消去する部分とボールを描画する部分の間あたりが良いでしょう。 `drawBall()` の呼び出しのすぐ前に次の行を追加してください。


```js
drawBricks();
```

自分のコードと比べる
----------

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

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

次のステップ
------

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

* « 前のページ
* 次のページ »
asm.js
======

**非推奨:** この機能は非推奨になりました。まだ対応しているブラウザーがあるかもしれませんが、すでに関連するウェブ標準から削除されているか、削除の手続き中であるか、互換性のためだけに残されている可能性があります。使用を避け、できれば既存のコードは更新してください。このページの下部にある互換性一覧表を見て判断してください。この機能は突然動作しなくなる可能性があることに注意してください。

asm.js は 高度に最適化可能な JavaScript のサブセットを規定する仕様です。この文書では、asm.js で可能なこと、利点、利用方法、そして関連する情報と使用例を解説します。

asm.js とは
---------

極めて小さく、厳密な JavaScript のサブセットです。while や if、数値型、トップレベルの名前付き関数といくつかの単純な生成物のみ利用可能です。オブジェクト、文字列、クロージャや、ヒープを必要とするものは利用できません。asm.js のコードは多くの点で C のそれと類似していますが、全ての JavaScript エンジンで動作します。JavaScript エンジンの最適化を助ける一方、Emscripten のようなコンパイラーが出力するべきコードを明確に規定しています。asm.js のコードと、それがどのように動作するのか、そしてどのように利用できるかを解説します。

JavaScript のサブセットは Just-In-Time (JIT) コンパイラーを持つ多くのエンジンで高度に最適化されています。しかし、明確な標準を定めることによって、この種のコードの最適化により取り組むことができ、また驚くほどの高速化が可能となります。議論と測定が容易になるため、複数の JS エンジンの間での協力がより簡単になります。この種のコードは全てのエンジンで高速に動作するべきで、そうでないのはバグであるべきです。そのためのエンジンが最適化するべき仕様となっています。

標準は Web 向けにハイパフォーマンスなコードを出力したいと考えるコンパイラー製作者たちも助けます。asm.js の仕様を参考にでき、asm.js に忠実であれば高速に動作するということがわかるからです。C/C++ を JavaScript へコンパイルする Emscripten は asm.js を出力し、そのコードはいくつかのブラウザでネイティブと同等の速度で動作します。

またエンジンが asm.js のコードを識別べきする場合、さらなる最適化を行えます。現在のところ、それが可能なブラウザは Firefox のみとなっています。

asm.js 言語のまとめ
-------------

asm.js は中間言語です。厳密に型づけされた整数および浮動小数点演算、関数呼び出しとヒープ領域へのアクセスのみが許されるため、パフォーマンスレートの予測が極めて容易です。通常の JavaScript と比べ、そのパフォーマンス特性はネイティブコードに近くなっています。主要なブラウザは既に asm.js をサポートしています。asm.js はブラウザ内で動作するため、ブラウザとハードウェアに大きく依存します。
WebRTC データチャネル
==============

WebRTC (Web Real-Time Communications、ウェブリアルタイム通信) API は、主に音声や動画の通信に対応していることで知られていますが、ピアツーピアのデータチャネルも提供されています。この記事では、このことについて詳しく説明し、ゲームにデータチャンネルを搭載するためにライブラリーを使用する方法を紹介します。

データチャネルとは?
----------

WebRTC データチャネルを使用すると、ピアとのアクティブな接続を介してテキストまたはバイナリーデータを送信することができます。ゲームのコンテキストでは、プレイヤーはテキストチャットやゲームのステータス情報など、互いにデータを送信できます。データチャネルには 2 種類のタイプがあります。

**信頼性の高いチャンネル (Reliable channels)** は、送信したメッセージが相手ピアに、送信したのと同じ順序で到着することを保証します。これは TCP ソケットに類似しています。

**信頼性のないチャンネル (Unreliable channels)** は、そのような保証はありません。これは UDP ソケットに類似しています。

私たちの文書化には WebRTC を使用するためのドキュメントがあります。しかし、この記事では、この作業を些細なものにするのに役立ついくつかのライブラリーを利用し、ブラウザ間の実装の違いを回避するために抽象化を使用する方法を説明します。もちろん、このような差異が時間の経過とともに消えていくことを期待しています。

p2p ライブラリーを使用する
---------------

使用できるライブラリーの一つにp2pライブラリーがあります。このライブラリーは、ピア接続を作成し、ストリームとデータチャネルを設定するための簡単なAPIを提供しています。また、ブローカーサーバーコンポーネントとホスティングブローカーもあり、自分で設定する代わりに使用することができます。

**メモ:** 近々、ここにコンテンツを追加していく予定です。

原典情報
----

* 著者: Alan Kligman
* 原典: WebRTC Data Channels for Great Multiplayer
* その他の貢献者: Robert Nyman
* 著作権情報: Alan Kligman, 2013
asm.js の非同期スクリプト
================

全ての中～大規模ゲームでは、コンパイル処理を最適化してブラウザーを最大限柔軟にする、非同期スクリプトとして asm.js コードをコンパイルします。 Gecko では、非同期コンパイルによって、ゲームの読み込み時に JavaScript エンジンがメインスレッド外で asm.js をコンパイルし、生成した機械語コードをキャッシュして、それ以降の読み込み時にコンパイル不要となります（Firefox 28から）。違いを見るには、`about:config` で `javascript.options.parallel_parsing` を反転させてください。

非同期を動作させる
---------

非同期のコンパイルは簡単です。 JavaScript を書く時に、単に `async` 属性を使います。


```html
<script async src="file.js"></script>
```


あるいは、スクリプトで同じことを行います。


```js
const script = document.createElement("script");
script.src = "file.js";
document.body.appendChild(script);
```


（スクリプトによって生成されるスクリプトは既定で非同期です。）既定の HTML シェル Emscripten は、後者を生成します。

非同期とそうでない時?
-----------

スクリプトが非同期で *ない* 、よく似た状況 (仕様に定義されている通り) では次の通りです。


```html
<script async>
 code;
</script>
```


および


```js
const script = document.createElement("script");
script.textContent = "code";
document.body.appendChild(script);
```


両方とも「インライン」スクリプトと考えられ、コンパイルされて、すぐに実行されます。

コードが JS 文字列内にあった場合はどうでしょう? `eval` や `innerHTML`（両方とも同期コンパイルを起動します）を使う代わりに、 オブジェクトURLと一緒の Blob を使います。


```js
const blob = new Blob([codeString]);
const script = document.createElement("script");
const url = URL.createObjectURL(blob);
script.onload = script.onerror = () => URL.revokeObjectURL(url);
script.src = url;
document.body.appendChild(script);
```


`innerHTML` ではなく `src`　をセットすると、スクリプトが非同期になります。