はじめに|ゲームに「敵」と「ルール」が加わると本物っぽくなる!
前回の記事では、自機を左右に動かし、スペースキーで弾を発射するところまで作成しました。

今回はついに「敵実装編」です!
以下の要素を実装して、遊べるゲームに仕上げていきましょう!!コピペで動きます👇
- 敵キャラの出現と動き
- 弾との当たり判定(ヒット処理)
- 敵に当たると消える
- 敵がプレイヤーにぶつかるとゲームオーバー
この記事での完成映像はこちら!
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 で実装 |
敵が下に到達 | ゲームオーバー処理 |
弾が当たる | 敵を消して再出現 |
次回予告
さらに本格的なゲームにチャレンジしたい方へ!
次回は「スコア機能とステージ進行」を実装し、よりゲームらしく仕上げていきます!
コメント