【初心者向け】第四回 メモ帳だけでゲーム作ってみた〈神経衰弱編〉

今回も、パソコンにある「メモ帳」を使って、「神経衰弱」を作っていきたいと思います!

前回の記事をまだ読んでいない方は、ぜひそちらを先に読んでください!


今回作るもの

前回は、トランプの柄と数字を表示し、カードを52枚にしましたね!

  1. 準備編
  2. カードの枠を表示させよう!
  3. カードの数字を表示させよう! ←前回
  4. キー入力で動かせるようにしよう! ←今回
  5. キー入力でカードをひっくり返すようにしよう!
  6. 乱数を使ってカードを並べ替えよう!

そして今回は、キーボード入力で動かせるポインターを作っていきたいと思います!

今回の完成イメージは以下の通りです!

違いが分かりずらいですが、♧2の枠が太くなっているのが分かりますね!

矢印キーでこの枠(ポインター)を操作できるようにします!


今回必要になる知識

今回もコードを書いていく上で、必要になってくる知識が、2つあります!

まず1つ目が、関数です!

関数については、下記の記事で詳しくまとめたので、ぜひ参考にしてください!

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

プログラミングを勉強していく中で、関数とは非常に便利な存在です! 完全に理解して使いこなせるようになるまでは、…

そして、2つ目が条件分岐です!

条件分岐についても、下記の記事で詳しくまとめたので、参考にしてください!


コードを書いていこう!

では、ここからは前回と同様にメモ帳に、ポインターを動かすためのコードを書いていきましょう!

今回は、関数を条件分岐をうまく使いコードを組んでいくので、関数と条件分岐がいまいちわかっていないという方にとっては、少し難しく感じるかもしれません。

ですが、深く考えずに、大体わかったら次に進もうといった感じで進めていきましょう!


関数を使ってまとめる

前回は、繰り返しを使ってコードをうまくまとめ、短くしました!

そして、今回はまず初めに、
先ほどご紹介した「関数」を使って見やすくしていきたいと思います!

まずは、前回作ったトランプを表示させるコードを「drawCard」という関数にしましょう!

function drawCard() {
    CONTEXT.font = "40px 'MS ゴシック'";
    CONTEXT.textAlign = "center";

    CONTEXT.beginPath();

    for (let j = 0; j < 4; j++) {
      for (let i = 0; i < 13; i++) {
        CONTEXT.rect(70 + 100 * i, 60 + 100 * j, card_width, card_height);
        CONTEXT.stroke();
        CONTEXT.fillText(card[j][i], 100 + 100 * i, 110 + 100 * j);
      }
    }
}

drawCard();

function drawCard()~ の部分で、仕事の内容を決めて、

最後の「drawCard();」で、その仕事を呼び出していますね!

そしてもう一つ!

キーが押されたときに、ポインターを動かす処理を

「movePointer」という名前の関数として新しく作りましょう!

drawCard();

function movePointer(e) {
  
}

</script>

今回は、押されたキーによって、右に行くか左に行くか処理を変えるため、
「e」という引数を設定しました!

これで、関数はおしまいです!

これで実行しても、前回と同じようにカードが表示されるはずです!


変数を作る

では次に、今回使う変数を作っていきましょう!

前回使った配列の下に新しいのを追加します。

…
["♢A", "♢2", "♢3", "♢4", "♢5", "♢6", "♢7", "♢8", "♢9", "♢10", "♢J", "♢Q", "♢K"]
];

let x = 0;
let y = 0;
…

あとで詳しく説明しますが、xとyは下のように対応しています。

なので、例えば、xが3で、yが2の時は、「♡4」を指す、
ということだけ分かっていればOKです!


ポインターを表示させる

では、今度は先ほど作ったxとyの変数を使って、ポインターを表示させてみましょう!

これは、drawCardの関数の中の、初めに書きましょう!

function drawCard() {
    CONTEXT.beginPath();
    CONTEXT.rect(68 + 100 * x, 58 + 100 * y, card_width + 4, card_height + 4);
    CONTEXT.stroke();

    CONTEXT.font = "40px 'MS ゴシック'";
    CONTEXT.textAlign = "center";

    CONTEXT.beginPath();

    for (let j = 0; j < 4; j++) {
      for (let i = 0; i < 13; i++) {
        CONTEXT.rect(70 + 100 * i, 60 + 100 * j, card_width, card_height);
        CONTEXT.stroke();
        CONTEXT.fillText(card[j][i], 100 + 100 * i, 110 + 100 * j);
      }
    }
}

最初の部分ですね!

CONTEXT.rect(~);

というのは、第二回でも使いましたね!

これをうまく使って、表示するカードの少し外側に四角形を描かせることで、線を二重にしています!

これで実行すれば、「♤1」にポインターが表示されているはずです!

少し実験で、

let x = 3;
let y = 2;

など数字を少し変えてみましょう!

すると、おそらく先ほど見た、xとyが対応するカードの部分にポインターが表示させるはずです!

x=3 y=2 の時は、「♡4」になるはずです!

なぜそうなるか少し考えてから、次に進めましょう!


キーボードの入力を検知する

ポインターを動かす処理を実際に書いていく前に、キーボードの入力を検知するためのコードを1行だけ書きます!

先ほどの変数の下に書きましょう!

…
let y = 0;

document.addEventListener("keydown", movePointer);

function drawCard() {
…

真ん中の一行ですね。

これについて詳しく説明すると難しくなってしまうので、簡単に説明すると…

キーボードのキーのどれかが押されたときに、
「movePointer」という仕事をする

といった意味があります。


ポインターを動かす処理を書いていく

ということでここで本題です!

先ほど作った、「movePointer」という関数に、ポインターを動かす処理を書いていきましょう!

まず初めに、条件分岐を用いて、どのキーが押されたかを判別するコードを書きます!

function movePointer(e){
  if (e.key == "ArrowRight") {

  }else if (e.key == "ArrowLeft") {

  }else if (e.key == "ArrowDown") {

  }else if (e.key == "ArrowUp") {

  }
}

先ほども少し説明しましたが、どのキーが入力されたかが引数によってわかるので、

引数の「key」が「ArrowRight」(右矢印キー)なら~

といったように条件で分けました。

そしてここから、先ほど作った変数の「x」と「y」を使っていきます。

先ほども説明しましたが、xとyにはこういう意味があります!

つまり、右キーが押されたときは、xの数字を1つ大きくすれば良いということですね!

なので、

if (e.key == "ArrowRight") {
  x = x + 1;
}else if (e.key == "ArrowLeft") {

}else if (e.key == "ArrowDown") {

}else if (e.key == "ArrowUp") {

}

と書けることができます!

ですが、一つ気を付けないといけないのが、

xの値が12のとき(ポインターがKを指しているとき)は右には行けないですね!

なので、条件分岐をうまく使い、

if (e.key == "ArrowRight") {
  if (x <= 11) {
    x = x + 1;
  }
}else if (e.key == "ArrowLeft") {

}else if (e.key == "ArrowDown") {

}else if (e.key == "ArrowUp") {

}

このように、xが11以下の時だけ、xを1つ増やすという処理にすればいいですね!

あとは、ほかも同じように考えて、

左キーが押されたら、xの値を1つ減らす
下キーが押されたら、yの値を1つ増やす
上キーが押されたら、yの値を1つ減らす

となることから、

if (e.key == "ArrowRight") {
  if (x <= 11) {
    x = x + 1;
  }
}else if (e.key == "ArrowLeft") {
  if (x >= 1) {
    x = x - 1;
  }
}else if (e.key == "ArrowDown") {
  if (y <= 2) {
    y = y + 1;
  }
}else if (e.key == "ArrowUp") {
  if (y >= 1) {
    y = y - 1;
  }
}

このように書けばいいですね!

あとは、キーボードが押された後に、drawCard()という関数(=カードとポインターを表示させる仕事)をもう一度して、

画面を更新すればいいですね!

なので、

function movePointer(e) {
  CONTEXT.clearRect(0, 0, 1400, 500);
  if (e.key == "ArrowRight") {
    if (x <= 11) {
      x = x + 1;
    }
  }else if (e.key == "ArrowLeft") {
    if (x >= 1) {
      x = x - 1;
    }
  }else if (e.key == "ArrowDown") {
    if (y <= 2) {
      y = y + 1;
    }
  }else if (e.key == "ArrowUp") {
    if (y >= 1) {
      y = y - 1;
    }
  }

  drawCard();
}

と、最後に「drawCard();」と書けばいいですね!

これで一度実行してみましょう!

するとどうなりますか?

おそらく、キーボードの入力で、枠がどんどん増えていく状態になっているはずです。


ポインターが増えていく問題を解決する

ほかの動作はうまくいっていますが、動かした後の枠が消えていませんね!

そう、それが問題ですね!

なので、drawCardの仕事をしてもらう前に、一度画面を真っ白に戻してもらいましょう!

画面を消すには、以下のようにします!

function movePointer(e) {
  if (e.key == "ArrowRight") {
    if (x <= 11) {
      x = x + 1;
    }
  }else if (e.key == "ArrowLeft") {
    if (x >= 1) {
      x = x - 1;
    }
  }else if (e.key == "ArrowDown") {
    if (y <= 2) {
      y = y + 1;
    }
  }else if (e.key == "ArrowUp") {
    if (y >= 1) {
      y = y - 1;
    }
  }
  CONTEXT.clearRect(0, 0, 1400, 500);
  drawCard();
}

clearRectというのは、

clearRect(x座標, y座標, 横の長さ, 縦の長さ);

といった使い方をするので、ここでは、画面の全体を消すように設定できていますね!

これで、ブラウザで確認すればしっかりポインターが増えずに、矢印キーを使って、うまく動かすことができるはずです!

これで、今回の目標は達成です!

少しずつですが、できていくのを見るのは楽しいですね♪


うまくいかなかった方向け

うまくいかなかった方は、まずエラーが出ていないか確認しましょう!

エラーの確認方法については、別の記事で詳しくまとめたので、ぜひそちらを参考にしてください!

それでもうまくいかなければ、下のサンプルコードをダウンロードして、自分のコードを比較してみましょう!

ということで、第四回はここまでとしたいと思います!

次回は、すべてのカードを裏返し、エンターキーを押すとひっくり返せるようなコードを組んでいきたいと思います!

長くなってしまいましたが、

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

ご感想などあれば、コメントやTwitterにどしどしお寄せください!

第五回はこちらから!