fly game make only html css js

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 &nbsp;|&nbsp; 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>

Post a Comment

Previous Post Next Post