2
3

イージスアショア。自動ミサイル迎撃ゲーム。

Posted at

自動ミサイル迎撃ゲーム。

スクリーンショット 2024-09-16 211142.png

スクリーンショット 2024-09-16 211156.png

自動ミサイル追尾ゲームの実装

概要
本研究では、HTMLとJavaScriptを使用して自動ミサイル追尾ゲームを実装した。このゲームでは、画面下部に配置された3つの砲台が、画面上部からランダムに降下してくるミサイルを自動で追尾し、撃ち落とす。ゲームの描画とロジックはすべてクライアントサイドで処理され、2Dグラフィックスを用いたシンプルなゲーム体験を提供する。

  1. ゲーム環境の設定
    ゲームは要素を利用して描画され、背景色は青 (#0000FF) に設定されている。これにより、ゲームエリアが明確に視覚化され、プレイヤーにとっての視認性が向上する。ゲームタイトルは画面上部に白色 (#FFFFFF) のフォントで表示され、ユーザーにゲームの目的を伝える役割を果たしている。

  2. 砲台の設計
    ゲームには3つの砲台が配置されており、それぞれの砲台は画面下部に固定され、中央を基準に均等に配置されている。砲台の描画には、fillRectメソッドを使用して矩形を描画し、rotateメソッドで角度を調整することで、ミサイルに対する向きを変更する。


const turrets = [
    { x: canvas.width / 4, y: canvas.height - 30, width: 20, height: 20, angle: 0, cooldown: 0 },
    { x: canvas.width / 2, y: canvas.height - 30, width: 20, height: 20, angle: 0, cooldown: 0 },
    { x: (3 * canvas.width) / 4, y: canvas.height - 30, width: 20, height: 20, angle: 0, cooldown: 0 }
];
  1. ミサイルの生成と管理
    ミサイルはランダムな位置から画面上部に降下し、定期的に生成される。ミサイルの速度は一定に設定されており、setInterval関数を用いて一定間隔でミサイルを生成する。

function createMissile() {
    const missile = {
        x: Math.random() * canvas.width,
        y: 0,
        speed: 2
    };
    missiles.push(missile);
}
  1. 弾の発射と追尾
    砲台はミサイルの位置に基づいて自動的にターゲティングし、弾を発射する。弾の発射にはクールダウンタイムが設定されており、これにより過度な発射を防止する。弾は指定された角度と速度で移動し、ミサイルと衝突した場合には削除される。

function shootBullet(turret) {
    if (turret.cooldown <= 0) {
        const bullet = {
            x: turret.x,
            y: turret.y,
            speed: 5,
            angle: turret.angle
        };
        bullets.push(bullet);
        turret.cooldown = 20; // クールダウンタイム
    }
}
  1. 更新と描画のロジック
    updateGame関数では、ゲームの各要素(砲台、弾、ミサイル)の位置を更新し、画面上に描画する。ゲームループはrequestAnimationFrameを利用して連続的に実行され、ゲームの状態が常に更新される。これにより、リアルタイムでのゲームプレイが実現される。

function updateGame() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    aimTurrets();
    turrets.forEach(turret => shootBullet(turret));

    updateBullets();
    updateMissiles();
    drawTurrets();

    // 各砲台のクールダウン減少
    turrets.forEach(turret => {
        if (turret.cooldown > 0) {
            turret.cooldown--;
        }
    });

    requestAnimationFrame(updateGame);
}
  1. 結論
    本ゲームは、HTML5の要素とJavaScriptを用いて、シンプルでありながらも効果的な2Dゲーム体験を提供する。自動的にミサイルを追尾し撃ち落とす砲台のメカニズムは、ゲームの魅力を引き出し、ユーザーに対して挑戦的な体験を提供する。今後の改善点としては、ミサイルの種類や砲台のカスタマイズ、ゲームの難易度調整などが考えられる。

コード全体。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>自動ミサイル追尾ゲーム</title>
    <style>
        canvas {
            display: block;
            margin: 0 auto;
            background: #0000FF; /* 背景色を青に設定 */
        }
        #title {
            text-align: center;
            color: #FFFFFF;
            font-size: 24px;
            font-family: Arial, sans-serif;
            margin: 20px 0;
        }
    </style>
</head>
<body>
    <div id="title">自動ミサイル追尾ゲーム</div>
    <canvas id="gameCanvas" width="800" height="600"></canvas>
    <script>
        const canvas = document.getElementById('gameCanvas');
        const ctx = canvas.getContext('2d');

        // 砲台の設定
        const turrets = [
            { x: canvas.width / 4, y: canvas.height - 30, width: 20, height: 20, angle: 0, cooldown: 0 },
            { x: canvas.width / 2, y: canvas.height - 30, width: 20, height: 20, angle: 0, cooldown: 0 },
            { x: (3 * canvas.width) / 4, y: canvas.height - 30, width: 20, height: 20, angle: 0, cooldown: 0 }
        ];

        // 弾とミサイルのリスト
        const bullets = [];
        const missiles = [];

        // ミサイルを生成する関数
        function createMissile() {
            const missile = {
                x: Math.random() * canvas.width,
                y: 0,
                speed: 2
            };
            missiles.push(missile);
        }

        // 弾を発射する関数
        function shootBullet(turret) {
            if (turret.cooldown <= 0) {
                const bullet = {
                    x: turret.x,
                    y: turret.y,
                    speed: 5,
                    angle: turret.angle
                };
                bullets.push(bullet);
                turret.cooldown = 20; // クールダウンタイム
            }
        }

        // 各砲台がミサイルの方向に向ける関数
        function aimTurrets() {
            turrets.forEach(turret => {
                if (missiles.length > 0) {
                    const target = missiles[0];
                    const dx = target.x - turret.x;
                    const dy = target.y - turret.y;
                    turret.angle = Math.atan2(dy, dx);
                }
            });
        }

        // 弾の移動と描画
        function updateBullets() {
            for (let i = bullets.length - 1; i >= 0; i--) {
                const bullet = bullets[i];
                bullet.x += bullet.speed * Math.cos(bullet.angle);
                bullet.y += bullet.speed * Math.sin(bullet.angle);

                // 弾の描画
                ctx.fillStyle = 'yellow';
                ctx.beginPath();
                ctx.arc(bullet.x, bullet.y, 5, 0, Math.PI * 2);
                ctx.fill();

                // 弾が画面外に出たら削除
                if (bullet.x < 0 || bullet.x > canvas.width || bullet.y < 0 || bullet.y > canvas.height) {
                    bullets.splice(i, 1);
                }
            }
        }

        // ミサイルの移動と描画
        function updateMissiles() {
            for (let i = missiles.length - 1; i >= 0; i--) {
                const missile = missiles[i];
                missile.y += missile.speed;

                // ミサイルの描画
                ctx.fillStyle = 'red';
                ctx.beginPath();
                ctx.arc(missile.x, missile.y, 10, 0, Math.PI * 2);
                ctx.fill();

                // ミサイルが画面外に出たら削除
                if (missile.y > canvas.height) {
                    missiles.splice(i, 1);
                }

                // 弾とミサイルの衝突判定
                for (let j = bullets.length - 1; j >= 0; j--) {
                    const bullet = bullets[j];
                    const dx = bullet.x - missile.x;
                    const dy = bullet.y - missile.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);

                    if (distance < 10) { // 衝突判定
                        missiles.splice(i, 1);
                        bullets.splice(j, 1);
                        break;
                    }
                }
            }
        }

        // 各砲台の描画
        function drawTurrets() {
            turrets.forEach(turret => {
                ctx.save();
                ctx.translate(turret.x, turret.y);
                ctx.rotate(turret.angle);
                ctx.fillStyle = 'white';
                ctx.fillRect(-turret.width / 2, -turret.height / 2, turret.width, turret.height);
                ctx.restore();
            });
        }

        // ゲームの更新
        function updateGame() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            aimTurrets();
            turrets.forEach(turret => shootBullet(turret));

            updateBullets();
            updateMissiles();
            drawTurrets();

            // 各砲台のクールダウン減少
            turrets.forEach(turret => {
                if (turret.cooldown > 0) {
                    turret.cooldown--;
                }
            });

            requestAnimationFrame(updateGame);
        }

        // ミサイルを定期的に生成
        setInterval(createMissile, 1000);

        // ゲームの開始
        updateGame();
    </script>
</body>
</html>

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3