🎮KidHubb

Meteor Dodge

by SolarScout64
3419 lines115.0 KB
▶ Play
<!DOCTYPE html>

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <title>Meteor Dodge</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            -webkit-tap-highlight-color: transparent;
        }

```
    body {
        width: 100vw;
        height: 100vh;
        overflow: hidden;
        background: #000;
        font-family: 'Arial', sans-serif;
        touch-action: none;
    }

    #gameContainer {
        position: relative;
        width: 100vw;
        height: 100vh;
        overflow: hidden;
    }

    #gameCanvas {
        display: block;
        width: 100%;
        height: 100%;
        touch-action: none;
    }

    #hud {
        position: absolute;
        top: 20px;
        left: 20px;
        right: 20px;
        display: flex;
        justify-content: space-between;
        align-items: flex-start;
        pointer-events: none;
        z-index: 10;
    }

    .stat-box {
        background: rgba(0, 0, 0, 0.8);
        padding: 15px 25px;
        border-radius: 15px;
        border: 3px solid #ff6600;
        box-shadow: 0 0 20px rgba(255, 102, 0, 0.6);
    }

    .stat-label {
        font-size: 16px;
        color: #ff6600;
        margin-bottom: 5px;
        text-transform: uppercase;
    }

    .stat-value {
        font-size: 32px;
        font-weight: bold;
        color: #ffffff;
    }

    #health-bar-container {
        position: absolute;
        bottom: 40px;
        left: 50%;
        transform: translateX(-50%);
        z-index: 10;
        pointer-events: none;
    }

    #hearts-display {
        display: flex;
        gap: 15px;
        font-size: 48px;
        filter: drop-shadow(0 0 10px rgba(255, 0, 0, 0.8));
    }

    .heart {
        transition: opacity 0.3s, transform 0.3s;
    }

    .heart.lost {
        opacity: 0.2;
        transform: scale(0.8);
    }

    @keyframes pulse {
        0%, 100% { transform: translate(-50%, -50%) scale(1); }
        50% { transform: translate(-50%, -50%) scale(1.1); }
    }

    #startScreen, #gameOver {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: linear-gradient(135deg, #000000 0%, #1a0a00 100%);
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        z-index: 25;
        color: white;
    }

    #gameOver {
        display: none;
    }

    h1 {
        font-size: 56px;
        margin-bottom: 15px;
        color: #ff6600;
        text-shadow: 0 0 40px rgba(255, 102, 0, 1);
    }

    h2 {
        font-size: 32px;
        margin-bottom: 20px;
        color: #ffaa00;
        text-shadow: 0 0 20px rgba(255, 170, 0, 0.8);
    }

    p {
        font-size: 20px;
        margin-bottom: 10px;
        text-align: center;
        max-width: 600px;
        line-height: 1.5;
        color: #cccccc;
        padding: 0 20px;
    }

    .btn {
        background: linear-gradient(135deg, #ff6600 0%, #ff3300 100%);
        color: white;
        border: none;
        padding: 20px 50px;
        font-size: 28px;
        border-radius: 50px;
        cursor: pointer;
        margin-top: 20px;
        font-weight: bold;
        box-shadow: 0 8px 25px rgba(255, 102, 0, 0.6);
        transition: transform 0.2s;
    }

    .btn:active {
        transform: scale(0.95);
    }

    #instructions {
        position: absolute;
        bottom: 80px;
        left: 50%;
        transform: translateX(-50%);
        font-size: 22px;
        color: #ffaa00;
        text-align: center;
        text-shadow: 0 0 10px rgba(255, 170, 0, 0.6);
        pointer-events: none;
        z-index: 10;
        background: rgba(0, 0, 0, 0.7);
        padding: 15px 30px;
        border-radius: 15px;
    }

    #weaponDisplay {
        position: absolute;
        top: 100px;
        left: 50%;
        transform: translateX(-50%);
        font-size: 24px;
        font-weight: bold;
        color: #fff;
        text-align: center;
        text-shadow: 0 0 15px rgba(255, 255, 255, 0.8);
        pointer-events: none;
        z-index: 10;
        background: rgba(0, 0, 0, 0.85);
        padding: 15px 30px;
        border-radius: 15px;
        border: 3px solid #ffaa00;
        display: none;
    }

    #weaponNotification {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        font-size: 48px;
        font-weight: bold;
        text-align: center;
        pointer-events: none;
        z-index: 20;
        opacity: 0;
        transition: opacity 0.3s;
    }

    .star {
        position: absolute;
        background: white;
        border-radius: 50%;
        animation: twinkle 2s infinite;
    }

    @keyframes twinkle {
        0%, 100% { opacity: 0.3; }
        50% { opacity: 1; }
    }

    #upgradeShop {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: rgba(0, 0, 0, 0.95);
        display: none;
        flex-direction: column;
        align-items: center;
        padding: 40px 20px;
        overflow-y: auto;
        z-index: 30;
        color: white;
    }

    #upgradeShop h2 {
        font-size: 48px;
        margin-bottom: 10px;
        color: #ff6600;
        text-shadow: 0 0 20px rgba(255, 102, 0, 0.8);
    }

    #upgradeShop .credits-display {
        font-size: 28px;
        margin-bottom: 30px;
        color: #ffaa00;
    }

    .upgrade-container {
        display: flex;
        flex-direction: column;
        gap: 20px;
        max-width: 600px;
        width: 100%;
    }

    .upgrade-card {
        background: rgba(255, 255, 255, 0.1);
        border: 3px solid #ff6600;
        border-radius: 20px;
        padding: 25px;
        box-shadow: 0 4px 20px rgba(255, 102, 0, 0.3);
    }

    .upgrade-card h3 {
        font-size: 32px;
        margin-bottom: 10px;
        color: #ffaa00;
    }

    .upgrade-card p {
        font-size: 18px;
        margin-bottom: 15px;
        color: #ccc;
    }

    .upgrade-level {
        display: flex;
        align-items: center;
        gap: 10px;
        margin-bottom: 15px;
        font-size: 20px;
    }

    .level-bar {
        flex: 1;
        height: 30px;
        background: rgba(0, 0, 0, 0.5);
        border-radius: 15px;
        overflow: hidden;
        border: 2px solid #666;
    }

    .level-fill {
        height: 100%;
        background: linear-gradient(90deg, #ff6600, #ffaa00);
        transition: width 0.3s;
        box-shadow: 0 0 10px rgba(255, 102, 0, 0.6);
    }

    .upgrade-btn {
        background: linear-gradient(135deg, #00ff00 0%, #00cc00 100%);
        color: #000;
        border: none;
        padding: 15px 30px;
        font-size: 22px;
        border-radius: 25px;
        cursor: pointer;
        font-weight: bold;
        box-shadow: 0 4px 15px rgba(0, 255, 0, 0.4);
        transition: transform 0.2s;
    }

    .upgrade-btn:active {
        transform: scale(0.95);
    }

    .upgrade-btn:disabled {
        background: #666;
        cursor: not-allowed;
        box-shadow: none;
    }

    .upgrade-btn.maxed {
        background: linear-gradient(135deg, #ffaa00 0%, #ff6600 100%);
        color: white;
    }

    .close-shop-btn {
        background: linear-gradient(135deg, #ff6600 0%, #ff3300 100%);
        color: white;
        border: none;
        padding: 15px 40px;
        font-size: 24px;
        border-radius: 50px;
        cursor: pointer;
        margin-top: 30px;
        font-weight: bold;
        box-shadow: 0 6px 20px rgba(255, 102, 0, 0.6);
        transition: transform 0.2s;
    }

    .close-shop-btn:active {
        transform: scale(0.95);
    }
</style>
```

</head>
<body>
    <div id="gameContainer">
        <canvas id="gameCanvas"></canvas>

```
    <div id="hud">
        <div class="stat-box">
            <div class="stat-label">Score</div>
            <div class="stat-value" id="score">0</div>
        </div>
        <div class="stat-box">
            <div class="stat-label">Time</div>
            <div class="stat-value" id="time">0s</div>
        </div>
        <div class="stat-box">
            <div class="stat-label">Credits</div>
            <div class="stat-value" id="credits">0</div>
        </div>
    </div>

    <div id="health-bar-container">
        <div id="hearts-display"></div>
    </div>

    <div id="instructions">Drag to move • Tap to shoot</div>
    <div id="weaponDisplay"></div>
    <div id="weaponNotification"></div>

    <div id="startScreen">
        <h1>☄️ METEOR DODGE ☄️</h1>
        <h2>🚀 SURVIVAL MODE 🚀</h2>
        <p>
            <strong>MISSION BRIEFING:</strong><br><br>
            Drag your finger to pilot your spaceship<br>
            Tap anywhere to shoot laser bullets<br>
            Destroy meteors for bonus points!<br>
            Collect power-ups for shield repairs<br>
            Survive as long as possible!<br><br>
            The longer you survive, the harder it gets!
        </p>
        <button class="btn" id="startBtn">LAUNCH MISSION</button>
        <button class="btn" id="shopBtnStart" style="background: linear-gradient(135deg, #ffaa00 0%, #ff6600 100%); margin-top: 10px;">⬆️ UPGRADES</button>
    </div>

    <div id="gameOver">
        <h1>💥 SHIP DESTROYED 💥</h1>
        <p id="finalStats"></p>
        <p id="survivalTime"></p>
        <p id="creditsEarned" style="color: #ffaa00; font-size: 24px; margin-top: 15px;"></p>
        <button class="btn" id="upgradeBtn">⬆️ UPGRADES</button>
        <button class="btn" id="restartBtn">RETRY MISSION</button>
    </div>

    <div id="upgradeShop">
        <h2>🛠️ UPGRADE SHOP 🛠️</h2>
        <div class="credits-display">Credits: <span id="shopCredits">0</span> 💰</div>
        
        <div class="upgrade-container">
            <div class="upgrade-card">
                <h3>🛡️ SHIELD UPGRADE</h3>
                <p>Increase maximum hearts! Start each mission with more lives!</p>
                <div class="upgrade-level">
                    <span>Level:</span>
                    <div class="level-bar">
                        <div class="level-fill" id="shieldLevelBar" style="width: 20%"></div>
                    </div>
                    <span id="shieldLevelText">1/5</span>
                </div>
                <p style="font-size: 16px; color: #ffaa00;">Current Max: <span id="currentMaxHealth">3 Hearts</span></p>
                <button class="upgrade-btn" id="upgradeShieldBtn">
                    UPGRADE (500 Credits)
                </button>
            </div>

            <div class="upgrade-card">
                <h3>🔫 GUN UPGRADE</h3>
                <p>Upgrade your weapons! Faster fire rate and more powerful shots!</p>
                <div class="upgrade-level">
                    <span>Level:</span>
                    <div class="level-bar">
                        <div class="level-fill" id="gunLevelBar" style="width: 20%"></div>
                    </div>
                    <span id="gunLevelText">1/5</span>
                </div>
                <p style="font-size: 16px; color: #ffaa00;">Fire Rate: <span id="currentFireRate">Normal</span></p>
                <button class="upgrade-btn" id="upgradeGunBtn">
                    UPGRADE (300 Credits)
                </button>
            </div>
        </div>

        <button class="close-shop-btn" id="closeShopBtn">CLOSE SHOP</button>
    </div>
</div>

<script>
    const canvas = document.getElementById('gameCanvas');
    const ctx = canvas.getContext('2d');
    
    function resizeCanvas() {
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
    }
    resizeCanvas();
    window.addEventListener('resize', resizeCanvas);

    // Game state
    let gameRunning = false;
    let score = 0;
    let survivalTime = 0;
    let health = 100;
    let meteors = [];
    let powerups = [];
    let particles = [];
    let confetti = [];
    let stars = [];
    let highScore = localStorage.getItem('meteorDodgeHighScore') || 0;
    let gameStartTime = 0;
    let difficulty = 1;
    let bullets = [];
    let canShoot = true;
    let shootCooldown = 200; // milliseconds between shots
    let engineParticles = []; // Engine trail particles
    let shipDebris = []; // Ship pieces when destroyed
    let playerDestroyed = false;
    let ejectedAstronaut = null; // The pilot ejecting from ship
    let feedbackMessages = []; // Cool action feedback
    let consecutiveKills = 0;
    let lastKillTime = 0;

    // Minigame system
    let inMinigame = false;
    let minigameType = null;
    let minigameStartTime = 0;
    let minigameScore = 0;
    let minigameTimeLimit = 50; // 50 seconds for minigame
    let normalGameState = {}; // Store normal game state
    let minigameTriggered = false; // Prevent multiple triggers

    // Audio context for sound effects
    let audioContext = null;

    // Initialize audio on first user interaction
    function initAudio() {
        if (!audioContext) {
            audioContext = new (window.AudioContext || window.webkitAudioContext)();
        }
    }
    let screenShake = 0;
    let shakeIntensity = 0;

    // Weapon system
    let activeWeapon = 'normal';
    let weaponTimeLeft = 0;
    const weaponDuration = 15000; // 15 seconds per weapon powerup

    // Shield system
    let shieldActive = false;
    let shieldTimeLeft = 0;
    const shieldDuration = 10000; // 10 seconds of invincibility

    // Heart system (replaces health bar)
    let hearts = 3;
    let maxHearts = 3;

    // Upgrade system
    let credits = parseInt(localStorage.getItem('meteorCredits')) || 0;
    let shieldLevel = parseInt(localStorage.getItem('shieldLevel')) || 1;
    let gunLevel = parseInt(localStorage.getItem('gunLevel')) || 1;
    
    // Shield level now adds extra hearts
    maxHearts = 3 + (shieldLevel - 1); // +1 heart per shield level

    const upgradeCosts = {
        shield: [0, 500, 1000, 2000, 3500],
        gun: [0, 300, 750, 1500, 2500]
    };

    // Player ship
    const player = {
        x: 0,
        y: 0,
        width: 50,
        height: 50,
        targetX: 0,
        targetY: 0,
        speed: 0.15
    };

    // Create starfield
    function createStars() {
        stars = [];
        for (let i = 0; i < 150; i++) {
            stars.push({
                x: Math.random() * canvas.width,
                y: Math.random() * canvas.height,
                size: Math.random() * 2 + 0.5,
                speed: Math.random() * 0.5 + 0.2
            });
        }
    }
    createStars();

    class Meteor {
        constructor() {
            this.x = Math.random() * canvas.width;
            this.y = -50;
            this.size = Math.random() * 40 + 30;
            this.speed = (Math.random() * 2 + 2) * difficulty;
            this.rotation = Math.random() * Math.PI * 2;
            this.rotationSpeed = (Math.random() - 0.5) * 0.1;
            this.type = Math.random() > 0.7 ? 'large' : 'normal';
            
            if (this.type === 'large') {
                this.size *= 1.5;
                this.speed *= 0.7;
            }
        }

        update() {
            this.y += this.speed;
            this.rotation += this.rotationSpeed;
            return this.y < canvas.height + 100;
        }

        draw() {
            ctx.save();
            ctx.translate(this.x, this.y);
            ctx.rotate(this.rotation);

            // Meteor gradient
            const gradient = ctx.createRadialGradient(0, 0, 0, 0, 0, this.size);
            gradient.addColorStop(0, '#ff6600');
            gradient.addColorStop(0.4, '#cc3300');
            gradient.addColorStop(1, '#661100');

            ctx.fillStyle = gradient;
            ctx.beginPath();
            
            // Irregular shape
            const points = 8;
            for (let i = 0; i < points; i++) {
                const angle = (Math.PI * 2 / points) * i;
                const radius = this.size * (0.8 + Math.random() * 0.4);
                const x = Math.cos(angle) * radius;
                const y = Math.sin(angle) * radius;
                
                if (i === 0) {
                    ctx.moveTo(x, y);
                } else {
                    ctx.lineTo(x, y);
                }
            }
            ctx.closePath();
            ctx.fill();

            // Glowing edge
            ctx.strokeStyle = '#ff9933';
            ctx.lineWidth = 2;
            ctx.stroke();

            // Hot spots
            ctx.fillStyle = '#ffaa00';
            for (let i = 0; i < 3; i++) {
                const angle = Math.random() * Math.PI * 2;
                const dist = Math.random() * this.size * 0.5;
                ctx.beginPath();
                ctx.arc(Math.cos(angle) * dist, Math.sin(angle) * dist, 3, 0, Math.PI * 2);
                ctx.fill();
            }

            ctx.restore();
        }

        checkCollision(px, py, pw, ph) {
            const dist = Math.sqrt((this.x - px) ** 2 + (this.y - py) ** 2);
            return dist < (this.size + Math.min(pw, ph) / 2);
        }
    }

    class Asteroid {
        constructor() {
            this.x = Math.random() * canvas.width;
            this.y = -60;
            this.size = Math.random() * 25 + 35;
            this.speed = (Math.random() * 1.5 + 3) * difficulty;
            this.rotation = Math.random() * Math.PI * 2;
            this.rotationSpeed = (Math.random() - 0.5) * 0.15;
        }

        update() {
            this.y += this.speed;
            this.rotation += this.rotationSpeed;
            return this.y < canvas.height + 100;
        }

        draw() {
            ctx.save();
            ctx.translate(this.x, this.y);
            ctx.rotate(this.rotation);

            // Gray rocky asteroid
            ctx.fillStyle = '#8B8680';
            ctx.strokeStyle = '#696969';
            ctx.lineWidth = 2;

            ctx.beginPath();
            for (let i = 0; i < 6; i++) {
                const angle = (Math.PI * 2 / 6) * i;
                const radius = this.size * (0.7 + Math.random() * 0.3);
                const x = Math.cos(angle) * radius;
                const y = Math.sin(angle) * radius;
                if (i === 0) ctx.moveTo(x, y);
                else ctx.lineTo(x, y);
            }
            ctx.closePath();
            ctx.fill();
            ctx.stroke();

            // Craters
            ctx.fillStyle = '#696969';
            for (let i = 0; i < 3; i++) {
                const angle = Math.random() * Math.PI * 2;
                const dist = Math.random() * this.size * 0.4;
                ctx.beginPath();
                ctx.arc(Math.cos(angle) * dist, Math.sin(angle) * dist, 4, 0, Math.PI * 2);
                ctx.fill();
            }

            ctx.restore();
        }

        checkCollision(px, py, pw, ph) {
            const dist = Math.sqrt((this.x - px) ** 2 + (this.y - py) ** 2);
            return dist < (this.size + Math.min(pw, ph) / 2);
        }
    }

    class SpaceDebris {
        constructor() {
            // Spawn from sides sometimes
            if (Math.random() > 0.5) {
                this.x = Math.random() > 0.5 ? -30 : canvas.width + 30;
                this.y = Math.random() * canvas.height * 0.6;
                this.speedX = this.x < 0 ? 3 : -3;
                this.speedY = (Math.random() * 2 + 1) * difficulty;
            } else {
                this.x = Math.random() * canvas.width;
                this.y = -40;
                this.speedX = (Math.random() - 0.5) * 4;
                this.speedY = (Math.random() * 2 + 2.5) * difficulty;
            }
            
            this.size = Math.random() * 20 + 20;
            this.rotation = Math.random() * Math.PI * 2;
            this.rotationSpeed = (Math.random() - 0.5) * 0.2;
            this.type = Math.random() > 0.5 ? 'metal' : 'panel';
        }

        update() {
            this.x += this.speedX;
            this.y += this.speedY;
            this.rotation += this.rotationSpeed;
            return this.y < canvas.height + 60 && this.x > -60 && this.x < canvas.width + 60;
        }

        draw() {
            ctx.save();
            ctx.translate(this.x, this.y);
            ctx.rotate(this.rotation);

            if (this.type === 'metal') {
                // Metal debris
                ctx.fillStyle = '#C0C0C0';
                ctx.strokeStyle = '#888';
                ctx.lineWidth = 2;
                
                ctx.fillRect(-this.size/2, -this.size/2, this.size, this.size);
                ctx.strokeRect(-this.size/2, -this.size/2, this.size, this.size);
                
                // Rivets
                ctx.fillStyle = '#666';
                ctx.beginPath();
                ctx.arc(-this.size/3, -this.size/3, 2, 0, Math.PI * 2);
                ctx.arc(this.size/3, -this.size/3, 2, 0, Math.PI * 2);
                ctx.arc(-this.size/3, this.size/3, 2, 0, Math.PI * 2);
                ctx.arc(this.size/3, this.size/3, 2, 0, Math.PI * 2);
                ctx.fill();
            } else {
                // Solar panel
                ctx.fillStyle = '#1a3d5c';
                ctx.strokeStyle = '#4a7ba7';
                ctx.lineWidth = 2;
                
                ctx.fillRect(-this.size, -this.size/3, this.size * 2, this.size * 0.6);
                ctx.strokeRect(-this.size, -this.size/3, this.size * 2, this.size * 0.6);
                
                // Grid lines
                ctx.strokeStyle = '#6a9bc7';
                ctx.lineWidth = 1;
                for (let i = -this.size; i < this.size; i += 10) {
                    ctx.beginPath();
                    ctx.moveTo(i, -this.size/3);
                    ctx.lineTo(i, this.size/3);
                    ctx.stroke();
                }
            }

            ctx.restore();
        }

        checkCollision(px, py, pw, ph) {
            const dist = Math.sqrt((this.x - px) ** 2 + (this.y - py) ** 2);
            return dist < (this.size + Math.min(pw, ph) / 2);
        }
    }

    class IceCrystal {
        constructor() {
            this.x = Math.random() * canvas.width;
            this.y = -50;
            this.size = Math.random() * 20 + 25;
            this.speed = (Math.random() * 1 + 2) * difficulty;
            this.rotation = Math.random() * Math.PI * 2;
            this.rotationSpeed = (Math.random() - 0.5) * 0.12;
            this.shimmer = 0;
        }

        update() {
            this.y += this.speed;
            this.rotation += this.rotationSpeed;
            this.shimmer += 0.1;
            return this.y < canvas.height + 80;
        }

        draw() {
            ctx.save();
            ctx.translate(this.x, this.y);
            ctx.rotate(this.rotation);

            // Ice crystal
            const shimmerAlpha = 0.5 + Math.sin(this.shimmer) * 0.3;
            
            ctx.fillStyle = `rgba(173, 216, 230, ${shimmerAlpha})`;
            ctx.strokeStyle = `rgba(135, 206, 250, ${shimmerAlpha})`;
            ctx.lineWidth = 2;
            ctx.shadowBlur = 15;
            ctx.shadowColor = '#00ffff';

            // Star shape
            ctx.beginPath();
            for (let i = 0; i < 6; i++) {
                const angle = (Math.PI / 3) * i;
                const outerX = Math.cos(angle) * this.size;
                const outerY = Math.sin(angle) * this.size;
                const innerX = Math.cos(angle + Math.PI / 6) * (this.size * 0.5);
                const innerY = Math.sin(angle + Math.PI / 6) * (this.size * 0.5);
                
                if (i === 0) {
                    ctx.moveTo(outerX, outerY);
                } else {
                    ctx.lineTo(outerX, outerY);
                }
                ctx.lineTo(innerX, innerY);
            }
            ctx.closePath();
            ctx.fill();
            ctx.stroke();

            ctx.shadowBlur = 0;
            ctx.restore();
        }

        checkCollision(px, py, pw, ph) {
            const dist = Math.sqrt((this.x - px) ** 2 + (this.y - py) ** 2);
            return dist < (this.size + Math.min(pw, ph) / 2);
        }
    }

    class RocketShip {
        constructor() {
            // Spawn from left or right side
            this.fromLeft = Math.random() > 0.5;
            this.x = this.fromLeft ? -80 : canvas.width + 80;
            this.y = Math.random() * (canvas.height * 0.7) + 50;
            this.width = 60;
            this.height = 30;
            this.speedX = (this.fromLeft ? 4 : -4) * difficulty;
            this.speedY = (Math.random() - 0.5) * 1;
            this.engineFlicker = 0;
        }

        update() {
            this.x += this.speedX;
            this.y += this.speedY;
            this.engineFlicker += 0.3;
            
            // Keep in vertical bounds
            if (this.y < 50) this.y = 50;
            if (this.y > canvas.height - 100) this.y = canvas.height - 100;
            
            return this.fromLeft ? this.x < canvas.width + 100 : this.x > -100;
        }

        draw() {
            ctx.save();
            ctx.translate(this.x, this.y);
            
            // Flip if coming from right
            if (!this.fromLeft) {
                ctx.scale(-1, 1);
            }

            // Rocket body
            ctx.fillStyle = '#e74c3c';
            ctx.strokeStyle = '#c0392b';
            ctx.lineWidth = 2;
            
            // Main body
            ctx.fillRect(-25, -12, 45, 24);
            ctx.strokeRect(-25, -12, 45, 24);
            
            // Nose cone
            ctx.fillStyle = '#bdc3c7';
            ctx.beginPath();
            ctx.moveTo(20, -12);
            ctx.lineTo(35, 0);
            ctx.lineTo(20, 12);
            ctx.closePath();
            ctx.fill();
            ctx.stroke();

            // Window
            ctx.fillStyle = '#3498db';
            ctx.shadowBlur = 10;
            ctx.shadowColor = '#3498db';
            ctx.beginPath();
            ctx.arc(5, 0, 6, 0, Math.PI * 2);
            ctx.fill();
            ctx.shadowBlur = 0;

            // Wings
            ctx.fillStyle = '#95a5a6';
            ctx.strokeStyle = '#7f8c8d';
            ctx.beginPath();
            ctx.moveTo(-15, -12);
            ctx.lineTo(-15, -20);
            ctx.lineTo(-5, -12);
            ctx.closePath();
            ctx.fill();
            ctx.stroke();
            
            ctx.beginPath();
            ctx.moveTo(-15, 12);
            ctx.lineTo(-15, 20);
            ctx.lineTo(-5, 12);
            ctx.closePath();
            ctx.fill();
            ctx.stroke();

            // Engine flame
            const flameSize = 15 + Math.sin(this.engineFlicker) * 5;
            ctx.fillStyle = '#ff6600';
            ctx.shadowBlur = 20;
            ctx.shadowColor = '#ff6600';
            ctx.beginPath();
            ctx.moveTo(-25, -8);
            ctx.lineTo(-25 - flameSize, 0);
            ctx.lineTo(-25, 8);
            ctx.closePath();
            ctx.fill();
            
            // Inner flame
            ctx.fillStyle = '#ffaa00';
            ctx.beginPath();
            ctx.moveTo(-25, -5);
            ctx.lineTo(-25 - flameSize * 0.7, 0);
            ctx.lineTo(-25, 5);
            ctx.closePath();
            ctx.fill();

            ctx.shadowBlur = 0;
            ctx.restore();
        }

        checkCollision(px, py, pw, ph) {
            return px + pw/2 > this.x - this.width/2 &&
                   px - pw/2 < this.x + this.width/2 &&
                   py + ph/2 > this.y - this.height/2 &&
                   py - ph/2 < this.y + this.height/2;
        }
    }

    class SpaceSurfer {
        constructor() {
            // Spawn from left or right, moving diagonally
            this.fromLeft = Math.random() > 0.5;
            this.x = this.fromLeft ? -60 : canvas.width + 60;
            this.y = Math.random() * (canvas.height * 0.5);
            this.width = 40;
            this.height = 50;
            this.speedX = (this.fromLeft ? 3.5 : -3.5) * difficulty;
            this.speedY = Math.random() * 1.5 + 1;
            this.wobble = 0;
            this.sparkle = 0;
        }

        update() {
            this.x += this.speedX;
            this.y += this.speedY;
            this.wobble += 0.1;
            this.sparkle += 0.2;
            
            return (this.fromLeft ? this.x < canvas.width + 80 : this.x > -80) && 
                   this.y < canvas.height + 80;
        }

        draw() {
            ctx.save();
            ctx.translate(this.x, this.y);
            
            // Flip if coming from right
            if (!this.fromLeft) {
                ctx.scale(-1, 1);
            }

            const wobbleOffset = Math.sin(this.wobble) * 3;

            // Surfboard
            ctx.fillStyle = '#ff1493';
            ctx.strokeStyle = '#c71585';
            ctx.lineWidth = 2;
            ctx.shadowBlur = 15;
            ctx.shadowColor = '#ff1493';
            
            ctx.beginPath();
            ctx.ellipse(wobbleOffset, 15, 25, 8, Math.PI / 12, 0, Math.PI * 2);
            ctx.fill();
            ctx.stroke();
            ctx.shadowBlur = 0;

            // Surfboard sparkles
            if (Math.sin(this.sparkle) > 0.5) {
                ctx.fillStyle = '#ffffff';
                ctx.shadowBlur = 10;
                ctx.shadowColor = '#ffffff';
                ctx.beginPath();
                ctx.arc(wobbleOffset - 10, 15, 2, 0, Math.PI * 2);
                ctx.arc(wobbleOffset + 10, 15, 2, 0, Math.PI * 2);
                ctx.fill();
                ctx.shadowBlur = 0;
            }

            // Surfer body
            ctx.fillStyle = '#ffa500';
            ctx.fillRect(-5 + wobbleOffset, -5, 10, 15);
            
            // Head
            ctx.fillStyle = '#ffdbac';
            ctx.beginPath();
            ctx.arc(wobbleOffset, -12, 6, 0, Math.PI * 2);
            ctx.fill();

            // Helmet
            ctx.strokeStyle = '#ffffff';
            ctx.lineWidth = 2;
            ctx.shadowBlur = 10;
            ctx.shadowColor = '#00ffff';
            ctx.beginPath();
            ctx.arc(wobbleOffset, -12, 7, Math.PI, 0);
            ctx.stroke();
            ctx.shadowBlur = 0;

            // Arms
            ctx.strokeStyle = '#ffa500';
            ctx.lineWidth = 3;
            ctx.beginPath();
            ctx.moveTo(-5 + wobbleOffset, 0);
            ctx.lineTo(-12 + wobbleOffset, -5);
            ctx.moveTo(5 + wobbleOffset, 0);
            ctx.lineTo(12 + wobbleOffset, 5);
            ctx.stroke();

            // Energy trail from board
            ctx.fillStyle = 'rgba(0, 255, 255, 0.3)';
            ctx.shadowBlur = 20;
            ctx.shadowColor = '#00ffff';
            for (let i = 0; i < 3; i++) {
                ctx.beginPath();
                ctx.arc(-30 - i * 10 + wobbleOffset, 15, 4 - i, 0, Math.PI * 2);
                ctx.fill();
            }

            ctx.shadowBlur = 0;
            ctx.restore();
        }

        checkCollision(px, py, pw, ph) {
            return px + pw/2 > this.x - this.width/2 &&
                   px - pw/2 < this.x + this.width/2 &&
                   py + ph/2 > this.y - this.height/2 &&
                   py - ph/2 < this.y + this.height/2;
        }
    }

    class Satellite {
        constructor() {
            this.x = Math.random() * canvas.width;
            this.y = -60;
            this.width = 50;
            this.height = 30;
            this.speed = (Math.random() * 1.5 + 1.5) * difficulty;
            this.rotation = 0;
            this.panelRotation = 0;
            this.panelRotationSpeed = 0.02;
            this.blink = 0;
        }

        update() {
            this.y += this.speed;
            this.rotation += 0.01;
            this.panelRotation += this.panelRotationSpeed;
            this.blink += 0.1;
            return this.y < canvas.height + 80;
        }

        draw() {
            ctx.save();
            ctx.translate(this.x, this.y);
            ctx.rotate(this.rotation);

            // Solar panels (rotating)
            ctx.save();
            ctx.rotate(this.panelRotation);
            
            // Left panel
            ctx.fillStyle = '#1a3d5c';
            ctx.strokeStyle = '#4a7ba7';
            ctx.lineWidth = 2;
            ctx.fillRect(-45, -8, 25, 16);
            ctx.strokeRect(-45, -8, 25, 16);
            
            // Panel grid
            ctx.strokeStyle = '#6a9bc7';
            ctx.lineWidth = 1;
            for (let i = -40; i < -20; i += 5) {
                ctx.beginPath();
                ctx.moveTo(i, -8);
                ctx.lineTo(i, 8);
                ctx.stroke();
            }
            
            // Right panel
            ctx.fillStyle = '#1a3d5c';
            ctx.strokeStyle = '#4a7ba7';
            ctx.lineWidth = 2;
            ctx.fillRect(20, -8, 25, 16);
            ctx.strokeRect(20, -8, 25, 16);
            
            // Panel grid
            ctx.strokeStyle = '#6a9bc7';
            ctx.lineWidth = 1;
            for (let i = 25; i < 45; i += 5) {
                ctx.beginPath();
                ctx.moveTo(i, -8);
                ctx.lineTo(i, 8);
                ctx.stroke();
            }
            
            ctx.restore();

            // Main satellite body
            ctx.fillStyle = '#bdc3c7';
            ctx.strokeStyle = '#95a5a6';
            ctx.lineWidth = 2;
            ctx.fillRect(-15, -10, 30, 20);
            ctx.strokeRect(-15, -10, 30, 20);

            // Body details
            ctx.fillStyle = '#7f8c8d';
            ctx.fillRect(-12, -7, 24, 3);
            ctx.fillRect(-12, 4, 24, 3);

            // Antenna
            ctx.strokeStyle = '#7f8c8d';
            ctx.lineWidth = 2;
            ctx.beginPath();
            ctx.moveTo(0, -10);
            ctx.lineTo(0, -18);
            ctx.stroke();
            
            // Antenna dish
            ctx.fillStyle = '#ecf0f1';
            ctx.strokeStyle = '#bdc3c7';
            ctx.lineWidth = 1;
            ctx.beginPath();
            ctx.ellipse(0, -18, 5, 3, 0, 0, Math.PI * 2);
            ctx.fill();
            ctx.stroke();

            // Blinking lights
            const blinkOn = Math.sin(this.blink) > 0;
            if (blinkOn) {
                ctx.fillStyle = '#ff0000';
                ctx.shadowBlur = 10;
                ctx.shadowColor = '#ff0000';
                ctx.beginPath();
                ctx.arc(-10, 0, 2, 0, Math.PI * 2);
                ctx.fill();
                
                ctx.fillStyle = '#00ff00';
                ctx.shadowColor = '#00ff00';
                ctx.beginPath();
                ctx.arc(10, 0, 2, 0, Math.PI * 2);
                ctx.fill();
                ctx.shadowBlur = 0;
            }

            // Camera lens
            ctx.fillStyle = '#2c3e50';
            ctx.strokeStyle = '#34495e';
            ctx.lineWidth = 2;
            ctx.shadowBlur = 8;
            ctx.shadowColor = '#3498db';
            ctx.beginPath();
            ctx.arc(0, 0, 4, 0, Math.PI * 2);
            ctx.fill();
            ctx.stroke();
            ctx.shadowBlur = 0;

            ctx.restore();
        }

        checkCollision(px, py, pw, ph) {
            // Include solar panels in collision
            const totalWidth = 90; // Including panels
            return px + pw/2 > this.x - totalWidth/2 &&
                   px - pw/2 < this.x + totalWidth/2 &&
                   py + ph/2 > this.y - this.height/2 &&
                   py - ph/2 < this.y + this.height/2;
        }
    }

    class Powerup {
        constructor() {
            this.x = Math.random() * (canvas.width - 80) + 40;
            this.y = -50;
            this.size = 35; // Increased from 30 to 35
            this.speed = 2.5; // Slightly slower so easier to catch
            this.rotation = 0;
            this.pulse = 0;
            this.type = 'health'; // Mark as health powerup
        }

        update() {
            this.y += this.speed;
            this.rotation += 0.08;
            this.pulse += 0.15;
            return this.y < canvas.height + 60;
        }

        draw() {
            ctx.save();
            ctx.translate(this.x, this.y);
            ctx.rotate(this.rotation);

            // Pulsing glow effect
            const glowSize = this.size + Math.sin(this.pulse) * 5;
            
            // Outer glow
            ctx.strokeStyle = '#00ffff';
            ctx.lineWidth = 5;
            ctx.shadowBlur = 25;
            ctx.shadowColor = '#00ffff';
            
            ctx.beginPath();
            ctx.arc(0, 0, glowSize, 0, Math.PI * 2);
            ctx.stroke();
            
            // Inner circle
            ctx.strokeStyle = '#ffffff';
            ctx.lineWidth = 3;
            ctx.shadowBlur = 20;
            ctx.beginPath();
            ctx.arc(0, 0, this.size - 5, 0, Math.PI * 2);
            ctx.stroke();
            
            // Plus sign (shield/health symbol)
            ctx.strokeStyle = '#00ffff';
            ctx.lineWidth = 4;
            ctx.beginPath();
            ctx.moveTo(-18, 0);
            ctx.lineTo(18, 0);
            ctx.moveTo(0, -18);
            ctx.lineTo(0, 18);
            ctx.stroke();
            
            ctx.shadowBlur = 0;
            ctx.restore();
        }

        checkCollision(px, py, pw, ph) {
            const dist = Math.sqrt((this.x - px) ** 2 + (this.y - py) ** 2);
            return dist < (this.size + Math.min(pw, ph) / 2);
        }
    }

    class WeaponPowerup {
        constructor() {
            this.x = Math.random() * (canvas.width - 80) + 40;
            this.y = -50;
            this.size = 40;
            this.speed = 2.5;
            this.rotation = 0;
            this.pulse = 0;
            
            // Different weapon types
            const types = ['spread', 'laser', 'rapid', 'missile'];
            this.weaponType = types[Math.floor(Math.random() * types.length)];
            
            // Colors and symbols for each weapon
            this.config = {
                spread: { color: '#ff6600', symbol: '⚡', name: 'SPREAD SHOT' },
                laser: { color: '#00ff00', symbol: '━', name: 'LASER BEAM' },
                rapid: { color: '#ffff00', symbol: '※', name: 'RAPID FIRE' },
                missile: { color: '#ff00ff', symbol: '◈', name: 'MISSILES' }
            };
        }

        update() {
            this.y += this.speed;
            this.rotation += 0.1;
            this.pulse += 0.2;
            return this.y < canvas.height + 60;
        }

        draw() {
            const config = this.config[this.weaponType];
            
            ctx.save();
            ctx.translate(this.x, this.y);

            // Pulsing glow
            const glowSize = this.size + Math.sin(this.pulse) * 8;
            ctx.strokeStyle = config.color;
            ctx.lineWidth = 6;
            ctx.shadowBlur = 30;
            ctx.shadowColor = config.color;
            
            // Outer hexagon
            ctx.beginPath();
            for (let i = 0; i < 6; i++) {
                const angle = (Math.PI / 3) * i + this.rotation;
                const x = Math.cos(angle) * glowSize;
                const y = Math.sin(angle) * glowSize;
                if (i === 0) ctx.moveTo(x, y);
                else ctx.lineTo(x, y);
            }
            ctx.closePath();
            ctx.stroke();

            // Inner shape
            ctx.fillStyle = config.color;
            ctx.globalAlpha = 0.3;
            ctx.fill();
            ctx.globalAlpha = 1;

            // Weapon symbol
            ctx.shadowBlur = 15;
            ctx.fillStyle = '#ffffff';
            ctx.font = 'bold 30px Arial';
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            ctx.fillText(config.symbol, 0, 0);

            ctx.shadowBlur = 0;
            ctx.restore();
        }

        checkCollision(px, py, pw, ph) {
            const dist = Math.sqrt((this.x - px) ** 2 + (this.y - py) ** 2);
            return dist < (this.size + Math.min(pw, ph) / 2);
        }
    }

    class ShieldPowerup {
        constructor() {
            this.x = Math.random() * (canvas.width - 80) + 40;
            this.y = -50;
            this.size = 40;
            this.speed = 2.5;
            this.rotation = 0;
            this.pulse = 0;
            this.type = 'shield';
        }

        update() {
            this.y += this.speed;
            this.rotation += 0.12;
            this.pulse += 0.25;
            return this.y < canvas.height + 60;
        }

        draw() {
            ctx.save();
            ctx.translate(this.x, this.y);
            ctx.rotate(this.rotation);

            // Pulsing outer glow
            const glowSize = this.size + Math.sin(this.pulse) * 10;
            
            // Shield shape - diamond
            ctx.strokeStyle = '#4da6ff';
            ctx.lineWidth = 6;
            ctx.shadowBlur = 35;
            ctx.shadowColor = '#4da6ff';
            
            ctx.beginPath();
            ctx.moveTo(0, -glowSize);
            ctx.lineTo(glowSize * 0.7, 0);
            ctx.lineTo(0, glowSize);
            ctx.lineTo(-glowSize * 0.7, 0);
            ctx.closePath();
            ctx.stroke();

            // Inner fill
            ctx.fillStyle = '#4da6ff';
            ctx.globalAlpha = 0.4;
            ctx.fill();
            ctx.globalAlpha = 1;

            // Shield icon
            ctx.strokeStyle = '#ffffff';
            ctx.lineWidth = 4;
            ctx.shadowBlur = 20;
            ctx.shadowColor = '#ffffff';
            
            // Shield emblem
            ctx.beginPath();
            ctx.moveTo(0, -this.size * 0.5);
            ctx.lineTo(this.size * 0.4, 0);
            ctx.lineTo(0, this.size * 0.5);
            ctx.lineTo(-this.size * 0.4, 0);
            ctx.closePath();
            ctx.stroke();

            // Center dot
            ctx.fillStyle = '#ffffff';
            ctx.beginPath();
            ctx.arc(0, 0, 5, 0, Math.PI * 2);
            ctx.fill();

            ctx.shadowBlur = 0;
            ctx.restore();
        }

        checkCollision(px, py, pw, ph) {
            const dist = Math.sqrt((this.x - px) ** 2 + (this.y - py) ** 2);
            return dist < (this.size + Math.min(pw, ph) / 2);
        }
    }

    class Bullet {
        constructor(x, y, weaponType = 'normal', angle = 0) {
            this.x = x;
            this.y = y;
            this.width = 6;
            this.height = 20;
            this.speed = 12;
            this.weaponType = weaponType;
            this.angle = angle;
            
            // Weapon-specific properties
            if (weaponType === 'laser') {
                this.width = 8;
                this.speed = 20;
            }
            if (weaponType === 'missile') {
                this.width = 10;
                this.height = 25;
                this.speed = 10;
            }
        }

        update() {
            if (this.weaponType === 'spread') {
                this.x += Math.sin(this.angle) * this.speed;
                this.y -= Math.cos(this.angle) * this.speed;
            } else {
                this.y -= this.speed;
            }
            return this.y > -50;
        }

        draw() {
            ctx.save();
            
            if (this.weaponType === 'laser') {
                // Green laser beam
                ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
                ctx.fillRect(this.x - this.width/2, this.y, this.width, this.height + 15);
                
                ctx.fillStyle = '#00ff00';
                ctx.shadowBlur = 20;
                ctx.shadowColor = '#00ff00';
                ctx.fillRect(this.x - this.width/2, this.y, this.width, this.height);
                
            } else if (this.weaponType === 'rapid') {
                // Yellow rapid fire
                ctx.fillStyle = 'rgba(255, 255, 0, 0.4)';
                ctx.fillRect(this.x - this.width/2, this.y, this.width, this.height + 8);
                
                ctx.fillStyle = '#ffff00';
                ctx.shadowBlur = 15;
                ctx.shadowColor = '#ffff00';
                ctx.fillRect(this.x - this.width/2, this.y, this.width, this.height);
                
            } else if (this.weaponType === 'missile') {
                // Purple missiles
                ctx.translate(this.x, this.y + this.height/2);
                
                // Missile body
                ctx.fillStyle = '#ff00ff';
                ctx.shadowBlur = 20;
                ctx.shadowColor = '#ff00ff';
                ctx.fillRect(-this.width/2, -this.height/2, this.width, this.height);
                
                // Missile tip
                ctx.fillStyle = '#ffffff';
                ctx.beginPath();
                ctx.moveTo(0, -this.height/2 - 5);
                ctx.lineTo(-this.width/2, -this.height/2);
                ctx.lineTo(this.width/2, -this.height/2);
                ctx.closePath();
                ctx.fill();
                
                // Flame trail
                ctx.fillStyle = '#ff6600';
                ctx.beginPath();
                ctx.moveTo(-3, this.height/2);
                ctx.lineTo(0, this.height/2 + 8);
                ctx.lineTo(3, this.height/2);
                ctx.closePath();
                ctx.fill();
                
            } else if (this.weaponType === 'spread') {
                // Orange spread shot
                ctx.translate(this.x, this.y);
                ctx.rotate(this.angle);
                
                ctx.fillStyle = 'rgba(255, 102, 0, 0.4)';
                ctx.fillRect(-this.width/2, 0, this.width, this.height + 8);
                
                ctx.fillStyle = '#ff6600';
                ctx.shadowBlur = 15;
                ctx.shadowColor = '#ff6600';
                ctx.fillRect(-this.width/2, 0, this.width, this.height);
                
            } else {
                // Normal yellow bullet
                ctx.fillStyle = 'rgba(255, 255, 0, 0.5)';
                ctx.fillRect(this.x - this.width/2, this.y, this.width, this.height + 10);
                
                ctx.fillStyle = '#ffff00';
                ctx.shadowBlur = 15;
                ctx.shadowColor = '#ffff00';
                ctx.fillRect(this.x - this.width/2, this.y, this.width, this.height);
            }

            ctx.shadowBlur = 0;
            ctx.restore();
            
            // Bright tip
            ctx.fillStyle = '#ffffff';
            if (this.weaponType !== 'spread' && this.weaponType !== 'missile') {
                ctx.fillRect(this.x - this.width/2, this.y, this.width, 5);
            }
        }

        checkMeteorHit(obstacle) {
            // For obstacles with size property (circular collision)
            if (obstacle.size) {
                const dist = Math.sqrt((this.x - obstacle.x) ** 2 + (this.y - obstacle.y) ** 2);
                return dist < obstacle.size;
            }
            
            // For obstacles with width/height (rectangular collision)
            if (obstacle.width && obstacle.height) {
                return this.x > obstacle.x - obstacle.width/2 &&
                       this.x < obstacle.x + obstacle.width/2 &&
                       this.y > obstacle.y - obstacle.height/2 &&
                       this.y < obstacle.y + obstacle.height/2;
            }
            
            return false;
        }
    }

    class Particle {
        constructor(x, y, color) {
            this.x = x;
            this.y = y;
            this.speedX = (Math.random() - 0.5) * 12;
            this.speedY = (Math.random() - 0.5) * 12;
            this.life = 1;
            this.decay = Math.random() * 0.015 + 0.015;
            this.size = Math.random() * 10 + 5;
            this.color = color;
        }

        update() {
            this.x += this.speedX;
            this.y += this.speedY;
            this.speedY += 0.2;
            this.life -= this.decay;
            return this.life > 0;
        }

        draw() {
            ctx.save();
            ctx.globalAlpha = this.life;
            ctx.fillStyle = this.color;
            ctx.shadowBlur = 15;
            ctx.shadowColor = this.color;
            ctx.beginPath();
            ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
            ctx.fill();
            ctx.restore();
        }
    }

    class Confetti {
        constructor(x, y) {
            this.x = x;
            this.y = y;
            this.speedX = (Math.random() - 0.5) * 8;
            this.speedY = Math.random() * -8 - 4; // Shoot upward
            this.gravity = 0.3;
            this.rotation = Math.random() * Math.PI * 2;
            this.rotationSpeed = (Math.random() - 0.5) * 0.3;
            this.life = 1;
            this.decay = 0.008;
            this.width = Math.random() * 10 + 5;
            this.height = Math.random() * 15 + 8;
            const colors = ['#ff0000', '#00ff00', '#0000ff', '#ffff00', '#ff00ff', '#00ffff', '#ff6600', '#ff1493'];
            this.color = colors[Math.floor(Math.random() * colors.length)];
        }

        update() {
            this.speedY += this.gravity;
            this.x += this.speedX;
            this.y += this.speedY;
            this.rotation += this.rotationSpeed;
            this.life -= this.decay;
            return this.life > 0 && this.y < canvas.height + 50;
        }

        draw() {
            ctx.save();
            ctx.globalAlpha = this.life;
            ctx.translate(this.x, this.y);
            ctx.rotate(this.rotation);
            ctx.fillStyle = this.color;
            ctx.fillRect(-this.width/2, -this.height/2, this.width, this.height);
            ctx.restore();
        }
    }

    class EngineParticle {
        constructor(x, y) {
            this.x = x;
            this.y = y;
            this.speedX = (Math.random() - 0.5) * 2;
            this.speedY = Math.random() * 2 + 1; // Move downward/backward
            this.life = 1;
            this.decay = Math.random() * 0.03 + 0.02;
            this.size = Math.random() * 6 + 3;
            
            // Random fire colors
            const colors = ['#ff6600', '#ff9900', '#ffaa00', '#ff3300', '#ffcc00'];
            this.color = colors[Math.floor(Math.random() * colors.length)];
        }

        update() {
            this.x += this.speedX;
            this.y += this.speedY;
            this.life -= this.decay;
            this.size *= 0.97; // Shrink over time
            return this.life > 0;
        }

        draw() {
            ctx.save();
            ctx.globalAlpha = this.life;
            
            // Outer glow
            ctx.fillStyle = this.color;
            ctx.shadowBlur = 20;
            ctx.shadowColor = this.color;
            ctx.beginPath();
            ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
            ctx.fill();
            
            // Inner bright core
            ctx.fillStyle = '#ffffff';
            ctx.shadowBlur = 10;
            ctx.beginPath();
            ctx.arc(this.x, this.y, this.size * 0.4, 0, Math.PI * 2);
            ctx.fill();
            
            ctx.restore();
        }
    }

    class ShipDebris {
        constructor(x, y, type) {
            this.x = x;
            this.y = y;
            this.type = type; // 'nose', 'body', 'cockpit', 'fin', 'engine', 'stripe'
            this.speedX = (Math.random() - 0.5) * 8;
            this.speedY = (Math.random() - 0.5) * 8;
            this.rotation = Math.random() * Math.PI * 2;
            this.rotationSpeed = (Math.random() - 0.5) * 0.3;
            this.life = 1;
            this.decay = 0.015;
            this.size = 25; // Increased from 15 to 25
        }

        update() {
            this.x += this.speedX;
            this.y += this.speedY;
            this.speedY += 0.1; // Gravity
            this.rotation += this.rotationSpeed;
            this.life -= this.decay;
            return this.life > 0;
        }

        draw() {
            ctx.save();
            ctx.globalAlpha = this.life;
            ctx.translate(this.x, this.y);
            ctx.rotate(this.rotation);

            switch(this.type) {
                case 'nose':
                    // Red nose cone piece
                    ctx.fillStyle = '#e74c3c';
                    ctx.strokeStyle = '#c0392b';
                    ctx.lineWidth = 2;
                    ctx.beginPath();
                    ctx.moveTo(0, -this.size);
                    ctx.lineTo(-this.size/2, this.size/2);
                    ctx.lineTo(this.size/2, this.size/2);
                    ctx.closePath();
                    ctx.fill();
                    ctx.stroke();
                    break;

                case 'body':
                    // Red body panel
                    ctx.fillStyle = '#e74c3c';
                    ctx.strokeStyle = '#c0392b';
                    ctx.lineWidth = 2;
                    ctx.fillRect(-this.size/2, -this.size/2, this.size, this.size);
                    ctx.strokeRect(-this.size/2, -this.size/2, this.size, this.size);
                    break;

                case 'cockpit':
                    // Blue glowing cockpit window
                    ctx.fillStyle = '#3498db';
                    ctx.strokeStyle = '#2980b9';
                    ctx.lineWidth = 2;
                    ctx.shadowBlur = 15;
                    ctx.shadowColor = '#3498db';
                    ctx.beginPath();
                    ctx.arc(0, 0, this.size/2, 0, Math.PI * 2);
                    ctx.fill();
                    ctx.stroke();
                    ctx.shadowBlur = 0;
                    break;

                case 'fin':
                    // Gray fin piece
                    ctx.fillStyle = '#95a5a6';
                    ctx.strokeStyle = '#7f8c8d';
                    ctx.lineWidth = 2;
                    ctx.beginPath();
                    ctx.moveTo(0, 0);
                    ctx.lineTo(-this.size, this.size/2);
                    ctx.lineTo(-this.size, this.size);
                    ctx.lineTo(0, this.size/2);
                    ctx.closePath();
                    ctx.fill();
                    ctx.stroke();
                    break;

                case 'engine':
                    // Dark engine nozzle
                    ctx.fillStyle = '#34495e';
                    ctx.strokeStyle = '#2c3e50';
                    ctx.lineWidth = 2;
                    ctx.fillRect(-this.size/3, -this.size/2, this.size * 0.6, this.size);
                    ctx.strokeRect(-this.size/3, -this.size/2, this.size * 0.6, this.size);
                    
                    // Engine glow
                    ctx.fillStyle = '#ff6600';
                    ctx.shadowBlur = 10;
                    ctx.shadowColor = '#ff6600';
                    ctx.beginPath();
                    ctx.arc(0, this.size/3, 3, 0, Math.PI * 2);
                    ctx.fill();
                    ctx.shadowBlur = 0;
                    break;

                case 'stripe':
                    // White accent stripe
                    ctx.fillStyle = '#ffffff';
                    ctx.strokeStyle = '#ecf0f1';
                    ctx.lineWidth = 1;
                    ctx.fillRect(-this.size/2, -2, this.size, 4);
                    ctx.strokeRect(-this.size/2, -2, this.size, 4);
                    break;
            }

            ctx.restore();
        }
    }

    class FeedbackMessage {
        constructor(x, y, text, color, size = 36) {
            this.x = x;
            this.y = y;
            this.text = text;
            this.color = color;
            this.size = size;
            this.life = 1;
            this.decay = 0.02;
            this.speedY = -2; // Float upward
            this.scale = 0.5;
            this.targetScale = 1.2;
        }

        update() {
            this.y += this.speedY;
            this.life -= this.decay;
            
            // Grow then shrink
            if (this.scale < this.targetScale) {
                this.scale += 0.1;
            }
            
            return this.life > 0;
        }

        draw() {
            ctx.save();
            ctx.globalAlpha = this.life;
            ctx.translate(this.x, this.y);
            ctx.scale(this.scale, this.scale);
            
            ctx.font = `bold ${this.size}px Arial`;
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            
            // Outline
            ctx.strokeStyle = '#000';
            ctx.lineWidth = 4;
            ctx.strokeText(this.text, 0, 0);
            
            // Fill
            ctx.fillStyle = this.color;
            ctx.shadowBlur = 20;
            ctx.shadowColor = this.color;
            ctx.fillText(this.text, 0, 0);
            
            ctx.restore();
        }
    }

    class EjectedAstronaut {
        constructor(x, y) {
            this.x = x;
            this.y = y;
            this.speedX = (Math.random() - 0.5) * 3; // Small sideways motion
            this.speedY = 1; // Start falling immediately (positive = down)
            this.rotation = Math.random() * Math.PI * 2;
            this.rotationSpeed = (Math.random() - 0.5) * 0.15;
            this.life = 1;
            this.decay = 0.005; // Slow decay so visible longer
            this.armWave = 0;
            this.parachuteOpen = false;
            this.parachuteTimer = 0;
        }

        update() {
            this.parachuteTimer++;
            
            // Open parachute immediately (after 10 frames)
            if (this.parachuteTimer > 10) {
                this.parachuteOpen = true;
            }
            
            this.x += this.speedX;
            this.y += this.speedY;
            
            if (this.parachuteOpen) {
                // Gentle fall with parachute (faster than before)
                this.speedY += 0.015; // Gentle gravity
                this.speedY = Math.min(this.speedY, 2); // Moderate fall speed
                this.speedX *= 0.96; // Slow down horizontal movement
                this.rotation = 0; // Upright when parachute is open
                this.rotationSpeed = 0;
            } else {
                // Brief tumble before parachute opens
                this.speedY += 0.15;
                this.rotation += this.rotationSpeed;
            }
            
            this.life -= this.decay;
            this.armWave += 0.2;
            return this.life > 0 && this.y < canvas.height + 50;
        }

        draw() {
            ctx.save();
            ctx.globalAlpha = this.life;
            ctx.translate(this.x, this.y);
            ctx.rotate(this.rotation);

            // Parachute (if open)
            if (this.parachuteOpen) {
                const swayOffset = Math.sin(this.armWave * 0.5) * 3;
                
                // Parachute canopy
                ctx.fillStyle = '#ff6600';
                ctx.strokeStyle = '#cc5500';
                ctx.lineWidth = 2;
                ctx.shadowBlur = 10;
                ctx.shadowColor = '#ff6600';
                
                // Main canopy (dome shape)
                ctx.beginPath();
                ctx.moveTo(-25 + swayOffset, -25);
                ctx.quadraticCurveTo(0 + swayOffset, -40, 25 + swayOffset, -25);
                ctx.lineTo(20 + swayOffset, -20);
                ctx.quadraticCurveTo(0 + swayOffset, -30, -20 + swayOffset, -20);
                ctx.closePath();
                ctx.fill();
                ctx.stroke();
                ctx.shadowBlur = 0;
                
                // Parachute panels
                ctx.strokeStyle = '#ffffff';
                ctx.lineWidth = 1;
                for (let i = -1; i <= 1; i++) {
                    ctx.beginPath();
                    ctx.moveTo(i * 10 + swayOffset, -25);
                    ctx.lineTo(i * 8 + swayOffset, -20);
                    ctx.stroke();
                }
                
                // Parachute strings
                ctx.strokeStyle = '#ffffff';
                ctx.lineWidth = 1;
                ctx.beginPath();
                ctx.moveTo(-20 + swayOffset, -20);
                ctx.lineTo(-3, -8);
                ctx.moveTo(20 + swayOffset, -20);
                ctx.lineTo(3, -8);
                ctx.moveTo(0 + swayOffset, -20);
                ctx.lineTo(0, -8);
                ctx.stroke();
            }

            // Helmet (space suit)
            ctx.fillStyle = '#ffffff';
            ctx.strokeStyle = '#cccccc';
            ctx.lineWidth = 2;
            ctx.shadowBlur = 10;
            ctx.shadowColor = '#00ffff';
            ctx.beginPath();
            ctx.arc(0, -6, 8, 0, Math.PI * 2);
            ctx.fill();
            ctx.stroke();
            ctx.shadowBlur = 0;

            // Visor
            ctx.fillStyle = '#3498db';
            ctx.shadowBlur = 8;
            ctx.shadowColor = '#3498db';
            ctx.beginPath();
            ctx.arc(0, -6, 5, 0, Math.PI * 2);
            ctx.fill();
            ctx.shadowBlur = 0;

            // Visor reflection
            ctx.fillStyle = 'rgba(255, 255, 255, 0.6)';
            ctx.beginPath();
            ctx.arc(-2, -8, 2, 0, Math.PI * 2);
            ctx.fill();

            // Body (orange spacesuit)
            ctx.fillStyle = '#ff6600';
            ctx.strokeStyle = '#cc5500';
            ctx.lineWidth = 1.5;
            ctx.fillRect(-4, 2, 8, 10);
            ctx.strokeRect(-4, 2, 8, 10);

            // Life support backpack
            ctx.fillStyle = '#555555';
            ctx.fillRect(-3, 3, 6, 4);

            // Arms (waving)
            ctx.strokeStyle = '#ff6600';
            ctx.lineWidth = 2;
            const armOffset = Math.sin(this.armWave) * 2;
            
            // Left arm
            ctx.beginPath();
            ctx.moveTo(-4, 4);
            ctx.lineTo(-7, 6 + armOffset);
            ctx.stroke();

            // Right arm
            ctx.beginPath();
            ctx.moveTo(4, 4);
            ctx.lineTo(7, 6 - armOffset);
            ctx.stroke();

            // Legs
            ctx.strokeStyle = '#ff6600';
            ctx.lineWidth = 2;
            ctx.beginPath();
            ctx.moveTo(-2, 12);
            ctx.lineTo(-3, 16);
            ctx.moveTo(2, 12);
            ctx.lineTo(3, 16);
            ctx.stroke();

            // Boots
            ctx.fillStyle = '#333333';
            ctx.fillRect(-4, 15, 2, 3);
            ctx.fillRect(2, 15, 2, 3);

            ctx.restore();
        }
    }

    function createExplosion(x, y, color) {
        for (let i = 0; i < 25; i++) {
            particles.push(new Particle(x, y, color));
        }
    }

    function playExplosionSound() {
        if (!audioContext) return;
        
        const now = audioContext.currentTime;
        
        // Create multiple oscillators for a rich explosion sound
        // Low rumble
        const rumble = audioContext.createOscillator();
        const rumbleGain = audioContext.createGain();
        rumble.type = 'sawtooth';
        rumble.frequency.setValueAtTime(50, now);
        rumble.frequency.exponentialRampToValueAtTime(20, now + 0.5);
        rumbleGain.gain.setValueAtTime(0.3, now);
        rumbleGain.gain.exponentialRampToValueAtTime(0.01, now + 0.5);
        rumble.connect(rumbleGain);
        rumbleGain.connect(audioContext.destination);
        rumble.start(now);
        rumble.stop(now + 0.5);
        
        // Mid explosion crack
        const crack = audioContext.createOscillator();
        const crackGain = audioContext.createGain();
        crack.type = 'square';
        crack.frequency.setValueAtTime(200, now);
        crack.frequency.exponentialRampToValueAtTime(50, now + 0.3);
        crackGain.gain.setValueAtTime(0.4, now);
        crackGain.gain.exponentialRampToValueAtTime(0.01, now + 0.3);
        crack.connect(crackGain);
        crackGain.connect(audioContext.destination);
        crack.start(now);
        crack.stop(now + 0.3);
        
        // High frequency blast
        const blast = audioContext.createOscillator();
        const blastGain = audioContext.createGain();
        blast.type = 'square';
        blast.frequency.setValueAtTime(800, now);
        blast.frequency.exponentialRampToValueAtTime(100, now + 0.2);
        blastGain.gain.setValueAtTime(0.3, now);
        blastGain.gain.exponentialRampToValueAtTime(0.01, now + 0.2);
        blast.connect(blastGain);
        blastGain.connect(audioContext.destination);
        blast.start(now);
        blast.stop(now + 0.2);
        
        // White noise for debris
        const bufferSize = audioContext.sampleRate * 0.4;
        const noiseBuffer = audioContext.createBuffer(1, bufferSize, audioContext.sampleRate);
        const output = noiseBuffer.getChannelData(0);
        for (let i = 0; i < bufferSize; i++) {
            output[i] = Math.random() * 2 - 1;
        }
        
        const whiteNoise = audioContext.createBufferSource();
        const noiseGain = audioContext.createGain();
        const noiseFilter = audioContext.createBiquadFilter();
        
        whiteNoise.buffer = noiseBuffer;
        noiseFilter.type = 'lowpass';
        noiseFilter.frequency.setValueAtTime(2000, now);
        noiseFilter.frequency.exponentialRampToValueAtTime(200, now + 0.4);
        noiseGain.gain.setValueAtTime(0.2, now);
        noiseGain.gain.exponentialRampToValueAtTime(0.01, now + 0.4);
        
        whiteNoise.connect(noiseFilter);
        noiseFilter.connect(noiseGain);
        noiseGain.connect(audioContext.destination);
        whiteNoise.start(now);
        whiteNoise.stop(now + 0.4);
    }

    function explodeShip(x, y) {
        playerDestroyed = true;
        
        // If in minigame, end it immediately
        if (inMinigame) {
            setTimeout(() => {
                endMinigame(true); // Died in minigame
            }, 2000); // Wait 2 seconds to show explosion
        }
        
        // Play explosion sound
        playExplosionSound();
        
        // Screen shake effect
        screenShake = 30;
        shakeIntensity = 15;
        
        // Giant BOOM text
        feedbackMessages.push(new FeedbackMessage(x, y, '💥 BOOM! 💥', '#ff0000', 72));
        
        // Eject the pilot!
        ejectedAstronaut = new EjectedAstronaut(x, y - 10);
        
        // Create realistic ship debris pieces matching the rocket design
        shipDebris.push(new ShipDebris(x, y - 15, 'nose')); // Red nose cone
        shipDebris.push(new ShipDebris(x - 8, y - 5, 'body')); // Left body panel
        shipDebris.push(new ShipDebris(x + 8, y - 5, 'body')); // Right body panel
        shipDebris.push(new ShipDebris(x, y + 5, 'body')); // Center body
        shipDebris.push(new ShipDebris(x, y - 5, 'cockpit')); // Blue cockpit window
        shipDebris.push(new ShipDebris(x - 18, y + 12, 'fin')); // Left fin
        shipDebris.push(new ShipDebris(x + 18, y + 12, 'fin')); // Right fin
        shipDebris.push(new ShipDebris(x - 7, y + 18, 'engine')); // Left engine nozzle
        shipDebris.push(new ShipDebris(x + 7, y + 18, 'engine')); // Right engine nozzle
        shipDebris.push(new ShipDebris(x - 5, y, 'stripe')); // White stripe piece
        shipDebris.push(new ShipDebris(x + 5, y, 'stripe')); // White stripe piece
        
        // MASSIVE EXPLOSION - Much bigger and more dramatic!
        
        // First wave - Bright orange/yellow fire core (150 particles)
        for (let i = 0; i < 150; i++) {
            particles.push(new Particle(x, y, '#ff6600'));
            particles.push(new Particle(x, y, '#ffaa00'));
            particles.push(new Particle(x, y, '#ff8800'));
        }
        
        // Second wave - Bright white hot center (100 particles)
        for (let i = 0; i < 100; i++) {
            particles.push(new Particle(x, y, '#ffffff'));
            particles.push(new Particle(x, y, '#ffffcc'));
        }
        
        // Third wave - Red/orange outer ring (80 particles)
        for (let i = 0; i < 80; i++) {
            particles.push(new Particle(x, y, '#ff0000'));
            particles.push(new Particle(x, y, '#ff4400'));
        }
        
        // Fourth wave - Dark smoke particles (60 particles)
        for (let i = 0; i < 60; i++) {
            particles.push(new Particle(x, y, '#555555'));
            particles.push(new Particle(x, y, '#333333'));
        }
        
        // Shockwave ring effect
        for (let angle = 0; angle < Math.PI * 2; angle += 0.2) {
            const dist = 50;
            const px = x + Math.cos(angle) * dist;
            const py = y + Math.sin(angle) * dist;
            particles.push(new Particle(px, py, '#ffff00'));
            particles.push(new Particle(px, py, '#ffffff'));
        }
    }

    function shoot() {
        if (!gameRunning || !canShoot) return;
        
        const baseY = player.y - player.height/2;
        
        // Different shooting patterns based on active weapon
        switch(activeWeapon) {
            case 'spread':
                // 5 bullets in a spread pattern
                for (let i = -2; i <= 2; i++) {
                    const angle = i * 0.25; // Spread angle
                    bullets.push(new Bullet(player.x, baseY, 'spread', angle));
                }
                break;
                
            case 'laser':
                // Single powerful laser
                bullets.push(new Bullet(player.x, baseY, 'laser'));
                break;
                
            case 'rapid':
                // Triple shot
                bullets.push(new Bullet(player.x - 10, baseY, 'rapid'));
                bullets.push(new Bullet(player.x, baseY, 'rapid'));
                bullets.push(new Bullet(player.x + 10, baseY, 'rapid'));
                break;
                
            case 'missile':
                // Dual homing missiles
                bullets.push(new Bullet(player.x - 15, baseY, 'missile'));
                bullets.push(new Bullet(player.x + 15, baseY, 'missile'));
                break;
                
            default:
                // Normal gun with upgrade levels
                const bulletCount = gunLevel >= 3 ? 2 : 1;
                if (bulletCount === 2) {
                    bullets.push(new Bullet(player.x - 15, baseY));
                    bullets.push(new Bullet(player.x + 15, baseY));
                } else {
                    bullets.push(new Bullet(player.x, baseY));
                }
        }
        
        canShoot = false;
        
        // Weapon affects fire rate
        let cooldown;
        if (activeWeapon === 'rapid') {
            cooldown = 100; // Very fast
        } else if (activeWeapon === 'spread') {
            cooldown = 400; // Slower for balance
        } else if (activeWeapon === 'missile') {
            cooldown = 600; // Slowest but powerful
        } else {
            const cooldowns = [200, 175, 150, 120, 90];
            cooldown = cooldowns[gunLevel - 1];
        }
        
        setTimeout(() => {
            canShoot = true;
        }, cooldown);
    }

    function updateShopDisplay() {
        document.getElementById('shopCredits').textContent = credits;
        document.getElementById('credits').textContent = credits;
        
        // Shield upgrade
        document.getElementById('shieldLevelText').textContent = `${shieldLevel}/5`;
        document.getElementById('shieldLevelBar').style.width = (shieldLevel * 20) + '%';
        document.getElementById('currentMaxHealth').textContent = maxHearts + ' Hearts';
        
        const shieldBtn = document.getElementById('upgradeShieldBtn');
        if (shieldLevel >= 5) {
            shieldBtn.textContent = 'MAX LEVEL';
            shieldBtn.disabled = true;
            shieldBtn.classList.add('maxed');
        } else {
            const cost = upgradeCosts.shield[shieldLevel];
            shieldBtn.textContent = `UPGRADE (${cost} Credits)`;
            shieldBtn.disabled = credits < cost;
        }
        
        // Gun upgrade
        document.getElementById('gunLevelText').textContent = `${gunLevel}/5`;
        document.getElementById('gunLevelBar').style.width = (gunLevel * 20) + '%';
        
        const fireRates = ['Normal', 'Fast', 'Rapid', 'Very Rapid', 'EXTREME'];
        document.getElementById('currentFireRate').textContent = fireRates[gunLevel - 1];
        
        const gunBtn = document.getElementById('upgradeGunBtn');
        if (gunLevel >= 5) {
            gunBtn.textContent = 'MAX LEVEL';
            gunBtn.disabled = true;
            gunBtn.classList.add('maxed');
        } else {
            const cost = upgradeCosts.gun[gunLevel];
            gunBtn.textContent = `UPGRADE (${cost} Credits)`;
            gunBtn.disabled = credits < cost;
        }
    }

    function upgradeShield() {
        if (shieldLevel >= 5) return;
        
        const cost = upgradeCosts.shield[shieldLevel];
        if (credits >= cost) {
            credits -= cost;
            shieldLevel++;
            maxHearts = 3 + (shieldLevel - 1); // +1 heart per level
            
            localStorage.setItem('meteorCredits', credits);
            localStorage.setItem('shieldLevel', shieldLevel);
            
            updateShopDisplay();
        }
    }

    function upgradeGun() {
        if (gunLevel >= 5) return;
        
        const cost = upgradeCosts.gun[gunLevel];
        if (credits >= cost) {
            credits -= cost;
            gunLevel++;
            
            localStorage.setItem('meteorCredits', credits);
            localStorage.setItem('gunLevel', gunLevel);
            
            updateShopDisplay();
        }
    }

    function openShop() {
        updateShopDisplay();
        document.getElementById('upgradeShop').style.display = 'flex';
        document.getElementById('startScreen').style.display = 'none';
        document.getElementById('gameOver').style.display = 'none';
    }

    function closeShop() {
        document.getElementById('upgradeShop').style.display = 'none';
        document.getElementById('startScreen').style.display = 'flex';
    }

    function updateHeartsDisplay() {
        const heartsContainer = document.getElementById('hearts-display');
        heartsContainer.innerHTML = '';
        
        for (let i = 0; i < maxHearts; i++) {
            const heart = document.createElement('span');
            heart.className = 'heart';
            heart.textContent = '❤️';
            
            if (i >= hearts) {
                heart.classList.add('lost');
            }
            
            heartsContainer.appendChild(heart);
        }
    }

    function showWeaponNotification(weaponName) {
        const notification = document.getElementById('weaponNotification');
        notification.textContent = `🎯 ${weaponName} EQUIPPED! 🎯`;
        notification.style.opacity = '1';
        
        setTimeout(() => {
            notification.style.opacity = '0';
        }, 2000);
    }

    function updateWeaponDisplay() {
        const display = document.getElementById('weaponDisplay');
        
        if (weaponTimeLeft > 0 && !playerDestroyed) {
            const seconds = Math.ceil(weaponTimeLeft / 1000);
            const weaponNames = {
                spread: 'SPREAD SHOT',
                laser: 'LASER BEAM',
                rapid: 'RAPID FIRE',
                missile: 'MISSILES'
            };
            display.textContent = `${weaponNames[activeWeapon]} - ${seconds}s`;
            display.style.display = 'block';
            weaponTimeLeft -= 16; // Approximately 60 FPS
            
            if (weaponTimeLeft <= 0) {
                activeWeapon = 'normal';
                display.style.display = 'none';
            }
        } else {
            display.style.display = 'none';
        }

        // Update shield timer (only when player is alive)
        if (shieldTimeLeft > 0 && !playerDestroyed) {
            shieldTimeLeft -= 16;
            if (shieldTimeLeft <= 0) {
                shieldActive = false;
            }
        }
    }

    function drawPlayer() {
        ctx.save();
        ctx.translate(player.x, player.y);

        // Shield bubble when active
        if (shieldActive) {
            const shieldPulse = Math.sin(Date.now() / 100) * 5;
            const shieldRadius = player.width/2 + 25 + shieldPulse;
            
            ctx.strokeStyle = '#4da6ff';
            ctx.lineWidth = 4;
            ctx.shadowBlur = 30;
            ctx.shadowColor = '#4da6ff';
            
            ctx.beginPath();
            ctx.arc(0, 0, shieldRadius, 0, Math.PI * 2);
            ctx.stroke();
            
            ctx.fillStyle = 'rgba(77, 166, 255, 0.15)';
            ctx.fill();
            
            // Energy particles around shield
            for (let i = 0; i < 8; i++) {
                const angle = (Date.now() / 500 + i * Math.PI / 4) % (Math.PI * 2);
                const px = Math.cos(angle) * shieldRadius;
                const py = Math.sin(angle) * shieldRadius;
                
                ctx.fillStyle = '#ffffff';
                ctx.beginPath();
                ctx.arc(px, py, 3, 0, Math.PI * 2);
                ctx.fill();
            }
        }

        // Enhanced shield visual at higher levels (only when not in active shield mode)
        // REMOVED - no permanent glow around ship

        // ROCKET SHIP DESIGN
        
        // Nose cone (pointed front)
        ctx.fillStyle = '#e74c3c';
        ctx.strokeStyle = '#c0392b';
        ctx.lineWidth = 2;
        ctx.shadowBlur = 15;
        ctx.shadowColor = '#e74c3c';
        
        ctx.beginPath();
        ctx.moveTo(0, -player.height/2 - 10); // Sharp point
        ctx.lineTo(-12, -player.height/2 + 10);
        ctx.lineTo(12, -player.height/2 + 10);
        ctx.closePath();
        ctx.fill();
        ctx.stroke();
        ctx.shadowBlur = 0;

        // Main rocket body
        ctx.fillStyle = '#e74c3c';
        ctx.strokeStyle = '#c0392b';
        ctx.lineWidth = 2;
        ctx.fillRect(-12, -player.height/2 + 10, 24, player.height - 10);
        ctx.strokeRect(-12, -player.height/2 + 10, 24, player.height - 10);

        // Body accent stripe
        ctx.fillStyle = '#ffffff';
        ctx.fillRect(-10, -player.height/2 + 12, 20, 3);

        // Cockpit window
        ctx.fillStyle = '#3498db';
        ctx.strokeStyle = '#2980b9';
        ctx.lineWidth = 2;
        ctx.shadowBlur = 15;
        ctx.shadowColor = '#3498db';
        ctx.beginPath();
        ctx.arc(0, -player.height/2 + 20, 8, 0, Math.PI * 2);
        ctx.fill();
        ctx.stroke();
        
        // Window reflection
        ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';
        ctx.beginPath();
        ctx.arc(-2, -player.height/2 + 18, 3, 0, Math.PI * 2);
        ctx.fill();
        ctx.shadowBlur = 0;

        // Side fins (wings)
        ctx.fillStyle = '#95a5a6';
        ctx.strokeStyle = '#7f8c8d';
        ctx.lineWidth = 2;
        
        // Left fin
        ctx.beginPath();
        ctx.moveTo(-12, player.height/2 - 15);
        ctx.lineTo(-25, player.height/2 - 5);
        ctx.lineTo(-25, player.height/2);
        ctx.lineTo(-12, player.height/2 - 5);
        ctx.closePath();
        ctx.fill();
        ctx.stroke();
        
        // Right fin
        ctx.beginPath();
        ctx.moveTo(12, player.height/2 - 15);
        ctx.lineTo(25, player.height/2 - 5);
        ctx.lineTo(25, player.height/2);
        ctx.lineTo(12, player.height/2 - 5);
        ctx.closePath();
        ctx.fill();
        ctx.stroke();

        // Fin details
        ctx.strokeStyle = '#ecf0f1';
        ctx.lineWidth = 1;
        ctx.beginPath();
        ctx.moveTo(-22, player.height/2 - 3);
        ctx.lineTo(-15, player.height/2 - 8);
        ctx.moveTo(22, player.height/2 - 3);
        ctx.lineTo(15, player.height/2 - 8);
        ctx.stroke();

        // Engine nozzles
        ctx.fillStyle = '#34495e';
        ctx.strokeStyle = '#2c3e50';
        ctx.lineWidth = 2;
        
        // Left engine
        ctx.fillRect(-10, player.height/2 - 8, 6, 10);
        ctx.strokeRect(-10, player.height/2 - 8, 6, 10);
        
        // Right engine
        ctx.fillRect(4, player.height/2 - 8, 6, 10);
        ctx.strokeRect(4, player.height/2 - 8, 6, 10);

        // Engine glow (already handled by engine particles)
        ctx.fillStyle = '#ff6600';
        ctx.shadowBlur = 20;
        ctx.shadowColor = '#ff6600';
        ctx.beginPath();
        ctx.arc(-7, player.height/2 + 2, 4, 0, Math.PI * 2);
        ctx.arc(7, player.height/2 + 2, 4, 0, Math.PI * 2);
        ctx.fill();
        ctx.shadowBlur = 0;

        // Weapon indicators based on gun level
        if (gunLevel >= 3) {
            // Advanced weapons - dual laser ports
            ctx.fillStyle = '#ffff00';
            ctx.shadowBlur = 10;
            ctx.shadowColor = '#ffff00';
            ctx.fillRect(-15, -player.height/2 + 5, 4, 8);
            ctx.fillRect(11, -player.height/2 + 5, 4, 8);
            ctx.shadowBlur = 0;
        }
        
        if (gunLevel >= 4) {
            // Elite weapons - extra emitters
            ctx.fillStyle = '#ff00ff';
            ctx.beginPath();
            ctx.arc(-13, -player.height/2 + 2, 2, 0, Math.PI * 2);
            ctx.arc(13, -player.height/2 + 2, 2, 0, Math.PI * 2);
            ctx.fill();
        }

        ctx.restore();
    }

    let touchStartX = 0;
    let touchStartY = 0;
    let isDragging = false;

    function handleTouchStart(e) {
        if (!gameRunning) return;
        e.preventDefault();

        const rect = canvas.getBoundingClientRect();
        const touch = e.touches ? e.touches[0] : e;
        touchStartX = touch.clientX - rect.left;
        touchStartY = touch.clientY - rect.top;
        isDragging = false;
    }

    function handleTouchMove(e) {
        if (!gameRunning) return;
        e.preventDefault();

        const rect = canvas.getBoundingClientRect();
        const touch = e.touches ? e.touches[0] : e;
        const currentX = touch.clientX - rect.left;
        const currentY = touch.clientY - rect.top;
        
        // If moved more than 10 pixels, consider it a drag
        const dist = Math.sqrt((currentX - touchStartX) ** 2 + (currentY - touchStartY) ** 2);
        if (dist > 10) {
            isDragging = true;
            player.targetX = currentX;
            player.targetY = currentY;
        }
    }

    function handleTouchEnd(e) {
        if (!gameRunning) return;
        e.preventDefault();

        // If it wasn't a drag, it was a tap - shoot!
        if (!isDragging) {
            shoot();
        }
    }

    canvas.addEventListener('touchstart', handleTouchStart);
    canvas.addEventListener('touchmove', handleTouchMove);
    canvas.addEventListener('touchend', handleTouchEnd);
    canvas.addEventListener('mousedown', handleTouchStart);
    canvas.addEventListener('mousemove', handleTouchMove);
    canvas.addEventListener('mouseup', handleTouchEnd);

    // Spacebar to shoot on desktop
    document.addEventListener('keydown', (e) => {
        if (e.code === 'Space') {
            e.preventDefault();
            shoot();
        }
    });

    function gameLoop() {
        if (!gameRunning) return;

        // Update survival time and score (only if alive)
        if (!playerDestroyed) {
            survivalTime = Math.floor((Date.now() - gameStartTime) / 1000);
            document.getElementById('time').textContent = survivalTime + 's';
            
            // Update score based on mode
            if (inMinigame) {
                const minigameTime = Math.floor((Date.now() - minigameStartTime) / 1000);
                const timeRemaining = minigameTimeLimit - minigameTime;
                document.getElementById('time').textContent = timeRemaining + 's MINIGAME';
                document.getElementById('score').textContent = minigameScore + ' kills';
                
                // Check if minigame time is up
                if (timeRemaining <= 0) {
                    endMinigame(false); // Time's up, return to normal game
                }
            } else {
                score = survivalTime * 10;
                document.getElementById('score').textContent = score;
                
                // Check for WIN at 100 seconds
                if (survivalTime >= 100) {
                    winGame();
                    return; // Stop game loop
                }
                
                // Trigger minigame at 50 seconds (only once)
                if (survivalTime === 50 && !minigameTriggered) {
                    minigameTriggered = true;
                    startMinigame('survival50');
                }
            }
        }

        // Increase difficulty over time
        difficulty = 1 + (survivalTime / 30);

        // Clear canvas
        ctx.fillStyle = '#000510';
        ctx.fillRect(0, 0, canvas.width, canvas.height);

        // Draw planets in the background
        ctx.save();
        
        // Planet 1 - Large Gas Giant (Jupiter-like) in top right
        const planet1X = canvas.width - 150;
        const planet1Y = 120;
        const planet1Radius = 80;
        
        // Gas giant gradient
        const gasGiant = ctx.createRadialGradient(
            planet1X - 20, planet1Y - 20, 20,
            planet1X, planet1Y, planet1Radius
        );
        gasGiant.addColorStop(0, '#e8c4a0');
        gasGiant.addColorStop(0.4, '#d4a574');
        gasGiant.addColorStop(0.7, '#b87f4f');
        gasGiant.addColorStop(1, '#8a5c3a');
        ctx.fillStyle = gasGiant;
        ctx.shadowBlur = 25;
        ctx.shadowColor = '#d4a574';
        ctx.beginPath();
        ctx.arc(planet1X, planet1Y, planet1Radius, 0, Math.PI * 2);
        ctx.fill();
        ctx.shadowBlur = 0;
        
        // Gas giant bands
        ctx.strokeStyle = 'rgba(139, 92, 58, 0.4)';
        ctx.lineWidth = 8;
        for (let i = -2; i <= 2; i++) {
            ctx.beginPath();
            ctx.ellipse(planet1X, planet1Y, planet1Radius * 0.95, planet1Radius * 0.7, 0, 0, Math.PI * 2);
            ctx.stroke();
        }
        
        // Planet 2 - Blue Ice Planet (Neptune-like) in top left
        const planet2X = 100;
        const planet2Y = 100;
        const planet2Radius = 60;
        
        const icePlanet = ctx.createRadialGradient(
            planet2X - 15, planet2Y - 15, 15,
            planet2X, planet2Y, planet2Radius
        );
        icePlanet.addColorStop(0, '#a8d8ff');
        icePlanet.addColorStop(0.5, '#5ba3d8');
        icePlanet.addColorStop(1, '#2d5f8f');
        ctx.fillStyle = icePlanet;
        ctx.shadowBlur = 20;
        ctx.shadowColor = '#5ba3d8';
        ctx.beginPath();
        ctx.arc(planet2X, planet2Y, planet2Radius, 0, Math.PI * 2);
        ctx.fill();
        ctx.shadowBlur = 0;
        
        // Ice planet spots
        ctx.fillStyle = 'rgba(140, 190, 220, 0.3)';
        ctx.beginPath();
        ctx.arc(planet2X + 15, planet2Y - 10, 18, 0, Math.PI * 2);
        ctx.fill();
        ctx.beginPath();
        ctx.arc(planet2X - 20, planet2Y + 15, 15, 0, Math.PI * 2);
        ctx.fill();
        
        // Planet 3 - Red Rocky Planet (Mars-like) bottom left
        const planet3X = 120;
        const planet3Y = canvas.height - 100;
        const planet3Radius = 50;
        
        const rockyPlanet = ctx.createRadialGradient(
            planet3X - 12, planet3Y - 12, 12,
            planet3X, planet3Y, planet3Radius
        );
        rockyPlanet.addColorStop(0, '#e89b7a');
        rockyPlanet.addColorStop(0.5, '#c85a3a');
        rockyPlanet.addColorStop(1, '#8f3a24');
        ctx.fillStyle = rockyPlanet;
        ctx.shadowBlur = 18;
        ctx.shadowColor = '#c85a3a';
        ctx.beginPath();
        ctx.arc(planet3X, planet3Y, planet3Radius, 0, Math.PI * 2);
        ctx.fill();
        ctx.shadowBlur = 0;
        
        // Rocky craters
        ctx.fillStyle = 'rgba(100, 50, 30, 0.4)';
        ctx.beginPath();
        ctx.arc(planet3X + 15, planet3Y - 5, 12, 0, Math.PI * 2);
        ctx.fill();
        ctx.beginPath();
        ctx.arc(planet3X - 10, planet3Y + 15, 10, 0, Math.PI * 2);
        ctx.fill();
        ctx.beginPath();
        ctx.arc(planet3X - 20, planet3Y - 10, 8, 0, Math.PI * 2);
        ctx.fill();
        
        // Planet 4 - Purple/Pink Planet (Exotic) bottom right
        const planet4X = canvas.width - 100;
        const planet4Y = canvas.height - 120;
        const planet4Radius = 55;
        
        const exoticPlanet = ctx.createRadialGradient(
            planet4X - 13, planet4Y - 13, 13,
            planet4X, planet4Y, planet4Radius
        );
        exoticPlanet.addColorStop(0, '#e89bff');
        exoticPlanet.addColorStop(0.5, '#b85fd8');
        exoticPlanet.addColorStop(1, '#7a3a8f');
        ctx.fillStyle = exoticPlanet;
        ctx.shadowBlur = 22;
        ctx.shadowColor = '#b85fd8';
        ctx.beginPath();
        ctx.arc(planet4X, planet4Y, planet4Radius, 0, Math.PI * 2);
        ctx.fill();
        ctx.shadowBlur = 0;
        
        // Exotic swirls
        ctx.strokeStyle = 'rgba(200, 120, 220, 0.3)';
        ctx.lineWidth = 6;
        ctx.beginPath();
        ctx.ellipse(planet4X, planet4Y, planet4Radius * 0.8, planet4Radius * 0.5, 0.3, 0, Math.PI * 2);
        ctx.stroke();
        
        // Planet 5 - Small Green Planet (Earth-like) middle left
        const planet5X = 80;
        const planet5Y = canvas.height / 2;
        const planet5Radius = 35;
        
        const greenPlanet = ctx.createRadialGradient(
            planet5X - 8, planet5Y - 8, 8,
            planet5X, planet5Y, planet5Radius
        );
        greenPlanet.addColorStop(0, '#7dd87d');
        greenPlanet.addColorStop(0.5, '#4a9b4a');
        greenPlanet.addColorStop(1, '#2d5f2d');
        ctx.fillStyle = greenPlanet;
        ctx.shadowBlur = 15;
        ctx.shadowColor = '#4a9b4a';
        ctx.beginPath();
        ctx.arc(planet5X, planet5Y, planet5Radius, 0, Math.PI * 2);
        ctx.fill();
        ctx.shadowBlur = 0;
        
        // Green continents
        ctx.fillStyle = 'rgba(80, 150, 80, 0.5)';
        ctx.beginPath();
        ctx.arc(planet5X - 8, planet5Y - 8, 12, 0, Math.PI * 2);
        ctx.fill();
        ctx.beginPath();
        ctx.arc(planet5X + 10, planet5Y + 8, 10, 0, Math.PI * 2);
        ctx.fill();
        
        // Planet 6 - Ringed Planet (Saturn-like) middle right
        const planet6X = canvas.width - 120;
        const planet6Y = canvas.height / 2 + 50;
        const planet6Radius = 45;
        
        // Draw rings first (behind planet)
        ctx.strokeStyle = 'rgba(210, 180, 140, 0.6)';
        ctx.lineWidth = 8;
        ctx.shadowBlur = 10;
        ctx.shadowColor = 'rgba(210, 180, 140, 0.4)';
        ctx.beginPath();
        ctx.ellipse(planet6X, planet6Y, planet6Radius * 1.8, planet6Radius * 0.3, -0.2, 0, Math.PI);
        ctx.stroke();
        ctx.shadowBlur = 0;
        
        // Planet body
        const ringedPlanet = ctx.createRadialGradient(
            planet6X - 10, planet6Y - 10, 10,
            planet6X, planet6Y, planet6Radius
        );
        ringedPlanet.addColorStop(0, '#f5e6c8');
        ringedPlanet.addColorStop(0.5, '#d4b896');
        ringedPlanet.addColorStop(1, '#a38a6a');
        ctx.fillStyle = ringedPlanet;
        ctx.shadowBlur = 18;
        ctx.shadowColor = '#d4b896';
        ctx.beginPath();
        ctx.arc(planet6X, planet6Y, planet6Radius, 0, Math.PI * 2);
        ctx.fill();
        ctx.shadowBlur = 0;
        
        // Rings in front
        ctx.strokeStyle = 'rgba(180, 155, 120, 0.5)';
        ctx.lineWidth = 8;
        ctx.beginPath();
        ctx.ellipse(planet6X, planet6Y, planet6Radius * 1.8, planet6Radius * 0.3, -0.2, Math.PI, Math.PI * 2);
        ctx.stroke();
        
        ctx.restore();

        // Draw and update stars
        stars.forEach(star => {
            star.y += star.speed * difficulty;
            if (star.y > canvas.height) {
                star.y = 0;
                star.x = Math.random() * canvas.width;
            }
            
            ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
            ctx.beginPath();
            ctx.arc(star.x, star.y, star.size, 0, Math.PI * 2);
            ctx.fill();
        });

        // Smooth player movement
        player.x += (player.targetX - player.x) * player.speed;
        player.y += (player.targetY - player.y) * player.speed;

        // Keep player in bounds
        player.x = Math.max(player.width/2, Math.min(canvas.width - player.width/2, player.x));
        player.y = Math.max(player.height/2, Math.min(canvas.height - player.height/2, player.y));

        // Update and draw particles
        particles = particles.filter(p => {
            const alive = p.update();
            if (alive) p.draw();
            return alive;
        });

        // Create engine particles from ship's thrusters
        if (gameRunning && !playerDestroyed) {
            // Left engine
            engineParticles.push(new EngineParticle(
                player.x - player.width/4,
                player.y + player.height/2 - 5
            ));
            // Right engine
            engineParticles.push(new EngineParticle(
                player.x + player.width/4,
                player.y + player.height/2 - 5
            ));
        }

        // Update and draw engine particles (draw before player so they appear behind)
        engineParticles = engineParticles.filter(p => {
            const alive = p.update();
            if (alive) p.draw();
            return alive;
        });

        // Update and draw bullets
        bullets = bullets.filter(b => {
            const alive = b.update();
            if (alive) {
                b.draw();
                
                // Check bullet-meteor collision
                for (let i = meteors.length - 1; i >= 0; i--) {
                    if (b.checkMeteorHit(meteors[i])) {
                        // Different explosion colors matching each obstacle's actual color
                        let explosionColor = '#ff6600';
                        let killMessage = 'DESTROYED!';
                        
                        if (meteors[i].constructor.name === 'Satellite') {
                            explosionColor = '#bdc3c7'; // Gray/silver (satellite body color)
                            killMessage = 'SATELLITE DOWN!';
                        } else if (meteors[i].constructor.name === 'RocketShip') {
                            explosionColor = '#e74c3c'; // Red (rocket body color)
                            killMessage = 'SHIP DESTROYED!';
                        } else if (meteors[i].constructor.name === 'SpaceSurfer') {
                            explosionColor = '#ff1493'; // Pink (surfboard color)
                            killMessage = 'SURFER HIT!';
                        } else if (meteors[i].constructor.name === 'IceCrystal') {
                            explosionColor = '#add8e6'; // Light blue (ice color)
                        } else if (meteors[i].constructor.name === 'SpaceDebris') {
                            explosionColor = '#C0C0C0'; // Silver (metal color)
                        } else if (meteors[i].constructor.name === 'Asteroid') {
                            explosionColor = '#8B8680'; // Gray (asteroid color)
                        } else if (meteors[i].constructor.name === 'Meteor') {
                            explosionColor = '#ff6600'; // Orange (meteor fire color)
                        }
                        
                        createExplosion(meteors[i].x, meteors[i].y, explosionColor);
                        
                        // Track consecutive kills for combos
                        const now = Date.now();
                        if (now - lastKillTime < 1000) {
                            consecutiveKills++;
                        } else {
                            consecutiveKills = 1;
                        }
                        lastKillTime = now;
                        
                        // Show feedback based on combo
                        if (consecutiveKills >= 5) {
                            feedbackMessages.push(new FeedbackMessage(meteors[i].x, meteors[i].y, '🔥 ON FIRE! 🔥', '#ff6600', 48));
                            score += 100; // Bonus
                        } else if (consecutiveKills >= 3) {
                            feedbackMessages.push(new FeedbackMessage(meteors[i].x, meteors[i].y, '⚡ STREAK! ⚡', '#ffff00', 40));
                            score += 50; // Bonus
                        } else if (consecutiveKills === 2) {
                            feedbackMessages.push(new FeedbackMessage(meteors[i].x, meteors[i].y, 'DOUBLE KILL!', '#00ff00', 36));
                        } else {
                            // Random cool feedback for single kills with special messages
                            const messages = ['NICE!', 'BOOM!', 'GOT IT!', killMessage];
                            if (Math.random() > 0.7) {
                                feedbackMessages.push(new FeedbackMessage(meteors[i].x, meteors[i].y, messages[Math.floor(Math.random() * messages.length)], '#ffffff', 28));
                            }
                        }
                        
                        meteors.splice(i, 1);
                        
                        // Track score
                        if (inMinigame) {
                            minigameScore++; // Count kills in minigame
                        } else {
                            score += 50; // Base points for shooting meteors
                        }
                        document.getElementById('score').textContent = inMinigame ? minigameScore + ' kills' : score;
                        return false; // Remove bullet
                    }
                }
            }
            return alive;
        });

        // Spawn meteors and other obstacles (only when alive)
        if (!playerDestroyed) {
            // Always spawn meteors
            if (Math.random() < 0.02 * difficulty) {
                meteors.push(new Meteor()); // Fire meteors
            }
            
            // Spawn other obstacles
            if (Math.random() < 0.015 * difficulty) {
                const obstacleType = Math.random();
                
                if (obstacleType < 0.4) {
                    meteors.push(new Asteroid()); // 40% gray asteroids
                } else if (obstacleType < 0.7) {
                    meteors.push(new SpaceDebris()); // 30% metal debris
                } else if (obstacleType < 0.9) {
                    meteors.push(new IceCrystal()); // 20% ice crystals
                } else {
                    meteors.push(new Satellite()); // 10% satellites
                }
            }

            // Spawn rocket ships occasionally (horizontal movement)
            if (Math.random() < 0.005 * difficulty) {
                meteors.push(new RocketShip());
            }

            // Spawn space surfers occasionally
            if (Math.random() < 0.004 * difficulty) {
                meteors.push(new SpaceSurfer());
            }

            // Spawn powerups less frequently
            if (Math.random() < 0.006) { // Reduced from 0.015 to 0.006
                powerups.push(new Powerup());
            }

            // Spawn weapon powerups rarely
            if (Math.random() < 0.003) { // Reduced from 0.008 to 0.003
                powerups.push(new WeaponPowerup());
            }

            // Spawn shield powerups very rarely
            if (Math.random() < 0.0015) { // Reduced from 0.004 to 0.0015 (62% less)
                powerups.push(new ShieldPowerup());
            }
        }

        // Update and draw meteors
        meteors = meteors.filter(m => {
            // Don't update meteors when player is destroyed (they freeze in place)
            const alive = !playerDestroyed ? m.update() : true;
            if (alive) {
                m.draw();
                
                // Check collision only if player is alive
                if (!playerDestroyed && m.checkCollision(player.x, player.y, player.width, player.height)) {
                    // Determine explosion color based on obstacle type
                    let explosionColor = '#ff6600';
                    
                    if (m.constructor.name === 'Satellite') {
                        explosionColor = '#bdc3c7'; // Gray/silver
                    } else if (m.constructor.name === 'RocketShip') {
                        explosionColor = '#e74c3c'; // Red
                    } else if (m.constructor.name === 'SpaceSurfer') {
                        explosionColor = '#ff1493'; // Pink
                    } else if (m.constructor.name === 'IceCrystal') {
                        explosionColor = '#add8e6'; // Light blue
                    } else if (m.constructor.name === 'SpaceDebris') {
                        explosionColor = '#C0C0C0'; // Silver
                    } else if (m.constructor.name === 'Asteroid') {
                        explosionColor = '#8B8680'; // Gray
                    } else if (m.constructor.name === 'Meteor') {
                        explosionColor = '#ff6600'; // Orange
                    }
                    
                    createExplosion(m.x, m.y, explosionColor);
                    
                    // Only take damage if shield is not active
                    if (!shieldActive) {
                        hearts -= 1; // Lose 1 heart per hit
                        updateHeartsDisplay();
                        
                        if (hearts <= 0) {
                            explodeShip(player.x, player.y);
                            // Game will end when astronaut falls off screen
                        }
                    } else {
                        // Shield deflected it - cool feedback!
                        feedbackMessages.push(new FeedbackMessage(m.x, m.y, 'DEFLECTED!', '#4da6ff', 32));
                    }
                    return false;
                }
                
                // Check for close dodge (within 60 pixels but not hit)
                if (!playerDestroyed) {
                    const dist = Math.sqrt((m.x - player.x) ** 2 + (m.y - player.y) ** 2);
                    if (dist < 60 && Math.random() > 0.95 && !m.closeDodge) {
                        feedbackMessages.push(new FeedbackMessage(m.x, m.y, 'CLOSE!', '#ffaa00', 28));
                        m.closeDodge = true; // Mark so we don't spam
                    }
                }
            }
            return alive;
        });

        // Update and draw powerups
        powerups = powerups.filter(p => {
            const alive = p.update();
            if (alive) {
                p.draw();
                
                // Check collision only if player is alive
                if (!playerDestroyed && p.checkCollision(player.x, player.y, player.width, player.height)) {
                    if (p.type === 'health') {
                        // Health powerup - restore 1 heart
                        hearts = Math.min(maxHearts, hearts + 1);
                        updateHeartsDisplay();
                        createExplosion(p.x, p.y, '#00ffff');
                        score += 25;
                        feedbackMessages.push(new FeedbackMessage(p.x, p.y, '❤️ HEALTH +1', '#00ffff', 32));
                    } else if (p.type === 'shield') {
                        // Shield powerup - replaces weapon if active
                        const hadShield = shieldActive;
                        const hadWeapon = activeWeapon !== 'normal';
                        
                        // Deactivate any weapon
                        if (hadWeapon) {
                            feedbackMessages.push(new FeedbackMessage(p.x, p.y, `❌ ${p.config[activeWeapon].name} REMOVED!`, '#ff6600', 28));
                            activeWeapon = 'normal';
                            weaponTimeLeft = 0;
                        }
                        
                        shieldActive = true;
                        shieldTimeLeft = shieldDuration;
                        createExplosion(p.x, p.y, '#4da6ff');
                        score += 50;
                        
                        if (hadShield) {
                            // Refreshing existing shield
                            feedbackMessages.push(new FeedbackMessage(p.x, p.y + (hadWeapon ? 40 : 0), '🔄 SHIELD REFRESHED!', '#4da6ff', 38));
                        } else {
                            // New shield
                            feedbackMessages.push(new FeedbackMessage(p.x, p.y + (hadWeapon ? 40 : 0), '🛡️ SHIELD ACTIVE!', '#4da6ff', 42));
                        }
                        showWeaponNotification('INVINCIBILITY SHIELD');
                    } else {
                        // Weapon powerup - replaces shield if active
                        const previousWeapon = activeWeapon;
                        const hadWeapon = previousWeapon !== 'normal';
                        const hadShield = shieldActive;
                        
                        // Deactivate shield
                        if (hadShield) {
                            feedbackMessages.push(new FeedbackMessage(p.x, p.y, '❌ SHIELD REMOVED!', '#ff6600', 28));
                            shieldActive = false;
                            shieldTimeLeft = 0;
                        }
                        
                        // Set new weapon
                        activeWeapon = p.weaponType;
                        weaponTimeLeft = weaponDuration;
                        createExplosion(p.x, p.y, p.config[p.weaponType].color);
                        score += 50; // More points for weapon
                        
                        // Show notification
                        if (hadWeapon) {
                            // Replacing existing weapon
                            feedbackMessages.push(new FeedbackMessage(p.x, p.y + (hadShield ? 40 : 0), `❌ ${p.config[previousWeapon].name} REPLACED!`, '#ff6600', 28));
                            feedbackMessages.push(new FeedbackMessage(p.x, p.y + (hadShield ? 80 : 40), `✅ ${p.config[p.weaponType].name} EQUIPPED!`, p.config[p.weaponType].color, 38));
                        } else {
                            // New weapon
                            feedbackMessages.push(new FeedbackMessage(p.x, p.y + (hadShield ? 40 : 0), `✅ ${p.config[p.weaponType].name} EQUIPPED!`, p.config[p.weaponType].color, 38));
                        }
                        showWeaponNotification(p.config[p.weaponType].name);
                    }
                    document.getElementById('score').textContent = score;
                    return false;
                }
            }
            return alive;
        });

        // Update weapon timer
        updateWeaponDisplay();

        // Update and draw ship debris if destroyed
        shipDebris = shipDebris.filter(d => {
            const alive = d.update();
            if (alive) d.draw();
            return alive;
        });

        // Update and draw ejected astronaut
        if (ejectedAstronaut) {
            const alive = ejectedAstronaut.update();
            if (alive) {
                ejectedAstronaut.draw();
            } else {
                // Astronaut has fallen off screen
                ejectedAstronaut = null;
                // Only end normal game if not in minigame
                if (playerDestroyed && !inMinigame) {
                    endGame();
                }
            }
        }

        // Update and draw feedback messages
        feedbackMessages = feedbackMessages.filter(f => {
            const alive = f.update();
            if (alive) f.draw();
            return alive;
        });

        // Update and draw confetti
        confetti = confetti.filter(c => {
            const alive = c.update();
            if (alive) c.draw();
            return alive;
        });

        // Draw player (only if not destroyed)
        if (!playerDestroyed) {
            drawPlayer();
        }

        requestAnimationFrame(gameLoop);
    }

    function startMinigame(type) {
        inMinigame = true;
        minigameType = type;
        minigameStartTime = Date.now();
        minigameScore = 0;
        
        // Save current game state
        normalGameState = {
            survivalTime: survivalTime,
            score: score,
            hearts: hearts,
            difficulty: difficulty
        };
        
        // Reset for minigame
        meteors = [];
        bullets = [];
        particles = [];
        powerups = [];
        feedbackMessages = [];
        
        // Show minigame notification
        feedbackMessages.push(new FeedbackMessage(canvas.width/2, canvas.height/2, '🎮 MINIGAME START! 🎮', '#ffff00', 64));
        feedbackMessages.push(new FeedbackMessage(canvas.width/2, canvas.height/2 + 60, 'SURVIVE 50 SECONDS!', '#00ff00', 42));
        feedbackMessages.push(new FeedbackMessage(canvas.width/2, canvas.height/2 + 110, 'SHOOT AS MANY AS YOU CAN!', '#ffffff', 36));
    }
    
    function endMinigame(died) {
        const finalScore = minigameScore;
        
        // Clear everything first
        meteors = [];
        bullets = [];
        powerups = [];
        particles = [];
        engineParticles = [];
        feedbackMessages = [];
        shipDebris = [];
        ejectedAstronaut = null;
        
        // Show results
        if (died) {
            feedbackMessages.push(new FeedbackMessage(canvas.width/2, canvas.height/2, '💥 MINIGAME OVER! 💥', '#ff0000', 56));
            feedbackMessages.push(new FeedbackMessage(canvas.width/2, canvas.height/2 + 60, `You destroyed ${finalScore} obstacles!`, '#ffaa00', 38));
        } else {
            feedbackMessages.push(new FeedbackMessage(canvas.width/2, canvas.height/2, '✨ MINIGAME COMPLETE! ✨', '#00ff00', 56));
            feedbackMessages.push(new FeedbackMessage(canvas.width/2, canvas.height/2 + 60, `${finalScore} obstacles destroyed!`, '#ffaa00', 38));
        }
        
        // Restore normal game state
        survivalTime = normalGameState.survivalTime;
        score = normalGameState.score;
        hearts = normalGameState.hearts;
        difficulty = normalGameState.difficulty;
        
        // Reset player state
        playerDestroyed = false;
        player.x = canvas.width / 2;
        player.y = canvas.height - 100;
        player.targetX = player.x;
        player.targetY = player.y;
        updateHeartsDisplay();
        
        // Reset weapon states
        activeWeapon = 'normal';
        weaponTimeLeft = 0;
        shieldActive = false;
        shieldTimeLeft = 0;
        canShoot = true;
        
        // Reset minigame flags
        inMinigame = false;
        minigameType = null;
        minigameScore = 0;
        
        // Update display and recalculate game time
        gameStartTime = Date.now() - (survivalTime * 1000);
        document.getElementById('score').textContent = score;
        document.getElementById('time').textContent = survivalTime + 's';
    }

    function startGame() {
        // Initialize audio context
        initAudio();
        
        gameRunning = true;
        score = 0;
        survivalTime = 0;
        hearts = maxHearts; // Start with max hearts
        difficulty = 1;
        meteors = [];
        powerups = [];
        particles = [];
        confetti = [];
        bullets = [];
        engineParticles = [];
        shipDebris = [];
        feedbackMessages = [];
        ejectedAstronaut = null;
        playerDestroyed = false;
        consecutiveKills = 0;
        lastKillTime = 0;
        canShoot = true;
        activeWeapon = 'normal';
        weaponTimeLeft = 0;
        shieldActive = false;
        shieldTimeLeft = 0;
        
        // Reset minigame flags
        inMinigame = false;
        minigameTriggered = false;
        minigameScore = 0;
        
        player.x = canvas.width / 2;
        player.y = canvas.height - 100;
        player.targetX = player.x;
        player.targetY = player.y;
        
        gameStartTime = Date.now();
        
        document.getElementById('score').textContent = '0';
        document.getElementById('time').textContent = '0s';
        document.getElementById('credits').textContent = credits;
        document.getElementById('startScreen').style.display = 'none';
        document.getElementById('gameOver').style.display = 'none';
        document.getElementById('instructions').style.display = 'block';
        updateHeartsDisplay();

        setTimeout(() => {
            document.getElementById('instructions').style.display = 'none';
        }, 4000);

        gameLoop();
    }

    function endGame() {
        if (!gameRunning) return;
        gameRunning = false;
        
        // Award credits based on survival time (1 credit per second)
        const earnedCredits = survivalTime;
        credits += earnedCredits;
        localStorage.setItem('meteorCredits', credits);
        
        if (survivalTime > highScore) {
            highScore = survivalTime;
            localStorage.setItem('meteorDodgeHighScore', highScore);
        }
        
        document.getElementById('finalStats').innerHTML = 
            `<strong>Final Score: ${score}</strong>`;
        document.getElementById('survivalTime').innerHTML = 
            `Survived: ${survivalTime} seconds<br>Best: ${highScore} seconds`;
        document.getElementById('creditsEarned').innerHTML = 
            `💰 +${earnedCredits} Credits Earned! (1 credit/second)`;
        document.getElementById('gameOver').style.display = 'flex';
        
        updateShopDisplay();
    }

    function winGame() {
        if (!gameRunning) return;
        gameRunning = false;
        
        // CONFETTI EXPLOSION! 🎉
        for (let i = 0; i < 200; i++) {
            confetti.push(new Confetti(canvas.width / 2, canvas.height / 2));
        }
        
        // More confetti bursts from different positions
        setTimeout(() => {
            for (let i = 0; i < 100; i++) {
                confetti.push(new Confetti(canvas.width * 0.25, canvas.height * 0.3));
            }
        }, 200);
        
        setTimeout(() => {
            for (let i = 0; i < 100; i++) {
                confetti.push(new Confetti(canvas.width * 0.75, canvas.height * 0.3));
            }
        }, 400);
        
        // Bonus credits for winning!
        const earnedCredits = survivalTime + 100; // Survival credits + 100 bonus
        credits += earnedCredits;
        localStorage.setItem('meteorCredits', credits);
        
        if (survivalTime > highScore) {
            highScore = survivalTime;
            localStorage.setItem('meteorDodgeHighScore', highScore);
        }
        
        // Show WIN screen
        document.getElementById('finalStats').innerHTML = 
            `<strong style="color: #00ff00; font-size: 72px;">🏆 YOU WIN! 🏆</strong><br><strong>Final Score: ${score}</strong>`;
        document.getElementById('survivalTime').innerHTML = 
            `You survived 100 seconds!<br>Best: ${highScore} seconds`;
        document.getElementById('creditsEarned').innerHTML = 
            `💰 +${earnedCredits} Credits Earned!<br>(100 seconds + 100 BONUS!)`;
        document.getElementById('gameOver').style.display = 'flex';
        
        updateShopDisplay();
    }

    document.getElementById('startBtn').addEventListener('click', startGame);
    document.getElementById('restartBtn').addEventListener('click', startGame);
    document.getElementById('shopBtnStart').addEventListener('click', openShop);
    document.getElementById('upgradeBtn').addEventListener('click', openShop);
    document.getElementById('upgradeShieldBtn').addEventListener('click', upgradeShield);
    document.getElementById('upgradeGunBtn').addEventListener('click', upgradeGun);
    document.getElementById('closeShopBtn').addEventListener('click', closeShop);

    // Initialize shop display
    updateShopDisplay();

    // Background animation when not playing
    function backgroundLoop() {
        if (gameRunning) {
            requestAnimationFrame(backgroundLoop);
            return;
        }

        ctx.fillStyle = '#000510';
        ctx.fillRect(0, 0, canvas.width, canvas.height);

        stars.forEach(star => {
            star.y += star.speed * 0.5;
            if (star.y > canvas.height) {
                star.y = 0;
                star.x = Math.random() * canvas.width;
            }
            
            ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
            ctx.beginPath();
            ctx.arc(star.x, star.y, star.size, 0, Math.PI * 2);
            ctx.fill();
        });

        requestAnimationFrame(backgroundLoop);
    }
    backgroundLoop();
</script>
```

</body>
</html>

Game Source: Meteor Dodge

Creator: SolarScout64

Libraries: none

Complexity: complex (3419 lines, 115.0 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a KIDHUBB header at the top with "remix_of: meteor-dodge-solarscout64" to link back to the original. Then publish at kidhubb.com/publish.