WEBLEB
Inicio
Editora de código
Iniciar sesión
Pro
Español
English
Français
Español
Português
Deutsch
Italiano
हिंदी
HTML
CSS
JS
Neon Strike - Futuristic Space Game
SCORE
0
SHIELDS
LEVEL
1
NEON STRIKE
Futuristic Space Combat
START MISSION
WASD or Arrow Keys - Move
SPACE - Fire Weapons
ESC - Pause
MISSION FAILED
FINAL SCORE:
0
RETRY MISSION
MISSION PAUSED
RESUME
MAIN MENU
* { margin: 0; padding: 0; box-sizing: border-box; } body { background: radial-gradient(ellipse at center, #0a0a0a 0%, #000000 100%); font-family: 'Courier New', monospace; color: #00ffff; overflow: hidden; height: 100vh; display: flex; justify-content: center; align-items: center; } .game-container { position: relative; border: 2px solid #00ffff; border-radius: 10px; box-shadow: 0 0 20px #00ffff, inset 0 0 20px rgba(0, 255, 255, 0.1); background: rgba(0, 0, 0, 0.8); padding: 20px; } #gameCanvas { display: block; background: linear-gradient(45deg, #000511 0%, #001122 50%, #000511 100%); border: 1px solid #003366; border-radius: 5px; box-shadow: inset 0 0 50px rgba(0, 100, 200, 0.2); } .hud { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; padding: 10px 20px; background: linear-gradient(90deg, rgba(0, 255, 255, 0.1) 0%, rgba(0, 100, 255, 0.1) 100%); border: 1px solid rgba(0, 255, 255, 0.3); border-radius: 25px; backdrop-filter: blur(10px); } .score-display, .level-display { text-align: center; } .label { font-size: 12px; color: #66ccff; margin-bottom: 5px; text-shadow: 0 0 10px #66ccff; } #score, #level { font-size: 24px; font-weight: bold; color: #00ffff; text-shadow: 0 0 15px #00ffff; } .health-display { display: flex; flex-direction: column; align-items: center; } .health-bar { width: 200px; height: 20px; border: 2px solid #00ff88; border-radius: 10px; background: rgba(0, 0, 0, 0.5); overflow: hidden; box-shadow: 0 0 10px #00ff88, inset 0 0 10px rgba(0, 255, 136, 0.2); } #health-fill { height: 100%; width: 100%; background: linear-gradient(90deg, #ff0066 0%, #ffff00 50%, #00ff88 100%); border-radius: 8px; transition: width 0.3s ease; box-shadow: 0 0 20px rgba(0, 255, 136, 0.8); } .game-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.9); display: flex; justify-content: center; align-items: center; backdrop-filter: blur(5px); } .menu { text-align: center; padding: 40px; border: 2px solid #00ffff; border-radius: 15px; background: rgba(0, 20, 40, 0.9); box-shadow: 0 0 30px #00ffff, inset 0 0 30px rgba(0, 255, 255, 0.1); } .game-title { font-size: 48px; color: #00ffff; margin-bottom: 10px; text-shadow: 0 0 20px #00ffff, 0 0 40px #0088ff; animation: glow 2s ease-in-out infinite alternate; } .game-subtitle { font-size: 16px; color: #66ccff; margin-bottom: 30px; text-shadow: 0 0 10px #66ccff; } .game-over-title, .pause-title { font-size: 36px; color: #ff6600; margin-bottom: 20px; text-shadow: 0 0 20px #ff6600, 0 0 40px #ff3300; } .final-score { font-size: 24px; color: #00ffff; margin-bottom: 30px; text-shadow: 0 0 15px #00ffff; } .menu-btn { background: linear-gradient(45deg, #003366, #0066cc); border: 2px solid #00ffff; color: #00ffff; padding: 15px 30px; font-size: 18px; font-family: 'Courier New', monospace; border-radius: 25px; cursor: pointer; margin: 10px; transition: all 0.3s ease; text-shadow: 0 0 10px #00ffff; box-shadow: 0 0 15px rgba(0, 255, 255, 0.3), inset 0 0 15px rgba(0, 255, 255, 0.1); } .menu-btn:hover { background: linear-gradient(45deg, #0066cc, #0099ff); box-shadow: 0 0 25px #00ffff, inset 0 0 25px rgba(0, 255, 255, 0.2); transform: translateY(-2px); } .controls-info { margin-top: 30px; font-size: 14px; color: #66ccff; line-height: 1.6; } .controls-info p { margin: 5px 0; text-shadow: 0 0 5px #66ccff; } .hidden { display: none !important; } @keyframes glow { from { text-shadow: 0 0 20px #00ffff, 0 0 40px #0088ff, 0 0 60px #0066cc; } to { text-shadow: 0 0 30px #00ffff, 0 0 60px #0088ff, 0 0 90px #0066cc; } } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.7; } } .pulse { animation: pulse 1s ease-in-out infinite; }
class Game { constructor() { this.canvas = document.getElementById('gameCanvas'); this.ctx = this.canvas.getContext('2d'); this.width = this.canvas.width; this.height = this.canvas.height; this.gameState = 'menu'; // menu, playing, paused, gameOver this.score = 0; this.level = 1; this.maxHealth = 100; this.health = this.maxHealth; this.player = new Player(this.width / 2, this.height - 60); this.enemies = []; this.bullets = []; this.particles = []; this.powerUps = []; this.keys = {}; this.lastTime = 0; this.enemySpawnTimer = 0; this.powerUpSpawnTimer = 0; this.levelProgressTimer = 0; this.enemySpawnRate = 2000; // milliseconds this.powerUpSpawnRate = 15000; this.levelProgressRate = 30000; this.stars = this.generateStars(); this.initEventListeners(); this.showMenu(); } generateStars() { const stars = []; for (let i = 0; i < 100; i++) { stars.push({ x: Math.random() * this.width, y: Math.random() * this.height, size: Math.random() * 2, speed: Math.random() * 0.5 + 0.1, brightness: Math.random() }); } return stars; } initEventListeners() { document.addEventListener('keydown', (e) => { this.keys[e.code] = true; if (e.code === 'Escape') { if (this.gameState === 'playing') { this.pauseGame(); } else if (this.gameState === 'paused') { this.resumeGame(); } } if (e.code === 'Space') { e.preventDefault(); if (this.gameState === 'playing') { this.player.shoot(this.bullets); } } }); document.addEventListener('keyup', (e) => { this.keys[e.code] = false; }); document.getElementById('startBtn').addEventListener('click', () => this.startGame()); document.getElementById('restartBtn').addEventListener('click', () => this.startGame()); document.getElementById('resumeBtn').addEventListener('click', () => this.resumeGame()); document.getElementById('mainMenuBtn').addEventListener('click', () => this.showMenu()); } showMenu() { this.gameState = 'menu'; document.getElementById('gameOverlay').classList.remove('hidden'); document.getElementById('startMenu').classList.remove('hidden'); document.getElementById('gameOverMenu').classList.add('hidden'); document.getElementById('pauseMenu').classList.add('hidden'); } startGame() { this.gameState = 'playing'; this.score = 0; this.level = 1; this.health = this.maxHealth; this.enemies = []; this.bullets = []; this.particles = []; this.powerUps = []; this.player.reset(this.width / 2, this.height - 60); this.enemySpawnTimer = 0; this.powerUpSpawnTimer = 0; this.levelProgressTimer = 0; this.enemySpawnRate = 2000; document.getElementById('gameOverlay').classList.add('hidden'); this.gameLoop(); } pauseGame() { this.gameState = 'paused'; document.getElementById('gameOverlay').classList.remove('hidden'); document.getElementById('pauseMenu').classList.remove('hidden'); document.getElementById('startMenu').classList.add('hidden'); document.getElementById('gameOverMenu').classList.add('hidden'); } resumeGame() { this.gameState = 'playing'; document.getElementById('gameOverlay').classList.add('hidden'); this.gameLoop(); } gameOver() { this.gameState = 'gameOver'; document.getElementById('finalScore').textContent = this.score; document.getElementById('gameOverlay').classList.remove('hidden'); document.getElementById('gameOverMenu').classList.remove('hidden'); document.getElementById('startMenu').classList.add('hidden'); document.getElementById('pauseMenu').classList.add('hidden'); } update(deltaTime) { // Update player this.player.update(this.keys, this.width, this.height); // Spawn enemies this.enemySpawnTimer += deltaTime; if (this.enemySpawnTimer >= this.enemySpawnRate) { this.spawnEnemy(); this.enemySpawnTimer = 0; } // Spawn power-ups this.powerUpSpawnTimer += deltaTime; if (this.powerUpSpawnTimer >= this.powerUpSpawnRate) { this.spawnPowerUp(); this.powerUpSpawnTimer = 0; } // Level progression this.levelProgressTimer += deltaTime; if (this.levelProgressTimer >= this.levelProgressRate) { this.level++; this.enemySpawnRate = Math.max(500, this.enemySpawnRate - 200); this.levelProgressTimer = 0; this.createLevelUpEffect(); } // Update bullets this.bullets.forEach((bullet, index) => { bullet.update(); if (bullet.y < 0 || bullet.y > this.height) { this.bullets.splice(index, 1); } }); // Update enemies this.enemies.forEach((enemy, index) => { enemy.update(this.player); if (enemy.y > this.height + 50) { this.enemies.splice(index, 1); } }); // Update particles this.particles.forEach((particle, index) => { particle.update(); if (particle.life <= 0) { this.particles.splice(index, 1); } }); // Update power-ups this.powerUps.forEach((powerUp, index) => { powerUp.update(); if (powerUp.y > this.height + 50) { this.powerUps.splice(index, 1); } }); // Update stars this.stars.forEach(star => { star.y += star.speed; if (star.y > this.height) { star.y = 0; star.x = Math.random() * this.width; } }); this.checkCollisions(); this.updateUI(); } spawnEnemy() { const types = ['basic', 'fast', 'heavy']; const type = types[Math.floor(Math.random() * types.length)]; const x = Math.random() * (this.width - 60) + 30; this.enemies.push(new Enemy(x, -30, type, this.level)); } spawnPowerUp() { const types = ['health', 'rapidFire', 'shield']; const type = types[Math.floor(Math.random() * types.length)]; const x = Math.random() * (this.width - 40) + 20; this.powerUps.push(new PowerUp(x, -20, type)); } checkCollisions() { // Bullet vs Enemy collisions this.bullets.forEach((bullet, bulletIndex) => { if (bullet.fromPlayer) { this.enemies.forEach((enemy, enemyIndex) => { if (this.isColliding(bullet, enemy)) { enemy.takeDamage(bullet.damage); this.createExplosion(bullet.x, bullet.y, '#00ffff'); this.bullets.splice(bulletIndex, 1); if (enemy.health <= 0) { this.score += enemy.points; this.createExplosion(enemy.x, enemy.y, '#ff6600'); this.enemies.splice(enemyIndex, 1); } } }); } }); // Enemy vs Player collisions this.enemies.forEach((enemy, index) => { if (this.isColliding(enemy, this.player)) { this.health -= enemy.damage; this.createExplosion(enemy.x, enemy.y, '#ff0066'); this.enemies.splice(index, 1); if (this.health <= 0) { this.gameOver(); } } }); // Enemy bullets vs Player collisions this.bullets.forEach((bullet, index) => { if (!bullet.fromPlayer && this.isColliding(bullet, this.player)) { this.health -= bullet.damage; this.createExplosion(bullet.x, bullet.y, '#ff0066'); this.bullets.splice(index, 1); if (this.health <= 0) { this.gameOver(); } } }); // PowerUp vs Player collisions this.powerUps.forEach((powerUp, index) => { if (this.isColliding(powerUp, this.player)) { this.applyPowerUp(powerUp.type); this.createExplosion(powerUp.x, powerUp.y, '#00ff88'); this.powerUps.splice(index, 1); } }); } isColliding(obj1, obj2) { return obj1.x < obj2.x + obj2.width && obj1.x + obj1.width > obj2.x && obj1.y < obj2.y + obj2.height && obj1.y + obj1.height > obj2.y; } applyPowerUp(type) { switch (type) { case 'health': this.health = Math.min(this.maxHealth, this.health + 30); break; case 'rapidFire': this.player.fireRate = Math.max(50, this.player.fireRate / 2); setTimeout(() => { this.player.fireRate = this.player.originalFireRate; }, 10000); break; case 'shield': this.player.shielded = true; setTimeout(() => { this.player.shielded = false; }, 8000); break; } } createExplosion(x, y, color) { for (let i = 0; i < 10; i++) { this.particles.push(new Particle(x, y, color)); } } createLevelUpEffect() { for (let i = 0; i < 20; i++) { this.particles.push(new Particle( Math.random() * this.width, Math.random() * this.height, '#00ff88', 'level' )); } } updateUI() { document.getElementById('score').textContent = this.score; document.getElementById('level').textContent = this.level; const healthPercentage = (this.health / this.maxHealth) * 100; document.getElementById('health-fill').style.width = healthPercentage + '%'; } render() { // Clear canvas this.ctx.fillStyle = 'rgba(0, 5, 17, 0.1)'; this.ctx.fillRect(0, 0, this.width, this.height); // Draw stars this.stars.forEach(star => { this.ctx.fillStyle = `rgba(255, 255, 255, ${star.brightness})`; this.ctx.fillRect(star.x, star.y, star.size, star.size); }); // Draw game objects this.particles.forEach(particle => particle.render(this.ctx)); this.powerUps.forEach(powerUp => powerUp.render(this.ctx)); this.bullets.forEach(bullet => bullet.render(this.ctx)); this.enemies.forEach(enemy => enemy.render(this.ctx)); this.player.render(this.ctx); } gameLoop(currentTime = 0) { if (this.gameState !== 'playing') return; const deltaTime = currentTime - this.lastTime; this.lastTime = currentTime; this.update(deltaTime); this.render(); requestAnimationFrame((time) => this.gameLoop(time)); } } class Player { constructor(x, y) { this.x = x; this.y = y; this.width = 40; this.height = 40; this.speed = 5; this.fireRate = 150; this.originalFireRate = 150; this.lastShot = 0; this.shielded = false; } reset(x, y) { this.x = x; this.y = y; this.fireRate = this.originalFireRate; this.shielded = false; } update(keys, canvasWidth, canvasHeight) { if (keys['ArrowLeft'] || keys['KeyA']) { this.x = Math.max(0, this.x - this.speed); } if (keys['ArrowRight'] || keys['KeyD']) { this.x = Math.min(canvasWidth - this.width, this.x + this.speed); } if (keys['ArrowUp'] || keys['KeyW']) { this.y = Math.max(0, this.y - this.speed); } if (keys['ArrowDown'] || keys['KeyS']) { this.y = Math.min(canvasHeight - this.height, this.y + this.speed); } } shoot(bullets) { const now = Date.now(); if (now - this.lastShot > this.fireRate) { bullets.push(new Bullet(this.x + this.width / 2, this.y, true)); this.lastShot = now; } } render(ctx) { // Draw ship body ctx.fillStyle = this.shielded ? '#00ff88' : '#00ffff'; ctx.fillRect(this.x, this.y, this.width, this.height); // Draw ship details ctx.fillStyle = '#ffffff'; ctx.fillRect(this.x + 5, this.y + 5, this.width - 10, this.height - 10); ctx.fillStyle = '#0066cc'; ctx.fillRect(this.x + 10, this.y + 10, this.width - 20, this.height - 20); // Draw shield effect if (this.shielded) { ctx.strokeStyle = '#00ff88'; ctx.lineWidth = 3; ctx.beginPath(); ctx.arc(this.x + this.width / 2, this.y + this.height / 2, this.width / 2 + 10, 0, Math.PI * 2); ctx.stroke(); } // Draw glow effect ctx.shadowColor = this.shielded ? '#00ff88' : '#00ffff'; ctx.shadowBlur = 20; ctx.fillStyle = this.shielded ? '#00ff88' : '#00ffff'; ctx.fillRect(this.x, this.y, this.width, this.height); ctx.shadowBlur = 0; } } class Enemy { constructor(x, y, type, level) { this.x = x; this.y = y; this.type = type; this.level = level; this.width = 30; this.height = 30; this.lastShot = 0; switch (type) { case 'basic': this.speed = 1 + level * 0.2; this.health = 1; this.maxHealth = 1; this.points = 10; this.damage = 10; this.fireRate = 2000; this.color = '#ff6600'; break; case 'fast': this.speed = 2 + level * 0.3; this.health = 1; this.maxHealth = 1; this.points = 15; this.damage = 8; this.fireRate = 1500; this.color = '#ff0066'; break; case 'heavy': this.speed = 0.5 + level * 0.1; this.health = 3; this.maxHealth = 3; this.points = 25; this.damage = 20; this.fireRate = 3000; this.color = '#ff3300'; this.width = 40; this.height = 40; break; } } update(player) { this.y += this.speed; // Simple AI - shoot at player occasionally const now = Date.now(); if (now - this.lastShot > this.fireRate && Math.random() < 0.3) { if (game.bullets) { game.bullets.push(new Bullet(this.x + this.width / 2, this.y + this.height, false)); } this.lastShot = now; } } takeDamage(damage) { this.health -= damage; } render(ctx) { // Draw enemy body ctx.fillStyle = this.color; ctx.fillRect(this.x, this.y, this.width, this.height); // Draw health bar for heavy enemies if (this.type === 'heavy') { const healthWidth = (this.health / this.maxHealth) * this.width; ctx.fillStyle = '#ff0000'; ctx.fillRect(this.x, this.y - 8, this.width, 4); ctx.fillStyle = '#00ff00'; ctx.fillRect(this.x, this.y - 8, healthWidth, 4); } // Draw glow effect ctx.shadowColor = this.color; ctx.shadowBlur = 15; ctx.fillStyle = this.color; ctx.fillRect(this.x, this.y, this.width, this.height); ctx.shadowBlur = 0; } } class Bullet { constructor(x, y, fromPlayer) { this.x = x; this.y = y; this.width = 4; this.height = 10; this.fromPlayer = fromPlayer; this.speed = fromPlayer ? -8 : 4; this.damage = 1; this.color = fromPlayer ? '#00ffff' : '#ff6600'; } update() { this.y += this.speed; } render(ctx) { ctx.fillStyle = this.color; ctx.fillRect(this.x - this.width / 2, this.y, this.width, this.height); // Draw glow effect ctx.shadowColor = this.color; ctx.shadowBlur = 10; ctx.fillStyle = this.color; ctx.fillRect(this.x - this.width / 2, this.y, this.width, this.height); ctx.shadowBlur = 0; } } class PowerUp { constructor(x, y, type) { this.x = x; this.y = y; this.width = 20; this.height = 20; this.type = type; this.speed = 2; this.rotation = 0; switch (type) { case 'health': this.color = '#00ff88'; break; case 'rapidFire': this.color = '#ffff00'; break; case 'shield': this.color = '#00aaff'; break; } } update() { this.y += this.speed; this.rotation += 0.1; } render(ctx) { ctx.save(); ctx.translate(this.x + this.width / 2, this.y + this.height / 2); ctx.rotate(this.rotation); ctx.fillStyle = this.color; ctx.fillRect(-this.width / 2, -this.height / 2, this.width, this.height); // Draw glow effect ctx.shadowColor = this.color; ctx.shadowBlur = 15; ctx.fillStyle = this.color; ctx.fillRect(-this.width / 2, -this.height / 2, this.width, this.height); ctx.shadowBlur = 0; ctx.restore(); } } class Particle { constructor(x, y, color, type = 'explosion') { this.x = x; this.y = y; this.color = color; this.type = type; this.life = 1.0; this.decay = Math.random() * 0.02 + 0.01; if (type === 'explosion') { this.vx = (Math.random() - 0.5) * 10; this.vy = (Math.random() - 0.5) * 10; this.size = Math.random() * 4 + 2; } else if (type === 'level') { this.vx = (Math.random() - 0.5) * 5; this.vy = Math.random() * -3 - 1; this.size = Math.random() * 6 + 3; } } update() { this.x += this.vx; this.y += this.vy; this.life -= this.decay; if (this.type === 'explosion') { this.vx *= 0.98; this.vy *= 0.98; } } render(ctx) { ctx.save(); ctx.globalAlpha = this.life; ctx.fillStyle = this.color; ctx.fillRect(this.x, this.y, this.size, this.size); // Draw glow effect ctx.shadowColor = this.color; ctx.shadowBlur = 10; ctx.fillStyle = this.color; ctx.fillRect(this.x, this.y, this.size, this.size); ctx.shadowBlur = 0; ctx.restore(); } } // Initialize game let game; window.addEventListener('load', () => { game = new Game(); });
Validating your code, please wait...
HTML
CSS
JS
Neon Strike - Futuristic Space Game
SCORE
0
SHIELDS
LEVEL
1
NEON STRIKE
Futuristic Space Combat
START MISSION
WASD or Arrow Keys - Move
SPACE - Fire Weapons
ESC - Pause
MISSION FAILED
FINAL SCORE:
0
RETRY MISSION
MISSION PAUSED
RESUME
MAIN MENU
* { margin: 0; padding: 0; box-sizing: border-box; } body { background: radial-gradient(ellipse at center, #0a0a0a 0%, #000000 100%); font-family: 'Courier New', monospace; color: #00ffff; overflow: hidden; height: 100vh; display: flex; justify-content: center; align-items: center; } .game-container { position: relative; border: 2px solid #00ffff; border-radius: 10px; box-shadow: 0 0 20px #00ffff, inset 0 0 20px rgba(0, 255, 255, 0.1); background: rgba(0, 0, 0, 0.8); padding: 20px; } #gameCanvas { display: block; background: linear-gradient(45deg, #000511 0%, #001122 50%, #000511 100%); border: 1px solid #003366; border-radius: 5px; box-shadow: inset 0 0 50px rgba(0, 100, 200, 0.2); } .hud { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; padding: 10px 20px; background: linear-gradient(90deg, rgba(0, 255, 255, 0.1) 0%, rgba(0, 100, 255, 0.1) 100%); border: 1px solid rgba(0, 255, 255, 0.3); border-radius: 25px; backdrop-filter: blur(10px); } .score-display, .level-display { text-align: center; } .label { font-size: 12px; color: #66ccff; margin-bottom: 5px; text-shadow: 0 0 10px #66ccff; } #score, #level { font-size: 24px; font-weight: bold; color: #00ffff; text-shadow: 0 0 15px #00ffff; } .health-display { display: flex; flex-direction: column; align-items: center; } .health-bar { width: 200px; height: 20px; border: 2px solid #00ff88; border-radius: 10px; background: rgba(0, 0, 0, 0.5); overflow: hidden; box-shadow: 0 0 10px #00ff88, inset 0 0 10px rgba(0, 255, 136, 0.2); } #health-fill { height: 100%; width: 100%; background: linear-gradient(90deg, #ff0066 0%, #ffff00 50%, #00ff88 100%); border-radius: 8px; transition: width 0.3s ease; box-shadow: 0 0 20px rgba(0, 255, 136, 0.8); } .game-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.9); display: flex; justify-content: center; align-items: center; backdrop-filter: blur(5px); } .menu { text-align: center; padding: 40px; border: 2px solid #00ffff; border-radius: 15px; background: rgba(0, 20, 40, 0.9); box-shadow: 0 0 30px #00ffff, inset 0 0 30px rgba(0, 255, 255, 0.1); } .game-title { font-size: 48px; color: #00ffff; margin-bottom: 10px; text-shadow: 0 0 20px #00ffff, 0 0 40px #0088ff; animation: glow 2s ease-in-out infinite alternate; } .game-subtitle { font-size: 16px; color: #66ccff; margin-bottom: 30px; text-shadow: 0 0 10px #66ccff; } .game-over-title, .pause-title { font-size: 36px; color: #ff6600; margin-bottom: 20px; text-shadow: 0 0 20px #ff6600, 0 0 40px #ff3300; } .final-score { font-size: 24px; color: #00ffff; margin-bottom: 30px; text-shadow: 0 0 15px #00ffff; } .menu-btn { background: linear-gradient(45deg, #003366, #0066cc); border: 2px solid #00ffff; color: #00ffff; padding: 15px 30px; font-size: 18px; font-family: 'Courier New', monospace; border-radius: 25px; cursor: pointer; margin: 10px; transition: all 0.3s ease; text-shadow: 0 0 10px #00ffff; box-shadow: 0 0 15px rgba(0, 255, 255, 0.3), inset 0 0 15px rgba(0, 255, 255, 0.1); } .menu-btn:hover { background: linear-gradient(45deg, #0066cc, #0099ff); box-shadow: 0 0 25px #00ffff, inset 0 0 25px rgba(0, 255, 255, 0.2); transform: translateY(-2px); } .controls-info { margin-top: 30px; font-size: 14px; color: #66ccff; line-height: 1.6; } .controls-info p { margin: 5px 0; text-shadow: 0 0 5px #66ccff; } .hidden { display: none !important; } @keyframes glow { from { text-shadow: 0 0 20px #00ffff, 0 0 40px #0088ff, 0 0 60px #0066cc; } to { text-shadow: 0 0 30px #00ffff, 0 0 60px #0088ff, 0 0 90px #0066cc; } } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.7; } } .pulse { animation: pulse 1s ease-in-out infinite; }
class Game { constructor() { this.canvas = document.getElementById('gameCanvas'); this.ctx = this.canvas.getContext('2d'); this.width = this.canvas.width; this.height = this.canvas.height; this.gameState = 'menu'; // menu, playing, paused, gameOver this.score = 0; this.level = 1; this.maxHealth = 100; this.health = this.maxHealth; this.player = new Player(this.width / 2, this.height - 60); this.enemies = []; this.bullets = []; this.particles = []; this.powerUps = []; this.keys = {}; this.lastTime = 0; this.enemySpawnTimer = 0; this.powerUpSpawnTimer = 0; this.levelProgressTimer = 0; this.enemySpawnRate = 2000; // milliseconds this.powerUpSpawnRate = 15000; this.levelProgressRate = 30000; this.stars = this.generateStars(); this.initEventListeners(); this.showMenu(); } generateStars() { const stars = []; for (let i = 0; i < 100; i++) { stars.push({ x: Math.random() * this.width, y: Math.random() * this.height, size: Math.random() * 2, speed: Math.random() * 0.5 + 0.1, brightness: Math.random() }); } return stars; } initEventListeners() { document.addEventListener('keydown', (e) => { this.keys[e.code] = true; if (e.code === 'Escape') { if (this.gameState === 'playing') { this.pauseGame(); } else if (this.gameState === 'paused') { this.resumeGame(); } } if (e.code === 'Space') { e.preventDefault(); if (this.gameState === 'playing') { this.player.shoot(this.bullets); } } }); document.addEventListener('keyup', (e) => { this.keys[e.code] = false; }); document.getElementById('startBtn').addEventListener('click', () => this.startGame()); document.getElementById('restartBtn').addEventListener('click', () => this.startGame()); document.getElementById('resumeBtn').addEventListener('click', () => this.resumeGame()); document.getElementById('mainMenuBtn').addEventListener('click', () => this.showMenu()); } showMenu() { this.gameState = 'menu'; document.getElementById('gameOverlay').classList.remove('hidden'); document.getElementById('startMenu').classList.remove('hidden'); document.getElementById('gameOverMenu').classList.add('hidden'); document.getElementById('pauseMenu').classList.add('hidden'); } startGame() { this.gameState = 'playing'; this.score = 0; this.level = 1; this.health = this.maxHealth; this.enemies = []; this.bullets = []; this.particles = []; this.powerUps = []; this.player.reset(this.width / 2, this.height - 60); this.enemySpawnTimer = 0; this.powerUpSpawnTimer = 0; this.levelProgressTimer = 0; this.enemySpawnRate = 2000; document.getElementById('gameOverlay').classList.add('hidden'); this.gameLoop(); } pauseGame() { this.gameState = 'paused'; document.getElementById('gameOverlay').classList.remove('hidden'); document.getElementById('pauseMenu').classList.remove('hidden'); document.getElementById('startMenu').classList.add('hidden'); document.getElementById('gameOverMenu').classList.add('hidden'); } resumeGame() { this.gameState = 'playing'; document.getElementById('gameOverlay').classList.add('hidden'); this.gameLoop(); } gameOver() { this.gameState = 'gameOver'; document.getElementById('finalScore').textContent = this.score; document.getElementById('gameOverlay').classList.remove('hidden'); document.getElementById('gameOverMenu').classList.remove('hidden'); document.getElementById('startMenu').classList.add('hidden'); document.getElementById('pauseMenu').classList.add('hidden'); } update(deltaTime) { // Update player this.player.update(this.keys, this.width, this.height); // Spawn enemies this.enemySpawnTimer += deltaTime; if (this.enemySpawnTimer >= this.enemySpawnRate) { this.spawnEnemy(); this.enemySpawnTimer = 0; } // Spawn power-ups this.powerUpSpawnTimer += deltaTime; if (this.powerUpSpawnTimer >= this.powerUpSpawnRate) { this.spawnPowerUp(); this.powerUpSpawnTimer = 0; } // Level progression this.levelProgressTimer += deltaTime; if (this.levelProgressTimer >= this.levelProgressRate) { this.level++; this.enemySpawnRate = Math.max(500, this.enemySpawnRate - 200); this.levelProgressTimer = 0; this.createLevelUpEffect(); } // Update bullets this.bullets.forEach((bullet, index) => { bullet.update(); if (bullet.y < 0 || bullet.y > this.height) { this.bullets.splice(index, 1); } }); // Update enemies this.enemies.forEach((enemy, index) => { enemy.update(this.player); if (enemy.y > this.height + 50) { this.enemies.splice(index, 1); } }); // Update particles this.particles.forEach((particle, index) => { particle.update(); if (particle.life <= 0) { this.particles.splice(index, 1); } }); // Update power-ups this.powerUps.forEach((powerUp, index) => { powerUp.update(); if (powerUp.y > this.height + 50) { this.powerUps.splice(index, 1); } }); // Update stars this.stars.forEach(star => { star.y += star.speed; if (star.y > this.height) { star.y = 0; star.x = Math.random() * this.width; } }); this.checkCollisions(); this.updateUI(); } spawnEnemy() { const types = ['basic', 'fast', 'heavy']; const type = types[Math.floor(Math.random() * types.length)]; const x = Math.random() * (this.width - 60) + 30; this.enemies.push(new Enemy(x, -30, type, this.level)); } spawnPowerUp() { const types = ['health', 'rapidFire', 'shield']; const type = types[Math.floor(Math.random() * types.length)]; const x = Math.random() * (this.width - 40) + 20; this.powerUps.push(new PowerUp(x, -20, type)); } checkCollisions() { // Bullet vs Enemy collisions this.bullets.forEach((bullet, bulletIndex) => { if (bullet.fromPlayer) { this.enemies.forEach((enemy, enemyIndex) => { if (this.isColliding(bullet, enemy)) { enemy.takeDamage(bullet.damage); this.createExplosion(bullet.x, bullet.y, '#00ffff'); this.bullets.splice(bulletIndex, 1); if (enemy.health <= 0) { this.score += enemy.points; this.createExplosion(enemy.x, enemy.y, '#ff6600'); this.enemies.splice(enemyIndex, 1); } } }); } }); // Enemy vs Player collisions this.enemies.forEach((enemy, index) => { if (this.isColliding(enemy, this.player)) { this.health -= enemy.damage; this.createExplosion(enemy.x, enemy.y, '#ff0066'); this.enemies.splice(index, 1); if (this.health <= 0) { this.gameOver(); } } }); // Enemy bullets vs Player collisions this.bullets.forEach((bullet, index) => { if (!bullet.fromPlayer && this.isColliding(bullet, this.player)) { this.health -= bullet.damage; this.createExplosion(bullet.x, bullet.y, '#ff0066'); this.bullets.splice(index, 1); if (this.health <= 0) { this.gameOver(); } } }); // PowerUp vs Player collisions this.powerUps.forEach((powerUp, index) => { if (this.isColliding(powerUp, this.player)) { this.applyPowerUp(powerUp.type); this.createExplosion(powerUp.x, powerUp.y, '#00ff88'); this.powerUps.splice(index, 1); } }); } isColliding(obj1, obj2) { return obj1.x < obj2.x + obj2.width && obj1.x + obj1.width > obj2.x && obj1.y < obj2.y + obj2.height && obj1.y + obj1.height > obj2.y; } applyPowerUp(type) { switch (type) { case 'health': this.health = Math.min(this.maxHealth, this.health + 30); break; case 'rapidFire': this.player.fireRate = Math.max(50, this.player.fireRate / 2); setTimeout(() => { this.player.fireRate = this.player.originalFireRate; }, 10000); break; case 'shield': this.player.shielded = true; setTimeout(() => { this.player.shielded = false; }, 8000); break; } } createExplosion(x, y, color) { for (let i = 0; i < 10; i++) { this.particles.push(new Particle(x, y, color)); } } createLevelUpEffect() { for (let i = 0; i < 20; i++) { this.particles.push(new Particle( Math.random() * this.width, Math.random() * this.height, '#00ff88', 'level' )); } } updateUI() { document.getElementById('score').textContent = this.score; document.getElementById('level').textContent = this.level; const healthPercentage = (this.health / this.maxHealth) * 100; document.getElementById('health-fill').style.width = healthPercentage + '%'; } render() { // Clear canvas this.ctx.fillStyle = 'rgba(0, 5, 17, 0.1)'; this.ctx.fillRect(0, 0, this.width, this.height); // Draw stars this.stars.forEach(star => { this.ctx.fillStyle = `rgba(255, 255, 255, ${star.brightness})`; this.ctx.fillRect(star.x, star.y, star.size, star.size); }); // Draw game objects this.particles.forEach(particle => particle.render(this.ctx)); this.powerUps.forEach(powerUp => powerUp.render(this.ctx)); this.bullets.forEach(bullet => bullet.render(this.ctx)); this.enemies.forEach(enemy => enemy.render(this.ctx)); this.player.render(this.ctx); } gameLoop(currentTime = 0) { if (this.gameState !== 'playing') return; const deltaTime = currentTime - this.lastTime; this.lastTime = currentTime; this.update(deltaTime); this.render(); requestAnimationFrame((time) => this.gameLoop(time)); } } class Player { constructor(x, y) { this.x = x; this.y = y; this.width = 40; this.height = 40; this.speed = 5; this.fireRate = 150; this.originalFireRate = 150; this.lastShot = 0; this.shielded = false; } reset(x, y) { this.x = x; this.y = y; this.fireRate = this.originalFireRate; this.shielded = false; } update(keys, canvasWidth, canvasHeight) { if (keys['ArrowLeft'] || keys['KeyA']) { this.x = Math.max(0, this.x - this.speed); } if (keys['ArrowRight'] || keys['KeyD']) { this.x = Math.min(canvasWidth - this.width, this.x + this.speed); } if (keys['ArrowUp'] || keys['KeyW']) { this.y = Math.max(0, this.y - this.speed); } if (keys['ArrowDown'] || keys['KeyS']) { this.y = Math.min(canvasHeight - this.height, this.y + this.speed); } } shoot(bullets) { const now = Date.now(); if (now - this.lastShot > this.fireRate) { bullets.push(new Bullet(this.x + this.width / 2, this.y, true)); this.lastShot = now; } } render(ctx) { // Draw ship body ctx.fillStyle = this.shielded ? '#00ff88' : '#00ffff'; ctx.fillRect(this.x, this.y, this.width, this.height); // Draw ship details ctx.fillStyle = '#ffffff'; ctx.fillRect(this.x + 5, this.y + 5, this.width - 10, this.height - 10); ctx.fillStyle = '#0066cc'; ctx.fillRect(this.x + 10, this.y + 10, this.width - 20, this.height - 20); // Draw shield effect if (this.shielded) { ctx.strokeStyle = '#00ff88'; ctx.lineWidth = 3; ctx.beginPath(); ctx.arc(this.x + this.width / 2, this.y + this.height / 2, this.width / 2 + 10, 0, Math.PI * 2); ctx.stroke(); } // Draw glow effect ctx.shadowColor = this.shielded ? '#00ff88' : '#00ffff'; ctx.shadowBlur = 20; ctx.fillStyle = this.shielded ? '#00ff88' : '#00ffff'; ctx.fillRect(this.x, this.y, this.width, this.height); ctx.shadowBlur = 0; } } class Enemy { constructor(x, y, type, level) { this.x = x; this.y = y; this.type = type; this.level = level; this.width = 30; this.height = 30; this.lastShot = 0; switch (type) { case 'basic': this.speed = 1 + level * 0.2; this.health = 1; this.maxHealth = 1; this.points = 10; this.damage = 10; this.fireRate = 2000; this.color = '#ff6600'; break; case 'fast': this.speed = 2 + level * 0.3; this.health = 1; this.maxHealth = 1; this.points = 15; this.damage = 8; this.fireRate = 1500; this.color = '#ff0066'; break; case 'heavy': this.speed = 0.5 + level * 0.1; this.health = 3; this.maxHealth = 3; this.points = 25; this.damage = 20; this.fireRate = 3000; this.color = '#ff3300'; this.width = 40; this.height = 40; break; } } update(player) { this.y += this.speed; // Simple AI - shoot at player occasionally const now = Date.now(); if (now - this.lastShot > this.fireRate && Math.random() < 0.3) { if (game.bullets) { game.bullets.push(new Bullet(this.x + this.width / 2, this.y + this.height, false)); } this.lastShot = now; } } takeDamage(damage) { this.health -= damage; } render(ctx) { // Draw enemy body ctx.fillStyle = this.color; ctx.fillRect(this.x, this.y, this.width, this.height); // Draw health bar for heavy enemies if (this.type === 'heavy') { const healthWidth = (this.health / this.maxHealth) * this.width; ctx.fillStyle = '#ff0000'; ctx.fillRect(this.x, this.y - 8, this.width, 4); ctx.fillStyle = '#00ff00'; ctx.fillRect(this.x, this.y - 8, healthWidth, 4); } // Draw glow effect ctx.shadowColor = this.color; ctx.shadowBlur = 15; ctx.fillStyle = this.color; ctx.fillRect(this.x, this.y, this.width, this.height); ctx.shadowBlur = 0; } } class Bullet { constructor(x, y, fromPlayer) { this.x = x; this.y = y; this.width = 4; this.height = 10; this.fromPlayer = fromPlayer; this.speed = fromPlayer ? -8 : 4; this.damage = 1; this.color = fromPlayer ? '#00ffff' : '#ff6600'; } update() { this.y += this.speed; } render(ctx) { ctx.fillStyle = this.color; ctx.fillRect(this.x - this.width / 2, this.y, this.width, this.height); // Draw glow effect ctx.shadowColor = this.color; ctx.shadowBlur = 10; ctx.fillStyle = this.color; ctx.fillRect(this.x - this.width / 2, this.y, this.width, this.height); ctx.shadowBlur = 0; } } class PowerUp { constructor(x, y, type) { this.x = x; this.y = y; this.width = 20; this.height = 20; this.type = type; this.speed = 2; this.rotation = 0; switch (type) { case 'health': this.color = '#00ff88'; break; case 'rapidFire': this.color = '#ffff00'; break; case 'shield': this.color = '#00aaff'; break; } } update() { this.y += this.speed; this.rotation += 0.1; } render(ctx) { ctx.save(); ctx.translate(this.x + this.width / 2, this.y + this.height / 2); ctx.rotate(this.rotation); ctx.fillStyle = this.color; ctx.fillRect(-this.width / 2, -this.height / 2, this.width, this.height); // Draw glow effect ctx.shadowColor = this.color; ctx.shadowBlur = 15; ctx.fillStyle = this.color; ctx.fillRect(-this.width / 2, -this.height / 2, this.width, this.height); ctx.shadowBlur = 0; ctx.restore(); } } class Particle { constructor(x, y, color, type = 'explosion') { this.x = x; this.y = y; this.color = color; this.type = type; this.life = 1.0; this.decay = Math.random() * 0.02 + 0.01; if (type === 'explosion') { this.vx = (Math.random() - 0.5) * 10; this.vy = (Math.random() - 0.5) * 10; this.size = Math.random() * 4 + 2; } else if (type === 'level') { this.vx = (Math.random() - 0.5) * 5; this.vy = Math.random() * -3 - 1; this.size = Math.random() * 6 + 3; } } update() { this.x += this.vx; this.y += this.vy; this.life -= this.decay; if (this.type === 'explosion') { this.vx *= 0.98; this.vy *= 0.98; } } render(ctx) { ctx.save(); ctx.globalAlpha = this.life; ctx.fillStyle = this.color; ctx.fillRect(this.x, this.y, this.size, this.size); // Draw glow effect ctx.shadowColor = this.color; ctx.shadowBlur = 10; ctx.fillStyle = this.color; ctx.fillRect(this.x, this.y, this.size, this.size); ctx.shadowBlur = 0; ctx.restore(); } } // Initialize game let game; window.addEventListener('load', () => { game = new Game(); });