🎮ArcadeLab

Space Shooting Game

by RocketFox99
328 lines6.5 KB
▶ Play

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Space Shooting Game</title>

<style>
* { box-sizing: border-box; }

body {
  margin: 0;
  text-align: center;
  background: #080d20;
  color: white;
  font-family: Arial, sans-serif;
}

h1 { color: #38bdf8; }

#score { font-size: 22px; margin: 10px; }

#game {
  position: relative;
  width: 360px;
  height: 520px;
  max-width: 96vw;
  margin: auto;
  overflow: hidden;
  background: radial-gradient(#172554, #020617);
  border: 3px solid #38bdf8;
  border-radius: 12px;
  touch-action: none;
}

#player {
  position: absolute;
  bottom: 18px;
  left: 155px;
  width: 46px;
  height: 48px;
  font-size: 40px;
  line-height: 48px;
  user-select: none;
}

.bullet {
  position: absolute;
  width: 5px;
  height: 16px;
  border-radius: 5px;
  background: #facc15;
  box-shadow: 0 0 10px #facc15;
}

.enemy {
  position: absolute;
  width: 36px;
  height: 36px;
  font-size: 30px;
  line-height: 36px;
}

#overlay {
  position: absolute;
  inset: 0;
  background: #000c;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  z-index: 10;
}

button {
  border: 0;
  border-radius: 10px;
  padding: 13px 22px;
  margin: 6px;
  font-size: 17px;
  font-weight: bold;
  background: #22d3ee;
  cursor: pointer;
}

.controls {
  display: flex;
  justify-content: center;
  gap: 20px;
  margin: 12px;
}

.controls button {
  width: 95px;
  background: #1e40af;
  color: white;
  font-size: 24px;
  touch-action: none;
}

p { color: #cbd5e1; }
</style>
</head>

<body>
<h1>🚀 Space Shooter</h1>
<div id="score">Score: 0 | ❤️ Lives: 3</div>

<div id="game">
  <div id="player">🚀</div>

  <div id="overlay">
    <h2 id="title">SPACE SHOOTER</h2>
    <p id="info">Destroy enemies and survive!</p>
    <button id="start">START GAME</button>
  </div>
</div>

<div class="controls">
  <button id="left">⬅️</button>
  <button id="fire">🔥 FIRE</button>
  <button id="right">➡️</button>
</div>

<p>Move: Arrow keys / A-D | Shoot: Space</p>

<script>
const game = document.getElementById("game");
const player = document.getElementById("player");
const scoreText = document.getElementById("score");
const overlay = document.getElementById("overlay");
const startBtn = document.getElementById("start");

let x, score, lives, running;
let bullets = [];
let enemies = [];
let lastTime = 0;
let spawnTimer = 0;
let shotTimer = 0;
let animationId;

const keys = {};

function updateScore() {
  scoreText.textContent =
    `Score: ${score} | ❤️ Lives: ${lives}`;
}

function shoot() {
  if (!running) return;

  const bullet = document.createElement("div");
  bullet.className = "bullet";
  bullet.style.left = (x + 20) + "px";
  bullet.style.top = (game.clientHeight - 75) + "px";
  game.appendChild(bullet);
  bullets.push(bullet);
}

function spawnEnemy() {
  const enemy = document.createElement("div");
  enemy.className = "enemy";
  enemy.textContent = "👾";
  enemy.style.left =
    Math.random() * (game.clientWidth - 40) + "px";
  enemy.style.top = "-40px";
  game.appendChild(enemy);
  enemies.push(enemy);
}

function hit(a, b) {
  const A = a.getBoundingClientRect();
  const B = b.getBoundingClientRect();

  return A.left < B.right &&
         A.right > B.left &&
         A.top < B.bottom &&
         A.bottom > B.top;
}

function gameOver() {
  running = false;
  cancelAnimationFrame(animationId);
  overlay.style.display = "flex";
  document.getElementById("title").textContent = "💥 GAME OVER";
  document.getElementById("info").textContent =
    "Your score: " + score;
  startBtn.textContent = "PLAY AGAIN";
}

function loop(time) {
  if (!running) return;

  const dt = Math.min((time - lastTime) / 16.67 || 1, 2);
  lastTime = time;

  if (keys.ArrowLeft || keys.a) x -= 5 * dt;
  if (keys.ArrowRight || keys.d) x += 5 * dt;

  x = Math.max(0, Math.min(game.clientWidth - 46, x));
  player.style.left = x + "px";

  if (keys.Space && time - shotTimer > 220) {
    shoot();
    shotTimer = time;
  }

  spawnTimer += dt;
  if (spawnTimer > 42) {
    spawnEnemy();
    spawnTimer = 0;
  }

  for (let i = bullets.length - 1; i >= 0; i--) {
    const b = bullets[i];
    b.style.top = (parseFloat(b.style.top) - 8 * dt) + "px";

    if (parseFloat(b.style.top) < -20) {
      b.remove();
      bullets.splice(i, 1);
    }
  }

  for (let i = enemies.length - 1; i >= 0; i--) {
    const e = enemies[i];
    e.style.top = (parseFloat(e.style.top) + 2.5 * dt) + "px";

    if (hit(player, e)) {
      e.remove();
      enemies.splice(i, 1);
      lives--;
      updateScore();

      if (lives <= 0) {
        gameOver();
        return;
      }
      continue;
    }

    let destroyed = false;

    for (let j = bullets.length - 1; j >= 0; j--) {
      if (hit(e, bullets[j])) {
        e.remove();
        bullets[j].remove();
        enemies.splice(i, 1);
        bullets.splice(j, 1);
        score += 10;
        updateScore();
        destroyed = true;
        break;
      }
    }

    if (destroyed) continue;

    if (parseFloat(e.style.top) > game.clientHeight) {
      e.remove();
      enemies.splice(i, 1);
    }
  }

  animationId = requestAnimationFrame(loop);
}

function startGame() {
  cancelAnimationFrame(animationId);

  bullets.forEach(b => b.remove());
  enemies.forEach(e => e.remove());
  bullets = [];
  enemies = [];

  score = 0;
  lives = 3;
  x = (game.clientWidth - 46) / 2;
  lastTime = performance.now();
  spawnTimer = 0;
  shotTimer = 0;
  running = true;

  player.style.left = x + "px";
  updateScore();

  overlay.style.display = "none";
  animationId = requestAnimationFrame(loop);
}

document.addEventListener("keydown", e => {
  if (["ArrowLeft", "ArrowRight", "Space"].includes(e.code))
    e.preventDefault();

  keys[e.code === "Space" ? "Space" :
       e.key.length === 1 ? e.key.toLowerCase() : e.key] = true;
});

document.addEventListener("keyup", e => {
  keys[e.code === "Space" ? "Space" :
       e.key.length === 1 ? e.key.toLowerCase() : e.key] = false;
});

function holdButton(id, key) {
  const btn = document.getElementById(id);

  btn.addEventListener("pointerdown", e => {
    e.preventDefault();
    keys[key] = true;
    btn.setPointerCapture(e.pointerId);
  });

  function release() { keys[key] = false; }

  btn.addEventListener("pointerup", release);
  btn.addEventListener("pointercancel", release);
  btn.addEventListener("lostpointercapture", release);
}

holdButton("left", "ArrowLeft");
holdButton("right", "ArrowRight");
holdButton("fire", "Space");

startBtn.addEventListener("click", startGame);
</script>
</body>
</html>

Game Source: Space Shooting Game

Creator: RocketFox99

Libraries: none

Complexity: complex (328 lines, 6.5 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: space-shooting-game-rocketfox99" to link back to the original. Then publish at arcadelab.ai/publish.