Florr.io deepseek还原版

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Florr.io - 高度还原版</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            image-rendering: pixelated;
            image-rendering: -moz-crisp-edges;
            image-rendering: crisp-edges;
        }
        
        body {
            background: #1a1a2e;
            overflow: hidden;
            font-family: Arial, sans-serif;
            touch-action: none;
        }
        
        #gameContainer {
            position: relative;
            width: 100vw;
            height: 100vh;
            overflow: hidden;
        }
        
        #gameCanvas {
            position: absolute;
            top: 0;
            left: 0;
            background: #87CEEB;
        }
        
        #uiCanvas {
            position: absolute;
            top: 0;
            left: 0;
            pointer-events: none;
            z-index: 100;
        }
        
        /* Florr.io 风格UI */
        .ui-element {
            position: absolute;
            background: rgba(0, 0, 0, 0.7);
            border: 2px solid #4a4a6d;
            border-radius: 5px;
            color: white;
            font-family: Arial, sans-serif;
            font-size: 12px;
        }
        
        #playerInfo {
            top: 10px;
            left: 10px;
            padding: 8px;
            min-width: 150px;
        }
        
        .stat-bar {
            height: 6px;
            background: #333;
            border-radius: 3px;
            margin: 3px 0;
            overflow: hidden;
        }
        
        .health-bar {
            background: linear-gradient(to right, #ff4444, #ff8888);
        }
        
        .xp-bar {
            background: linear-gradient(to right, #44aaff, #88ccff);
        }
        
        #levelDisplay {
            position: absolute;
            top: 10px;
            right: 10px;
            background: rgba(0, 0, 0, 0.7);
            border: 2px solid gold;
            border-radius: 50%;
            width: 50px;
            height: 50px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 20px;
            font-weight: bold;
            color: gold;
        }
        
        #inventory {
            bottom: 10px;
            left: 50%;
            transform: translateX(-50%);
            padding: 5px;
            display: flex;
            gap: 5px;
            background: rgba(0, 0, 0, 0.7);
            border-radius: 10px;
        }
        
        .petal-slot {
            width: 40px;
            height: 40px;
            border: 2px solid #666;
            border-radius: 5px;
            position: relative;
            overflow: hidden;
        }
        
        .petal-slot.active {
            border-color: gold;
            box-shadow: 0 0 10px gold;
        }
        
        .petal-count {
            position: absolute;
            bottom: 1px;
            right: 2px;
            color: white;
            font-size: 10px;
            text-shadow: 1px 1px 1px black;
        }
        
        #miniMap {
            top: 10px;
            right: 70px;
            width: 150px;
            height: 150px;
            background: rgba(0, 0, 0, 0.5);
            border: 2px solid #4a4a6d;
        }
        
        #controls {
            position: absolute;
            bottom: 60px;
            right: 10px;
            display: flex;
            gap: 5px;
        }
        
        .control-btn {
            width: 50px;
            height: 50px;
            background: rgba(0, 0, 0, 0.7);
            border: 2px solid #666;
            border-radius: 10px;
            color: white;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 20px;
            cursor: pointer;
            user-select: none;
        }
        
        .control-btn:active {
            background: rgba(100, 100, 100, 0.7);
        }
        
        #mobileJoystick {
            position: absolute;
            bottom: 100px;
            left: 100px;
            width: 120px;
            height: 120px;
            display: none;
        }
        
        .joystick-base {
            position: absolute;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.5);
            border-radius: 50%;
            border: 2px solid rgba(255, 255, 255, 0.3);
        }
        
        .joystick-thumb {
            position: absolute;
            width: 60px;
            height: 60px;
            background: rgba(255, 255, 255, 0.7);
            border-radius: 50%;
            top: 30px;
            left: 30px;
        }
        
        .upgrade-panel {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: rgba(0, 0, 0, 0.9);
            border: 3px solid gold;
            border-radius: 10px;
            padding: 20px;
            display: none;
            z-index: 1000;
            min-width: 300px;
        }
        
        .upgrade-option {
            background: rgba(50, 50, 80, 0.8);
            border: 2px solid #666;
            border-radius: 5px;
            padding: 10px;
            margin: 5px 0;
            cursor: pointer;
            transition: all 0.2s;
        }
        
        .upgrade-option:hover {
            border-color: gold;
            background: rgba(80, 80, 120, 0.8);
        }
        
        .upgrade-title {
            color: gold;
            font-weight: bold;
            margin-bottom: 5px;
        }
        
        .death-screen {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: rgba(0, 0, 0, 0.9);
            border: 3px solid #ff4444;
            border-radius: 10px;
            padding: 30px;
            text-align: center;
            display: none;
            z-index: 1000;
        }
        
        .death-title {
            color: #ff4444;
            font-size: 32px;
            margin-bottom: 20px;
        }
        
        .stats-grid {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            gap: 10px;
            margin: 20px 0;
        }
        
        .stat-item {
            background: rgba(50, 50, 80, 0.8);
            padding: 10px;
            border-radius: 5px;
        }
        
        .stat-label {
            color: #aaa;
            font-size: 12px;
        }
        
        .stat-value {
            color: white;
            font-size: 18px;
            font-weight: bold;
        }
        
        .btn-restart {
            background: linear-gradient(to bottom, #4CAF50, #2E7D32);
            border: none;
            color: white;
            padding: 12px 24px;
            font-size: 16px;
            border-radius: 5px;
            cursor: pointer;
            margin-top: 20px;
        }
        
        .btn-restart:hover {
            background: linear-gradient(to bottom, #66BB6A, #388E3C);
        }
        
        .chat-box {
            position: absolute;
            bottom: 10px;
            left: 10px;
            width: 300px;
            max-height: 200px;
            overflow-y: auto;
            background: rgba(0, 0, 0, 0.5);
            border-radius: 5px;
            padding: 5px;
            display: none;
        }
        
        .chat-message {
            color: white;
            font-size: 12px;
            margin: 2px 0;
            word-break: break-word;
        }
        
        .damage-popup {
            position: absolute;
            color: #ff4444;
            font-weight: bold;
            font-size: 16px;
            pointer-events: none;
            z-index: 50;
            text-shadow: 1px 1px 2px black;
            animation: damageFloat 1s forwards;
        }
        
        @keyframes damageFloat {
            0% { opacity: 1; transform: translateY(0); }
            100% { opacity: 0; transform: translateY(-30px); }
        }
        
        .loading-screen {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: #1a1a2e;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            z-index: 10000;
        }
        
        .loading-title {
            color: white;
            font-size: 36px;
            margin-bottom: 20px;
        }
        
        .loading-bar {
            width: 300px;
            height: 20px;
            background: #333;
            border-radius: 10px;
            overflow: hidden;
        }
        
        .loading-fill {
            height: 100%;
            background: linear-gradient(to right, #4CAF50, #8BC34A);
            width: 0%;
            transition: width 0.3s;
        }
        
        /* 响应式设计 */
        @media (max-width: 768px) {
            #mobileJoystick {
                display: block;
            }
            
            .control-btn {
                width: 40px;
                height: 40px;
                font-size: 16px;
            }
            
            #inventory {
                bottom: 150px;
            }
            
            .petal-slot {
                width: 35px;
                height: 35px;
            }
            
            #miniMap {
                width: 100px;
                height: 100px;
                right: 10px;
                top: 70px;
            }
            
            #levelDisplay {
                top: 70px;
                right: 120px;
                width: 40px;
                height: 40px;
                font-size: 16px;
            }
        }
    </style>
</head>
<body>
    <div id="gameContainer">
        <canvas id="gameCanvas"></canvas>
        <canvas id="uiCanvas"></canvas>
        
        <!-- 加载界面 -->
        <div class="loading-screen" id="loadingScreen">
            <div class="loading-title">Florr.io</div>
            <div class="loading-bar">
                <div class="loading-fill" id="loadingFill"></div>
            </div>
            <div style="color: #aaa; margin-top: 10px;">加载中...</div>
        </div>
        
        <!-- 游戏UI -->
        <div id="playerInfo" class="ui-element">
            <div style="color: gold; font-weight: bold; margin-bottom: 5px;">玩家</div>
            <div style="display: flex; justify-content: space-between; margin-bottom: 5px;">
                <span>HP: <span id="hpValue">100/100</span></span>
                <span>XP: <span id="xpValue">0/100</span></span>
            </div>
            <div class="stat-bar">
                <div class="health-bar" id="healthBar" style="width: 100%"></div>
            </div>
            <div class="stat-bar">
                <div class="xp-bar" id="xpBar" style="width: 0%"></div>
            </div>
        </div>
        
        <div id="levelDisplay">1</div>
        
        <div id="miniMap" class="ui-element"></div>
        
        <div id="inventory" class="ui-element">
            <!-- 花瓣槽位将通过JS动态生成 -->
        </div>
        
        <div id="controls">
            <div class="control-btn" id="btnAuto">A</div>
            <div class="control-btn" id="btnSplit">S</div>
            <div class="control-btn" id="btnUpgrade">U</div>
        </div>
        
        <div id="mobileJoystick">
            <div class="joystick-base"></div>
            <div class="joystick-thumb"></div>
        </div>
        
        <div class="chat-box" id="chatBox"></div>
        
        <!-- 升级面板 -->
        <div class="upgrade-panel" id="upgradePanel">
            <div style="color: gold; font-size: 20px; text-align: center; margin-bottom: 20px;">选择升级</div>
            <div id="upgradeOptions">
                <!-- 升级选项将通过JS动态生成 -->
            </div>
        </div>
        
        <!-- 死亡界面 -->
        <div class="death-screen" id="deathScreen">
            <div class="death-title">游戏结束</div>
            <div class="stats-grid">
                <div class="stat-item">
                    <div class="stat-label">最终等级</div>
                    <div class="stat-value" id="finalLevel">1</div>
                </div>
                <div class="stat-item">
                    <div class="stat-label">游戏时间</div>
                    <div class="stat-value" id="finalTime">0s</div>
                </div>
                <div class="stat-item">
                    <div class="stat-label">击杀数</div>
                    <div class="stat-value" id="finalKills">0</div>
                </div>
                <div class="stat-item">
                    <div class="stat-label">最高分数</div>
                    <div class="stat-value" id="finalScore">0</div>
                </div>
            </div>
            <button class="btn-restart" onclick="restartGame()">重新开始</button>
        </div>
    </div>

    <script>
        // 游戏核心配置
        const CONFIG = {
            WORLD_SIZE: 5000,
            VIEWPORT_PADDING: 100,
            CELL_SIZE: 20,
            MAX_ENEMIES: 100,
            MAX_PELLETS: 200,
            PETAL_TYPES: 8,
            INITIAL_PETALS: 4
        };

        // 游戏状态
        const game = {
            canvas: null,
            uiCanvas: null,
            ctx: null,
            uiCtx: null,
            player: null,
            entities: [],
            pellets: [],
            enemies: [],
            particles: [],
            camera: { x: 0, y: 0 },
            keys: {},
            mouse: { x: 0, y: 0 },
            touch: { x: 0, y: 0, active: false },
            lastTime: 0,
            deltaTime: 0,
            gameTime: 0,
            isPaused: false,
            isAlive: true,
            upgradePending: false,
            autoShoot: false,
            
            // 花瓣数据
            petals: [
                { id: 0, name: "Basic", color: "#4CAF50", damage: 5, speed: 8, pierce: 1, count: 1, rarity: 0 },
                { id: 1, name: "Rose", color: "#E91E63", damage: 8, speed: 6, pierce: 1, count: 1, rarity: 1 },
                { id: 2, name: "Lily", color: "#FFFFFF", damage: 4, speed: 10, pierce: 2, count: 1, rarity: 1 },
                { id: 3, name: "Sunflower", color: "#FFC107", damage: 3, speed: 5, pierce: 1, count: 2, rarity: 0 },
                { id: 4, name: "Cactus", color: "#8BC34A", damage: 12, speed: 4, pierce: 1, count: 1, rarity: 2 },
                { id: 5, name: "Egg", color: "#FFEB3B", damage: 2, speed: 7, pierce: 1, count: 3, rarity: 0 },
                { id: 6, name: "Triplet", color: "#2196F3", damage: 6, speed: 8, pierce: 1, count: 3, rarity: 2 },
                { id: 7, name: "Square", color: "#9C27B0", damage: 10, speed: 6, pierce: 2, count: 4, rarity: 3 }
            ],
            
            // 敌人数据
            enemyTypes: [
                { name: "Ladybug", color: "#E53935", size: 20, health: 30, speed: 2, damage: 5, xp: 10 },
                { name: "Bee", color: "#FFB300", size: 15, health: 20, speed: 3, damage: 3, xp: 7 },
                { name: "Spider", color: "#5D4037", size: 25, health: 50, speed: 1.5, damage: 8, xp: 15 },
                { name: "Ant", color: "#424242", size: 12, health: 15, speed: 2.5, damage: 2, xp: 5 },
                { name: "Beetle", color: "#37474F", size: 30, health: 100, speed: 1, damage: 12, xp: 30 }
            ],
            
            // 升级选项
            upgrades: [
                { type: "health", name: "最大生命值", desc: "+20 最大生命值", value: 20 },
                { type: "damage", name: "伤害", desc: "+2 伤害", value: 2 },
                { type: "speed", name: "移动速度", desc: "+0.5 移动速度", value: 0.5 },
                { type: "attackSpeed", name: "攻击速度", desc: "+0.1 攻击速度", value: 0.1 },
                { type: "pierce", name: "穿透", desc: "+1 穿透", value: 1 },
                { type: "regen", name: "生命恢复", desc: "+0.5 生命恢复", value: 0.5 },
                { type: "petalCount", name: "额外花瓣", desc: "获得一个随机花瓣", value: 1 }
            ]
        };

        // 玩家类
        class Player {
            constructor() {
                this.x = CONFIG.WORLD_SIZE / 2;
                this.y = CONFIG.WORLD_SIZE / 2;
                this.size = 25;
                this.color = "#2196F3";
                this.maxHealth = 100;
                this.health = 100;
                this.speed = 5;
                this.damage = 5;
                this.attackSpeed = 1;
                this.pierce = 1;
                this.regen = 0.1;
                this.level = 1;
                this.xp = 0;
                this.xpToNext = 100;
                this.kills = 0;
                this.score = 0;
                this.petals = [];
                this.inventory = [];
                this.selectedSlot = 0;
                this.attackCooldown = 0;
                this.lastRegen = 0;
                
                // 初始化花瓣
                this.initializePetals();
            }
            
            initializePetals() {
                for (let i = 0; i < CONFIG.INITIAL_PETALS; i++) {
                    const randomPetal = Math.floor(Math.random() * 4); // 基础花瓣
                    this.addPetal(randomPetal);
                }
                this.updateInventory();
            }
            
            addPetal(petalId) {
                const petal = { ...game.petals[petalId], count: 1 };
                this.petals.push(petal);
                this.updateInventory();
            }
            
            updateInventory() {
                const inventory = document.getElementById('inventory');
                inventory.innerHTML = '';
                
                this.petals.forEach((petal, index) => {
                    const slot = document.createElement('div');
                    slot.className = `petal-slot ${index === this.selectedSlot ? 'active' : ''}`;
                    slot.style.background = petal.color;
                    slot.innerHTML = `<div class="petal-count">${petal.count}</div>`;
                    slot.onclick = () => this.selectSlot(index);
                    inventory.appendChild(slot);
                });
            }
            
            selectSlot(index) {
                this.selectedSlot = index;
                this.updateInventory();
            }
            
            update(deltaTime) {
                if (!game.isAlive) return;
                
                // 移动
                let moveX = 0;
                let moveY = 0;
                
                if (game.keys['w'] || game.keys['ArrowUp']) moveY -= 1;
                if (game.keys['s'] || game.keys['ArrowDown']) moveY += 1;
                if (game.keys['a'] || game.keys['ArrowLeft']) moveX -= 1;
                if (game.keys['d'] || game.keys['ArrowRight']) moveX += 1;
                
                // 触摸控制
                if (game.touch.active) {
                    const joyX = game.touch.x;
                    const joyY = game.touch.y;
                    const dist = Math.sqrt(joyX * joyX + joyY * joyY);
                    
                    if (dist > 10) {
                        moveX = joyX / 50;
                        moveY = joyY / 50;
                    }
                }
                
                // 归一化移动向量
                if (moveX !== 0 || moveY !== 0) {
                    const magnitude = Math.sqrt(moveX * moveX + moveY * moveY);
                    moveX /= magnitude;
                    moveY /= magnitude;
                    
                    this.x += moveX * this.speed;
                    this.y += moveY * this.speed;
                    
                    // 边界检查
                    this.x = Math.max(this.size, Math.min(CONFIG.WORLD_SIZE - this.size, this.x));
                    this.y = Math.max(this.size, Math.min(CONFIG.WORLD_SIZE - this.size, this.y));
                }
                
                // 攻击
                this.attackCooldown -= deltaTime;
                if (this.attackCooldown <= 0 && (game.autoShoot || game.keys[' '])) {
                    this.attack();
                    this.attackCooldown = 60 / (this.attackSpeed * 10);
                }
                
                // 生命恢复
                this.lastRegen += deltaTime;
                if (this.lastRegen >= 60) { // 每秒恢复
                    this.heal(this.regen);
                    this.lastRegen = 0;
                }
                
                // 更新相机
                game.camera.x = this.x - game.canvas.width / 2;
                game.camera.y = this.y - game.canvas.height / 2;
            }
            
            attack() {
                if (this.petals.length === 0) return;
                
                const petal = this.petals[this.selectedSlot];
                const count = petal.count;
                const angleStep = (Math.PI * 2) / count;
                
                for (let i = 0; i < count; i++) {
                    const angle = Math.atan2(game.mouse.y, game.mouse.x) + angleStep * i;
                    
                    const projectile = {
                        x: this.x,
                        y: this.y,
                        vx: Math.cos(angle) * petal.speed,
                        vy: Math.sin(angle) * petal.speed,
                        damage: this.damage + petal.damage,
                        pierce: this.pierce + petal.pierce - 1,
                        size: 8,
                        color: petal.color,
                        lifetime: 120,
                        owner: this
                    };
                    
                    game.entities.push(projectile);
                }
                
                // 攻击特效
                for (let i = 0; i < 5; i++) {
                    const angle = Math.atan2(game.mouse.y, game.mouse.x) + (Math.random() - 0.5) * 0.5;
                    game.particles.push({
                        x: this.x,
                        y: this.y,
                        vx: Math.cos(angle) * 3,
                        vy: Math.sin(angle) * 3,
                        size: 3,
                        color: petal.color,
                        lifetime: 20
                    });
                }
            }
            
            takeDamage(damage) {
                this.health -= damage;
                
                // 伤害数字
                createDamagePopup(this.x, this.y, damage);
                
                // 受伤特效
                for (let i = 0; i < 10; i++) {
                    game.particles.push({
                        x: this.x + (Math.random() - 0.5) * 20,
                        y: this.y + (Math.random() - 0.5) * 20,
                        vx: (Math.random() - 0.5) * 5,
                        vy: (Math.random() - 0.5) * 5,
                        size: 4,
                        color: '#ff4444',
                        lifetime: 30
                    });
                }
                
                if (this.health <= 0) {
                    this.die();
                }
                
                updateUI();
            }
            
            heal(amount) {
                this.health = Math.min(this.maxHealth, this.health + amount);
                updateUI();
            }
            
            addXP(amount) {
                this.xp += amount;
                this.score += amount;
                
                while (this.xp >= this.xpToNext) {
                    this.levelUp();
                }
                
                updateUI();
            }
            
            levelUp() {
                this.xp -= this.xpToNext;
                this.level++;
                this.xpToNext = Math.floor(100 * Math.pow(1.2, this.level - 1));
                game.upgradePending = true;
                showUpgradePanel();
                
                // 升级特效
                for (let i = 0; i < 20; i++) {
                    const angle = (i / 20) * Math.PI * 2;
                    game.particles.push({
                        x: this.x + Math.cos(angle) * 30,
                        y: this.y + Math.sin(angle) * 30,
                        vx: Math.cos(angle) * 2,
                        vy: Math.sin(angle) * 2,
                        size: 6,
                        color: '#FFD700',
                        lifetime: 40
                    });
                }
            }
            
            die() {
                game.isAlive = false;
                
                // 死亡特效
                for (let i = 0; i < 30; i++) {
                    const angle = (i / 30) * Math.PI * 2;
                    game.particles.push({
                        x: this.x + Math.cos(angle) * 20,
                        y: this.y + Math.sin(angle) * 20,
                        vx: Math.cos(angle) * 5,
                        vy: Math.sin(angle) * 5,
                        size: 8,
                        color: this.color,
                        lifetime: 60
                    });
                }
                
                showDeathScreen();
            }
            
            draw(ctx) {
                const screenX = this.x - game.camera.x;
                const screenY = this.y - game.camera.y;
                
                // 绘制玩家
                ctx.save();
                ctx.translate(screenX, screenY);
                
                // 身体
                ctx.fillStyle = this.color;
                ctx.beginPath();
                ctx.arc(0, 0, this.size, 0, Math.PI * 2);
                ctx.fill();
                
                // 边框
                ctx.strokeStyle = '#000';
                ctx.lineWidth = 2;
                ctx.stroke();
                
                // 眼睛
                ctx.fillStyle = '#fff';
                ctx.beginPath();
                ctx.arc(-8, -5, 6, 0, Math.PI * 2);
                ctx.arc(8, -5, 6, 0, Math.PI * 2);
                ctx.fill();
                
                ctx.fillStyle = '#000';
                ctx.beginPath();
                const lookAngle = Math.atan2(game.mouse.y, game.mouse.x);
                ctx.arc(-8 + Math.cos(lookAngle) * 3, -5 + Math.sin(lookAngle) * 3, 3, 0, Math.PI * 2);
                ctx.arc(8 + Math.cos(lookAngle) * 3, -5 + Math.sin(lookAngle) * 3, 3, 0, Math.PI * 2);
                ctx.fill();
                
                // 嘴巴
                ctx.beginPath();
                ctx.arc(0, 8, 10, 0.2, 0.8 * Math.PI);
                ctx.stroke();
                
                ctx.restore();
            }
        }

        // 敌人类
        class Enemy {
            constructor(type, x, y) {
                const enemyType = game.enemyTypes[type];
                Object.assign(this, enemyType);
                
                this.x = x;
                this.y = y;
                this.maxHealth = this.health;
                this.target = game.player;
                this.attackCooldown = 0;
            }
            
            update(deltaTime) {
                if (!game.isAlive) return;
                
                // 追踪玩家
                const dx = this.target.x - this.x;
                const dy = this.target.y - this.y;
                const dist = Math.sqrt(dx * dx + dy * dy);
                
                if (dist > 0) {
                    this.x += (dx / dist) * this.speed;
                    this.y += (dy / dist) * this.speed;
                }
                
                // 攻击玩家
                this.attackCooldown -= deltaTime;
                if (dist < this.size + game.player.size && this.attackCooldown <= 0) {
                    game.player.takeDamage(this.damage);
                    this.attackCooldown = 60;
                }
            }
            
            takeDamage(damage) {
                this.health -= damage;
                
                // 伤害数字
                createDamagePopup(this.x, this.y, damage);
                
                if (this.health <= 0) {
                    this.die();
                    return true;
                }
                return false;
            }
            
            die() {
                // 给玩家经验
                game.player.addXP(this.xp);
                game.player.kills++;
                
                // 掉落花瓣
                if (Math.random() < 0.1) {
                    spawnPellet(this.x, this.y);
                }
                
                // 死亡特效
                for (let i = 0; i < 15; i++) {
                    game.particles.push({
                        x: this.x + (Math.random() - 0.5) * 20,
                        y: this.y + (Math.random() - 0.5) * 20,
                        vx: (Math.random() - 0.5) * 8,
                        vy: (Math.random() - 0.5) * 8,
                        size: 5,
                        color: this.color,
                        lifetime: 40
                    });
                }
            }
            
            draw(ctx) {
                const screenX = this.x - game.camera.x;
                const screenY = this.y - game.camera.y;
                
                // 绘制敌人
                ctx.save();
                ctx.translate(screenX, screenY);
                
                // 身体
                ctx.fillStyle = this.color;
                ctx.beginPath();
                ctx.arc(0, 0, this.size, 0, Math.PI * 2);
                ctx.fill();
                
                // 边框
                ctx.strokeStyle = '#000';
                ctx.lineWidth = 2;
                ctx.stroke();
                
                // 生命条
                if (this.health < this.maxHealth) {
                    const healthPercent = this.health / this.maxHealth;
                    const barWidth = this.size * 2;
                    const barHeight = 4;
                    
                    ctx.fillStyle = '#f00';
                    ctx.fillRect(-this.size, -this.size - 10, barWidth, barHeight);
                    
                    ctx.fillStyle = '#0f0';
                    ctx.fillRect(-this.size, -this.size - 10, barWidth * healthPercent, barHeight);
                }
                
                ctx.restore();
            }
        }

        // 游戏功能
        function spawnEnemy() {
            if (game.enemies.length >= CONFIG.MAX_ENEMIES) return;
            
            const type = Math.floor(Math.random() * game.enemyTypes.length);
            const angle = Math.random() * Math.PI * 2;
            const distance = 1000;
            const x = game.player.x + Math.cos(angle) * distance;
            const y = game.player.y + Math.sin(angle) * distance;
            
            // 确保在边界内
            const validX = Math.max(50, Math.min(CONFIG.WORLD_SIZE - 50, x));
            const validY = Math.max(50, Math.min(CONFIG.WORLD_SIZE - 50, y));
            
            const enemy = new Enemy(type, validX, validY);
            game.enemies.push(enemy);
        }

        function spawnPellet(x, y) {
            if (game.pellets.length >= CONFIG.MAX_PELLETS) return;
            
            const petalId = Math.floor(Math.random() * game.petals.length);
            const petal = game.petals[petalId];
            
            game.pellets.push({
                x: x,
                y: y,
                size: 10,
                color: petal.color,
                petalId: petalId,
                collected: false
            });
        }

        function updateEntities(deltaTime) {
            // 更新玩家
            game.player.update(deltaTime);
            
            // 更新敌人
            for (let i = game.enemies.length - 1; i >= 0; i--) {
                const enemy = game.enemies[i];
                enemy.update(deltaTime);
                
                if (enemy.health <= 0) {
                    game.enemies.splice(i, 1);
                }
            }
            
            // 更新弹幕
            for (let i = game.entities.length - 1; i >= 0; i--) {
                const entity = game.entities[i];
                entity.x += entity.vx;
                entity.y += entity.vy;
                entity.lifetime--;
                
                // 边界检查
                if (entity.x < 0 || entity.x > CONFIG.WORLD_SIZE ||
                    entity.y < 0 || entity.y > CONFIG.WORLD_SIZE ||
                    entity.lifetime <= 0) {
                    game.entities.splice(i, 1);
                    continue;
                }
                
                // 击中敌人
                if (entity.owner === game.player) {
                    for (let j = 0; j < game.enemies.length; j++) {
                        const enemy = game.enemies[j];
                        const dx = entity.x - enemy.x;
                        const dy = entity.y - enemy.y;
                        const dist = Math.sqrt(dx * dx + dy * dy);
                        
                        if (dist < entity.size + enemy.size) {
                            if (enemy.takeDamage(entity.damage)) {
                                // 敌人死亡
                                if (entity.pierce <= 0) {
                                    game.entities.splice(i, 1);
                                    break;
                                } else {
                                    entity.pierce--;
                                }
                            } else {
                                game.entities.splice(i, 1);
                                break;
                            }
                        }
                    }
                }
            }
            
            // 更新掉落物
            for (let i = game.pellets.length - 1; i >= 0; i--) {
                const pellet = game.pellets[i];
                const dx = game.player.x - pellet.x;
                const dy = game.player.y - pellet.y;
                const dist = Math.sqrt(dx * dx + dy * dy);
                
                if (dist < game.player.size + pellet.size) {
                    // 收集花瓣
                    game.player.addPetal(pellet.petalId);
                    game.pellets.splice(i, 1);
                    
                    // 收集特效
                    for (let j = 0; j < 10; j++) {
                        game.particles.push({
                            x: pellet.x,
                            y: pellet.y,
                            vx: (Math.random() - 0.5) * 5,
                            vy: (Math.random() - 0.5) * 5,
                            size: 3,
                            color: pellet.color,
                            lifetime: 30
                        });
                    }
                }
            }
            
            // 更新粒子
            for (let i = game.particles.length - 1; i >= 0; i--) {
                const particle = game.particles[i];
                particle.x += particle.vx;
                particle.y += particle.vy;
                particle.vx *= 0.95;
                particle.vy *= 0.95;
                particle.lifetime--;
                
                if (particle.lifetime <= 0) {
                    game.particles.splice(i, 1);
                }
            }
        }

        function drawWorld() {
            const ctx = game.ctx;
            const canvas = game.canvas;
            
            // 清空画布
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            
            // 绘制背景网格
            drawGrid();
            
            // 绘制所有实体
            game.pellets.forEach(pellet => {
                const screenX = pellet.x - game.camera.x;
                const screenY = pellet.y - game.camera.y;
                
                ctx.fillStyle = pellet.color;
                ctx.beginPath();
                ctx.arc(screenX, screenY, pellet.size, 0, Math.PI * 2);
                ctx.fill();
                
                // 发光效果
                ctx.shadowColor = pellet.color;
                ctx.shadowBlur = 10;
                ctx.fill();
                ctx.shadowBlur = 0;
            });
            
            game.enemies.forEach(enemy => enemy.draw(ctx));
            game.entities.forEach(entity => {
                const screenX = entity.x - game.camera.x;
                const screenY = entity.y - game.camera.y;
                
                ctx.fillStyle = entity.color;
                ctx.beginPath();
                ctx.arc(screenX, screenY, entity.size, 0, Math.PI * 2);
                ctx.fill();
                
                // 拖尾
                ctx.strokeStyle = entity.color;
                ctx.lineWidth = 2;
                ctx.beginPath();
                ctx.moveTo(screenX, screenY);
                ctx.lineTo(screenX - entity.vx, screenY - entity.vy);
                ctx.stroke();
            });
            
            if (game.isAlive) {
                game.player.draw(ctx);
            }
            
            game.particles.forEach(particle => {
                const screenX = particle.x - game.camera.x;
                const screenY = particle.y - game.camera.y;
                
                ctx.fillStyle = particle.color;
                ctx.globalAlpha = particle.lifetime / 60;
                ctx.beginPath();
                ctx.arc(screenX, screenY, particle.size, 0, Math.PI * 2);
                ctx.fill();
                ctx.globalAlpha = 1;
            });
        }

        function drawGrid() {
            const ctx = game.ctx;
            const canvas = game.canvas;
            const gridSize = 100;
            
            const startX = Math.floor(game.camera.x / gridSize) * gridSize;
            const startY = Math.floor(game.camera.y / gridSize) * gridSize;
            
            ctx.strokeStyle = 'rgba(255, 255, 255, 0.1)';
            ctx.lineWidth = 1;
            
            for (let x = startX; x < game.camera.x + canvas.width; x += gridSize) {
                const screenX = x - game.camera.x;
                ctx.beginPath();
                ctx.moveTo(screenX, 0);
                ctx.lineTo(screenX, canvas.height);
                ctx.stroke();
            }
            
            for (let y = startY; y < game.camera.y + canvas.height; y += gridSize) {
                const screenY = y - game.camera.y;
                ctx.beginPath();
                ctx.moveTo(0, screenY);
                ctx.lineTo(canvas.width, screenY);
                ctx.stroke();
            }
        }

        function drawUI() {
            const ctx = game.uiCtx;
            const canvas = game.uiCanvas;
            
            // 清空UI画布
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            
            // 绘制小地图
            drawMiniMap();
            
            // 绘制准星
            if (game.isAlive) {
                const centerX = canvas.width / 2;
                const centerY = canvas.height / 2;
                
                ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)';
                ctx.lineWidth = 1;
                
                // 十字准星
                ctx.beginPath();
                ctx.moveTo(centerX - 10, centerY);
                ctx.lineTo(centerX + 10, centerY);
                ctx.moveTo(centerX, centerY - 10);
                ctx.lineTo(centerX, centerY + 10);
                ctx.stroke();
                
                // 外圈
                ctx.beginPath();
                ctx.arc(centerX, centerY, 20, 0, Math.PI * 2);
                ctx.stroke();
            }
        }

        function drawMiniMap() {
            const ctx = game.uiCtx;
            const map = document.getElementById('miniMap');
            const rect = map.getBoundingClientRect();
            
            const scale = 0.02;
            const centerX = rect.width / 2;
            const centerY = rect.height / 2;
            
            // 清空小地图
            ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
            
            // 绘制地图边界
            ctx.strokeStyle = '#4a4a6d';
            ctx.lineWidth = 2;
            ctx.strokeRect(rect.left, rect.top, rect.width, rect.height);
            
            // 绘制玩家位置
            ctx.fillStyle = game.player.color;
            ctx.beginPath();
            ctx.arc(
                rect.left + centerX,
                rect.top + centerY,
                4, 0, Math.PI * 2
            );
            ctx.fill();
            
            // 绘制敌人位置
            ctx.fillStyle = '#ff4444';
            game.enemies.forEach(enemy => {
                const dx = (enemy.x - game.player.x) * scale;
                const dy = (enemy.y - game.player.y) * scale;
                
                if (Math.abs(dx) < centerX && Math.abs(dy) < centerY) {
                    ctx.beginPath();
                    ctx.arc(
                        rect.left + centerX + dx,
                        rect.top + centerY + dy,
                        2, 0, Math.PI * 2
                    );
                    ctx.fill();
                }
            });
            
            // 绘制花瓣位置
            ctx.fillStyle = '#ffff00';
            game.pellets.forEach(pellet => {
                const dx = (pellet.x - game.player.x) * scale;
                const dy = (pellet.y - game.player.y) * scale;
                
                if (Math.abs(dx) < centerX && Math.abs(dy) < centerY) {
                    ctx.beginPath();
                    ctx.arc(
                        rect.left + centerX + dx,
                        rect.top + centerY + dy,
                        1, 0, Math.PI * 2
                    );
                    ctx.fill();
                }
            });
        }

        function updateUI() {
            const player = game.player;
            
            // 更新生命值
            document.getElementById('hpValue').textContent = 
                `${Math.floor(player.health)}/${Math.floor(player.maxHealth)}`;
            document.getElementById('healthBar').style.width = 
                `${(player.health / player.maxHealth) * 100}%`;
            
            // 更新经验值
            document.getElementById('xpValue').textContent = 
                `${Math.floor(player.xp)}/${Math.floor(player.xpToNext)}`;
            document.getElementById('xpBar').style.width = 
                `${(player.xp / player.xpToNext) * 100}%`;
            
            // 更新等级
            document.getElementById('levelDisplay').textContent = player.level;
            
            // 更新游戏时间
            document.getElementById('finalTime').textContent = 
                `${Math.floor(game.gameTime / 60)}s`;
        }

        function createDamagePopup(x, y, damage) {
            const popup = document.createElement('div');
            popup.className = 'damage-popup';
            popup.textContent = Math.floor(damage);
            popup.style.left = (x - game.camera.x) + 'px';
            popup.style.top = (y - game.camera.y) + 'px';
            
            document.getElementById('gameContainer').appendChild(popup);
            
            setTimeout(() => {
                popup.remove();
            }, 1000);
        }

        function showUpgradePanel() {
            const panel = document.getElementById('upgradePanel');
            const options = document.getElementById('upgradeOptions');
            options.innerHTML = '';
            
            // 选择3个随机升级
            const shuffled = [...game.upgrades].sort(() => 0.5 - Math.random());
            const selected = shuffled.slice(0, 3);
            
            selected.forEach(upgrade => {
                const option = document.createElement('div');
                option.className = 'upgrade-option';
                option.innerHTML = `
                    <div class="upgrade-title">${upgrade.name}</div>
                    <div style="color: #aaa; font-size: 12px;">${upgrade.desc}</div>
                `;
                option.onclick = () => applyUpgrade(upgrade);
                options.appendChild(option);
            });
            
            panel.style.display = 'block';
        }

        function applyUpgrade(upgrade) {
            const player = game.player;
            
            switch(upgrade.type) {
                case 'health':
                    player.maxHealth += upgrade.value;
                    player.health += upgrade.value;
                    break;
                case 'damage':
                    player.damage += upgrade.value;
                    break;
                case 'speed':
                    player.speed += upgrade.value;
                    break;
                case 'attackSpeed':
                    player.attackSpeed += upgrade.value;
                    break;
                case 'pierce':
                    player.pierce += upgrade.value;
                    break;
                case 'regen':
                    player.regen += upgrade.value;
                    break;
                case 'petalCount':
                    const randomPetal = Math.floor(Math.random() * game.petals.length);
                    player.addPetal(randomPetal);
                    break;
            }
            
            game.upgradePending = false;
            document.getElementById('upgradePanel').style.display = 'none';
        }

        function showDeathScreen() {
            const player = game.player;
            
            document.getElementById('finalLevel').textContent = player.level;
            document.getElementById('finalTime').textContent = `${Math.floor(game.gameTime / 60)}s`;
            document.getElementById('finalKills').textContent = player.kills;
            document.getElementById('finalScore').textContent = player.score;
            
            document.getElementById('deathScreen').style.display = 'block';
        }

        function restartGame() {
            // 重置游戏状态
            game.player = new Player();
            game.entities = [];
            game.pellets = [];
            game.enemies = [];
            game.particles = [];
            game.gameTime = 0;
            game.isAlive = true;
            game.upgradePending = false;
            
            // 隐藏死亡界面
            document.getElementById('deathScreen').style.display = 'none';
            
            // 生成初始敌人和掉落物
            for (let i = 0; i < 10; i++) spawnEnemy();
            for (let i = 0; i < 20; i++) {
                const x = Math.random() * CONFIG.WORLD_SIZE;
                const y = Math.random() * CONFIG.WORLD_SIZE;
                spawnPellet(x, y);
            }
            
            updateUI();
        }

        // 游戏主循环
        function gameLoop(currentTime) {
            if (!game.lastTime) game.lastTime = currentTime;
            game.deltaTime = (currentTime - game.lastTime) / 16.67; // 标准化到60fps
            game.lastTime = currentTime;
            
            if (game.isAlive) {
                game.gameTime++;
                
                // 生成新敌人
                if (Math.random() < 0.01 && game.enemies.length < CONFIG.MAX_ENEMIES) {
                    spawnEnemy();
                }
                
                // 生成新掉落物
                if (Math.random() < 0.005 && game.pellets.length < CONFIG.MAX_PELLETS) {
                    const x = Math.random() * CONFIG.WORLD_SIZE;
                    const y = Math.random() * CONFIG.WORLD_SIZE;
                    spawnPellet(x, y);
                }
                
                // 更新游戏状态
                updateEntities(game.deltaTime);
                
                // 绘制游戏
                drawWorld();
                drawUI();
            }
            
            requestAnimationFrame(gameLoop);
        }

        // 事件监听
        function initEventListeners() {
            // 键盘控制
            document.addEventListener('keydown', (e) => {
                const key = e.key.toLowerCase();
                game.keys[key] = true;
                
                if (key === ' ') e.preventDefault(); // 防止空格键滚动
                
                // 数字键切换花瓣槽
                if (key >= '1' && key <= '8') {
                    const index = parseInt(key) - 1;
                    if (index < game.player.petals.length) {
                        game.player.selectSlot(index);
                    }
                }
                
                // 自动射击切换
                if (key === 'a') {
                    game.autoShoot = !game.autoShoot;
                }
                
                // 升级面板
                if (key === 'u' && game.upgradePending) {
                    showUpgradePanel();
                }
            });
            
            document.addEventListener('keyup', (e) => {
                game.keys[e.key.toLowerCase()] = false;
            });
            
            // 鼠标控制
            game.canvas.addEventListener('mousemove', (e) => {
                const rect = game.canvas.getBoundingClientRect();
                game.mouse.x = e.clientX - rect.left - game.canvas.width / 2;
                game.mouse.y = e.clientY - rect.top - game.canvas.height / 2;
            });
            
            // 触摸控制
            let touchStartX = 0;
            let touchStartY = 0;
            
            game.canvas.addEventListener('touchstart', (e) => {
                e.preventDefault();
                const touch = e.touches[0];
                const rect = game.canvas.getBoundingClientRect();
                
                touchStartX = touch.clientX;
                touchStartY = touch.clientY;
                
                // 检查是否点击了控制按钮
                const x = touch.clientX - rect.left;
                const y = touch.clientY - rect.top;
                
                // 启动摇杆
                if (x < 200 && y > game.canvas.height - 200) {
                    game.touch.active = true;
                    game.touch.x = 0;
                    game.touch.y = 0;
                } else {
                    // 设置鼠标位置
                    game.mouse.x = x - game.canvas.width / 2;
                    game.mouse.y = y - game.canvas.height / 2;
                }
            });
            
            game.canvas.addEventListener('touchmove', (e) => {
                e.preventDefault();
                if (e.touches.length === 1) {
                    const touch = e.touches[0];
                    const rect = game.canvas.getBoundingClientRect();
                    
                    if (game.touch.active) {
                        // 更新摇杆位置
                        const joyX = touch.clientX - touchStartX;
                        const joyY = touch.clientY - touchStartY;
                        const dist = Math.sqrt(joyX * joyX + joyY * joyY);
                        
                        if (dist > 50) {
                            game.touch.x = (joyX / dist) * 50;
                            game.touch.y = (joyY / dist) * 50;
                        } else {
                            game.touch.x = joyX;
                            game.touch.y = joyY;
                        }
                        
                        // 更新摇杆视觉位置
                        const joystick = document.querySelector('.joystick-thumb');
                        if (joystick) {
                            joystick.style.transform = `translate(${game.touch.x}px, ${game.touch.y}px)`;
                        }
                    } else {
                        // 更新鼠标位置
                        const x = touch.clientX - rect.left;
                        const y = touch.clientY - rect.top;
                        game.mouse.x = x - game.canvas.width / 2;
                        game.mouse.y = y - game.canvas.height / 2;
                    }
                }
            });
            
            game.canvas.addEventListener('touchend', (e) => {
                e.preventDefault();
                game.touch.active = false;
                game.touch.x = 0;
                game.touch.y = 0;
                
                // 重置摇杆位置
                const joystick = document.querySelector('.joystick-thumb');
                if (joystick) {
                    joystick.style.transform = 'translate(0px, 0px)';
                }
            });
            
            // 控制按钮
            document.getElementById('btnAuto').addEventListener('click', () => {
                game.autoShoot = !game.autoShoot;
                document.getElementById('btnAuto').style.background = 
                    game.autoShoot ? 'rgba(76, 175, 80, 0.7)' : 'rgba(0, 0, 0, 0.7)';
            });
            
            document.getElementById('btnUpgrade').addEventListener('click', () => {
                if (game.upgradePending) {
                    showUpgradePanel();
                }
            });
            
            // 窗口大小调整
            window.addEventListener('resize', resizeCanvases);
            
            // 防止右键菜单
            game.canvas.addEventListener('contextmenu', (e) => e.preventDefault());
        }

        function resizeCanvases() {
            const container = document.getElementById('gameContainer');
            
            game.canvas.width = container.clientWidth;
            game.canvas.height = container.clientHeight;
            
            game.uiCanvas.width = container.clientWidth;
            game.uiCanvas.height = container.clientHeight;
        }

        // 加载资源
        function loadResources() {
            const loadingFill = document.getElementById('loadingFill');
            let progress = 0;
            
            const interval = setInterval(() => {
                progress += Math.random() * 20;
                if (progress >= 100) {
                    progress = 100;
                    clearInterval(interval);
                    
                    // 加载完成
                    setTimeout(() => {
                        document.getElementById('loadingScreen').style.display = 'none';
                        startGame();
                    }, 500);
                }
                loadingFill.style.width = `${progress}%`;
            }, 100);
        }

        function startGame() {
            // 初始化画布
            game.canvas = document.getElementById('gameCanvas');
            game.uiCanvas = document.getElementById('uiCanvas');
            game.ctx = game.canvas.getContext('2d');
            game.uiCtx = game.uiCanvas.getContext('2d');
            
            // 设置画布大小
            resizeCanvases();
            
            // 初始化玩家
            game.player = new Player();
            
            // 初始化事件监听
            initEventListeners();
            
            // 生成初始内容
            for (let i = 0; i < 10; i++) spawnEnemy();
            for (let i = 0; i < 20; i++) {
                const x = Math.random() * CONFIG.WORLD_SIZE;
                const y = Math.random() * CONFIG.WORLD_SIZE;
                spawnPellet(x, y);
            }
            
            // 更新UI
            updateUI();
            
            // 开始游戏循环
            requestAnimationFrame(gameLoop);
        }

        // 启动游戏
        window.onload = loadResources;
    </script>
</body>
</html>
posted @ 2026-02-24 20:12  bz02_2023f2  阅读(4)  评论(0)    收藏  举报  来源