B L O G

ブログ記事

thumbnail

純粋なJavascriptでのブロック崩しの作り方③

やりたいこと

フレームワークやライブラリを使わず、純粋な javascript のみでブロック崩しを作る。
今回は第 3 回目となり、ボールを壁で跳ね返させる処理を作っていきます!

前回はボールが移動する処理まで作成しました ↓

ゲーム制作においては欠かせない、衝突判定について簡単に学べるかと思います。
ではさっそくやっていきましょう!

環境

  • Google Chrome : Version: 130.0.6723.92
  • VSCode : Version : 1.90.2 (Universal)

ボールの半径の変数を定義

まずは前回書いたボールを描く drawBall()関数の中のボールを定義してる箇所を思い出して見てください。


ctx.arc(x, y, 10, 0, Math.PI \* 2);

現在はボールの半径を 10 としてるかと思います。
ボールの半径は、当たり判定の時に必要になってくるので、変数として定義しておくと便利です。

下記のコードを、ボールの座標を定義してる箇所の下にでも追加してください!


// ボールの半径
const ballRadius = 10;

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


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

上下の壁でボールを跳ね返す処理

ボールを跳ね返す壁は全部で上下左右の 4 つありますが、まずは上下だけに注目しましょう。

ボールが壁に触れてるかの条件

ボールを跳ね返す為には、毎フレーム、ボールが上下に触れているかどうかを確認する必要があります。

それは下記のような if 文で確認できます。


if (y + dy < 0) {

}

y というのはボールの現在の座標を表し、dy はボールの移動量を表してるんでしたね!

そしてY 座標の 0 は Canvas の上端のことです。

つまり、ボールの座標と移動量を足したものが 0 未満(マイナス)だったらという条件式です。

if(y < 0)では無く、if(y + dy < 0)にしてる理由は、 次に dy を足したときに、ボールが画面の上端を超えるかどうかを判定してるからです。
こうすることで、ボールが Canvas 外に出る前にこの処理を行うことができます。

これでボールが壁に触れているかの条件式が完成しました。

ボールを跳ね返す処理

次に壁に当たった時に処理の中身に、跳ね返す処理を書いていきましょう。
これはとても簡単です。

次のようにコードを足してみてください。


if (y + dy < 0) {
dy = -dy; //向きを反転
}

そして、x の移動量を 0 にしてみてください。


// 移動量
let dx = 0;

そうすると、下記のように無事にボールが上端で跳ね返ったと思います。

ブロック崩しのボールの跳ね返る処理

dy = -dy; の部分は符号反転させた値を設定することで、Y 軸方向の動きの向きを変えます。

続いて、下端でもボールが跳ね返らせてみましょう。
先程の上端を跳ね返す処理の下にこのコードを追加してみてください。


if (y + dy > canvas.height) {
dy = -dy; //向きを反転
}

canvas.height は最初に設定した canvas の高さ、(今回は 300px)を表します。 Canvas の高さ = 下端なので、y + dy > canvas.height は次に dy を足したときに、ボールが画面の下端を超えるかどうかを判定できます。
そして先程同様、dy = -dy;で向きを反転をする処理を追加してます。

これだけでも機能面は完成してますが、コードの冗長さを減らす為、下記のようにコードをまとめることができます。
上端と下端のコードを削除し、このように書き換えてみてください。


// 垂直方向の反転
if (y + dy > canvas.height || y + dy < 0) {
dy = -dy;
}

下記のように、上端と下端でボールが反転するようになったと思います。

ブロック崩しのボールの跳ね返る処理

||で上端と下端の条件をコードを繋げてあげることで、どちらかが true の場合、dy = -dy;が実行されてボールが反転するようになります。

左右の壁でボールを跳ね返す処理

無事、上下の壁でボールを跳ね返すことが出来たので、左右でボールを跳ね返す処理を作っていきましょう!
左右の処理は上下の処理にとても似ていて、簡単です。

垂直方向の反転処理の上に次のように追加してみてください。


// 水平方向の反転
if (x + dx > canvas.width || x + dx < 0) {
dx = -dx;
}

お気づきでしょうか?
垂直方向の処理の y を x をに変えて、canvas.height を width に変えてるだけです。
これだけで、水平方向の反転処理を追加できてしまいます!

そして、0 に設定していた dx の値を 2 に戻してみてください


// 移動量
let dx = 2;

そうすると、下記のようにボールが上下左右の壁で跳ね返ったと思います。

ブロック崩しのボールの跳ね返る処理

壁にボールが隠れるのを修正

四辺での跳ね返す処理は完成しましたが、よく見るとボールがめり込んでるのが確認できるかと思います。
これを修正していきましょう!

ブロック崩しのボールの跳ね返る処理

何故このようにめり込んでしまうのかと言いますと、ボールの当たり判定が中心にあるためです。
つまり現時点ではボールのちょうど半径分、壁にのめり込んでしまいます。

これを修正するには、初めに定義していた ballRadius 値を使用して、半径分当たり判定を含めてあげます。

先程のボールを反転させる処理をこのように修正してあげてみてください。


// 水平方向の反転
if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
dx = -dx;
}

// 垂直方向の反転
if (y + dy > canvas.height - ballRadius || y + dy < ballRadius) {
dy = -dy;
}

先程のコードに半径を辺の長さから引き、もう一方では足すことで衝突検出が正しく行われます。

ブロック崩しのボールの跳ね返る処理の修正

上記のようにボールがめり込むのを修正され、自然な感じになったかと思います。

今回は以上です。お疲れ様でした!
次回はパドルとキーボード操作について書いていきたいと思います。

参考

出典: Mozilla Contributors. “純粋な JavaScript を使ったブロック崩しゲーム”. MDN Web Docs.

この内容は、Creative Commons Attribution-ShareAlike (CC-BY-SA) 2.5(またはそれ以上)のライセンスのもとで公開されています。

関連する記事