< < < < <Space Invaders < body { margin: 0; padding: 0; background-color: #000; color: #fff; font-family: 'Courier New', Courier, monospace; display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; overflow: hidden; user-select: none; } #game-container { position: relative; box-shadow: 0 0 20px rgba(0, 255, 0, 0.2); border: 2px solid #333; } canvas { display: block; background-color: #000; } #ui { position: absolute; top: 0; left: 0; width: 100%; padding: 10px 20px; box-sizing: border-box; display: flex; justify-content: space-between; font-size: 24px; pointer-events: none; text-shadow: 2px 2px #000; z-index: 5; } #overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.8); display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; z-index: 10; } h1 { font-size: 48px; color: #0f0; margin-bottom: 20px; } p { font-size: 18px; margin-bottom: 30px; line-height: 1.5; } button { padding: 15px 30px; font-size: 20px; font-family: 'Courier New', Courier, monospace; background: #0f0; color: #000; border: none; cursor: pointer; font-weight: bold; transition: background 0.2s; } button:hover { background: #0a0; } .hidden { display: none !important; } < <
SCORE: <0
LIVES: <3
< < <SPACE INVADERS <Use LEFT/RIGHT arrows to move<Press SPACE to shoot

<START GAME < const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); const scoreEl = document.getElementById('score'); const livesEl = document.getElementById('lives'); const overlay = document.getElementById('overlay'); const overlayTitle = document.getElementById('overlay-title'); const overlayDesc = document.getElementById('overlay-desc'); const startBtn = document.getElementById('start-btn'); // Game Constants canvas.width = 800; canvas.height = 600; const PLAYER_WIDTH = 40; const PLAYER_HEIGHT = 20; const ALIEN_ROWS = 5; const ALIEN_COLS = 11; const ALIEN_SIZE = 30; const ALIEN_PADDING = 15; const BULLET_SPEED = 7; const ALIEN_BULLET_SPEED = 4; const BUNKER_BLOCK_SIZE = 5; // Game State let state = 'START'; let score = 0; let lives = 3; let keys = {}; let player = { x: canvas.width / 2 - PLAYER_WIDTH / 2, y: canvas.height - 40 }; let aliens = []; let alienDirection = 1; let alienMoveTimer = 0; let alienMoveInterval = 60; let bullets = []; let bunkers = []; let lastShotTime = 0; window.addEventListener('keydown', e => keys[e.code] = true); window.addEventListener('keyup', e => keys[e.code] = false); function initGame() { score = 0; lives = 3; player.x = canvas.width / 2 - PLAYER_WIDTH / 2; bullets = []; aliens = []; bunkers = []; alienDirection = 1; alienMoveInterval = 60; for (let row = 0; row << AL ALIEN_ROWS; row++) { for (let col = 0; col << AL ALIEN_COLS; col++) { aliens.push({ x: col * (ALIEN_SIZE + ALIEN_PADDING) + 50, y: row * (ALIEN_SIZE + ALIEN_PADDING) + 80, width: ALIEN_SIZE, height: ALIEN_SIZE, type: row }); } } const bunkerCount = 4; const bunkerWidth = 80; const bunkerHeight = 60; const spacing = (canvas.width - (bunkerCount * bunkerWidth)) / (bunkerCount + 1); for (let i = 0; i << bunker bunkerCount; i++) { const bx = spacing + i * (bunkerWidth + spacing); const by = canvas.height - 120; for (let row = 0; row << bunker bunkerHeight / BUNKER_BLOCK_SIZE; row++) { for (let col = 0; col << bunker bunkerWidth / BUNKER_BLOCK_SIZE; col++) { if (!(row === bunkerHeight / BUNKER_BLOCK_SIZE - 1 && col > 10 && col << 20)) { bunkers.push({ x: bx + col * BUNKER_BLOCK_SIZE, y: by + row * BUNKER_BLOCK_SIZE, w: BUNKER_BLOCK_SIZE, h: BUNKER_BLOCK_SIZE }); } } } } scoreEl.innerText = score; livesEl.innerText = lives; } function drawPlayer() { ctx.fillStyle = '#0f0'; ctx.fillRect(player.x, player.y + 5, PLAYER_WIDTH, PLAYER_HEIGHT - 5); ctx.fillRect(player.x + PLAYER_WIDTH / 2 - 3, player.y, 6, 5); } function drawAliens() { aliens.forEach(alien => { ctx.fillStyle = alien.type === 0 ? '#f0f' : (alien.type >= 3 ? '#0ff' : '#ff0'); if (alien.type === 0) { ctx.fillRect(alien.x + 5, alien.y, 20, 20); ctx.fillRect(alien.x, alien.y + 10, 5, 10); ctx.fillRect(alien.x + 25, alien.y + 10, 5, 10); ctx.fillRect(alien.x + 5, alien.y + 20, 5, 5); ctx.fillRect(alien.x + 20, alien.y + 20, 5, 5); } else if (alien.type >= 3) { ctx.fillRect(alien.x + 5, alien.y + 5, 20, 15); ctx.fillRect(alien.x, alien.y, 5, 5); ctx.fillRect(alien.x + 25, alien.y, 5, 5); ctx.fillRect(alien.x, alien.y + 20, 5, 5); ctx.fillRect(alien.x + 25, alien.y + 20, 5, 5); } else { ctx.fillRect(alien.x + 5, alien.y, 20, 20); ctx.fillRect(alien.x, alien.y + 5, 5, 10); ctx.fillRect(alien.x + 25, alien.y + 5, 5, 10); } }); } function drawBunkers() { ctx.fillStyle = '#0f0'; bunkers.forEach(b => { ctx.fillRect(b.x, b.y, b.w, b.h); }); } function drawBullets() { bullets.forEach(b => { ctx.fillStyle = b.owner === 'player' ? '#fff' : '#f00'; ctx.fillRect(b.x, b.y, 3, 10); }); } function update() { if (state !== 'PLAYING') return; if (keys['ArrowLeft'] && player.x > 0) player.x -= 5; if (keys['ArrowRight'] && player.x << canvas canvas.width - PLAYER_WIDTH) player.x += 5; const now = Date.now(); if (keys['Space'] && now - lastShotTime > 500) { bullets.push({ x: player.x + PLAYER_WIDTH / 2 - 1.5, y: player.y, dy: -BULLET_SPEED, owner: 'player' }); lastShotTime = now; } alienMoveTimer++; if (alienMoveTimer >= alienMoveInterval) { let hitEdge = false; aliens.forEach(a => { a.x += 10 * alienDirection; if (a.x + ALIEN_SIZE > canvas.width - 10 || a.x << 10) { hitEdge = true; } }); if (hitEdge) { alienDirection *= -1; aliens.forEach(a => { a.y += 20; }); alienMoveInterval = Math.max(10, 60 - ((ALIEN_ROWS * ALIEN_COLS - aliens.length) * 2)); } alienMoveTimer = 0; } if (Math.random() << 0.02 && aliens.length > 0) { const shooter = aliens[Math.floor(Math.random() * aliens.length)]; bullets.push({ x: shooter.x + ALIEN_SIZE / 2, y: shooter.y + ALIEN_SIZE, dy: ALIEN_BULLET_SPEED, owner: 'alien' }); } for (let i = bullets.length - 1; i >= 0; i--) { const b = bullets[i]; b.y += b.dy; if (b.y << 0 || b.y > canvas.height) { bullets.splice(i, 1); continue; } if (b.owner === 'player') { for (let j = aliens.length - 1; j >= 0; j--) { const a = aliens[j]; if (b.x > a.x && b.x << a a.x + a.width && b.y > a.y && b.y << a a.y + a.height) { aliens.splice(j, 1); bullets.splice(i, 1); score += 10; scoreEl.innerText = score; break; } } } else if (b.owner === 'alien') { if (b.x > player.x && b.x << player player.x + PLAYER_WIDTH && b.y > player.y && b.y << player player.y + PLAYER_HEIGHT) { bullets.splice(i, 1); lives--; livesEl.innerText = lives; if (lives <= 0) gameOver(false); continue; } } if (bullets[i]) { const bCurr = bullets[i]; for (let k = bunkers.length - 1; k >= 0; k--) { const bun = bunkers[k]; if (bCurr.x > bun.x && bCurr.x << bun bun.x + bun.w && bCurr.y > bun.y && bCurr.y << bun bun.y + bun.h) { bunkers.splice(k, 1); bullets.splice(i, 1); break; } } } } if (aliens.length === 0) gameOver(true); aliens.forEach(a => { if (a.y + a.height >= player.y) gameOver(false); }); } function gameOver(win) { state = win ? 'WIN' : 'GAMEOVER'; overlay.classList.remove('hidden'); overlayTitle.innerText = win ? 'YOU WON!' : 'GAME OVER'; overlayTitle.style.color = win ? '#0f0' : '#f00'; overlayDesc.innerHTML = `Final Score: ${score}`; startBtn.innerText = 'TRY AGAIN'; } function loop() { ctx.clearRect(0, 0, canvas.width, canvas.height); update(); drawBunkers(); drawPlayer(); drawAliens(); drawBullets(); requestAnimationFrame(loop); } startBtn.addEventListener('click', () => { overlay.classList.add('hidden'); initGame(); state = 'PLAYING'; }); loop();