Skip to content

About

A faithful recreation of the classic 1978 arcade game Space Invaders, built entirely with vanilla HTML/CSS/JS

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 

Repository files navigation

Space Invaders

A faithful recreation of the classic 1978 arcade game Space Invaders, built entirely with web technologies.

Space Invaders Screenshot

Overview

This is a complete, self-contained Space Invaders clone featuring the iconic alien formation, destructible bunkers, bonus UFO, and progressive difficulty — all running directly in your browser with authentic retro sound effects.

Features

  • Three distinct alien types — Squid (top), Crab (middle), and Octopus (bottom)
  • Pixel art sprites — Authentic retro-style graphics with animated sprites
  • Destructible bunkers — Four shields that erode from both player and enemy fire
  • Bonus UFO — Randomly appears for bonus points (50–300)
  • Particle explosions — Classic arcade-style particle effects
  • Procedural sound effects — All sounds generated via Web Audio API (no audio files needed)
  • Progressive difficulty — Aliens speed up as fewer remain and each level increases challenge
  • Starfield background — Twinkling stars for atmosphere

Architecture

Technology Stack

This game is built as a single-file, zero-dependency web application using:

Technology Purpose
HTML5 Canvas 2D rendering for all game graphics
CSS3 UI styling and layout (start screen, game over)
Vanilla JavaScript All game logic, state management, and rendering
Web Audio API Procedural sound generation (no external files)
RequestAnimationFrame Smooth 60fps game loop

File Structure

space-invaders/
└── index.html          # Complete game in a single file
    ├── <style>         # Game UI and layout CSS
    ├── <canvas>        # Main game rendering surface
    ├── Start screen    # HTML overlay for title screen
    ├── Game Over screen # HTML overlay for game over state
    └── <script>        # All game logic (~700 lines)

The entire game fits in a single index.html file — no build tools, no dependencies, no installation. Just open it in a browser.

Core Game Loop

The game follows the classic update-render cycle:

┌─────────────────────────────────────────────┐
│                 requestAnimationFrame        │
└──────────────────┬──────────────────────────┘
                   │
           ┌───────▼────────┐
           │    UPDATE()    │  ← Game logic
           ├────────────────┤     - Player movement
           │                │     - Alien marching
           │                │     - Bullet physics
           │                │     - Collision detection
           │                │     - Particle updates
           │                │     - Game state transitions
           └───────┬────────┘
                   │
           ┌───────▼────────┐
           │    RENDER()    │  ← Drawing
           ├────────────────┤     - Clear canvas
           │                │     - Draw starfield
           │                │     - Draw bunkers
           │                │     - Draw player
           │                │     - Draw aliens
           │                │     - Draw bullets
           │                │     - Draw particles
           │                │     - Draw UFO
           └───────┬────────┘
                   │
           ┌───────▼────────┐
           │     Repeat     │
           └────────────────┘

Key Systems

1. Game State Management

The game tracks its state with a single gameState variable:

let gameState = 'start';  // 'start' | 'playing' | 'gameOver'

State transitions are triggered by player input (Space key) and game events (player death, level complete).

2. Entity Component Model

Entities (player, aliens, bullets, UFO, bunkers) are simple objects with position, size, and behavior properties:

// Player
let player = { x: W / 2, y: H - 50, width: 40, height: 24 };

// Aliens (array of objects)
let aliens = [
  { x: 40, y: 80, width: 28, height: 20, type: 0, alive: true },
  // ... more aliens
];

// Bullets (shared array, distinguished by flag)
let playerBullets = [
  { x: 398, y: 550, width: 4, height: 12 },           // player bullet
  { x: 100, y: 200, width: 4, height: 12, isEnemy: true } // enemy bullet
];

This lightweight approach avoids the complexity of full ECS while keeping entities easily iterable and serializable.

3. Rendering Pipeline

Graphics use Canvas 2D API with pixelated rendering:

canvas {
  image-rendering: pixelated;  /* Crisp pixels, no smoothing */
}

Sprites are defined as pixel grid arrays — coordinate pairs that map directly to drawn rectangles:

const squidSprite = [
  [3,0],[4,0],[5,0],        // Top row of pixels
  [2,1],[3,1],[4,1],[5,1],[6,1],  // Next row...
  // ... more rows
];

function drawPixelSprite(data, x, y, size, color) {
  ctx.fillStyle = color;
  data.forEach(([px, py]) => {
    ctx.fillRect(x + px * size, y + py * size, size, size);
  });
}

This approach:

  • Eliminates image file dependencies
  • Allows procedural sprite generation
  • Makes sprite editing trivial (just edit arrays)
  • Keeps the file self-contained

4. Collision Detection

Two collision methods are used:

Rectangle-Rectangle (AABB) — For static checks:

function rectCollision(a, b) {
  return a.x < b.x + b.width &&
         a.x + a.width > b.x &&
         a.y < b.y + b.height &&
         a.y + a.height > b.y;
}

Line-Rectangle — To prevent "tunneling" when fast bullets skip over thin targets:

function lineRectCollision(bullet, topY, bottomY, rect) {
  // Check if the bullet's path (previous → current position)
  // intersects the target rectangle
}

The line-based check traces the bullet's previous position to its current position, catching any collisions that would otherwise be missed at high speeds.

5. Audio System

All sounds are generated procedurally using the Web Audio API:

function playShoot() {
  const osc = audioCtx.createOscillator();
  const gain = audioCtx.createGain();
  osc.type = 'square';
  osc.frequency.setValueAtTime(880, audioCtx.currentTime);
  osc.frequency.exponentialRampToValueAtTime(440, audioCtx.currentTime + 0.1);
  // ... envelope and connection
}

Sound effects include:

  • Player shoot — Square wave descending tone
  • Alien march — Classic 4-note descending sequence
  • Alien hit — Sawtooth wave crash
  • Player hit — Dramatic descending wail
  • UFO approach — Sine wave hover
  • UFO hit — Rapid descending blips
  • Level complete — Ascending fanfare

Each sound uses an ADSR-like envelope for authentic retro character.

6. Alien AI

Aliens follow a simple but engaging behavior pattern:

  1. March — All aliens move horizontally together
  2. Drop — When any alien hits the screen edge, the entire formation shifts down
  3. Accelerate — As fewer aliens remain, the formation speeds up (classic tension mechanic)
  4. Shoot — Aliens randomly fire from bottom-row columns
  5. Escalate — Shooting frequency increases with level and remaining alien count
// Speed increases as aliens are destroyed
const speedMultiplier = 1 + (1 - aliveAliens.length / aliens.length) * 2;

// Shooting rate increases with difficulty
const shootRate = Math.max(30, 120 - level * 15 - 
  (1 - aliveAliens.length / aliens.length) * 60);

Game Constants

Constant Value Purpose
Canvas size 800 × 600 Game world resolution
Alien rows 5 Number of alien rows
Alien columns 11 Number of alien columns
Total aliens 55 5 × 11 formation
Player lives 3 Starting lives
Bunkers 4 Defendable shields
Bunker health 100 Degrades on hit

Alien Types

Type Points Color Shape Animation
0 (Squid) 30 × level Red 9×8 pixels Tentacle wave
1 (Crab) 20 × level Orange 13×13 pixels Claw raise/lower
2 (Octopus) 10 × level Green 13×13 pixels Tentacle spread

Why This Stack?

HTML5 Canvas + JavaScript

I chose vanilla HTML/Canvas/JavaScript for several reasons:

1. Zero Barriers to Entry

  • No installation required — Works in any modern browser
  • No build tools — No Webpack, Vite, npm, or package.json
  • No dependencies — Pure, self-contained file
  • Instant playability — Double-click and play

2. Perfect for 2D Arcade Games

  • Canvas 2D API was designed for exactly this use case
  • Pixel manipulation is straightforward with fillRect
  • requestAnimationFrame provides smooth 60fps
  • image-rendering: pixelated gives crisp retro graphics

3. Accessibility

  • Runs on any device with a browser (desktop, tablet, phone)
  • No platform-specific binaries
  • Shareable via a single file or URL

4. Learning Value

  • Demonstrates core game dev concepts without framework complexity
  • Easy to modify and experiment with
  • Forces understanding of the fundamentals: game loop, state, rendering, input

5. Performance

  • Canvas 2D is fast enough for 55 animated sprites at 60fps
  • No overhead from virtual DOM or framework re-renders
  • Direct pixel access for maximum control

Why Not Other Options?

Option Why Not
Python/Pygame Requires Python installation; not shareable via URL
React/Vue Framework overhead unnecessary for simple 2D rendering
WebGL Overkill for simple 2D; steep learning curve
Game engines (Unity, Godot) Heavy toolchain; overkill for a single-file clone

Controls

Key Action
← → or A D Move ship left/right
Space Shoot / Start / Restart

Getting Started

  1. Open index.html in any modern browser
  2. Press Space to start
  3. Destroy all aliens to advance to the next level
  4. Don't let aliens reach the bottom!

Future Enhancements

  • Power-ups (spread shot, shield, slow-motion)
  • High score persistence (localStorage)
  • More alien patterns (V-formation, circle)
  • Background music
  • Touch controls for mobile
  • Sound toggle
  • Multiple ship types

Technical Details

  • Canvas resolution: 800 × 600 pixels
  • Sprite size: 3px per pixel (scaled from 13×13 pixel sprites)
  • Frame rate: 60fps via requestAnimationFrame
  • Audio sample rate: Browser default (typically 44.1kHz)
  • File size: ~30KB (entire game)

AI Development Environment

This project was developed using pi, a minimal terminal-based coding agent harness that extends LLM capabilities through a powerful TypeScript extension system.

AI Model

Property Value
Provider llama.cpp (self-hosted server at http://100.88.205.86:8080)
Model Qwen3.6-35B-A3B-MTP-GGUF (quantized to UD-Q5_K_M)
Thinking Level Medium
Framework pi — minimal, extensible coding agent

pi is a terminal coding harness that ships with powerful defaults (read, write, edit, bash tools) but skips features like sub-agents and plan mode. Instead, it is aggressively extensible — capabilities are added via TypeScript extensions, skills, prompt templates, and pi packages. It supports multiple providers (Anthropic, OpenAI, Google, xAI, and many more via API keys or subscriptions) as well as self-hosted llama.cpp servers.

Installed Extensions

1. pi-llama-cpp (npm: pi-llama-cpp)

Enables llama.cpp integration for pi. Supports router, single, and legacy models across multiple servers. This is how the self-hosted Qwen model is made available to pi as a provider.

2. searxng-suite (npm: @blazer2k/searxng-suite)

Provides SearxNG-based web search with category filtering and multi-format URL extraction. Registers the web_search and web_extract tools, enabling the agent to look up information during development.

Why This Stack?

Aspect Reason
Self-hosted model Full control over model choice, no API costs, no rate limits
pi over Claude Code More extensible, no vendor lock-in, runs locally, open source
TypeScript extensions Full system access, custom tools, UI components, event hooks
llama.cpp Efficient GGUF inference, runs on any hardware, mature ecosystem

Built with ❤ and vanilla JavaScript. No game engines were harmed in the making of this game.

About

A faithful recreation of the classic 1978 arcade game Space Invaders, built entirely with vanilla HTML/CSS/JS

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages