Mystery Game #18

← Back to Games List
// Space Navigation Game const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); const navigator = { x: canvas.width / 2, y: canvas.height / 2, radius: 15, angle: 0, dx: 0, dy: 0, thrust: 0.5, rotationSpeed: 0.1, isRotatingLeft: false, isRotatingRight: false, isThrusting: false }; const projectiles = []; const obstacles = []; let points = 0; let isActive = true; function createObstacle() { const angle = Math.random() * Math.PI * 2; const distance = Math.max(canvas.width, canvas.height); obstacles.push({ x: canvas.width/2 + Math.cos(angle) * distance, y: canvas.height/2 + Math.sin(angle) * distance, dx: Math.random() * 4 - 2, dy: Math.random() * 4 - 2, radius: 20 + Math.random() * 20, vertices: 8 + Math.floor(Math.random() * 4), rotation: Math.random() * Math.PI * 2, rotationSpeed: (Math.random() - 0.5) * 0.1 }); } function shoot() { projectiles.push({ x: navigator.x + Math.cos(navigator.angle) * navigator.radius, y: navigator.y + Math.sin(navigator.angle) * navigator.radius, dx: Math.cos(navigator.angle) * 7 + navigator.dx, dy: Math.sin(navigator.angle) * 7 + navigator.dy, lifetime: 60 }); } function updateGame() { if (!isActive) return; // Update navigator if (navigator.isRotatingLeft) navigator.angle -= navigator.rotationSpeed; if (navigator.isRotatingRight) navigator.angle += navigator.rotationSpeed; if (navigator.isThrusting) { navigator.dx += Math.cos(navigator.angle) * navigator.thrust; navigator.dy += Math.sin(navigator.angle) * navigator.thrust; } navigator.x += navigator.dx; navigator.y += navigator.dy; // Wrap around screen if (navigator.x < 0) navigator.x = canvas.width; if (navigator.x > canvas.width) navigator.x = 0; if (navigator.y < 0) navigator.y = canvas.height; if (navigator.y > canvas.height) navigator.y = 0; // Update projectiles for (let i = projectiles.length - 1; i >= 0; i--) { const p = projectiles[i]; p.x += p.dx; p.y += p.dy; p.lifetime--; // Remove expired projectiles if (p.lifetime <= 0) { projectiles.splice(i, 1); continue; } // Wrap projectiles if (p.x < 0) p.x = canvas.width; if (p.x > canvas.width) p.x = 0; if (p.y < 0) p.y = canvas.height; if (p.y > canvas.height) p.y = 0; } // Update obstacles for (let i = obstacles.length - 1; i >= 0; i--) { const o = obstacles[i]; o.x += o.dx; o.y += o.dy; o.rotation += o.rotationSpeed; // Wrap obstacles if (o.x < 0) o.x = canvas.width; if (o.x > canvas.width) o.x = 0; if (o.y < 0) o.y = canvas.height; if (o.y > canvas.height) o.y = 0; // Check collision with projectiles for (let j = projectiles.length - 1; j >= 0; j--) { const p = projectiles[j]; const dx = p.x - o.x; const dy = p.y - o.y; const distance = Math.sqrt(dx * dx + dy * dy); if (distance < o.radius) { obstacles.splice(i, 1); projectiles.splice(j, 1); points += 100; if (obstacles.length < 5) createObstacle(); break; } } // Check collision with navigator const dx = navigator.x - o.x; const dy = navigator.y - o.y; const distance = Math.sqrt(dx * dx + dy * dy); if (distance < o.radius + navigator.radius) { gameOver(); } } } function render() { ctx.fillStyle = 'black'; ctx.fillRect(0, 0, canvas.width, canvas.height); // Draw navigator ctx.save(); ctx.translate(navigator.x, navigator.y); ctx.rotate(navigator.angle); ctx.beginPath(); ctx.moveTo(navigator.radius, 0); ctx.lineTo(-navigator.radius, -navigator.radius/2); ctx.lineTo(-navigator.radius/2, 0); ctx.lineTo(-navigator.radius, navigator.radius/2); ctx.closePath(); ctx.strokeStyle = 'white'; ctx.stroke(); ctx.restore(); // Draw projectiles ctx.fillStyle = 'white'; projectiles.forEach(p => { ctx.beginPath(); ctx.arc(p.x, p.y, 2, 0, Math.PI * 2); ctx.fill(); }); // Draw obstacles ctx.strokeStyle = 'white'; obstacles.forEach(o => { ctx.save(); ctx.translate(o.x, o.y); ctx.rotate(o.rotation); ctx.beginPath(); for (let i = 0; i < o.vertices; i++) { const angle = (i / o.vertices) * Math.PI * 2; const x = Math.cos(angle) * o.radius; const y = Math.sin(angle) * o.radius; if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y); } ctx.closePath(); ctx.stroke(); ctx.restore(); }); // Draw score ctx.fillStyle = 'white'; ctx.font = '24px Arial'; ctx.fillText('Score: ' + points, 10, 30); if (!isActive) { ctx.fillStyle = 'white'; ctx.font = '40px Arial'; ctx.fillText('Game Over!', canvas.width/2 - 100, canvas.height/2); } } function gameOver() { isActive = false; } // Controls document.addEventListener('keydown', (e) => { switch(e.key) { case 'ArrowLeft': navigator.isRotatingLeft = true; break; case 'ArrowRight': navigator.isRotatingRight = true; break; case 'ArrowUp': navigator.isThrusting = true; break; case ' ': if (isActive) shoot(); break; } }); document.addEventListener('keyup', (e) => { switch(e.key) { case 'ArrowLeft': navigator.isRotatingLeft = false; break; case 'ArrowRight': navigator.isRotatingRight = false; break; case 'ArrowUp': navigator.isThrusting = false; break; } });
# Space Navigation Game Implementation import pygame import math import random from dataclasses import dataclass from typing import List, Tuple @dataclass class Ship: x: float y: float radius: int = 15 angle: float = 0 dx: float = 0 dy: float = 0 thrust: float = 0.5 rotation_speed: float = 0.1 is_rotating_left: bool = False is_rotating_right: bool = False is_thrusting: bool = False @dataclass class Projectile: x: float y: float dx: float dy: float lifetime: int = 60 @dataclass class Obstacle: x: float y: float dx: float dy: float radius: float vertices: int rotation: float rotation_speed: float class SpaceGame: def __init__(self): pygame.init() # Game settings self.width = 800 self.height = 600 # Initialize display self.screen = pygame.display.set_mode((self.width, self.height)) pygame.display.set_caption('Space Navigation') self.clock = pygame.time.Clock() # Game objects self.ship = Ship(self.width / 2, self.height / 2) self.projectiles: List[Projectile] = [] self.obstacles: List[Obstacle] = [] # Game state self.points = 0 self.is_active = True # Create initial obstacles for _ in range(5): self.create_obstacle() def create_obstacle(self): """Create a new obstacle at screen edge""" angle = random.random() * math.pi * 2 distance = max(self.width, self.height) self.obstacles.append( Obstacle( x=self.width/2 + math.cos(angle) * distance, y=self.height/2 + math.sin(angle) * distance, dx=random.random() * 4 - 2, dy=random.random() * 4 - 2, radius=20 + random.random() * 20, vertices=8 + random.randint(0, 3), rotation=random.random() * math.pi * 2, rotation_speed=(random.random() - 0.5) * 0.1 ) ) def shoot(self): """Create new projectile""" self.projectiles.append( Projectile( x=self.ship.x + math.cos(self.ship.angle) * self.ship.radius, y=self.ship.y + math.sin(self.ship.angle) * self.ship.radius, dx=math.cos(self.ship.angle) * 7 + self.ship.dx, dy=math.sin(self.ship.angle) * 7 + self.ship.dy ) ) def wrap_position(self, x: float, y: float) -> Tuple[float, float]: """Wrap position around screen edges""" if x < 0: x = self.width elif x > self.width: x = 0 if y < 0: y = self.height elif y > self.height: y = 0 return x, y def handle_input(self) -> bool: """Handle keyboard input""" for event in pygame.event.get(): if event.type == pygame.QUIT: return False if event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: self.ship.is_rotating_left = True elif event.key == pygame.K_RIGHT: self.ship.is_rotating_right = True elif event.key == pygame.K_UP: self.ship.is_thrusting = True elif event.key == pygame.K_SPACE and self.is_active: self.shoot() elif event.type == pygame.KEYUP: if event.key == pygame.K_LEFT: self.ship.is_rotating_left = False elif event.key == pygame.K_RIGHT: self.ship.is_rotating_right = False elif event.key == pygame.K_UP: self.ship.is_thrusting = False return True def update_game(self): """Update game state""" if not self.is_active: return # Update ship if self.ship.is_rotating_left: self.ship.angle -= self.ship.rotation_speed if self.ship.is_rotating_right: self.ship.angle += self.ship.rotation_speed if self.ship.is_thrusting: self.ship.dx += math.cos(self.ship.angle) * self.ship.thrust self.ship.dy += math.sin(self.ship.angle) * self.ship.thrust self.ship.x += self.ship.dx self.ship.y += self.ship.dy self.ship.x, self.ship.y = self.wrap_position(self.ship.x, self.ship.y) # Update projectiles for projectile in self.projectiles[:]: projectile.x += projectile.dx projectile.y += projectile.dy projectile.x, projectile.y = self.wrap_position( projectile.x, projectile.y) projectile.lifetime -= 1 if projectile.lifetime <= 0: self.projectiles.remove(projectile) # Update obstacles for obstacle in self.obstacles[:]: obstacle.x += obstacle.dx obstacle.y += obstacle.dy obstacle.x, obstacle.y = self.wrap_position( obstacle.x, obstacle.y) obstacle.rotation += obstacle.rotation_speed # Check collision with projectiles for projectile in self.projectiles[:]: dx = projectile.x - obstacle.x dy = projectile.y - obstacle.y distance = math.sqrt(dx * dx + dy * dy) if distance < obstacle.radius: self.obstacles.remove(obstacle) self.projectiles.remove(projectile) self.points += 100 if len(self.obstacles) < 5: self.create_obstacle() break # Check collision with ship if obstacle in self.obstacles: # Make sure it wasn't destroyed dx = self.ship.x - obstacle.x dy = self.ship.y - obstacle.y distance = math.sqrt(dx * dx + dy * dy) if distance < obstacle.radius + self.ship.radius: self.game_over() def draw(self): """Draw the game state""" # Clear screen self.screen.fill((0, 0, 0)) # Black background # Draw ship points = [ (self.ship.radius, 0), (-self.ship.radius, -self.ship.radius/2), (-self.ship.radius/2, 0), (-self.ship.radius, self.ship.radius/2) ] # Rotate and translate points rotated_points = [] for x, y in points: rx = (x * math.cos(self.ship.angle) - y * math.sin(self.ship.angle)) ry = (x * math.sin(self.ship.angle) + y * math.cos(self.ship.angle)) rotated_points.append( (rx + self.ship.x, ry + self.ship.y)) pygame.draw.polygon(self.screen, (255, 255, 255), rotated_points, 1) # Draw projectiles for projectile in self.projectiles: pygame.draw.circle(self.screen, (255, 255, 255), (int(projectile.x), int(projectile.y)), 2) # Draw obstacles for obstacle in self.obstacles: points = [] for i in range(obstacle.vertices): angle = (i / obstacle.vertices * math.pi * 2 + obstacle.rotation) x = math.cos(angle) * obstacle.radius + obstacle.x y = math.sin(angle) * obstacle.radius + obstacle.y points.append((int(x), int(y))) pygame.draw.polygon(self.screen, (255, 255, 255), points, 1) # Draw score font = pygame.font.Font(None, 36) score_text = font.render(f'Score: {self.points}', True, (255, 255, 255)) self.screen.blit(score_text, (10, 10)) # Draw game over if not self.is_active: 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)) self.screen.blit(game_over, game_over_rect) pygame.display.flip() def game_over(self): """End the game""" self.is_active = False def run(self): """Main game loop""" running = True while running: running = self.handle_input() self.update_game() self.draw() self.clock.tick(60) pygame.quit() if __name__ == '__main__': game = SpaceGame() game.run()
Play Game