Meta Description" name="description" />
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bus Driver Blitz</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background-color: #1a1a1a;
color: #fff;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
overflow: hidden;
}
#game-container {
position: relative;
width: 400px;
height: 600px;
background: #2c3e50;
border: 4px solid #fff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 10px 30px rgba(0,0,0,0.5);
}
#canvas {
width: 100%;
height: 100%;
display: block;
}
#hud {
position: absolute;
top: 10px;
left: 10px;
right: 10px;
display: flex;
justify-content: space-between;
font-size: 18px;
font-weight: bold;
text-shadow: 2px 2px 4px rgba(0,0,0,0.8);
z-index: 10;
}
#game-over {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.85);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 20;
}
.hidden {
display: none !important;
}
h1 {
color: #f1c40f;
margin-bottom: 10px;
}
button {
padding: 12px 24px;
font-size: 18px;
font-weight: bold;
background: #27ae60;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
margin-top: 20px;
transition: background 0.2s;
}
button:hover {
background: #2ecc71;
}
.controls-hint {
margin-top: 15px;
font-size: 14px;
color: #ccc;
text-align: center;
}
</style>
</head>
<body>
<div id="game-container">
<div id="hud">
<div>Score: <span id="score">0</span></div>
<div>Passengers: <span id="passengers">0</span></div>
</div>
<canvas id="canvas" width="400" height="600"></canvas>
<div id="game-over">
<h1 id="menu-title">BUS DRIVER</h1>
<p id="final-score" class="hidden">Final Score: 0</p>
<button id="start-btn">START GAME</button>
<div class="controls-hint">
Use <b>LEFT / RIGHT</b> Arrows or <b>A / D</b> to steer.<br>
Avoid π Cars | Pick up πΆ Passengers
</div>
</div>
</div>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const scoreEl = document.getElementById('score');
const passengersEl = document.getElementById('passengers');
const gameOverScreen = document.getElementById('game-over');
const startBtn = document.getElementById('start-btn');
const menuTitle = document.getElementById('menu-title');
const finalScoreEl = document.getElementById('final-score');
// Game State
let gameRunning = false;
let score = 0;
let passengersCollected = 0;
let roadOffset = 0;
let speed = 5;
// Player Bus
const bus = {
x: 170,
y: 480,
width: 60,
height: 100,
speed: 6,
dx: 0
};
// Inputs
const keys = { left: false, right: false };
// Entities
let obstacles = [];
let passengers = [];
// Controls
document.addEventListener('keydown', (e) => {
if (e.key === 'ArrowLeft' || e.key === 'a') keys.left = true;
if (e.key === 'ArrowRight' || e.key === 'd') keys.right = true;
});
document.addEventListener('keyup', (e) => {
if (e.key === 'ArrowLeft' || e.key === 'a') keys.left = false;
if (e.key === 'ArrowRight' || e.key === 'd') keys.right = false;
});
startBtn.addEventListener('click', startGame);
function startGame() {
gameRunning = true;
score = 0;
passengersCollected = 0;
obstacles = [];
passengers = [];
bus.x = 170;
speed = 5;
scoreEl.textContent = score;
passengersEl.textContent = passengersCollected;
gameOverScreen.classList.add('hidden');
requestAnimationFrame(gameLoop);
}
function endGame() {
gameRunning = false;
menuTitle.textContent = "CRASHED!";
finalScoreEl.textContent = `Score: ${score} | Passengers: ${passengersCollected}`;
finalScoreEl.classList.remove('hidden');
startBtn.textContent = "PLAY AGAIN";
gameOverScreen.classList.remove('hidden');
}
// Spawning
function spawnEntities() {
// Spawn Obstacle (Car)
if (Math.random() < 0.02) {
const lane = Math.floor(Math.random() * 3);
const xPos = 60 + lane * 100 + 25; // Centered in lane
obstacles.push({ x: xPos, y: -80, width: 50, height: 80, color: '#e74c3c' });
}
// Spawn Passenger (Bus Stop)
if (Math.random() < 0.015) {
const isLeft = Math.random() < 0.5;
const xPos = isLeft ? 25 : 355; // Side of the road
passengers.push({ x: xPos, y: -30, radius: 12, side: isLeft ? 'left' : 'right' });
}
}
// Main Loop
function gameLoop() {
if (!gameRunning) return;
update();
draw();
requestAnimationFrame(gameLoop);
}
function update() {
// Steering
if (keys.left && bus.x > 50) bus.x -= bus.speed;
if (keys.right && bus.x < canvas.width - 50 - bus.width) bus.x += bus.speed;
// Animate Road
roadOffset = (roadOffset + speed) % 40;
// Increase Score & Difficulty
score += 1;
scoreEl.textContent = score;
if (score % 500 === 0) speed += 0.5;
spawnEntities();
// Update Obstacles
for (let i = obstacles.length - 1; i >= 0; i--) {
let obs = obstacles[i];
obs.y += speed * 0.8; // Moves slightly slower than road speed
// Collision Detection with Bus
if (
bus.x < obs.x + obs.width &&
bus.x + bus.width > obs.x &&
bus.y < obs.y + obs.height &&
bus.y + bus.height > obs.y
) {
endGame();
}
if (obs.y > canvas.height) obstacles.splice(i, 1);
}
// Update Passengers
for (let i = passengers.length - 1; i >= 0; i--) {
let p = passengers[i];
p.y += speed;
// Pick up detection (bus needs to get close to the shoulder)
const busEdge = p.side === 'left' ? bus.x : bus.x + bus.width;
const distY = Math.abs((bus.y + bus.height / 2) - p.y);
const distX = Math.abs(busEdge - p.x);
if (distX < 35 && distY < 40) {
passengersCollected += 1;
score += 100;
passengersEl.textContent = passengersCollected;
passengers.splice(i, 1);
continue;
}
if (p.y > canvas.height) passengers.splice(i, 1);
}
}
function draw() {
// Clear Frame
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw Grass Sides
ctx.fillStyle = '#27ae60';
ctx.fillRect(0, 0, 50, canvas.height);
ctx.fillRect(350, 0, 50, canvas.height);
// Draw Road
ctx.fillStyle = '#34495e';
ctx.fillRect(50, 0, 300, canvas.height);
// Draw Road Lines (Lanes)
ctx.strokeStyle = '#fff';
ctx.lineWidth = 4;
ctx.setLineDash([20, 20]);
ctx.lineDashOffset = -roadOffset;
ctx.beginPath();
ctx.moveTo(150, 0);
ctx.lineTo(150, canvas.height);
ctx.moveTo(250, 0);
ctx.lineTo(250, canvas.height);
ctx.stroke();
ctx.setLineDash([]); // Reset dash
// Draw Passengers (Bus Stops)
passengers.forEach(p => {
ctx.fillStyle = '#f39c12';
ctx.beginPath();
ctx.arc(p.x, p.y, p.radius, 0, Math.PI * 2);
ctx.fill();
// Stick figure head outline
ctx.strokeStyle = '#fff';
ctx.lineWidth = 2;
ctx.stroke();
});
// Draw Obstacle Cars
obstacles.forEach(obs => {
// Car Body
ctx.fillStyle = obs.color;
ctx.fillRect(obs.x, obs.y, obs.width, obs.height);
// Roof
ctx.fillStyle = '#2c3e50';
ctx.fillRect(obs.x + 5, obs.y + 20, obs.width - 10, obs.height - 40);
// Headlights
ctx.fillStyle = '#f1c40f';
ctx.fillRect(obs.x + 4, obs.y + obs.height - 6, 10, 6);
ctx.fillRect(obs.x + obs.width - 14, obs.y + obs.height - 6, 10, 6);
});
// Draw Bus (Player)
// Main Body
ctx.fillStyle = '#f1c40f'; // School bus yellow
ctx.fillRect(bus.x, bus.y, bus.width, bus.height);
// Windshield & Windows
ctx.fillStyle = '#3498db';
ctx.fillRect(bus.x + 5, bus.y + 10, bus.width - 10, 20); // Front windshield
ctx.fillRect(bus.x + 5, bus.y + 40, 8, 40); // Left windows
ctx.fillRect(bus.x + bus.width - 13, bus.y + 40, 8, 40); // Right windows
// Roof detail
ctx.fillStyle = '#d68910';
ctx.fillRect(bus.x + 18, bus.y + 38, bus.width - 36, 45);
// Taillights
ctx.fillStyle = '#c0392b';
ctx.fillRect(bus.x + 4, bus.y + bus.height - 6, 10, 6);
ctx.fillRect(bus.x + bus.width - 14, bus.y + bus.height - 6, 10, 6);
}
</script>
</body>
</html>
1
1
11KB
11KB
179.0ms
220.0ms
179.0ms