B L O G

ブログ記事

thumbnail

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

やりたいこと

フレームワークやライブラリを使わず、純粋な javascript のみでブロック崩しを作る。
今回は第 4 回目となり、ユーザーが操作できるパドルを追加するところまでやっていきましょう! 前回はボールが移動する処理まで作成しました ↓

現状ではボールが跳ね返っているのを眺めることしかできず、ゲームとしては面白くありませんね!
操作するパドルを追加してあげることで、ゲーム性が格段にあがると思います。
ではさっそくやっていきましょう!

環境

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

パドルの追加

パドルを追加するには、まずはパドルの位置や大きさを定義してあげる必要があります。

他の変数が定義されてる箇所の近くに、下記のコードを追加してみてください!


// パドルの設定
const paddleHeight = 10;
const paddleWidth = 75;
let paddleX = (canvas.width - paddleWidth) / 2;

最初の 2 行でパドルの高さと幅を定義してます。

paddleX = (canvas.width - paddleWidth) / 2;は X 軸上のパドルの座標を定義してます。

cavans.width で定義していた Canvas の幅(今回は 300px)を表し、それを paddleWidth 分引いてあげたものを、2 で割っています。

paddleWidth 分引いてあげる必要があるのは、四角形の時の座標の始まりは中心では無く、左上の点から始まるからです。
仮に canvas.width - paddleWidth / 2;とした場合は Canvas の中心からちょうど paddleWidth 分右にズレた図形になるかと思います。

次のコードではこれらを用いてさらなる計算が行われます。パドルを画面上に表示する関数を作成しましょう。 drawBall() のすぐ下に次の関数を追加してください。


// パドルを描く関数
function drawPaddle() {
ctx.beginPath();
ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}

純粋な Javascript でのブロック崩しの作り方 ① でも説明したことを思いだしてみてください。
四角形の定義は rect()メソッドで左から順に X 座標、Y 座標、横幅、高さを指定できるのでしたね。

これを先程宣言した変数に置き換えてあげてるだけです。

canvas.height - paddleHeight としてるのは、先程の四角形の時の座標は左上の点から始まることを思い返せば思い返せばすぐに意味が理解できますね!
canvas.height のみだとちょうどパドルが見えない位置に描画されてしまいます。

関数は定義しただけでは使えないので、drawball()と同じように、draw()関数の中で drawPaddle();を読んであげる必要があります。


drawPaddle();

そうすると、下記のようにパドルが描画されたかと思います。

ブロック崩しのパドル実装

パドルの操作

現状ではだだ四角形を描画したにすぎません。
キーボードを操作を実装してパドルとして操作できるようにしていきましょう。
その為には下記のよう機能が必要です。

  • 左ボタンが押されているか、右ボタンが押されているかという情報を保存する 2 つの変数。

  • ボタンを押してる時とボタンを離した時に指定の関数を発火させる仕組み。

  • ボタンを押してる時とボタンを離した時に実行される関数

  • パドルを左右に動かす機能

一つ一つやっていきましょう。

ボタンが押されているかという情報を保存する 2 つの変数

ボタンが押されているかどうかは論理値(true or false)で判断できます。 他の変数の近くに下記のコードを追加してみてください。


// ボタンが押されてるか確認する変数
let rightPressed = false;
let leftPressed = false;

初期値は false(ボタンを押してない)にしてあげてます。 流れとしては、ボタンが押された時に false から true にしてあげて、条件分岐で true の場合にパドルを動かすような感じです。

これで 1 つ目のボタンが押されているかという情報を保存する 2 つの変数を定義することは終わりました。

ボタンを押してる時と離した時に指定の関数を発火させる仕組み

ボタンを押してる時と離した時に指定の関数を発火させる仕組みは document.addEventListener という、Javascript の機能を使うことで、簡単に実現できます。

下記のようなコードをコード内の一番下に追加してみてください


// ボタンが押された時
document.addEventListener("keydown", keyDownHandler);
// ボタンが離れた時
document.addEventListener("keyup", keyUpHandler);

document というのはページ全体を表し、ここに対してイベントリスナーを設定することで、ページ全体でキー入力を監視できるようにしています。

addEventListener は、特定のイベントが起こった時に他の関数を呼び出すことができる仕組みで、引数は左から順に、イベントタイプ、呼び出す関数の順番で値を定義できる。

keydown イベント(ボタンを押してる時)が発生した時に keyDownHandler という関数を呼び、
keyup イベント(ボタンを離した時)が発生した時に keyUpHandler という関数を呼んであげてます。

これで 2 つ目のボタンを押してる時とボタンを離した時に指定の関数を発火させる仕組みは完成しましたが、keyDownHandler、keyUpHandler を作ってないので、現時点で何も起こりません。 なので、それぞれの関数を追加していきましょう。

ボタンを押してる時とボタンを離した時に実行される関数

次のコードを先程のイベントリスナーの下に追加してみてください。


// ボタンが押された時の処理
function keyDownHandler(e) {
if (e.key === "ArrowRight") {
rightPressed = true;
} else if (e.key === "ArrowLeft") {
leftPressed = true;
}
}

// ボタンが離れた時の処理
function keyUpHandler(e) {
if (e.key === "ArrowRight") {
rightPressed = false;
} else if (e.key === "ArrowLeft") {
leftPressed = false;
}
}

(e)で引数としてイベントの情報を渡しています。
そしてその e をe.keyとすることで、なんと押されたキーボードのボタンが分かってしまいます。

keyDownHandler の if (e.key === “ArrowRight”)で、押されてたキーボードが右なら先程定義した rightPressed を true に変えてあげます。 左も同様です。

そして、keyUpHandler でそれぞれのボタンが離れた時に false に戻してあげています。
これにより、それぞれに対応したボタンが押されている間だけ、条件を true にすることができます。

これで 3 つ目のボタンを押してる時とボタンを離した時に実行される関数を定義することができました。
ここまでこれば、あとは true の場合にパドルを移動させる処理を追加するだけです!

パドルを左右に動かす機能

ここまで書いたコードを利用して、パドルを移動させます。 draw()関数の中で下記のようなコードを追加してみてください。


// パドルの移動処理
if (rightPressed) {
paddleX += 7;
} else if (leftPressed) {
paddleX -= 7;
}

条件で rightPressed だけ入れると、この値が true の場合のみ実行されます。
そして、処理の内容を paddleX += 7;としています。
これにより、ボタンが押されている間はパドルが毎フレームプラスされます。

これで 4 つ目のパドルを左右に動かす機能は完成しました!
実際にブラウザで動作を見てみてください。

ブロック崩しのパドル実装

上記のように、無事パドルを動かすことに成功たかと思います。
ですが、パドルが画面外も移動できてしまうことに気づいたかと思います。

これを修正していきましょう

パドルが画面外に行くのを修正

先程のコードをこのように修正してみてください


// パドルの移動処理
if (rightPressed) {
paddleX = Math.min(paddleX + 7, canvas.width - paddleWidth); //最も小さい値を取る
} else if (leftPressed) {
paddleX = Math.max(paddleX - 7, 0); //最も大きい値を取る
}

下記のように、Canvas 外に出ることは無くなったかと思います。

ブロック崩しのパドル実装

Math.min は()の中指定した値の中で最も小さい値を返してくれるという機能を持ってます。
これを利用して、Cnavas 外に出ることを防ぐことができます。

()の中は paddleX + 7 と、 canvas.width - paddleWidth という値の 2 つがあると思います。

Canvas 内にパドルがある時は paddleX + 7 の値を続け、パドルの座標が canvas.width - paddleWidth より高くなる時は、
ボタンを押しても常に canvas.width - paddleWidth の値を取るつづけるというわけです。

Math.max はその逆で、()の中指定した値の中で最も大きい値を返してくれるという機能を持ってます。 これを利用して、Cavans 外に出そうになったら常に 0 の座標を取ってあげています。

今回は以上です。お疲れ様でした!
次回はゲームオーバーの機能を追加する予定です。

参考

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

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

関連する記事