LoginSignup
1
2

【HTMLのみ】簡易シューティングゲームを作ってみた

Last updated at Posted at 2023-06-28

ゲームの概要

ここでは、非常に簡単なインベーダーゲームのような遊びができる、シューティングゲームの作り方をご紹介します。下記のゲーム画面のように、遊ぶことができます。

ゲームのプレイはコチラから

スクリーンショット 2023-06-28 20.58.58.png

同梱物

  • index.html(ゲームのメインプログラムです)
  • 背景画像(ゲームの背景となる画像です)
  • 敵オブジェクト(牡蠣の画像です)
  • Playerオブジェクト(忍者の画像です)

仕様

  • 移動:左右の矢印ボタンで移動します(移動は左右のみ)
  • 攻撃:スペースで弾を発射します(押しっぱなしで連続発射も可能)
  • 得点:牡蠣1体撃破につき、+10点
  • 当たり判定:牡蠣との接触では、当たり判定のカウントなし
  • ゲームオーバー:設定なし

ソースコードや同梱物は、Githubへ公開中です(下記参照)

ソースコード(html)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>KAKI-WARS</title>
  <style>
    body {
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
      margin: 0;
      background-color: #222;
      background-image: url("back.png");
      background-size: cover;
    }
    canvas {
      border: 1px solid #ffffff;
    }
  </style>
</head>
<body>
  <canvas id="gameCanvas" width="480" height="320"></canvas>
  <script>
    const canvas = document.getElementById('gameCanvas');
    const ctx = canvas.getContext('2d');
    const keys = {};


    document.addEventListener('keydown', (e) => {
      keys[e.code] = true;

      // 追加: スペースキーが押されたときに弾を発射
      if (e.code === 'Space') {
        player.bullets.push({
          x: player.x + player.size / 2 - 2,
          y: player.y - 10,
          size: 4,
          speed: 6
        });
      }
    });

    document.addEventListener('keyup', (e) => {
      keys[e.code] = false;
    });

    let player = {
      x: canvas.width / 2,
      y: canvas.height - 30 - 30, // 上に30px移動
      size: 60,
      speed: 4,
      bullets: [],
      ready: false
    };

    let enemies = [];
    let enemySpawnCounter = 0;
    let moveDirection = 1;
    let moveDownCounter = 0;
    let score = 0;

    let playerImage = new Image();
    playerImage.src = "忍者-ジャンプ4.png";
    playerImage.onload = function() {
      player.image = playerImage;
      player.ready = true;
    };

    let enemyImage = new Image();
    enemyImage.src = "kaki.png";
    enemyImage.onload = function() {
      for (const enemy of enemies) {
        enemy.image = enemyImage;
        enemy.ready = true;
      }
    };

    function drawEnemies() {
      for (const enemy of enemies) {
        if (enemy.ready) {
          ctx.drawImage(enemy.image, enemy.x, enemy.y, enemy.size, enemy.size);
        }
      }
    }

    function drawBullets() {
      ctx.fillStyle = 'green';
      for (const bullet of player.bullets) {
        ctx.fillRect(bullet.x, bullet.y, bullet.size, bullet.size);
      }
    }

    function update() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);

      if (player.ready) {
        ctx.drawImage(player.image, player.x, player.y, player.size, player.size);
      }

      drawEnemies();
      drawBullets();

      if (keys['ArrowLeft']) {
        player.x -= player.speed;
      }
      if (keys['ArrowRight']) {
        player.x += player.speed;
      }

      for (const bullet of player.bullets) {
        bullet.y -= bullet.speed;
      }
      player.bullets = player.bullets.filter(bullet => bullet.y > 0);

      // 弾と敵の衝突判定を追加
      player.bullets.forEach((bullet) => {
        enemies.forEach((enemy) => {
          if (
            bullet.x < enemy.x + enemy.size &&
            bullet.x + bullet.size > enemy.x &&
            bullet.y < enemy.y + enemy.size &&
            bullet.y + bullet.size > enemy.y
          ) {
            bullet.toRemove = true;
            enemy.toRemove = true;
            score += 10;
          }
        });
      });

      player.bullets = player.bullets.filter((bullet) => !bullet.toRemove);
      enemies = enemies.filter((enemy) => !enemy.toRemove);

      enemySpawnCounter++;
      if (enemySpawnCounter >= 30) {
        let newEnemy = {
          x: Math.random() * (canvas.width - 20),
          y: 10,
          size: 40,
          speed: 2,
          ready: false
        };
        newEnemy.image = enemyImage;
        newEnemy.ready = true;
        enemies.push(newEnemy);
        enemySpawnCounter = 0;
      }

      moveDownCounter++;
      if (moveDownCounter >= 60) {
        moveDirection = -moveDirection;
        for (const enemy of enemies) {
          enemy.y += 20;
        }
        moveDownCounter = 0;
      }

      for (const enemy of enemies) {
        enemy.x += enemy.speed * moveDirection;
      }
      enemies = enemies.filter(enemy => enemy.y < canvas.height);

      ctx.fillStyle = "white";
      ctx.font = "16px Arial";
      ctx.fillText("Score: " + score, 10, 20);

      requestAnimationFrame(update);
    }

    canvas.addEventListener('click', (e) => {
      player.bullets.push({
        x: player.x + player.size / 2 - 2,
        y: player.y - 10,
        size: 4,
        speed: 6
      });
    });

    update();
  </script>
</body>
</html>

ゲームパッケージ

最後に…「KAKI WARS」ということで、あの懐かしいゲームの外箱っぽいデザインに仕上げてみました。もちろん、パッケージは存在しないので、架空の外箱となります。

NINJA 牡蠣.png

この記事は、著者が運営するメディア「ぬるぺでぃあ」でも読むことができます(記事はコチラ

1
2
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
1
2