消灭乳糖小游戏by FHS-China @iGEM2026

9次阅读
没有评论

共计 14805 个字符,预计需要花费 38 分钟才能阅读完成。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <title>乳糖酶大冒险 · 消化系统奇遇记</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            user-select: none;
        }

        body {
            background: linear-gradient(145deg, #d4eefe 0%, #b8d9f5 100%);
            min-height: 100vh;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            padding: 20px;
            font-family: 'Segoe UI', 'system-ui', 'Poppins', sans-serif;
        }

        /* 游戏主容器 */
        .game-container {
            background: #2b4f6e;
            padding: 12px;
            border-radius: 28px;
            box-shadow: 0 20px 35px rgba(0, 0, 0, 0.3), inset 0 1px 2px rgba(255, 255, 255, 0.2);
        }

        canvas {
            display: block;
            margin: 0 auto;
            border-radius: 16px;
            box-shadow: 0 6px 12px rgba(0, 0, 0, 0.4);
            cursor: pointer;
        }

        .info-panel {
            background: #fff7e8;
            border-radius: 48px;
            padding: 8px 20px;
            margin-bottom: 14px;
            width: 800px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            font-weight: bold;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
            border: 1px solid #ffdd99;
            backdrop-filter: blur(2px);
        }

        .hp-area {
            display: flex;
            align-items: center;
            gap: 12px;
            background: #2d2f36;
            padding: 5px 15px;
            border-radius: 40px;
            color: white;
            text-shadow: 0 1px 0 black;
        }

        .bar-box {
            width: 120px;
            height: 18px;
            background-color: #4a2a2a;
            border-radius: 20px;
            overflow: hidden;
            border: 1px solid #ffb347;
        }

        .hp-bar {
            width: 100%;
            height: 100%;
            background: #e63946;
            transition: width 0.1s ease;
            border-radius: 20px;
        }

        .score-board {
            background: #1e2f3c;
            padding: 5px 20px;
            border-radius: 32px;
            color: #f9d56e;
            font-family: monospace;
            font-size: 1.2rem;
            letter-spacing: 1px;
        }

        .state-badge {
            background: #3a5e3f;
            padding: 5px 18px;
            border-radius: 28px;
            color: #e9f5db;
            font-size: 0.9rem;
            box-shadow: inset 0 0 4px #7abf7e, 0 2px 4px rgba(0,0,0,0.2);
        }

        .tip {
            margin-top: 16px;
            background: #fef9e6;
            padding: 8px 20px;
            border-radius: 60px;
            font-size: 14px;
            color: #2c4b32;
            font-weight: 500;
            width: 800px;
            text-align: center;
            box-shadow: 0 2px 6px rgba(0,0,0,0.1);
            border: 1px solid #ffcf9a;
        }

        .tip kbd {
            background: #333;
            color: white;
            border-radius: 6px;
            padding: 2px 8px;
            font-family: monospace;
            margin: 0 4px;
            font-weight: bold;
        }

        @keyframes pulse {
            0% { opacity: 0.7; }
            100% { opacity: 1; }
        }
    </style>
</head>
<body>
<div class="info-panel">
    <div class="hp-area">
        💊 酶活性 · 血量
        <div class="bar-box">
            <div id="hp-bar" class="hp-bar" style="width: 100%"></div>
        </div>
        <span id="hp-text" style="min-width: 45px;">3/3</span>
    </div>
    <div class="score-board">
        🧬 第 <span id="level">1</span> 关  |  乳糖收集:<span id="score">0</span> / <span id="targetNum">22</span>
    </div>
    <div class="state-badge" id="state">
        🟢 乳糖酶活性正常
    </div>
</div>

<div class="game-container">
    <canvas id="gameCanvas" width="800" height="420" style="border: 3px solid #ffcf8a; background: #9fc9e0;"></canvas>
</div>

<div class="tip">
    🎮 <kbd></kbd> <kbd></kbd> 移动   |   <kbd>空格</kbd> 跳跃 <br>
    🧪 收集黄色 <span style="color:#e5b83c;"></span> 乳糖达标自动过关   |   🍇 绿色 <span style="color:#45b634;"></span> 葡萄糖回血(5 秒刷新)<br>
    🦠 避开黑色病菌  |  🔵 镁离子获得无敌 + 净化  |  ⚠️ 红 / 紫 / 灰 / 绿地面会失活并持续掉血
</div>

<script>
    (function(){
        // ---------- CANVAS ----------
        const canvas = document.getElementById('gameCanvas');
        const ctx = canvas.getContext('2d');

        // ---------- 全局状态 ----------
        let nowLevel = 1;
        let score = 0, target = 22;
        let hp = 3, maxHp = 3;
        let isInactive = false, inactiveTimer = 0;
        let isLowTemp = false, lowTempTimer = 0;
        let inDanger = false;           // 是否站在危险地形上
        let dangerDamageCooldown = 0;   // 危险地形伤害间隔(帧)
        let invincible = 0;              // 无敌帧数
        let healTimer = 0;
        const GLU_REFRESH_TIME = 300;    // 葡萄糖刷新帧数(5 秒 60fps ≈300)

        // 玩家属性
        const player = {
            x: 40, y: 320, w: 30, h: 36,
            speed: 3.2,
            jumpSp: -11.8,
            grav: 0.52,
            vy: 0,
            onGround: true
        };

        // ---------- 关卡数据(完整修复断层 + 衔接跳板)----------
        const levelData = {
            1: {
                target: 22,
                map: [
                    {x:0,y:380,w:110,h:40,t:0},{x:110,y:380,w:130,h:40,t:1},{x:240,y:380,w:95,h:40,t:0},
                    {x:335,y:380,w:105,h:40,t:2},{x:440,y:380,w:85,h:40,t:0},{x:525,y:380,w:120,h:40,t:3},
                    {x:645,y:380,w:75,h:40,t:0},{x:720,y:380,w:80,h:40,t:4},
                    {x:70,y:305,w:65,h:22,t:0},{x:180,y:275,w:72,h:22,t:5},{x:295,y:310,w:68,h:22,t:0},
                    {x:405,y:265,w:75,h:22,t:5},{x:530,y:300,w:70,h:22,t:0},{x:640,y:255,w:80,h:22,t:0},
                    {x:150,y:210,w:75,h:22,t:0},{x:270,y:175,w:82,h:22,t:4},{x:395,y:205,w:78,h:22,t:0},
                    {x:520,y:160,w:85,h:22,t:1},{x:655,y:195,w:72,h:22,t:0},{x:320,y:110,w:90,h:22,t:0}
                ],
                lactose: [
                    {x:55,y:342,w:18,h:18},{x:270,y:342,w:18,h:18},{x:470,y:342,w:18,h:18},{x:675,y:342,w:18,h:18},
                    {x:92,y:267,w:18,h:18},{x:205,y:237,w:18,h:18},{x:318,y:272,w:18,h:18},
                    {x:430,y:227,w:18,h:18},{x:552,y:262,w:18,h:18},{x:668,y:217,w:18,h:18},
                    {x:175,y:172,w:18,h:18},{x:318,y:132,w:18,h:18},{x:422,y:167,w:18,h:18},
                    {x:555,y:122,w:18,h:18},{x:678,y:157,w:18,h:18},{x:355,y:67,w:18,h:18},
                    {x:15,y:342,w:18,h:18},{x:395,y:342,w:18,h:18},{x:575,y:342,w:18,h:18},
                    {x:122,y:267,w:18,h:18},{x:460,y:227,w:18,h:18},{x:235,y:172,w:18,h:18}
                ],
                glucose: [
                    {x:100,y:265,w:16,h:16,exist:true,cd:0,originX:100,originY:265},
                    {x:440,y:225,w:16,h:16,exist:true,cd:0,originX:440,originY:225},
                    {x:665,y:155,w:16,h:16,exist:true,cd:0,originX:665,originY:155}
                ],
                germs: [
                    {x:535,y:274,w:26,h:26,minX:530,maxX:595,speed:0.55,dir:1},
                    {x:660,y:169,w:26,h:26,minX:655,maxX:722,speed:0.55,dir:-1}
                ],
                mg: {x:358,y:70,w:20,h:20,exist:true},
                playerStart: {x:40,y:320}
            },
            2: {
                target: 24,
                map: [
                    {x:0,y:380,w:90,h:40,t:1},{x:90,y:380,w:120,h:40,t:0},{x:210,y:380,w:100,h:40,t:3},
                    {x:310,y:380,w:110,h:40,t:0},{x:420,y:380,w:95,h:40,t:4},{x:515,y:380,w:105,h:40,t:0},
                    {x:620,y:380,w:90,h:40,t:2},{x:710,y:380,w:90,h:40,t:0},
                    {x:50,y:295,w:70,h:22,t:5},{x:160,y:260,w:80,h:22,t:0},{x:275,y:300,w:75,h:22,t:5},
                    {x:390,y:250,w:82,h:22,t:0},{x:510,y:290,w:76,h:22,t:5},{x:630,y:240,w:85,h:22,t:0},
                    {x:120,y:200,w:80,h:22,t:0},
                    {x:210,y:182,w:45,h:22,t:0},{x:235,y:165,w:78,h:22,t:1},
                    {x:322,y:182,w:38,h:22,t:0},{x:355,y:195,w:83,h:22,t:0},
                    {x:475,y:150,w:80,h:22,t:0},{x:560,y:168,w:35,h:22,t:0},
                    {x:595,y:180,w:75,h:22,t:4},{x:290,y:100,w:95,h:22,t:0}
                ],
                lactose: [
                    {x:115,y:342,w:18,h:18},{x:340,y:342,w:18,h:18},{x:540,y:342,w:18,h:18},{x:730,y:342,w:18,h:18},
                    {x:72,y:257,w:18,h:18},{x:185,y:222,w:18,h:18},{x:300,y:257,w:18,h:18},
                    {x:418,y:212,w:18,h:18},{x:538,y:252,w:18,h:18},{x:658,y:202,w:18,h:18},
                    {x:145,y:157,w:18,h:18},{x:262,y:122,w:18,h:18},{x:382,y:152,w:18,h:18},
                    {x:502,y:107,w:18,h:18},{x:622,y:137,w:18,h:18},{x:322,y:57,w:18,h:18},
                    {x:20,y:342,w:18,h:18},{x:445,y:342,w:18,h:18},{x:645,y:342,w:18,h:18},
                    {x:98,y:257,w:18,h:18},{x:443,y:212,w:18,h:18},{x:258,y:157,w:18,h:18},
                    {x:525,y:107,w:18,h:18},{x:682,y:202,w:18,h:18}
                ],
                glucose: [
                    {x:182,y:220,w:16,h:16,exist:true,cd:0,originX:182,originY:220},
                    {x:535,y:250,w:16,h:16,exist:true,cd:0,originX:535,originY:250},
                    {x:500,y:105,w:16,h:16,exist:true,cd:0,originX:500,originY:105}
                ],
                germs: [
                    {x:165,y:234,w:26,h:26,minX:160,maxX:238,speed:0.55,dir:1},
                    {x:635,y:214,w:26,h:26,minX:630,maxX:713,speed:0.55,dir:-1}
                ],
                mg: {x:325,y:58,w:20,h:20,exist:true},
                playerStart: {x:30,y:320}
            }
        };

        // 当前关卡动态数据
        let currentMap = [];
        let currentLactose = [];
        let currentGlucose = [];
        let currentGerms = [];
        let currentMg = {};

        // ---------- 辅助函数 ----------
        function updateHpUI() {
            let percent = (hp / maxHp) * 100;
            document.getElementById('hp-bar').style.width = percent + '%';
            document.getElementById('hp-text').innerText = `${hp}/${maxHp}`;
        }

        // AABB 碰撞检测
        function rectCollide(r1, r2) {
            return !(r2.x > r1.x + r1.w ||
                r2.x + r2.w < r1.x ||
                r2.y > r1.y + r1.h ||
                r2.y + r2.h < r1.y);
        }

        // 受到伤害
        function loseHp() {
            if (invincible > 0) return;
            hp--;
            invincible = 55;   // 大约 0.9 秒无敌
            updateHpUI();
            if (hp <= 0) {
                alert('💔 乳糖酶失活!病菌与恶劣环境破坏了酶结构... 重新挑战本关');
                loadLevel(nowLevel);
            }
        }

        // 葡萄糖回血 + 刷新计时
        function addHpByGlc(item) {
            if (hp < maxHp) {
                hp++;
                updateHpUI();
            }
            item.exist = false;
            item.cd = GLU_REFRESH_TIME;
        }

        // 加载关卡
        function loadLevel(lv) {
            const data = levelData[lv];
            if (!data) return;
            nowLevel = lv;
            target = data.target;
            score = 0;
            hp = maxHp;
            invincible = 0;
            isInactive = false; inactiveTimer = 0;
            isLowTemp = false; lowTempTimer = 0;
            inDanger = false;
            dangerDamageCooldown = 0;
            healTimer = 0;

            // 深拷贝避免引用混乱
            currentMap = JSON.parse(JSON.stringify(data.map));
            currentLactose = JSON.parse(JSON.stringify(data.lactose));
            currentGlucose = JSON.parse(JSON.stringify(data.glucose));
            currentGerms = JSON.parse(JSON.stringify(data.germs));
            currentMg = JSON.parse(JSON.stringify(data.mg));

            player.x = data.playerStart.x;
            player.y = data.playerStart.y;
            player.vy = 0;
            player.onGround = true;

            document.getElementById('level').innerText = lv;
            document.getElementById('targetNum').innerText = target;
            document.getElementById('score').innerText = score;
            updateHpUI();
        }

        // ---------- 键盘控制 ----------
        const keys = { left: false, right: false, jump: false };
        window.addEventListener('keydown', (e) => {
            if (e.code === 'ArrowLeft') keys.left = true;
            if (e.code === 'ArrowRight') keys.right = true;
            if (e.code === 'Space') {
                keys.jump = true;
                e.preventDefault();
            }
            // 防止方向键滚动页面
            if (e.code === 'ArrowUp' || e.code === 'ArrowDown') e.preventDefault();
        });
        window.addEventListener('keyup', (e) => {
            if (e.code === 'ArrowLeft') keys.left = false;
            if (e.code === 'ArrowRight') keys.right = false;
            if (e.code === 'Space') keys.jump = false;
        });

        // ---------- 游戏主循环 & 逻辑 ----------
        function updateGame() {
            // 1. 无敌递减
            if (invincible > 0) invincible--;

            // 2. 异常状态计时
            if (isInactive) {
                inactiveTimer--;
                if (inactiveTimer <= 0) isInactive = false;
            }
            if (isLowTemp) {
                lowTempTimer--;
                if (lowTempTimer <= 0) isLowTemp = false;
            }

            // 3. 速度 / 跳跃倍率(失活 & 低温)
            let spRate = 1.0, jumpRate = 1.0;
            if (isInactive) { spRate = 0.5; jumpRate = 0.62; }
            else if (isLowTemp) { spRate = 0.76; jumpRate = 0.86; }
            let moveSpeed = player.speed * spRate;
            let jumpPower = player.jumpSp * jumpRate;

            // 4. 移动
            if (keys.left) player.x -= moveSpeed;
            if (keys.right) player.x += moveSpeed;
            player.x = Math.max(2, Math.min(canvas.width - player.w - 2, player.x));

            // 5. 跳跃
            if (keys.jump && player.onGround) {
                player.vy = jumpPower;
                player.onGround = false;
            }

            // 6. 重力
            player.vy += player.grav;
            player.y += player.vy;
            player.onGround = false;

            // 7. 地形碰撞 (暂存安全 / 危险标志)
            let safeGroundFlag = false;
            let dangerFlag = false;
            let newInactiveFlag = false;
            let newLowTempFlag = false;
            let inactiveTimerAdd = 0;
            let lowTempTimerAdd = 0;

            // 先按 y 排序从下往上处理? 但简单循环即可,每碰撞修正一次位置
            for (let i = 0; i < currentMap.length; i++) {
                const plat = currentMap[i];
                if (rectCollide(player, plat)) {
                    // 碰撞方向: 主要处理从上往下落到平台上
                    let playerBottom = player.y + player.h;
                    let platTop = plat.y;
                    let prevBottom = playerBottom - player.vy;
                    if (player.vy >= 0 && prevBottom <= platTop) {
                        // 落到平台上
                        player.y = plat.y - player.h;
                        player.vy = 0;
                        player.onGround = true;
                        // 根据平台类型施加效果
                        if (plat.t === 0) {
                            safeGroundFlag = true;    // 安全地面
                        } 
                        else if (plat.t === 1 || plat.t === 2 || plat.t === 3 || plat.t === 4) {
                            // 危险失活地面
                            dangerFlag = true;
                            newInactiveFlag = true;
                            inactiveTimerAdd = 180;
                        }
                        else if (plat.t === 5) {
                            // 低温地面
                            newLowTempFlag = true;
                            lowTempTimerAdd = 220;
                        }
                    }
                    // 防止头顶卡砖(简单向上顶头)
                    else if (player.vy < 0 && player.y <= plat.y + plat.h && player.y + player.h > plat.y) {
                        player.y = plat.y + plat.h;
                        if (player.vy < 0) player.vy = 0;
                    }
                    // 左右墙推开(极少情况,但避免卡墙)
                    else if (player.x + player.w > plat.x && player.x < plat.x + plat.w) {
                        if (player.x + player.w - plat.x < plat.x + plat.w - player.x) {
                            player.x = plat.x - player.w;
                        } else {
                            player.x = plat.x + plat.w;
                        }
                    }
                }
            }

            // 应用地面效果(失活 / 低温)
            if (newInactiveFlag) {
                isInactive = true;
                inactiveTimer = Math.max(inactiveTimer, inactiveTimerAdd);
            }
            if (newLowTempFlag) {
                isLowTemp = true;
                lowTempTimer = Math.max(lowTempTimer, lowTempTimerAdd);
            }
            inDanger = dangerFlag;

            // 8. 危险地形掉血(间隔伤害,每 25 帧约 0.4 秒掉 1 血,避免瞬间蒸发)
            if (inDanger && !isInactive) {
                if (dangerDamageCooldown <= 0) {
                    loseHp();
                    dangerDamageCooldown = 28;   // 伤害间隔
                } else {
                    dangerDamageCooldown--;
                }
            } else {
                dangerDamageCooldown = 0;
            }

            // 9. 边界掉落死亡 (掉出画布)
            if (player.y + player.h > canvas.height + 30) {
                loseHp();
                // 重置位置到起点
                const startX = levelData[nowLevel].playerStart.x;
                const startY = levelData[nowLevel].playerStart.y;
                player.x = startX;
                player.y = startY;
                player.vy = 0;
                player.onGround = false;
                if (hp > 0) {
                    // 轻微惩罚: 避免连续掉落致死, 但已经扣血一次了
                }
            }

            // 10. 站在安全地面回血 (且无失活 / 低温)
            if (safeGroundFlag && !isInactive && !isLowTemp && hp < maxHp) {
                healTimer++;
                if (healTimer >= 150) {  // 2.5 秒回 1 血 (60 帧)
                    hp++;
                    if (hp > maxHp) hp = maxHp;
                    updateHpUI();
                    healTimer = 0;
                }
            } else {
                healTimer = 0;
            }

            // 11. 乳糖收集
            for (let i = 0; i < currentLactose.length; i++) {
                const lac = currentLactose[i];
                if (rectCollide(player, lac)) {
                    score++;
                    document.getElementById('score').innerText = score;
                    currentLactose.splice(i,1);
                    i--;
                }
            }

            // 12. 过关检测
            if (score >= target) {
                if (nowLevel === 1) {
                    alert('🎉 第一关通过!乳糖酶活力充沛,前往更复杂的肠道环境!');
                    loadLevel(2);
                } else if (nowLevel === 2) {
                    alert('🏆 完美通关!乳糖酶成功消化所有乳糖,肠道恢复健康!🎊');
                    loadLevel(1);  // 循环重新开始
                }
                return; // 关卡重载后直接跳帧重置,避免额外操作
            }

            // 13. 镁离子 (净化 + 无敌)
            if (currentMg.exist) {
                if (rectCollide(player, currentMg)) {
                    currentMg.exist = false;
                    invincible = 320;        // 超长无敌
                    // 清除负面状态
                    isInactive = false;
                    inactiveTimer = 0;
                    isLowTemp = false;
                    lowTempTimer = 0;
                }
            }

            // 14. 葡萄糖刷新与拾取
            for (let g of currentGlucose) {
                if (!g.exist) {
                    g.cd--;
                    if (g.cd <= 0) {
                        g.exist = true;
                        g.x = g.originX;
                        g.y = g.originY;
                    }
                }
                if (g.exist && rectCollide(player, g)) {
                    addHpByGlc(g);
                }
            }

            // 15. 病菌移动 & 碰撞
            for (let g of currentGerms) {
                g.x += g.speed * g.dir;
                if (g.x <= g.minX) { g.x = g.minX; g.dir = 1; }
                if (g.x >= g.maxX) { g.x = g.maxX; g.dir = -1; }
                if (rectCollide(player, g)) {
                    loseHp();
                }
            }
        }

        // ---------- 绘图模块 ----------
        function draw() {
            ctx.clearRect(0, 0, 800, 420);
            // 背景装饰(肠道氛围)
            ctx.fillStyle = '#9fc9e0';
            ctx.fillRect(0,0,800,420);
            ctx.fillStyle = '#c1e2f0';
            for(let i=0;i<12;i++) {
                ctx.beginPath();
                ctx.arc(70+i*70, 40+Math.sin(Date.now()*0.002+i)*12, 12,0,Math.PI*2);
                ctx.fill();
            }

            // 1. 绘制地形
            for (let p of currentMap) {
                let col = '#f5ecd8';
                switch(p.t){
                    case 0: col='#f5e6c4'; break;
                    case 1: col='#e35f3e'; break;
                    case 2: col='#4d9b3a'; break;
                    case 3: col='#b87bcb'; break;
                    case 4: col='#6e6c6a'; break;
                    case 5: col='#7ac5e0'; break;
                }
                ctx.fillStyle = col;
                ctx.shadowBlur = 0;
                ctx.fillRect(p.x, p.y, p.w, p.h);
                // 质感边缘
                ctx.strokeStyle = 'rgba(0,0,0,0.2)';
                ctx.strokeRect(p.x, p.y, p.w, p.h);
            }

            // 2. 乳糖(金黄色小球)
            for (let lac of currentLactose) {
                ctx.fillStyle = '#FFD966';
                ctx.shadowBlur = 8;
                ctx.shadowColor = '#ccaa44';
                ctx.beginPath();
                ctx.arc(lac.x + lac.w/2, lac.y + lac.h/2, 9, 0, Math.PI*2);
                ctx.fill();
                ctx.fillStyle = '#f0b27a';
                ctx.beginPath();
                ctx.arc(lac.x + lac.w/2 - 2, lac.y + lac.h/2 - 2, 2, 0, Math.PI*2);
                ctx.fill();
            }

            // 3. 葡萄糖(绿色能量球)
            for (let g of currentGlucose) {
                if(g.exist){
                    ctx.fillStyle = '#5FDD9D';
                    ctx.shadowBlur = 6;
                    ctx.beginPath();
                    ctx.arc(g.x+8, g.y+8, 8, 0, Math.PI*2);
                    ctx.fill();
                    ctx.fillStyle = '#226622';
                    ctx.beginPath();
                    ctx.arc(g.x+5, g.y+5, 2, 0, Math.PI*2);
                    ctx.fill();
                }
            }

            // 4. 镁离子(闪耀蓝光)
            if (currentMg.exist) {
                ctx.fillStyle = '#3B9EFF';
                ctx.shadowBlur = 12;
                ctx.beginPath();
                ctx.arc(currentMg.x+10, currentMg.y+10, 12, 0, Math.PI*2);
                ctx.fill();
                ctx.fillStyle = '#FFFFFF';
                ctx.beginPath();
                ctx.arc(currentMg.x+7, currentMg.y+7, 3, 0, Math.PI*2);
                ctx.fill();
            }

            // 5. 病菌
            for (let g of currentGerms) {
                ctx.fillStyle = '#2F2E2F';
                ctx.shadowBlur = 2;
                ctx.fillRect(g.x, g.y, g.w, g.h);
                ctx.fillStyle = '#5a3e2e';
                ctx.fillRect(g.x+5, g.y+5, 6, 6);
                ctx.fillRect(g.x+15, g.y+5, 6, 6);
                ctx.fillStyle = '#961010';
                ctx.fillRect(g.x+10, g.y+15, 6, 5);
            }

            // 6. 玩家 - 乳糖酶(可爱酶蛋白)
            ctx.shadowBlur = 5;
            if(invincible > 0 && (Math.floor(Date.now()/60)%3 < 1)) {
                ctx.fillStyle = '#F9F3C1';
            } else if(isInactive) {
                ctx.fillStyle = '#7C7F8C';
            } else if(isLowTemp) {
                ctx.fillStyle = '#5FA7CF';
            } else {
                ctx.fillStyle = '#E65348';
            }
            ctx.fillRect(player.x, player.y, player.w, player.h);
            // 酶的眼睛
            ctx.fillStyle = "#FFFFFF";
            ctx.fillRect(player.x+6, player.y+8, 7, 7);
            ctx.fillRect(player.x+18, player.y+8, 7, 7);
            ctx.fillStyle = "#1F2A2E";
            ctx.fillRect(player.x+7, player.y+10, 4, 4);
            ctx.fillRect(player.x+19, player.y+10, 4, 4);
            // 微笑
            ctx.beginPath();
            ctx.arc(player.x+15, player.y+22, 8, 0.05, Math.PI - 0.05);
            ctx.strokeStyle = "#341C0E";
            ctx.lineWidth = 2;
            ctx.stroke();

            ctx.shadowBlur = 0;
            // 状态特效(显示危险标识)
            if(inDanger && !isInactive) {
                ctx.font = "bold 18px monospace";
                ctx.fillStyle = "#ff5555aa";
                ctx.fillText("⚠️", player.x-10, player.y-5);
            }
        }

        // 刷新 UI 文字
        function updateUItext() {
            let statusMsg = '';
            if (isInactive) statusMsg = '❄️ 变性失活 · 虚弱';
            else if (isLowTemp) statusMsg = '🧊 低温抑制 · 活性下降';
            else statusMsg = '✅ 乳糖酶活性正常';
            document.getElementById('state').innerHTML = statusMsg;
            document.getElementById('score').innerText = score;
        }

        // ---------- 动画循环 ----------
        function gameLoop() {
            updateGame();
            draw();
            updateUItext();
            requestAnimationFrame(gameLoop);
        }

        // 启动游戏!
        loadLevel(1);
        gameLoop();
    })();
</script>
</body>
</html>

HTML

正文完
 0
lara2026
版权声明:本站原创文章,由 lara2026 于2026-06-05发表,共计14805字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)