【初心者向け】第三回 メモ帳だけでゲーム作ってみた〈ブロック崩し編〉

2020年8月30日

今回もメモ帳だけで、HTMLとJavaScriptを用いてブロック崩しというゲームを作っていきたいと思います!

今回から少し難しくなってくるかもしれませんが、軽く理解できたら大丈夫です!

第一回及び第二回をまだ読んでいない方はそちらを先に読んでください!


今回作るもの

  1. 準備編
  2. ボールを作ろう! ←前回
  3. 動くバーを作ろう! ←今回
  4. ブロックを作ろう!
  5. 完成させよう!

第一回は準備をして、第二回にはボールを作りました!

そして今回は、操作ができるバーを作っていきたいと思います。

完成イメージは以下の画像の通りです。

下のバーの部分ですね。
これをキーボードの矢印キーを使って操作できるようにしたいと思います!


今回必要になる知識

今回もコードを書いていくうえで必要になってくる、プログラミングの知識があります。

それが、関数です!
関数について詳しくまとめた記事があるので、下のリンクを参照してください!

【誰でもわかる!】関数とは

プログラミングを勉強していく中で、関数とは非常に便利な存在です! 完全に理解して使いこなせるようになるまでは、少し時間がかかるかもしれませんが、使いこなせるとプログラムがきれいになるなど様々なメリットがあるため、ぜひマス […]


コードを書いていこう!

変数を作る

まず初めに、今回、動くバーを作っていく際に必要になる変数を作っていきましょう。


let ball_speed_y = 5;

let bar_x = 0;
let bar_y = 700;
let bar_width = 100;
let bar_height = 10;
let bar_speed = 10;

let left_pressed = false;
let right_pressed = false;

バー(= bar)の場所や、バーの横幅(width)や縦の幅(height)、スピード(speed)を設定しました。

そした下の二行には「false」という新しいものが出てきました。

「false」という単語の対義語に、「true」というものがあります。
「true」と「false」というのは、スイッチの「on」と「off」と同じで、切り替えることができます。

今回は、「true」と「false」をここでしか使わないので、「true」というのはキーが押されている状態で、「false」というのはキーが押されていない状態である、と考えていただいて大丈夫です。

そのため、left_pressedが「false」の時は、左が押されていないので左に動かさず、「true」の時は、左が押されているのでバーを左に動かす、といったコードを書けばいいですね。
そして、right_pressedの時も同様です!


関数を使ってきれいにする

前回には関数というのをまだ知らない状態で作ったコードなので、非常に見にくくなっています。なのでこの回で見やすく書き直してみましょう!

ここからはコードが非常に長くなってしまうので、コードの例の表示が少し変わりますが、ご了承ください。

…
let right_pressed = false;

setInterval(function(){
  eraseCanvas();
  drawBall();
},30);

function eraseCanvas() {
  CONTEXT.clearRect(0, 0, canvas_width, canvas_height);
}

function drawBall() {

  if ( canvas_width - ball_r < ball_x + ball_speed_x) {
    ball_speed_x = - ball_speed_x;
  }

  if ( canvas_height - ball_r < ball_y + ball_speed_y) {
    ball_speed_y = - ball_speed_y;
  }

  if ( 0 + ball_r > ball_x + ball_speed_x){
    ball_speed_x = - ball_speed_x;
  }

  if ( 0 + ball_r > ball_y + ball_speed_y){
    ball_speed_y = - ball_speed_y;
  }

  ball_x = ball_x + ball_speed_x;
  ball_y = ball_y + ball_speed_y;

  CONTEXT.beginPath();
  CONTEXT.arc(ball_x, ball_y, ball_r, 0, 2 * Math.PI);
  CONTEXT.fill();
}

</script>

上のように、関数で画面を消す作業(=eraseCanvas)と、ボールを表示する作業(=drawBall)を見やすくまとめてみました。
こうすることによって、今からバーを表示するコードを書くときに、ごちゃごちゃにならず見やすくなります!

また、これで実行してみても全く同じ動作になるはずです!

キー入力を検知させる

ここからは、今書いているコードに、キーボードの右矢印と左矢印キーが押されているか押されていないか、わかるようにしていきます!

変数をたくさん書いた行の下に以下のコードを書いて見ましょう!

…
let right_pressed = false;

document.addEventListener("keydown", keyDown, false);
document.addEventListener("keyup", keyUp, false);

function keyDown(e) {
  if (e.code == "ArrowRight") {
    right_pressed = true;
  }
  if (e.code == "ArrowLeft") {
    left_pressed = true;
  }
}

function keyUp(e) {
  if (e.code == "ArrowRight") {
    right_pressed = false;
  }
  if (e.code == "ArrowLeft") {
    left_pressed = false;
  }
}

setInterval( function() {
…

今回書くコードで一番理解が難しい場所がここなので、深くは理解する必要はありませんが、どういう意味なのかということだけ簡単に説明します!

まず、document.addEventListener(~)というのは、キーが押されたことや離されたことを検知してくれるものです。

そしてキーが押されたと検知されたら、keyDown(e)という関数が動き、もし押されたキーがArrowRight、つまりキーボードの右矢印キーだったら、right_pressed = true; にする、つまり、right_pressedを「true」にしてバーを右側に動かす処理をさせる、といった流れになります。

キーが離されたと検知したら、keyUp(e)という関数が処理され、もしその話されたキーが右矢印キーがったら、バーを右に動かす処理をやめさせるといった感じです。


バーを表示させる

一つ前の「キーの入力を検知する」の部分は少し理解しずらいものだったかもしれませんが、ここからは前回ボールを表示させた要領とほとんど同じなので、そこまで難しくありません。

まずは、setIntervalの中に、バーを表示させる処理を書きましょう!

setInterval(function(){
  eraseCanvas();
  drawBar();
  drawBall();
},30);

そして次に、drawBar()という関数を書きましょう!

…
function eraseCanvas() {
  CONTEXT.clearRect(0, 0, canvas_width, canvas_height);
}

function drawBar() {
  CONTEXT.fillRect(bar_x, bar_y, bar_width, bar_height);
}

function drawBall() {
…

fillRectというのは、四角形を描かせるといったもので、(bar_x, bar_y)という座標に四角形を書かせる処理を書きました!

これで実行してみると、細長い四角形が下の方に表示されているはずです!

後は、キーボードが押されているときに、左右に動かす、つまり、bar_xの数字を増やしたり減らしたりすればOKですね!

function drawBar() {

  if (right_pressed == true) {
      bar_x = bar_x + bar_speed;
  }

  if (left_pressed == true) {
    bar_x = bar_x - bar_speed;
  }

  CONTEXT.fillRect(bar_x, bar_y, bar_width, bar_height);
}

右キーが押されているときは、バーのx座標を増やして、左キーが押されているときは、バーのx座標を減らせばいいですね!


バーに当たったらボールを跳ね返らさせる

ほとんど完成しましたが、このままではバーとボールが当たったときに跳ね返るように設定していませんね!

跳ね返る処理は第二回で書いた処理に似ているので分かりやすいかもしれません!

まず、バーができたことによって、下の壁に跳ね返らさせる必要はなくなったので、消しましょう!
どれが下の壁に跳ね返る処理かわかりますか?

function drawBall() {

  if ( canvas_width - ball_r < ball_x + ball_speed_x) {
    ball_speed_x = - ball_speed_x;
  }

  if ( 0 + ball_r > ball_x + ball_speed_x){
    ball_speed_x = - ball_speed_x;
  }

  if ( 0 + ball_r > ball_y + ball_speed_y){
    ball_speed_y = - ball_speed_y;
  }

  ball_x = ball_x + ball_speed_x;
  ball_y = ball_y + ball_speed_y;

  CONTEXT.beginPath();
  CONTEXT.arc(ball_x, ball_y, ball_r, 0, 2 * Math.PI);
  CONTEXT.fill();
}

上から二つ目の、if文ですね!

ここからはボールとバーが当たっているか、つまり当たり判定を考えるわけなんですが、これが少し難しいので、まずはx座標だけで、どのような時が当たっているか考えてみましょう!

バーの左端から右端までに、ball_xが入っていればいいですね!

つまり、ball_x >= bar_x かつ ball_x <= bar_x + bar_width の時になります。

かつというのは、JavaScriptでは「&&」を使うので、

if (ball_x >= bar_x && ball_x <= bar_x + bar_width) {

}

となります!

次にy座標だけを考えてみましょう!

バーに重なったときなので、バーの一番上にからバーの一番下までに、ball_y + ball_rが入っていればいいですね!

こちらも、「&&」と用いて、

if ( ball_y + ball_r >= bar_y && ball_y + ball_r <= bar_y + bar_height){

}

これで、xとyの両方でif文ができましたね!

後はこれらを組み合わせて、跳ね返らさせましょう!

function drawBall() {

  if ( canvas_width - ball_r < ball_x + ball_speed_x) {
    ball_speed_x = - ball_speed_x;
  }

  if (ball_x >= bar_x && ball_x <= bar_x + bar_width) {
    if (ball_y + ball_r >= bar_y && ball_y + ball_r <= bar_y + bar_height) {
      ball_speed_y = - ball_speed_y;
    }
  }

  if ( 0 + ball_r > ball_x + ball_speed_x){
    ball_speed_x = - ball_speed_x;
  }

  if ( 0 + ball_r > ball_y + ball_speed_y){
    ball_speed_y = - ball_speed_y;
  }

  ball_x = ball_x + ball_speed_x;
  ball_y = ball_y + ball_speed_y;

  CONTEXT.beginPath();
  CONTEXT.arc(ball_x, ball_y, ball_r, 0, 2 * Math.PI);
  CONTEXT.fill();
}

これでバーにボールが当たれば跳ね返るコードが完成しました!


ということで第三回はここまでにしたいと思います。

もしうまくいかなかったら自分が書いたコードを見直しましょう!
タイプミスがあるかもしれません!
それでもうまくいかなければ、ここに直接コメントするか、Twitterの方にお願いします!

今回は少し長かったですが、少しずつ理解していきましょう!

次回は、ボールが当たったら崩れるブロックを作っていきたいと思います!

最後まで読んでいただきありがとうございます!

第四回はこちらから!