
純粋な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(またはそれ以上)のライセンスのもとで公開されています。