<!DOCTYPE html><html lang="zh-CN"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>太空枪战</title> <style> body { margin: 0; padding: 20px; display: flex; flex-direction: column; align-items: center; background-color: #1a1a2e; font-family: Arial, sans-serif; color: #fff; } #gameCanvas { border: 2px solid #4CAF50; background-color: #16213e; cursor: none; } .game-stats { margin-bottom: 15px; font-size: 1.2em; } h1 { margin: 0 0 10px 0; } </style></head><body> <h1>🔫 太空枪战</h1> <div class="game-stats">分数:<span id="score">0</span></div> <canvas id="gameCanvas" width="600" height="500"></canvas> <div class="game-stats">⬅️ ➡️ 移动 | 空格键射击</div> <script> (function() { const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); const scoreElement = document.getElementById('score'); const player = { x: canvas.width / 2 - 25, y: canvas.height - 60, width: 50, height: 40, speed: 6, dx: 0 }; const bullets = []; const bulletConfig = { width: 4, height: 12, speed: 8, color: '#ff2e63' }; const enemies = []; const enemyConfig = { width: 40, height: 40, minSpeed: 2, maxSpeed: 5, color: '#08d9d6' }; let score = 0; let gameOver = false; let enemySpawnTimer = 0; let enemySpawnInterval = 40; const keys = {}; window.addEventListener('keydown', (e) => { keys[e.key] = true; if (e.key === ' ' || e.key === 'Spacebar') { e.preventDefault(); if (!gameOver) { fireBullet(); } else { resetGame(); } } }); window.addEventListener('keyup', (e) => { keys[e.key] = false; }); function fireBullet() { bullets.push({ x: player.x + player.width / 2 - bulletConfig.width / 2, y: player.y, width: bulletConfig.width, height: bulletConfig.height, color: bulletConfig.color }); } function spawnEnemy() { if (gameOver) return; const speed = enemyConfig.minSpeed + Math.random() * (enemyConfig.maxSpeed - enemyConfig.minSpeed); enemies.push({ x: Math.random() * (canvas.width - enemyConfig.width), y: -enemyConfig.height, width: enemyConfig.width, height: enemyConfig.height, speed: speed, color: enemyConfig.color }); } function rectCollision(r1, r2) { return r1.x < r2.x + r2.width && r1.x + r1.width > r2.x && r1.y < r2.y + r2.height && r1.y + r1.height > r2.y; } function resetGame() { score = 0; gameOver = false; bullets.length = 0; enemies.length = 0; player.x = canvas.width / 2 - player.width / 2; player.dx = 0; enemySpawnTimer = 0; enemySpawnInterval = 40; updateScore(); } function updateScore() { scoreElement.textContent = score; } function update() { if (gameOver) return; if (keys['ArrowLeft'] || keys['a'] || keys['A']) { player.dx = -player.speed; } else if (keys['ArrowRight'] || keys['d'] || keys['D']) { player.dx = player.speed; } else { player.dx = 0; } player.x += player.dx; if (player.x < 0) player.x = 0; if (player.x + player.width > canvas.width) player.x = canvas.width - player.width; for (let i = bullets.length - 1; i >= 0; i--) { bullets[i].y -= bulletConfig.speed; if (bullets[i].y + bullets[i].height < 0) { bullets.splice(i, 1); } } enemySpawnTimer++; if (enemySpawnTimer >= enemySpawnInterval) { enemySpawnTimer = 0; spawnEnemy(); enemySpawnInterval = Math.max(15, enemySpawnInterval - 0.2); } for (let i = enemies.length - 1; i >= 0; i--) { enemies[i].y += enemies[i].speed; if (enemies[i].y > canvas.height) { gameOver = true; break; } } for (let i = bullets.length - 1; i >= 0; i--) { for (let j = enemies.length - 1; j >= 0; j--) { if (rectCollision(bullets[i], enemies[j])) { bullets.splice(i, 1); enemies.splice(j, 1); score += 10; updateScore(); break; } } } const playerRect = { x: player.x, y: player.y, width: player.width, height: player.height }; for (let enemy of enemies) { if (rectCollision(playerRect, enemy)) { gameOver = true; break; } } } function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = '#4CAF50'; ctx.fillRect(player.x, player.y, player.width, player.height); ctx.fillStyle = '#ffeb3b'; ctx.fillRect(player.x + player.width / 2 - 3, player.y - 8, 6, 10); ctx.fillStyle = '#fff'; ctx.fillRect(player.x + 10, player.y + 10, 8, 8); ctx.fillRect(player.x + 32, player.y + 10, 8, 8); ctx.fillStyle = '#000'; ctx.fillRect(player.x + 14, player.y + 14, 4, 4); ctx.fillRect(player.x + 36, player.y + 14, 4, 4); for (let bullet of bullets) { ctx.fillStyle = bullet.color; ctx.fillRect(bullet.x, bullet.y, bullet.width, bullet.height); } for (let enemy of enemies) { ctx.fillStyle = enemy.color; ctx.fillRect(enemy.x, enemy.y, enemy.width, enemy.height); ctx.fillStyle = '#fff'; ctx.fillRect(enemy.x + 8, enemy.y + 10, 8, 8); ctx.fillRect(enemy.x + 24, enemy.y + 10, 8, 8); ctx.fillStyle = '#000'; ctx.fillRect(enemy.x + 12, enemy.y + 14, 4, 4); ctx.fillRect(enemy.x + 28, enemy.y + 14, 4, 4); } if (gameOver) { ctx.fillStyle = 'rgba(0, 0, 0, 0.7)'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = '#ff2e63'; ctx.font = 'bold 40px Arial'; ctx.textAlign = 'center'; ctx.fillText('游戏结束', canvas.width / 2, canvas.height / 2 - 20); ctx.fillStyle = '#fff'; ctx.font = '20px Arial'; ctx.fillText('按空格键重新开始', canvas.width / 2, canvas.height / 2 + 30); ctx.textAlign = 'start'; } } function gameLoop() { update(); draw(); requestAnimationFrame(gameLoop); } resetGame(); gameLoop(); })(); </script></body></html>