Basic code:-
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BMW M5: V8 TWIN TURBO EDITION</title>
<style>
body { margin: 0; overflow: hidden; background: #020202; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
canvas { display: block; margin: auto; box-shadow: 0 0 50px rgba(0, 242, 255, 0.2); }
/* --- START SCREEN --- */
#start-screen {
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
background: radial-gradient(circle, rgba(20,20,20,0.9) 0%, rgba(0,0,0,1) 100%);
display: flex; flex-direction: column;
justify-content: center; align-items: center; z-index: 200;
}
/* --- DASHBOARD UI --- */
#ui-layer {
position: absolute; bottom: 0; left: 50%; transform: translateX(-50%);
width: 500px; height: 130px; pointer-events: none;
display: flex; justify-content: space-between; align-items: flex-end;
padding-bottom: 20px; box-sizing: border-box;
background: linear-gradient(to top, #000 0%, transparent 100%);
}
.hud-panel {
background: rgba(10, 10, 15, 0.85);
border-top: 2px solid #00f2ff;
padding: 10px; width: 30%; text-align: center;
transform: skewX(-10deg);
backdrop-filter: blur(10px);
box-shadow: 0px -5px 20px rgba(0, 242, 255, 0.15);
border-radius: 8px 8px 0 0;
}
.hud-panel.center-cluster {
width: 38%; height: 100px;
border-top: 4px solid #ff3300; /* M Performance Red */
transform: skewX(0deg);
display: flex; flex-direction: column; justify-content: center;
box-shadow: 0px -5px 30px rgba(255, 51, 0, 0.2);
}
h2 { margin: 0; color: #888; font-size: 10px; text-transform: uppercase; letter-spacing: 2px; }
.stat-value { font-size: 20px; color: #fff; font-weight: 800; margin-top: 5px; }
#speedDisplay { font-size: 36px; color: #fff; text-shadow: 0 0 10px rgba(255,255,255,0.5); font-family: monospace;}
/* Nitro Bar */
.nitro-container {
width: 100%; height: 6px; background: #222; margin-top: 5px;
border: 1px solid #444; overflow: hidden;
}
#nitro-bar {
width: 100%; height: 100%; background: linear-gradient(90deg, #ff9900, #ff0055);
box-shadow: 0 0 15px #ff0055; transform: translateX(-100%); transition: transform 0.1s;
}
/* Controls Hint */
.controls-hint {
position: absolute; top: 20px; width: 100%; text-align: center;
color: rgba(255,255,255,0.4); font-size: 11px; letter-spacing: 2px;
text-transform: uppercase; pointer-events: none;
}
/* Game Over */
#game-over {
display: none; position: absolute; top: 50%; left: 50%;
transform: translate(-50%, -50%);
background: rgba(0,0,0,0.95);
padding: 40px; text-align: center; border: 2px solid #ff0055;
box-shadow: 0 0 50px #ff0055; z-index: 100;
}
button {
background: linear-gradient(45deg, #00f2ff, #0088ff); border: none; padding: 15px 50px;
font-size: 18px; font-weight: 900; cursor: pointer; color: #000;
text-transform: uppercase; letter-spacing: 1px;
clip-path: polygon(10% 0, 100% 0, 90% 100%, 0% 100%);
transition: 0.2s;
}
button:hover { transform: scale(1.05); filter: brightness(1.2); }
/* M Logo colors for fun */
.m-stripe { height: 4px; width: 100%; display: flex; margin-bottom: 20px;}
.m-stripe div { flex: 1; height: 100%; }
</style>
</head>
<body>
<div id="start-screen">
<div class="m-stripe" style="width: 200px;">
<div style="background:#008ac9"></div>
<div style="background:#2b115a"></div>
<div style="background:#f10202"></div>
</div>
<h1 style="color: #fff; font-size: 32px; margin: 0; font-style: italic;">FLY M5</h1>
<h2 style="color: #aaa; margin-bottom: 30px;">SUPER FLY</h2>
<button onclick="startGame()">IGNITION START</button>
</div>
<div class="controls-hint">Arrow Keys: Steer | Shift: Turbo Boost|Master_Dexterity</div>
<div id="ui-layer">
<div class="hud-panel">
<h2>Distance</h2>
<div class="stat-value" id="score">0</div>
</div>
<div class="hud-panel center-cluster">
<h2>Speed</h2>
<div class="stat-value" id="speedDisplay">0 <span style="font-size:14px; color:#aaa">KM/H</span></div>
</div>
<div class="hud-panel">
<h2>Boost</h2>
<div class="nitro-container">
<div id="nitro-bar"></div>
</div>
<div style="font-size: 9px; color: #666; margin-top: 4px; letter-spacing: 1px;">M-POWER</div>
</div>
</div>
<div id="game-over">
<h1 style="color:#ff0055; font-size: 40px; margin:0 0 20px 0;">TOTALED</h1>
<p style="color:#fff; margin-bottom: 20px;">Distance Covered: <span id="finalScore" style="color:#00f2ff">0</span> m</p>
<button onclick="location.reload()">RESTART ENGINE</button>
</div>
<canvas id="gameCanvas"></canvas>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
canvas.width = 500;
canvas.height = window.innerHeight;
// --- ADVANCED ENGINE SOUND SYSTEM (V8 SIMULATION) ---
let audioCtx;
let masterGain;
// We use multiple oscillators to create a rich engine tone
const oscs = [];
let distortionNode;
let audioInitialized = false;
function makeDistortionCurve(amount) {
const k = typeof amount === 'number' ? amount : 50;
const n_samples = 44100;
const curve = new Float32Array(n_samples);
const deg = Math.PI / 180;
for (let i = 0; i < n_samples; ++i) {
const x = i * 2 / n_samples - 1;
curve[i] = (3 + k) * x * 20 * deg / (Math.PI + k * Math.abs(x));
}
return curve;
}
function initAudio() {
try {
const AudioContext = window.AudioContext || window.webkitAudioContext;
audioCtx = new AudioContext();
masterGain = audioCtx.createGain();
masterGain.gain.value = 0.2; // Master volume
// Distortion for the "Growl"
distortionNode = audioCtx.createWaveShaper();
distortionNode.curve = makeDistortionCurve(200); // Amount of grit
distortionNode.oversample = '4x';
masterGain.connect(audioCtx.destination);
// --- Layer 1: Low Rumble (Sawtooth) ---
createOscillatorLayer('sawtooth', 0.5, 0.4);
// --- Layer 2: Mid Tone (Square for body) ---
createOscillatorLayer('square', 1.0, 0.2);
// --- Layer 3: High Harmonic (Triangle for whine) ---
createOscillatorLayer('triangle', 1.5, 0.1);
audioInitialized = true;
} catch(e) {
console.log("Audio not supported", e);
}
}
function createOscillatorLayer(type, pitchMult, vol) {
const osc = audioCtx.createOscillator();
const gain = audioCtx.createGain();
osc.type = type;
osc.frequency.value = 50 * pitchMult; // Base idle freq
osc.connect(gain);
// Connect oscillators to distortion -> then master
gain.connect(distortionNode);
distortionNode.connect(masterGain);
osc.start();
// Store reference to update later
oscs.push({ node: osc, gainNode: gain, baseFreq: 50 * pitchMult, baseVol: vol });
}
function updateEngineSound(speedRatio) {
if (!audioInitialized) return;
// speedRatio is approx 1.0 at normal speed, 2.0 at turbo
// Pitch calculation (Idle 60Hz -> Redline ~600Hz)
const rpm = 60 + (speedRatio * 200);
// Add some random "jitter" to simulate engine vibration
const jitter = Math.random() * 5;
oscs.forEach(layer => {
// Update Frequency
layer.node.frequency.setTargetAtTime(
(rpm * (layer.baseFreq / 50)) + jitter,
audioCtx.currentTime,
0.05
);
// Update Volume: Louder at higher speeds
let targetVol = layer.baseVol + (speedRatio * 0.1);
if (isBoosting) targetVol += 0.1; // Extra loud on boost
layer.gainNode.gain.setTargetAtTime(targetVol, audioCtx.currentTime, 0.1);
});
// Reduce distortion at high speeds to simulate cleaner high-RPM scream
// More distortion at low speeds = grumble
// Less distortion at high speeds = scream
}
// --- CONFIGURATION ---
const PLAYER_EMOJI = "🪰";
const ENEMY_EMOJIS = ["🦉", "🦐", "🦂", "🦠", "🐞"];
// --- GAME STATE ---
let score = 0;
let gameActive = false;
let baseSpeed = 8;
let speedMultiplier = 1;
let frame = 0;
let nitro = 100;
let isBoosting = false;
let shakeIntensity = 0;
let gameOverTransition = false;
const lanes = [100, 250, 400];
// --- INPUTS ---
const keys = {};
window.onkeydown = (e) => keys[e.key] = true;
window.onkeyup = (e) => keys[e.key] = false;
function startGame() {
document.getElementById('start-screen').style.display = 'none';
initAudio();
gameActive = true;
loop();
}
// --- CLASSES ---
class Particle {
constructor(x, y, color, isExhaust = false) {
this.x = x + (Math.random() - 0.5) * 10;
this.y = y;
this.size = Math.random() * 4 + 2;
this.speedY = isExhaust ? Math.random() * 8 + 4 : Math.random() * 5 + 2;
this.color = color;
this.life = 1.0;
this.decay = isExhaust ? 0.03 : 0.05;
}
update() {
this.y += this.speedY + (baseSpeed * speedMultiplier * 0.5);
this.life -= this.decay;
this.x += (Math.random() - 0.5) * 4; // More scatter
}
draw() {
ctx.globalAlpha = Math.max(0, this.life);
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
ctx.globalAlpha = 1;
}
}
class Player {
constructor() {
this.x = 250;
this.y = canvas.height - 180;
this.targetX = 250;
this.tilt = 0;
this.particles = [];
}
update() {
// Handling Controls
if (gameActive) {
if (keys.ArrowLeft) {
this.targetX -= 9;
this.tilt = -0.25;
} else if (keys.ArrowRight) {
this.targetX += 9;
this.tilt = 0.25;
} else {
this.tilt *= 0.8;
}
}
// Boost Logic
if (keys.Shift && nitro > 0 && gameActive) {
isBoosting = true;
speedMultiplier = 2.2; // Faster boost
nitro -= 1;
shakeIntensity = 6;
// Blue flame + Orange core
this.particles.push(new Particle(this.x - 10, this.y + 30, '#00f2ff', true));
this.particles.push(new Particle(this.x + 10, this.y + 30, '#ff0055', true));
} else {
isBoosting = false;
speedMultiplier = 1.0;
if (nitro < 100 && gameActive) nitro += 0.3;
shakeIntensity *= 0.8;
}
// Physics
this.targetX = Math.max(50, Math.min(canvas.width - 50, this.targetX));
this.x += (this.targetX - this.x) * 0.15;
// Normal Exhaust (Grey smoke)
if(gameActive && frame % 3 === 0) {
this.particles.push(new Particle(this.x - 15, this.y + 25, 'rgba(100,100,100,0.4)', true));
this.particles.push(new Particle(this.x + 15, this.y + 25, 'rgba(100,100,100,0.4)', true));
}
this.particles.forEach((p, i) => {
p.update();
if (p.life <= 0) this.particles.splice(i, 1);
});
// Audio
updateEngineSound(speedMultiplier + (baseSpeed/20));
}
draw() {
this.particles.forEach(p => p.draw());
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(this.tilt);
ctx.shadowColor = "rgba(0,0,0,0.8)";
ctx.shadowBlur = 20;
ctx.font = "80px sans-serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(PLAYER_EMOJI, 0, 0);
ctx.restore();
}
}
class Enemy {
constructor() {
this.lane = Math.floor(Math.random() * 3);
this.x = lanes[this.lane];
this.y = -100;
this.speed = Math.random() * 3 + 4;
this.emoji = ENEMY_EMOJIS[Math.floor(Math.random() * ENEMY_EMOJIS.length)];
}
update() {
this.y += (baseSpeed * speedMultiplier) - this.speed;
}
draw() {
ctx.save();
ctx.translate(this.x, this.y);
ctx.font = "70px sans-serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(this.emoji, 0, Math.sin(frame * 0.1) * 2);
ctx.restore();
}
}
// --- GLOBAL VARIABLES ---
const player = new Player();
let enemies = [];
let roadOffset = 0;
// --- MAIN LOOP ---
function drawRoad() {
ctx.fillStyle = "#111"; // Darker road
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.lineWidth = 8;
ctx.strokeStyle = "rgba(255, 255, 255, 0.2)";
ctx.setLineDash([50, 100]);
roadOffset += baseSpeed * speedMultiplier;
ctx.lineDashOffset = -roadOffset;
// Draw Lanes
ctx.beginPath();
ctx.moveTo(canvas.width / 3, 0);
ctx.lineTo(canvas.width / 3, canvas.height);
ctx.moveTo(canvas.width * 2 / 3, 0);
ctx.lineTo(canvas.width * 2 / 3, canvas.height);
ctx.stroke();
// Side Neon (Dynamic)
let glow = isBoosting ? 40 : 15;
ctx.shadowBlur = glow;
ctx.shadowColor = isBoosting ? "#ff0055" : "#00f2ff";
ctx.fillStyle = isBoosting ? "#aa0033" : "#004455";
ctx.fillRect(0, 0, 15, canvas.height);
ctx.fillRect(canvas.width - 15, 0, 15, canvas.height);
ctx.shadowBlur = 0;
}
function checkCollision(enemy) {
let dx = player.x - enemy.x;
let dy = player.y - enemy.y;
let distance = Math.sqrt(dx*dx + dy*dy);
return distance < 65;
}
function updateHUD() {
document.getElementById('score').innerText = Math.floor(score);
let kph = Math.floor((baseSpeed * speedMultiplier) * 18);
document.getElementById('speedDisplay').innerHTML = kph + '<span style="font-size:14px; color:#aaa"> KM/H</span>';
// Smooth Nitro Bar
const nitroElem = document.getElementById('nitro-bar');
nitroElem.style.transform = `translateX(${nitro - 100}%)`; // Slide effect
if(isBoosting) {
document.getElementById('speedDisplay').style.color = "#ff0055";
} else {
document.getElementById('speedDisplay').style.color = "#fff";
}
}
function stopAudio() {
if(audioInitialized && masterGain) {
// Ramp down volume
masterGain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + 0.5);
// Stop oscillators after fade
setTimeout(() => {
oscs.forEach(o => o.node.stop());
}, 600);
}
}
function loop() {
// Screen Shake
let shakeX = (Math.random() - 0.5) * shakeIntensity;
let shakeY = (Math.random() - 0.5) * shakeIntensity;
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.translate(shakeX, shakeY);
if (gameActive) {
frame++;
baseSpeed += 0.001; // Accelerate slowly
score += (0.1 * speedMultiplier);
}
drawRoad();
player.update();
player.draw();
if (gameActive && frame % Math.floor(60 / speedMultiplier) === 0) {
enemies.push(new Enemy());
}
enemies.forEach((enemy, index) => {
enemy.update();
enemy.draw();
if (gameActive && checkCollision(enemy)) {
gameActive = false;
stopAudio(); // Cut engine
// Play crash tone (optional simple beep or silence)
document.getElementById('game-over').style.display = 'block';
document.getElementById('finalScore').innerText = Math.floor(score);
}
if (enemy.y > canvas.height + 100) enemies.splice(index, 1);
});
updateHUD();
ctx.restore();
requestAnimationFrame(loop);
}
</script>
</body>
</html>