Mystery Game #10

← Back to Games List
// Missile Command Game Implementation const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); // Game settings canvas.width = 800; canvas.height = 600; const groundHeight = 40; const baseWidth = 40; const baseHeight = 20; // Game objects const bases = [ { x: 100, y: canvas.height - groundHeight - baseHeight, ammo: 10 }, { x: canvas.width/2, y: canvas.height - groundHeight - baseHeight, ammo: 10 }, { x: canvas.width - 100, y: canvas.height - groundHeight - baseHeight, ammo: 10 } ]; const cities = [ { x: 200, y: canvas.height - groundHeight - 30, alive: true }, { x: 300, y: canvas.height - groundHeight - 30, alive: true }, { x: 500, y: canvas.height - groundHeight - 30, alive: true }, { x: 600, y: canvas.height - groundHeight - 30, alive: true } ]; let missiles = []; let enemyMissiles = []; let explosions = []; let score = 0; let gameOver = false; let mouseX = 0; let mouseY = 0; let selectedBase = 1; // Middle base selected by default // Track mouse position canvas.addEventListener('mousemove', (e) => { const rect = canvas.getBoundingClientRect(); mouseX = e.clientX - rect.left; mouseY = e.clientY - rect.top; }); // Handle click to fire canvas.addEventListener('click', (e) => { if (gameOver) { resetGame(); return; } if (bases[selectedBase].ammo > 0) { const base = bases[selectedBase]; missiles.push({ x: base.x, y: base.y, targetX: mouseX, targetY: mouseY, speed: 5, dx: 0, dy: 0 }); bases[selectedBase].ammo--; // Calculate direction const angle = Math.atan2(mouseY - base.y, mouseX - base.x); missiles[missiles.length-1].dx = Math.cos(angle) * 5; missiles[missiles.length-1].dy = Math.sin(angle) * 5; } }); // Switch bases with number keys document.addEventListener('keydown', (e) => { if (e.key >= '1' && e.key <= '3') { selectedBase = parseInt(e.key) - 1; } }); function spawnEnemyMissile() { const startX = Math.random() * canvas.width; let targetX; let targetY; // Target either a city or base if (Math.random() < 0.7) { // 70% chance to target a city const aliveCities = cities.filter(city => city.alive); if (aliveCities.length > 0) { const target = aliveCities[Math.floor(Math.random() * aliveCities.length)]; targetX = target.x; targetY = target.y; } } else { // 30% chance to target a base const target = bases[Math.floor(Math.random() * bases.length)]; targetX = target.x; targetY = target.y; } if (targetX !== undefined) { enemyMissiles.push({ x: startX, y: 0, targetX: targetX, targetY: targetY, speed: 2, dx: 0, dy: 0 }); // Calculate direction const angle = Math.atan2(targetY, targetX - startX); enemyMissiles[enemyMissiles.length-1].dx = Math.cos(angle) * 2; enemyMissiles[enemyMissiles.length-1].dy = Math.sin(angle) * 2; } } function updateMissiles() { // Update player missiles for (let i = missiles.length - 1; i >= 0; i--) { const missile = missiles[i]; missile.x += missile.dx; missile.y += missile.dy; // Check if missile reached target const dx = missile.x - missile.targetX; const dy = missile.y - missile.targetY; if (Math.sqrt(dx * dx + dy * dy) < 5) { explosions.push({ x: missile.x, y: missile.y, radius: 0, maxRadius: 30, growing: true }); missiles.splice(i, 1); } } // Update enemy missiles for (let i = enemyMissiles.length - 1; i >= 0; i--) { const missile = enemyMissiles[i]; missile.x += missile.dx; missile.y += missile.dy; // Check collision with explosions for (const explosion of explosions) { const dx = missile.x - explosion.x; const dy = missile.y - explosion.y; if (Math.sqrt(dx * dx + dy * dy) < explosion.radius) { enemyMissiles.splice(i, 1); score += 10; break; } } // Check if missile hit ground if (missile.y >= canvas.height - groundHeight) { explosions.push({ x: missile.x, y: missile.y, radius: 0, maxRadius: 30, growing: true }); enemyMissiles.splice(i, 1); // Check if explosion hit any cities or bases checkExplosionDamage(missile.x, missile.y); } } } function updateExplosions() { for (let i = explosions.length - 1; i >= 0; i--) { const explosion = explosions[i]; if (explosion.growing) { explosion.radius += 1; if (explosion.radius >= explosion.maxRadius) { explosion.growing = false; } } else { explosion.radius -= 0.5; if (explosion.radius <= 0) { explosions.splice(i, 1); } } } } function checkExplosionDamage(x, y) { const radius = 30; // Check cities cities.forEach(city => { if (city.alive) { const dx = city.x - x; const dy = city.y - y; if (Math.sqrt(dx * dx + dy * dy) < radius) { city.alive = false; } } }); // Check bases bases.forEach(base => { const dx = base.x - x; const dy = base.y - y; if (Math.sqrt(dx * dx + dy * dy) < radius) { base.ammo = 0; } }); // Check game over if (cities.every(city => !city.alive)) { gameOver = true; } } function draw() { // Clear canvas ctx.fillStyle = 'black'; ctx.fillRect(0, 0, canvas.width, canvas.height); // Draw ground ctx.fillStyle = '#333'; ctx.fillRect(0, canvas.height - groundHeight, canvas.width, groundHeight); // Draw bases bases.forEach((base, index) => { ctx.fillStyle = index === selectedBase ? '#0f0' : '#666'; ctx.fillRect(base.x - baseWidth/2, base.y, baseWidth, baseHeight); // Draw ammo count ctx.fillStyle = 'white'; ctx.font = '12px Arial'; ctx.textAlign = 'center'; ctx.fillText(base.ammo, base.x, base.y - 5); }); // Draw cities cities.forEach(city => { if (city.alive) { ctx.fillStyle = '#00f'; ctx.beginPath(); ctx.moveTo(city.x - 15, city.y + 30); ctx.lineTo(city.x, city.y); ctx.lineTo(city.x + 15, city.y + 30); ctx.fill(); } }); // Draw missiles ctx.strokeStyle = '#0f0'; ctx.lineWidth = 2; missiles.forEach(missile => { ctx.beginPath(); ctx.moveTo(missile.x, missile.y); ctx.lineTo(missile.x - missile.dx * 2, missile.y - missile.dy * 2); ctx.stroke(); }); // Draw enemy missiles ctx.strokeStyle = 'red'; enemyMissiles.forEach(missile => { ctx.beginPath(); ctx.moveTo(missile.x, missile.y); ctx.lineTo(missile.x - missile.dx * 2, missile.y - missile.dy * 2); ctx.stroke(); }); // Draw explosions explosions.forEach(explosion => { ctx.beginPath(); ctx.arc(explosion.x, explosion.y, explosion.radius, 0, Math.PI * 2); ctx.fillStyle = `rgba(255, 200, 0, ${0.5 * (explosion.radius / explosion.maxRadius)})`; ctx.fill(); }); // Draw score ctx.fillStyle = 'white'; ctx.font = '20px Arial'; ctx.textAlign = 'left'; ctx.fillText('Score: ' + score, 10, 30); // Draw game over if (gameOver) { ctx.fillStyle = 'rgba(0, 0, 0, 0.7)'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = 'white'; ctx.font = '40px Arial'; ctx.textAlign = 'center'; ctx.fillText('Game Over!', canvas.width/2, canvas.height/2 - 20); ctx.font = '20px Arial'; ctx.fillText('Final Score: ' + score, canvas.width/2, canvas.height/2 + 20); ctx.fillText('Click to Play Again', canvas.width/2, canvas.height/2 + 50); } } function resetGame() { missiles = []; enemyMissiles = []; explosions = []; score = 0; gameOver = false; // Reset bases bases.forEach(base => base.ammo = 10); // Reset cities cities.forEach(city => city.alive = true); } function gameLoop() { if (!gameOver) { // Spawn enemy missiles if (Math.random() < 0.02) { // 2% chance each frame spawnEnemyMissile(); } updateMissiles(); updateExplosions(); } draw(); requestAnimationFrame(gameLoop); } // Start game gameLoop();
# Missile Command Game Implementation import pygame import random import math from dataclasses import dataclass from typing import List, Tuple @dataclass class Base: x: int y: int ammo: int = 10 @dataclass class City: x: int y: int alive: bool = True @dataclass class Missile: x: float y: float target_x: float target_y: float speed: float dx: float = 0.0 dy: float = 0.0 @dataclass class Explosion: x: float y: float radius: float = 0.0 max_radius: float = 30.0 growing: bool = True class MissileCommand: def __init__(self): pygame.init() # Game settings self.width = 800 self.height = 600 self.ground_height = 40 self.base_width = 40 self.base_height = 20 # Initialize display self.screen = pygame.display.set_mode((self.width, self.height)) pygame.display.set_caption('Missile Command') self.clock = pygame.time.Clock() # Game objects self.bases = [ Base(100, self.height - self.ground_height - self.base_height), Base(self.width//2, self.height - self.ground_height - self.base_height), Base(self.width - 100, self.height - self.ground_height - self.base_height) ] self.cities = [ City(200, self.height - self.ground_height - 30), City(300, self.height - self.ground_height - 30), City(500, self.height - self.ground_height - 30), City(600, self.height - self.ground_height - 30) ] self.missiles: List[Missile] = [] self.enemy_missiles: List[Missile] = [] self.explosions: List[Explosion] = [] # Game state self.score = 0 self.game_over = False self.selected_base = 1 # Middle base selected by default self.mouse_x = 0 self.mouse_y = 0 def handle_input(self) -> bool: for event in pygame.event.get(): if event.type == pygame.QUIT: return False if event.type == pygame.MOUSEMOTION: self.mouse_x, self.mouse_y = event.pos if event.type == pygame.MOUSEBUTTONDOWN: if self.game_over: self.reset_game() else: self.fire_missile() if event.type == pygame.KEYDOWN: if event.unicode in ['1', '2', '3']: self.selected_base = int(event.unicode) - 1 return True def fire_missile(self): base = self.bases[self.selected_base] if base.ammo > 0: # Calculate direction angle = math.atan2(self.mouse_y - base.y, self.mouse_x - base.x) dx = math.cos(angle) * 5 dy = math.sin(angle) * 5 self.missiles.append( Missile(base.x, base.y, self.mouse_x, self.mouse_y, 5, dx, dy)) base.ammo -= 1 def spawn_enemy_missile(self): start_x = random.random() * self.width target_x = None target_y = None # Target either a city or base if random.random() < 0.7: # 70% chance to target a city alive_cities = [city for city in self.cities if city.alive] if alive_cities: target = random.choice(alive_cities) target_x = target.x target_y = target.y else: # 30% chance to target a base target = random.choice(self.bases) target_x = target.x target_y = target.y if target_x is not None: # Calculate direction angle = math.atan2(target_y, target_x - start_x) dx = math.cos(angle) * 2 dy = math.sin(angle) * 2 self.enemy_missiles.append( Missile(start_x, 0, target_x, target_y, 2, dx, dy)) def update_missiles(self): # Update player missiles for missile in self.missiles[:]: missile.x += missile.dx missile.y += missile.dy # Check if missile reached target dx = missile.x - missile.target_x dy = missile.y - missile.target_y if math.sqrt(dx * dx + dy * dy) < 5: self.explosions.append(Explosion(missile.x, missile.y)) self.missiles.remove(missile) # Update enemy missiles for missile in self.enemy_missiles[:]: missile.x += missile.dx missile.y += missile.dy # Check collision with explosions for explosion in self.explosions: dx = missile.x - explosion.x dy = missile.y - explosion.y if math.sqrt(dx * dx + dy * dy) < explosion.radius: self.enemy_missiles.remove(missile) self.score += 10 break # Check if missile hit ground if missile in self.enemy_missiles and missile.y >= self.height - self.ground_height: self.explosions.append(Explosion(missile.x, missile.y)) self.enemy_missiles.remove(missile) self.check_explosion_damage(missile.x, missile.y) def update_explosions(self): for explosion in self.explosions[:]: if explosion.growing: explosion.radius += 1 if explosion.radius >= explosion.max_radius: explosion.growing = False else: explosion.radius -= 0.5 if explosion.radius <= 0: self.explosions.remove(explosion) def check_explosion_damage(self, x: float, y: float): radius = 30 # Check cities for city in self.cities: if city.alive: dx = city.x - x dy = city.y - y if math.sqrt(dx * dx + dy * dy) < radius: city.alive = False # Check bases for base in self.bases: dx = base.x - x dy = base.y - y if math.sqrt(dx * dx + dy * dy) < radius: base.ammo = 0 # Check game over if not any(city.alive for city in self.cities): self.game_over = True def draw(self): # Clear screen self.screen.fill((0, 0, 0)) # Draw ground pygame.draw.rect(self.screen, (51, 51, 51), (0, self.height - self.ground_height, self.width, self.ground_height)) # Draw bases for i, base in enumerate(self.bases): color = (0, 255, 0) if i == self.selected_base else (102, 102, 102) pygame.draw.rect(self.screen, color, (base.x - self.base_width//2, base.y, self.base_width, self.base_height)) # Draw ammo count font = pygame.font.Font(None, 24) text = font.render(str(base.ammo), True, (255, 255, 255)) text_rect = text.get_rect(center=(base.x, base.y - 10)) self.screen.blit(text, text_rect) # Draw cities for city in self.cities: if city.alive: points = [ (city.x - 15, city.y + 30), (city.x, city.y), (city.x + 15, city.y + 30) ] pygame.draw.polygon(self.screen, (0, 0, 255), points) # Draw missiles for missile in self.missiles: pygame.draw.line(self.screen, (0, 255, 0), (missile.x, missile.y), (missile.x - missile.dx * 2, missile.y - missile.dy * 2), 2) # Draw enemy missiles for missile in self.enemy_missiles: pygame.draw.line(self.screen, (255, 0, 0), (missile.x, missile.y), (missile.x - missile.dx * 2, missile.y - missile.dy * 2), 2) # Draw explosions for explosion in self.explosions: alpha = int(128 * (explosion.radius / explosion.max_radius)) surface = pygame.Surface((explosion.radius * 2, explosion.radius * 2), pygame.SRCALPHA) pygame.draw.circle(surface, (255, 200, 0, alpha), (explosion.radius, explosion.radius), explosion.radius) self.screen.blit(surface, (explosion.x - explosion.radius, explosion.y - explosion.radius)) # Draw score font = pygame.font.Font(None, 36) score_text = font.render(f'Score: {self.score}', True, (255, 255, 255)) self.screen.blit(score_text, (10, 10)) # Draw game over if self.game_over: overlay = pygame.Surface((self.width, self.height)) overlay.fill((0, 0, 0)) overlay.set_alpha(178) # 70% opacity self.screen.blit(overlay, (0, 0)) font = pygame.font.Font(None, 64) game_over = font.render('Game Over!', True, (255, 255, 255)) game_over_rect = game_over.get_rect( center=(self.width//2, self.height//2 - 20)) self.screen.blit(game_over, game_over_rect) font = pygame.font.Font(None, 36) score = font.render(f'Final Score: {self.score}', True, (255, 255, 255)) score_rect = score.get_rect( center=(self.width//2, self.height//2 + 20)) self.screen.blit(score, score_rect) play_again = font.render('Click to Play Again', True, (255, 255, 255)) play_again_rect = play_again.get_rect( center=(self.width//2, self.height//2 + 50)) self.screen.blit(play_again, play_again_rect) pygame.display.flip() def reset_game(self): self.missiles.clear() self.enemy_missiles.clear() self.explosions.clear() self.score = 0 self.game_over = False # Reset bases for base in self.bases: base.ammo = 10 # Reset cities for city in self.cities: city.alive = True def run(self): running = True while running: running = self.handle_input() if not self.game_over: # Spawn enemy missiles if random.random() < 0.02: # 2% chance each frame self.spawn_enemy_missile() self.update_missiles() self.update_explosions() self.draw() self.clock.tick(60) pygame.quit() if __name__ == '__main__': game = MissileCommand() game.run()
Play Game