Mystery Game #16
← Back to Games List
// Vertical Obstacle Course Game
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const entity = {
x: canvas.width / 4,
y: canvas.height / 2,
radius: 15,
velocity: 0
};
const barriers = [];
const physics = 0.5;
const lift = -8;
let points = 0;
let isActive = true;
function createBarrier() {
const gap = 150;
const minY = gap;
const maxY = canvas.height - gap;
const openingY = Math.random() * (maxY - minY) + minY;
barriers.push({
x: canvas.width,
openingY: openingY,
gapSize: gap,
counted: false
});
}
function updateGame() {
if (!isActive) return;
// Entity physics
entity.velocity += physics;
entity.y += entity.velocity;
// Generate barriers
if (barriers.length === 0 || barriers[barriers.length - 1].x < canvas.width - 300) {
createBarrier();
}
// Update barriers
for (let i = barriers.length - 1; i >= 0; i--) {
barriers[i].x -= 2;
// Score points
if (!barriers[i].counted && barriers[i].x < entity.x) {
barriers[i].counted = true;
points++;
}
// Remove off-screen barriers
if (barriers[i].x < -60) {
barriers.splice(i, 1);
continue;
}
// Collision detection
const b = barriers[i];
if (entity.x + entity.radius > b.x &&
entity.x - entity.radius < b.x + 60) {
if (entity.y - entity.radius < b.openingY - b.gapSize/2 ||
entity.y + entity.radius > b.openingY + b.gapSize/2) {
gameOver();
}
}
}
// Ground/ceiling collision
if (entity.y > canvas.height || entity.y < 0) {
gameOver();
}
}
function render() {
// Clear canvas
ctx.fillStyle = 'skyblue';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw barriers
ctx.fillStyle = 'green';
barriers.forEach(b => {
// Upper barrier
ctx.fillRect(b.x, 0, 60, b.openingY - b.gapSize/2);
// Lower barrier
ctx.fillRect(b.x, b.openingY + b.gapSize/2, 60, canvas.height);
});
// Draw entity
ctx.beginPath();
ctx.arc(entity.x, entity.y, entity.radius, 0, Math.PI * 2);
ctx.fillStyle = 'yellow';
ctx.fill();
ctx.strokeStyle = 'orange';
ctx.stroke();
// Draw score
ctx.fillStyle = 'black';
ctx.font = '24px Arial';
ctx.fillText('Score: ' + points, 10, 30);
if (!isActive) {
ctx.fillStyle = 'black';
ctx.font = '40px Arial';
ctx.fillText('Game Over!', canvas.width/2 - 100, canvas.height/2);
}
}
function gameOver() {
isActive = false;
}
// Controls
document.addEventListener('keydown', (e) => {
if (e.code === 'Space') {
entity.velocity = lift;
}
});
# Vertical Obstacle Course Game Implementation
import pygame
import random
from dataclasses import dataclass
from typing import List
@dataclass
class Entity:
x: float
y: float
radius: int = 15
velocity: float = 0
@dataclass
class Barrier:
x: float
opening_y: float
gap_size: int
counted: bool = False
class ObstacleCourseGame:
def __init__(self):
pygame.init()
# Game settings
self.width = 800
self.height = 600
self.physics = 0.5
self.lift = -8
# Initialize display
self.screen = pygame.display.set_mode((self.width, self.height))
pygame.display.set_caption('Obstacle Course')
self.clock = pygame.time.Clock()
# Game objects
self.entity = Entity(self.width / 4, self.height / 2)
self.barriers: List[Barrier] = []
# Game state
self.points = 0
self.is_active = True
def create_barrier(self):
"""Create a new barrier with random opening"""
gap = 150
min_y = gap
max_y = self.height - gap
opening_y = random.uniform(min_y, max_y)
self.barriers.append(
Barrier(x=self.width,
opening_y=opening_y,
gap_size=gap)
)
def update_game(self):
"""Update game state"""
if not self.is_active:
return
# Entity physics
self.entity.velocity += self.physics
self.entity.y += self.entity.velocity
# Generate barriers
if (len(self.barriers) == 0 or
self.barriers[-1].x < self.width - 300):
self.create_barrier()
# Update barriers
for barrier in self.barriers[:]:
barrier.x -= 2
# Score points
if not barrier.counted and barrier.x < self.entity.x:
barrier.counted = True
self.points += 1
# Remove off-screen barriers
if barrier.x < -60:
self.barriers.remove(barrier)
continue
# Collision detection
if (self.entity.x + self.entity.radius > barrier.x and
self.entity.x - self.entity.radius < barrier.x + 60):
if (self.entity.y - self.entity.radius <
barrier.opening_y - barrier.gap_size/2 or
self.entity.y + self.entity.radius >
barrier.opening_y + barrier.gap_size/2):
self.game_over()
# Ground/ceiling collision
if (self.entity.y > self.height or self.entity.y < 0):
self.game_over()
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_SPACE:
self.entity.velocity = self.lift
return True
def draw(self):
"""Draw the game state"""
# Clear screen
self.screen.fill((135, 206, 235)) # skyblue
# Draw barriers
for barrier in self.barriers:
# Upper barrier
pygame.draw.rect(self.screen, (0, 255, 0),
(barrier.x, 0,
60, barrier.opening_y - barrier.gap_size/2))
# Lower barrier
pygame.draw.rect(self.screen, (0, 255, 0),
(barrier.x,
barrier.opening_y + barrier.gap_size/2,
60, self.height))
# Draw entity
pygame.draw.circle(self.screen, (255, 255, 0), # yellow
(int(self.entity.x), int(self.entity.y)),
self.entity.radius)
pygame.draw.circle(self.screen, (255, 165, 0), # orange
(int(self.entity.x), int(self.entity.y)),
self.entity.radius, 2)
# Draw score
font = pygame.font.Font(None, 36)
score_text = font.render(f'Score: {self.points}',
True, (0, 0, 0))
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, (0, 0, 0))
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 = ObstacleCourseGame()
game.run()
Play Game