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