/
純粋なJavascriptでのブロック崩しの作り方⑥
やりたいこと
フレームワークやライブラリを使わず、純粋なjavascriptのみでブロック崩しを作る。
今回は第6回目となり、ブロックを描画させるとこまでやっていきます。
前回はゲームオーバーを実装するところまでやりました↓
ブロック崩しにはかかせない、ブロックの描画処理を配列を使用して描画していきます。
ではさっそくやっていきましょう!
環境
- Google Chrome : Version: 130.0.6723.92
- VSCode : Version : 1.90.2 (Universal)
ブロック変数を定義する
まずはブロックを描画するのに必要な変数を定義指定していきます。 他の変数が宣言されている箇所の近くに下記のようなコードを追加してみてください。
// ブロック変数の定義
const blockRowCount = 3; // ブロックの行数(3行)
const blockColumnCount = 5; // ブロックの列数(5列)
const blockWidth = 50; // ブロックの幅(75ピクセル)
const blockHeight = 20; // ブロックの高さ(20ピクセル)
const blockPadding = 5; // ブロック同士の間隔(10ピクセル)
const blockOffsetTop = 15; // 上からのオフセット(30ピクセル)
const blockOffsetLeft = 15; // 左からのオフセット(30ピクセル)
まずbrickRowCountとbrickColumnCountで行と列を定義してあげます。
3 × 5 = 15個のブロックを描画予定です。
blockWidthとblockHeightで幅と高さ、blockPaddingでブロック同士の間隔を定義しています。
blockOffsetTopとblockOffsetLeft初期値からのはオフセットの値です。
次に、15個のブロック全てを二次元配列で取得していきます。
下記のコードを先程の変数の下に追加してみてください。
// ブロックの格納するための配列
const blocks = []; // 空の配列を定義
for (let c = 0; c < blockColumnCount; c++) {
blocks[c] = []; // 空の配列を代入
for (let r = 0; r < blockRowCount; r++) {
blocks[c][r] = { x: 0, y: 0 }; // それぞれの座標を0, 0に定義
}
}
まず、const blocks = []; で空の配列を定義します。 その後、for文でブロックを取得します。
一度空の配列を指定する必要がある理由は、いきなりblocks[c][r] = { x: 0, y: 0 };を定義しようとすると、エラーになります。
JavaScriptでは、配列に新しい要素を追加する際、その要素が既に存在していることを前提としていないからです。
次にfor (let c = 0; c < blockColumnCount; c++)の部分に注目します。
let c = 0で変数を定義し、cがblockColumnCount(5)以上になるまで、繰り返します。
5以上になったら処理を停止するので、0 ~ 4回でしっかり5回処理が繰り返されてるのが分かるかと思います。
そして、blocks[c] = [];で空の配列をそれぞれに代入してあげます。
これも先程同様、blocks[c]が定義されてない状態で、blocks[c][r] = { x: 0, y: 0 };を定義すると、エラーになるからです。
次に先程の列のfor文と同じで、for (let r = 0; r < blockRowCount; r++)で新しいrという変数を定義し、blockRowCount(3)以上になるまで処理を繰り返します。
ちなみにcとrという変数はrow(行)とcolum(列)の略です。
そして、blocks[c][r] = { x: 0, y: 0 }; で全てのブロックを座標0,0に設定しています。
現時点では、全てのブロックがCanvasの左上に重なってる感じです。
試しに下記のようにコンソールログを追加して、15個のブロックのデータが取得できているか確認してみます。
for (let r = 0; r < blockRowCount; r++) {
blocks[c][r] = { x: 0, y: 0 }; // それぞれの座標を0, 0に定義
console.log(blocks[c][r]);
}
すると、以下のように15個のx,yの座標を持つオブジェクトが15個取得できてると思います。
ブロックを描画
実際にブロックを描画する関数をdrowPaddle関数の下に、下記のように追加してみてください。
// ブロックを描く関数
function drawBlocks() {
for (let c = 0; c < blockColumnCount; c++) {
for (let r = 0; r < blockRowCount; r++) {
blocks[c][r].x = 0;
blocks[c][r].y = 0;
ctx.beginPath();
ctx.rect(0, 0, blockWidth, blockHeight);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
}
}
この関数をdraw関数の中でdrawBlocks();のように呼んであげてください。
そうすると、下記のようにブロックが描画されたかと思います。
現段階では、ctx.rect(0, 0, blockWidth, blockHeight);で、座標を0,0からの描画に設定しているので、全てのブロックが左上に描画されてしまっています。
これを解決するには、blocks[c][r]で各ブロックにアクセスできるのを利用し、計算によりそれぞれの座標を求めて、描画することができます。
// ブロックを描く関数
function drawBlocks() {
for (let c = 0; c < blockColumnCount; c++) {
for (let r = 0; r < blockRowCount; r++) {
// ブロックの座標を計算
const blockX = c * (blockWidth + blockPadding) + blockOffsetLeft;
const blockY = r * (blockHeight + blockPadding) + blockOffsetTop;
// ブロックの座標を代入
blocks[c][r].x = blockX;
blocks[c][r].y = blockY;
ctx.beginPath();
ctx.rect(blockX, blockY, blockWidth, blockHeight);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
}
}
下記のようにdrawBlocksを修正してみてください。
次のように、ブロックが描画することに成功したかと思います。
まず、const blockX = c * (blockWidth + blockPadding) + blockOffsetLeft;という部分に注目します。
新しくblockXという定数を定義し、計算したブロックのX座標を代入しています。
c * (blockWidth + blockPadding)により、余白分空けた分の各列のX座標を計算し、最後にblockOffsetLeftにより、初期値からのオフセットの値を足してあげてます。
例えばcが0の場合はc * (blockWidth + blockPadding)でこの値は0になり、blockOffsetLeftの値が一番初めのブロックのX座標になることが分かります。
後はbricks[c][r].x = blockX;で、計算したX座標(blockX)を各ブロックに合うブロック番号に代入し、 ctx.rect(blockX, blockY, blockWidth, blockkHeight);で使ってあげます。
Y座標も同様の考え方でblockYとして各Y座標を定義してます。
今回は以上です。お疲れ様でした!
次回はブロックの衝突判定を追加予定です。
参考
出典: Mozilla Contributors. “純粋なJavaScriptを使ったブロック崩しゲーム”. MDN Web Docs.
この内容は、Creative Commons Attribution-ShareAlike (CC-BY-SA) 2.5(またはそれ以上)のライセンスのもとで公開されています。