Mystery Game #3
← Back to Games List
// Catapult Game Implementation
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// Game objects
const catapult = {
x: 50,
y: canvas.height - 50,
width: 30,
height: 30,
angle: 0,
power: 0
};
const projectile = {
x: catapult.x,
y: catapult.y,
radius: 5,
active: false,
dx: 0,
dy: 0
};
const targets = [];
const gravity = 0.5;
let isDragging = false;
let startX = 0;
let startY = 0;
let score = 0;
let shots = 0;
// Create targets
function createTargets() {
for (let i = 0; i < 3; i++) {
targets.push({
x: canvas.width - 200 + (i * 60),
y: canvas.height - 30 - (i * 40),
width: 30,
height: 30,
hit: false
});
}
}
// Mouse controls
canvas.addEventListener('mousedown', (e) => {
const rect = canvas.getBoundingClientRect();
startX = e.clientX - rect.left;
startY = e.clientY - rect.top;
if (!projectile.active) {
isDragging = true;
}
});
canvas.addEventListener('mousemove', (e) => {
if (isDragging && !projectile.active) {
const rect = canvas.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
const mouseY = e.clientY - rect.top;
// Calculate angle and power from drag distance
const dx = mouseX - startX;
const dy = mouseY - startY;
catapult.angle = Math.atan2(-dy, dx);
catapult.power = Math.min(Math.sqrt(dx * dx + dy * dy) / 10, 20);
}
});
canvas.addEventListener('mouseup', () => {
if (isDragging && !projectile.active) {
launchProjectile();
shots++;
}
isDragging = false;
});
function launchProjectile() {
projectile.x = catapult.x;
projectile.y = catapult.y;
projectile.dx = Math.cos(catapult.angle) * catapult.power;
projectile.dy = Math.sin(catapult.angle) * -catapult.power;
projectile.active = true;
}
function updateProjectile() {
if (projectile.active) {
projectile.x += projectile.dx;
projectile.y += projectile.dy;
projectile.dy += gravity;
// Check for collisions with targets
targets.forEach(target => {
if (!target.hit && checkCollision(projectile, target)) {
target.hit = true;
score += 100;
}
});
// Check if projectile is out of bounds
if (projectile.y > canvas.height ||
projectile.x < 0 ||
projectile.x > canvas.width) {
projectile.active = false;
}
}
}
function checkCollision(projectile, target) {
return projectile.x > target.x &&
projectile.x < target.x + target.width &&
projectile.y > target.y &&
projectile.y < target.y + target.height;
}
function draw() {
// Clear canvas
ctx.fillStyle = 'skyblue';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw ground
ctx.fillStyle = 'green';
ctx.fillRect(0, canvas.height - 20, canvas.width, 20);
// Draw catapult
ctx.save();
ctx.translate(catapult.x, catapult.y);
ctx.rotate(catapult.angle);
ctx.fillStyle = 'brown';
ctx.fillRect(0, -catapult.height/2, catapult.width, catapult.height);
ctx.restore();
// Draw aiming line when dragging
if (isDragging && !projectile.active) {
ctx.beginPath();
ctx.moveTo(catapult.x, catapult.y);
ctx.lineTo(
catapult.x + Math.cos(catapult.angle) * (catapult.power * 10),
catapult.y + Math.sin(catapult.angle) * (catapult.power * 10)
);
ctx.strokeStyle = 'rgba(255,255,255,0.5)';
ctx.stroke();
}
// Draw projectile
if (projectile.active) {
ctx.beginPath();
ctx.arc(projectile.x, projectile.y, projectile.radius, 0, Math.PI * 2);
ctx.fillStyle = 'black';
ctx.fill();
}
// Draw targets
targets.forEach(target => {
ctx.fillStyle = target.hit ? 'red' : 'orange';
ctx.fillRect(target.x, target.y, target.width, target.height);
});
// Draw score and shots
ctx.fillStyle = 'black';
ctx.font = '20px Arial';
ctx.fillText('Score: ' + score, 10, 30);
ctx.fillText('Shots: ' + shots, 10, 60);
// Check for win
if (targets.every(target => target.hit)) {
ctx.fillStyle = 'black';
ctx.font = '40px Arial';
ctx.fillText('You Win!', canvas.width/2 - 80, canvas.height/2);
}
}
function startGame() {
// Reset game state
targets.length = 0;
createTargets();
score = 0;
shots = 0;
projectile.active = false;
catapult.angle = 0;
catapult.power = 0;
// Start game loop
function gameLoop() {
updateProjectile();
draw();
requestAnimationFrame(gameLoop);
}
gameLoop();
}
# Catapult Game Implementation
import pygame
import math
from dataclasses import dataclass
from typing import List
@dataclass
class Catapult:
x: float
y: float
width: int = 30
height: int = 30
angle: float = 0
power: float = 0
@dataclass
class Projectile:
x: float
y: float
radius: int = 5
active: bool = False
dx: float = 0
dy: float = 0
@dataclass
class Target:
x: float
y: float
width: int = 30
height: int = 30
hit: bool = False
class CatapultGame:
def __init__(self):
pygame.init()
self.width = 800
self.height = 600
self.screen = pygame.display.set_mode((self.width, self.height))
pygame.display.set_caption('Catapult Game')
self.catapult = Catapult(50, self.height - 50)
self.projectile = Projectile(self.catapult.x, self.catapult.y)
self.targets: List[Target] = []
self.gravity = 0.5
self.is_dragging = False
self.start_x = 0
self.start_y = 0
self.score = 0
self.shots = 0
self.clock = pygame.time.Clock()
self.create_targets()
def create_targets(self):
for i in range(3):
self.targets.append(Target(
x=self.width - 200 + (i * 60),
y=self.height - 30 - (i * 40)
))
def handle_input(self) -> bool:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return False
if event.type == pygame.MOUSEBUTTONDOWN:
if not self.projectile.active:
self.start_x, self.start_y = pygame.mouse.get_pos()
self.is_dragging = True
elif event.type == pygame.MOUSEBUTTONUP:
if self.is_dragging and not self.projectile.active:
self.launch_projectile()
self.shots += 1
self.is_dragging = False
if self.is_dragging and not self.projectile.active:
mouse_x, mouse_y = pygame.mouse.get_pos()
dx = mouse_x - self.start_x
dy = mouse_y - self.start_y
self.catapult.angle = math.atan2(-dy, dx)
self.catapult.power = min(math.sqrt(dx * dx + dy * dy) / 10, 20)
return True
def launch_projectile(self):
self.projectile.x = self.catapult.x
self.projectile.y = self.catapult.y
self.projectile.dx = math.cos(self.catapult.angle) * self.catapult.power
self.projectile.dy = math.sin(self.catapult.angle) * -self.catapult.power
self.projectile.active = True
def update(self):
if self.projectile.active:
self.projectile.x += self.projectile.dx
self.projectile.y += self.projectile.dy
self.projectile.dy += self.gravity
# Check for collisions with targets
for target in self.targets:
if not target.hit and self.check_collision(self.projectile, target):
target.hit = True
self.score += 100
# Check if projectile is out of bounds
if (self.projectile.y > self.height or
self.projectile.x < 0 or
self.projectile.x > self.width):
self.projectile.active = False
def check_collision(self, projectile: Projectile, target: Target) -> bool:
return (projectile.x > target.x and
projectile.x < target.x + target.width and
projectile.y > target.y and
projectile.y < target.y + target.height)
def draw(self):
# Clear screen
self.screen.fill((135, 206, 235)) # skyblue
# Draw ground
pygame.draw.rect(self.screen, (0, 255, 0),
(0, self.height - 20, self.width, 20))
# Draw catapult
surface = pygame.Surface((self.catapult.width, self.catapult.height))
surface.fill((139, 69, 19)) # brown
rotated = pygame.transform.rotate(
surface, -math.degrees(self.catapult.angle))
rect = rotated.get_rect(
center=(self.catapult.x, self.catapult.y))
self.screen.blit(rotated, rect)
# Draw aiming line
if self.is_dragging and not self.projectile.active:
end_x = (self.catapult.x +
math.cos(self.catapult.angle) *
(self.catapult.power * 10))
end_y = (self.catapult.y +
math.sin(self.catapult.angle) *
(self.catapult.power * 10))
pygame.draw.line(self.screen, (255, 255, 255, 128),
(self.catapult.x, self.catapult.y),
(end_x, end_y))
# Draw projectile
if self.projectile.active:
pygame.draw.circle(self.screen, (0, 0, 0),
(int(self.projectile.x), int(self.projectile.y)),
self.projectile.radius)
# Draw targets
for target in self.targets:
color = (255, 0, 0) if target.hit else (255, 165, 0)
pygame.draw.rect(self.screen, color,
(target.x, target.y, target.width, target.height))
# Draw score and shots
font = pygame.font.Font(None, 36)
score_text = font.render(f'Score: {self.score}', True, (0, 0, 0))
shots_text = font.render(f'Shots: {self.shots}', True, (0, 0, 0))
self.screen.blit(score_text, (10, 10))
self.screen.blit(shots_text, (10, 40))
# Check for win
if all(target.hit for target in self.targets):
win_font = pygame.font.Font(None, 72)
win_text = win_font.render('You Win!', True, (0, 0, 0))
text_rect = win_text.get_rect(
center=(self.width/2, self.height/2))
self.screen.blit(win_text, text_rect)
pygame.display.flip()
def run(self):
while True:
if not self.handle_input():
break
self.update()
self.draw()
self.clock.tick(60)
pygame.quit()
if __name__ == '__main__':
game = CatapultGame()
game.run()
Play Game