HTML・CSSでかんたんなシューティングゲームを作ろう!その3

目次

はじめに|ゲームに「敵」と「ルール」が加わると本物っぽくなる!

前回の記事では、自機を左右に動かし、スペースキーで弾を発射するところまで作成しました。

今回はついに「敵実装編」です!
以下の要素を実装して、遊べるゲームに仕上げていきましょう!!コピペで動きます👇

  • 敵キャラの出現と動き
  • 弾との当たり判定(ヒット処理)
  • 敵に当たると消える
  • 敵がプレイヤーにぶつかるとゲームオーバー

この記事での完成映像はこちら!

Step1|移動処理の改修

今回の敵実装にあたってプレイヤーの移動処理を少し改修します!
前回の記事で作成したこちらを分離します

// キーが押されたとき
document.addEventListener("keydown", (e) => {
    if (e.key === "ArrowLeft") moveLeft = true;
    if (e.key === "ArrowRight") moveRight = true;

    // スペースキーで弾発射
    if (e.code === "Space") {
      fireBullet();
    }
});

以下に分離しましょう!!

document.addEventListener("keydown", handleKeydown);
function handleKeydown(e) {
    if (e.key === "ArrowLeft") moveLeft = true;
    if (e.key === "ArrowRight") moveRight = true;

    if (e.code === "Space") {
        shoot();
    }
}

Step2|HTMLに敵エリアを追加

まずはゲームメッセージを表示させるためのdivをHTMLに追加しましょう。
ゲームエリア内に以下を追加します👇

<div id="message"></div>

これでゲームメッセージの表示場所が用意されました。

Step3|CSSでメッセージを作る

見た目の設定です。以下をstyle.cssなどに追加してください。

#message {
  position: absolute;
  top: 200px;
  left: 200px;
  font-size: 24px;
  color: white;
  visibility: hidden;
}

messageはゲームオーバーなどのテキスト表示用です。

Step4|敵を少しずつ下に動かす

次にJavaScriptで敵を動かします。

const enemy = document.getElementById("enemy");
let enemyY = 0;

setInterval(() => {
  enemyY += 2;
  enemy.style.top = enemyY + "px";

  // ゲームオーバー判定
  if (checkCollision(player, enemy)) {
    endGame("ゲームオーバー!");
  }

  // 敵が画面外に出たらリセット
  if (enemyY > 400) {
    resetEnemy();
  }
}, 30);
  • enemyYを加算して、敵を下に移動させています。
  • 一定位置まできたらゲームオーバー
  • 敵が下まで行ったらリセットされて上から出てきます

Step5|弾との当たり判定を実装

弾が敵に当たったとき、敵と弾が消えるようにしましょう。

function checkCollision(objA, objB) {
  const a = objA.getBoundingClientRect();
  const b = objB.getBoundingClientRect();

  return !(a.right < b.left || a.left > b.right || a.bottom < b.top || a.top > b.bottom);
}

弾発射時の処理を書き換えます👇

function shoot() {
    const bullet = document.createElement("div");
    bullet.className = "bullet";
    bullet.style.left = playerX + 15 + "px";
    bullet.style.bottom = "60px";
    document.getElementById("gameArea").appendChild(bullet);

    let bulletY = 60;

    function moveBullet() {
        bulletY += 5;
        bullet.style.bottom = bulletY + "px";

        if (bulletY > 400) {
            bullet.remove();
            return;
        }

        // 衝突判定
        if (checkCollision(bullet, enemy)) {
            bullet.remove();
            resetEnemy();
            return;
        }

        requestAnimationFrame(moveBullet); // 次のフレームで再実行
    }

    requestAnimationFrame(moveBullet);
}

以下の処理は不要なので消しちゃいましょう

// 弾を上に動かす処理の中
const interval = setInterval(() => {
  const currentBottom = parseInt(bullet.style.bottom);
  if (currentBottom > 400) {
    bullet.remove();
    clearInterval(interval);
  } else {
    bullet.style.bottom = currentBottom + 5 + "px";

    // 弾が敵に当たったら
    if (checkCollision(bullet, enemy)) {
      bullet.remove();
      resetEnemy();
      clearInterval(interval);
    }
  }
}, 10);

このようにすることで、弾と敵が重なったときにヒット判定が出ます。

Step6|ゲームオーバー処理

ゲームオーバー時の処理をまとめて関数にします。

function endGame(messageText) {
  document.getElementById("message").textContent = messageText;
  document.getElementById("message").style.visibility = "visible";

  // 入力禁止にする
  document.removeEventListener("keydown", handleKeydown);
}

この関数をcheckCollisionの中から呼び出せばOKです。

document.removeEventListener("keydown", handleKeydown);
これでゲームオーバー時にプレイヤーの行動ができなくなります!

Step7|敵をランダムに再出現

敵が消えたらランダム位置から再出現させましょう。

function resetEnemy() {
    // 一時的に非表示にする
    enemy.style.visibility = "hidden";

    // Y位置リセット
    enemyY = 0;
    enemy.style.top = enemyY + "px";

    // X座標をランダムに変更
    const randomX = Math.floor(Math.random() * 560);
    enemy.style.left = randomX + "px";

    // 少し後に表示(描画タイミングをズラす)
    setTimeout(() => {
        enemy.style.visibility = "visible";
    }, 10); // 10msだけ描画を遅らせる
}

これで、敵の出現が予測できなくなり、ゲーム性がUPします!

🎮 ほぼ完成!プレイしてみよう!

これであなたのシューティングゲームはほぼ完成です!

・自機は左右にスムーズに移動
・スペースキーで弾を撃つ
・敵が降ってきて、弾で当てれば倒せる
・当たるとゲームオーバー

まとめ

今回の記事では、以下のようにゲームの完成形を目指して実装しました:

要素実装内容
敵出現ランダムな位置から出現
弾と敵の当たり判定getBoundingClientRectで実装
敵が下に到達ゲームオーバー処理
弾が当たる敵を消して再出現

次回予告

さらに本格的なゲームにチャレンジしたい方へ!

次回は「スコア機能とステージ進行」を実装し、よりゲームらしく仕上げていきます!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

スマホ系ゲーム会社現役サーバーエンジニア

Google Cloud Professional Cloud Architect取得済み

趣味:キャンプ、格闘ゲーム、動画視聴

コメント

コメントする

目次