🎮ArcadeLab

💣 3D拆弹三人组 - 随机身份

by FlashPhoenix67
534 lines27.0 KB
▶ Play
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>💣 3D拆弹三人组 - 随机身份</title>
    <script src="https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.min.js"></script>
    <style>
        *{margin:0; padding:0; box-sizing:border-box; font-family:'Microsoft YaHei',sans-serif;}
        body{background:#0f172a; color:#fff; overflow:hidden; height:100vh;}
        canvas{position:fixed; top:0; left:0; z-index:1;}
        .ui-layer{position:relative; z-index:2; pointer-events:none; height:100vh; display:flex; flex-direction:column;}
        .ui-layer > *{pointer-events:auto;}
        
        /* 开始界面 */
        .start-screen{position:absolute; inset:0; background:rgba(15,23,42,0.95); display:flex; flex-direction:column; align-items:center; justify-content:center; padding:30px; z-index:100;}
        .start-box{background:#1e293b; border-radius:20px; padding:35px; max-width:500px; width:100%; border:2px solid #334155; box-shadow:0 0 40px rgba(239,68,68,0.2);}
        h1{text-align:center; color:#f87171; font-size:2rem; margin-bottom:10px;}
        .subtitle{text-align:center; color:#94a3b8; margin-bottom:25px;}
        .role-preview{display:grid; grid-template-columns:repeat(3,1fr); gap:12px; margin-bottom:25px;}
        .role-card{background:#334155; border-radius:12px; padding:15px; text-align:center; border:2px solid transparent; transition:0.3s;}
        .role-card .emoji{font-size:2.5rem; margin-bottom:8px;}
        .role-card .name{font-weight:bold; font-size:1.1rem; margin-bottom:5px;}
        .role-card .desc{font-size:0.8rem; color:#94a3b8; line-height:1.4;}
        .btn-start{width:100%; padding:16px; font-size:1.2rem; font-weight:bold; background:linear-gradient(90deg,#ef4444,#dc2626); color:#fff; border:none; border-radius:12px; cursor:pointer; transition:0.3s;}
        .btn-start:hover{transform:scale(1.03); box-shadow:0 0 20px rgba(239,68,68,0.4);}
        .tip{margin-top:15px; text-align:center; color:#64748b; font-size:0.9rem;}
        
        /* 身份分配界面 */
        .assign-screen{position:absolute; inset:0; background:rgba(15,23,42,0.95); display:none; flex-direction:column; align-items:center; justify-content:center; z-index:100;}
        .assign-box{background:#1e293b; border-radius:20px; padding:40px; text-align:center; border:3px solid #f59e0b; animation:glow 2s infinite;}
        @keyframes glow{0%{box-shadow:0 0 20px #f59e0b40;} 50%{box-shadow:0 0 40px #f59e0b80;} 100%{box-shadow:0 0 20px #f59e0b40;}}
        .assign-role-emoji{font-size:5rem; margin-bottom:15px;}
        .assign-role-name{font-size:1.8rem; font-weight:bold; color:#fbbf24; margin-bottom:10px;}
        .assign-role-desc{color:#cbd5e1; max-width:350px; line-height:1.8; margin-bottom:25px;}
        .btn-begin{padding:14px 40px; font-size:1.1rem; font-weight:bold; background:linear-gradient(90deg,#10b981,#059669); color:#fff; border:none; border-radius:10px; cursor:pointer;}
        
        /* 游戏UI */
        .game-header{padding:15px 20px; display:flex; justify-content:space-between; align-items:center; background:rgba(0,0,0,0.5);}
        .role-badge{display:flex; align-items:center; gap:10px; background:rgba(30,41,59,0.8); padding:8px 15px; border-radius:30px; border:2px solid;}
        .role-badge.blind{border-color:#facc15; color:#facc15;}
        .role-badge.mute{border-color:#a78bfa; color:#a78bfa;}
        .role-badge.deaf{border-color:#22d3ee; color:#22d3ee;}
        .level-info{font-size:1.1rem; color:#fbbf24;}
        .timer-box{font-size:2rem; font-weight:bold; font-family:monospace; color:#fff; text-shadow:0 0 10px #fff;}
        .timer-box.warning{color:#fbbf24; text-shadow:0 0 15px #fbbf24;}
        .timer-box.danger{color:#ef4444; text-shadow:0 0 15px #ef4444; animation:blink 0.5s infinite;}
        @keyframes blink{0%,100%{opacity:1;} 50%{opacity:0.4;}}
        
        /* 提示面板 */
        .hint-panel{position:absolute; bottom:0; left:0; right:0; padding:20px; background:linear-gradient(to top, rgba(0,0,0,0.9), transparent);}
        .hint-content{background:rgba(30,41,59,0.9); border-radius:12px; padding:18px; margin-bottom:15px; border-left:4px solid;}
        .hint-content.blind{border-left-color:#facc15;}
        .hint-content.deaf{border-left-color:#22d3ee;}
        .hint-title{font-weight:bold; margin-bottom:10px; font-size:1.05rem; display:flex; align-items:center; gap:8px;}
        .hint-title.blind{color:#facc15;}
        .hint-title.deaf{color:#22d3ee;}
        .hint-text{font-family:monospace; font-size:1rem; line-height:1.8; white-space:pre-wrap; color:#e2e8f0;}
        
        /* 电线操作区 */
        .wire-control{display:flex; flex-wrap:wrap; gap:12px; margin-bottom:15px; justify-content:center;}
        .wire-btn{width:80px; height:50px; border-radius:8px; border:none; font-weight:bold; font-size:1.1rem; cursor:pointer; transition:0.2s; color:#000;}
        .wire-btn:hover{transform:scale(1.1);}
        .wire-btn.selected{outline:3px solid #fff; box-shadow:0 0 15px #fff;}
        .wire-btn:disabled{opacity:0.4; cursor:not-allowed; transform:none;}
        .confirm-btn{display:block; width:200px; margin:0 auto; padding:12px; font-size:1.1rem; font-weight:bold; background:linear-gradient(90deg,#22c55e,#16a34a); color:#fff; border:none; border-radius:10px; cursor:pointer;}
        .confirm-btn:disabled{opacity:0.4; cursor:not-allowed;}
        
        /* 角色遮罩效果 */
        .mask-blind{filter:grayscale(1) contrast(1.2);}
        .mask-blind canvas{filter:grayscale(1);}
        .mask-deaf .hint-panel .hint-content.blind{display:none !important;}
        .mask-mute .wire-control{pointer-events:none; opacity:0.5;}
        .mute-note{text-align:center; color:#a78bfa; font-style:italic; margin-top:10px;}
        
        /* 结果弹窗 */
        .result-popup{position:absolute; inset:0; background:rgba(0,0,0,0.85); display:none; flex-direction:column; align-items:center; justify-content:center; z-index:200;}
        .result-box{background:#1e293b; border-radius:20px; padding:40px; text-align:center; max-width:400px; border:2px solid;}
        .result-box.success{border-color:#22c55e;}
        .result-box.fail{border-color:#ef4444;}
        .result-emoji{font-size:4rem; margin-bottom:15px;}
        .result-title{font-size:1.8rem; font-weight:bold; margin-bottom:10px;}
        .result-desc{color:#94a3b8; margin-bottom:25px; line-height:1.6;}
        .result-btn{padding:12px 30px; font-size:1rem; font-weight:bold; border:none; border-radius:8px; cursor:pointer; margin:5px;}
        .btn-next{background:linear-gradient(90deg,#3b82f6,#2563eb); color:#fff;}
        .btn-retry{background:linear-gradient(90deg,#f97316,#ea580c); color:#fff;}
        .btn-menu{background:#475569; color:#fff;}
    </style>
</head>
<body>
    <!-- 3D画布 -->
    <canvas id="bombCanvas"></canvas>
    
    <!-- 开始界面 -->
    <div class="start-screen" id="startScreen">
        <div class="start-box">
            <h1>💣 3D绝境拆弹</h1>
            <p class="subtitle">三人协作 · 随机身份 · 生死与共</p>
            <div class="role-preview">
                <div class="role-card">
                    <div class="emoji">👁️‍🗨️</div>
                    <div class="name">瞎子</div>
                    <div class="desc">能看到数字/密码/颜色线索<br>看不到电线与操作按钮</div>
                </div>
                <div class="role-card">
                    <div class="emoji">🗣️</div>
                    <div class="name">哑巴</div>
                    <div class="desc">能看到全部界面<br>能操作但不能说话打字</div>
                </div>
                <div class="role-card">
                    <div class="emoji">👂</div>
                    <div class="name">耳聋</div>
                    <div class="desc">能看到电线颜色与顺序<br>看不到文字提示</div>
                </div>
            </div>
            <button class="btn-start" onclick="startGame()">🎲 随机分配身份并开始</button>
            <p class="tip">💡 三人各打开一份链接,每人获得不同随机身份,互相配合完成拆弹!</p>
        </div>
    </div>
    
    <!-- 身份分配界面 -->
    <div class="assign-screen" id="assignScreen">
        <div class="assign-box">
            <div class="assign-role-emoji" id="assignEmoji">🎲</div>
            <div class="assign-role-name" id="assignName">分配中...</div>
            <div class="assign-role-desc" id="assignDesc"></div>
            <button class="btn-begin" onclick="enterGame()">✅ 确认身份,进入游戏</button>
        </div>
    </div>
    
    <!-- 游戏UI层 -->
    <div class="ui-layer" id="gameUI" style="display:none;">
        <div class="game-header">
            <div class="role-badge" id="roleBadge">
                <span id="roleEmoji">👤</span>
                <span id="roleName">未知</span>
            </div>
            <div class="level-info" id="levelInfo">第 1 关 / 10</div>
            <div class="timer-box" id="timerBox">60</div>
        </div>
        
        <div class="hint-panel">
            <!-- 瞎子提示区 -->
            <div class="hint-content blind" id="blindHintArea">
                <div class="hint-title blind">👁️‍🗨️ 线索提示</div>
                <div class="hint-text" id="blindHint">加载中...</div>
            </div>
            
            <!-- 耳聋提示区 -->
            <div class="hint-content deaf" id="deafHintArea">
                <div class="hint-title deaf">👂 电线布局</div>
                <div class="hint-text" id="deafHint">加载中...</div>
            </div>
            
            <!-- 哑巴操作区 -->
            <div class="wire-control" id="muteControl">
                <!-- 动态生成电线按钮 -->
            </div>
            <button class="confirm-btn" id="confirmBtn" onclick="confirmCut()" disabled>✂️ 确认剪线</button>
            <p class="mute-note" id="muteNote" style="display:none;">🤐 你是哑巴 — 只能用手势/表情与队友交流</p>
        </div>
    </div>
    
    <!-- 结果弹窗 -->
    <div class="result-popup" id="resultPopup">
        <div class="result-box" id="resultBox">
            <div class="result-emoji" id="resultEmoji">🎉</div>
            <div class="result-title" id="resultTitle">成功!</div>
            <div class="result-desc" id="resultDesc">炸弹已拆除!</div>
            <div style="display:flex; gap:10px; justify-content:center; flex-wrap:wrap;">
                <button class="result-btn btn-next" id="nextBtn" onclick="nextLevel()">➡️ 下一关</button>
                <button class="result-btn btn-retry" onclick="restartLevel()">🔄 重试本关</button>
                <button class="result-btn btn-menu" onclick="backToMenu()">🏠 返回菜单</button>
            </div>
        </div>
    </div>

    <script>
        // ========== 游戏配置 ==========
        const ROLES = {
            blind: { 
                name: '瞎子', emoji: '👁️‍🗨️', 
                desc: '你能看到数字、密码和颜色线索,但看不到电线和操作按钮。请把线索告诉队友!'
            },
            mute: { 
                name: '哑巴', emoji: '🗣️', 
                desc: '你能看到全部界面,可以操作按钮,但全程不能说话或打字!只能用手势和表情交流!'
            },
            deaf: { 
                name: '耳聋', emoji: '👂', 
                desc: '你能看到电线的颜色和顺序布局,但看不到文字提示。请指挥队友剪哪根线!'
            }
        };
        
        const COLORS = {
            red: '#ff4444', blue: '#0099ff', yellow: '#ffcc00',
            green: '#00cc66', purple: '#9933ff', orange: '#ff8800'
        };
        const COLOR_NAMES = {
            red: '红色', blue: '蓝色', yellow: '黄色',
            green: '绿色', purple: '紫色', orange: '橙色'
        };
        
        const LEVELS = [
            { wires: 4, time: 60, difficulty: '简单' },
            { wires: 4, time: 55, difficulty: '简单' },
            { wires: 4, time: 50, difficulty: '简单' },
            { wires: 5, time: 50, difficulty: '普通' },
            { wires: 5, time: 45, difficulty: '普通' },
            { wires: 5, time: 40, difficulty: '普通' },
            { wires: 6, time: 40, difficulty: '困难' },
            { wires: 6, time: 35, difficulty: '困难' },
            { wires: 6, time: 30, difficulty: '困难' },
            { wires: 6, time: 30, difficulty: '地狱' }
        ];

        // ========== 全局状态 ==========
        let gameState = {
            role: null, level: 1, timeLeft: 60, timerInterval: null,
            correctWire: null, wires: [], selectedWire: null,
            isRunning: false, scene: null, camera: null, renderer: null,
            bomb: null, wireMeshes: []
        };

        // ========== 3D场景初始化 ==========
        function init3D() {
            const canvas = document.getElementById('bombCanvas');
            const scene = new THREE.Scene();
            scene.background = new THREE.Color(0x0f172a);
            const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
            const renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
            
            // 灯光
            const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
            scene.add(ambientLight);
            const pointLight = new THREE.PointLight(0xff0000, 1, 20);
            pointLight.position.set(0, 2, 5);
            scene.add(pointLight);
            
            // 炸弹主体
            const bombGroup = new THREE.Group();
            const bodyGeo = new THREE.SphereGeometry(1.5, 32, 32);
            const bodyMat = new THREE.MeshPhongMaterial({ 
                color: 0xdc2626, shininess: 100, specular: 0x440000
            });
            const body = new THREE.Mesh(bodyGeo, bodyMat);
            bombGroup.add(body);
            
            // 顶部盖子
            const capGeo = new THREE.CylinderGeometry(0.5, 0.8, 0.6, 32);
            const capMat = new THREE.MeshPhongMaterial({ color: 0x333333 });
            const cap = new THREE.Mesh(capGeo, capMat);
            cap.position.y = 1.5;
            bombGroup.add(cap);
            
            // 显示屏
            const screenGeo = new THREE.BoxGeometry(1, 0.6, 0.1);
            const screenMat = new THREE.MeshBasicMaterial({ color: 0x111111 });
            const screen = new THREE.Mesh(screenGeo, screenMat);
            screen.position.set(0, 0.3, 1.45);
            bombGroup.add(screen);
            
            // 电线支架
            const wireHolderGeo = new THREE.BoxGeometry(2.5, 0.2, 1);
            const wireHolderMat = new THREE.MeshPhongMaterial({ color: 0x222222 });
            const wireHolder = new THREE.Mesh(wireHolderGeo, wireHolderMat);
            wireHolder.position.y = -1.2;
            bombGroup.add(wireHolder);
            
            bombGroup.position.z = -3;
            bombGroup.position.y = 0.5;
            scene.add(bombGroup);
            
            // 存储引用
            gameState.scene = scene;
            gameState.camera = camera;
            gameState.renderer = renderer;
            gameState.bomb = bombGroup;
            
            // 窗口适配
            window.addEventListener('resize', () => {
                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();
                renderer.setSize(window.innerWidth, window.innerHeight);
            });
            
            // 动画循环
            function animate() {
                requestAnimationFrame(animate);
                bombGroup.rotation.y += 0.005; // 缓慢旋转
                renderer.render(scene, camera);
            }
            animate();
        }

        // 生成3D电线
        function generate3DWires(wireData) {
            // 清除旧电线
            gameState.wireMeshes.forEach(m => gameState.scene.remove(m));
            gameState.wireMeshes = [];
            
            wireData.forEach((wire, idx) => {
                const colorHex = parseInt(COLORS[wire.color].slice(1), 16);
                const wireGeo = new THREE.CylinderGeometry(0.05, 0.05, 1.2, 8);
                const wireMat = new THREE.MeshPhongMaterial({ color: colorHex, emissive: colorHex, emissiveIntensity: 0.3 });
                const wireMesh = new THREE.Mesh(wireGeo, wireMat);
                
                // 排列位置
                const total = wireData.length;
                const spacing = 2 / (total + 1);
                wireMesh.position.x = -1 + spacing * (idx + 1);
                wireMesh.position.y = -1.8;
                wireMesh.position.z = -2.8;
                wireMesh.rotation.x = Math.PI / 2;
                
                gameState.bomb.add(wireMesh);
                gameState.wireMeshes.push(wireMesh);
            });
        }

        // ========== 身份分配 ==========
        function pickRandomRole() {
            const roles = Object.keys(ROLES);
            // 尝试从URL参数获取,确保三人不同 - 简单伪随机但可复现
            const params = new URLSearchParams(window.location.search);
            let roleIndex = params.get('role');
            if (roleIndex !== null && roleIndex >= 0 && roleIndex < 3) {
                return roles[parseInt(roleIndex)];
            }
            // 纯随机
            return roles[Math.floor(Math.random() * 3)];
        }

        function startGame() {
            gameState.role = pickRandomRole();
            const role = ROLES[gameState.role];
            
            // 显示分配界面
            document.getElementById('startScreen').style.display = 'none';
            document.getElementById('assignScreen').style.display = 'flex';
            document.getElementById('assignEmoji').textContent = role.emoji;
            document.getElementById('assignName').textContent = role.name;
            document.getElementById('assignDesc').textContent = role.desc;
        }

        function enterGame() {
            document.getElementById('assignScreen').style.display = 'none';
            document.getElementById('gameUI').style.display = 'flex';
            
            // 应用角色UI效果
            document.body.classList.remove('mask-blind', 'mask-deaf', 'mask-mute');
            const role = gameState.role;
            
            // 更新角色徽章
            document.getElementById('roleEmoji').textContent = ROLES[role].emoji;
            document.getElementById('roleName').textContent = ROLES[role].name;
            document.getElementById('roleBadge').className = 'role-badge ' + role;
            
            // 根据角色显示/隐藏内容
            if (role === 'blind') {
                document.body.classList.add('mask-blind');
                document.getElementById('deafHintArea').style.display = 'none';
                document.getElementById('muteControl').style.display = 'none';
                document.getElementById('confirmBtn').style.display = 'none';
            } else if (role === 'deaf') {
                document.body.classList.add('mask-deaf');
                document.getElementById('blindHintArea').style.display = 'none';
            } else if (role === 'mute') {
                document.getElementById('blindHintArea').style.display = 'none';
                document.getElementById('deafHintArea').style.display = 'none';
                document.getElementById('muteNote').style.display = 'block';
            }
            
            // 初始化3D
            if (!gameState.renderer) init3D();
            
            // 加载第一关
            loadLevel();
        }

        // ========== 关卡逻辑 ==========
        function loadLevel() {
            const cfg = LEVELS[gameState.level - 1];
            if (gameState.timerInterval) clearInterval(gameState.timerInterval);
            gameState.timeLeft = cfg.time;
            gameState.isRunning = true;
            gameState.selectedWire = null;
            
            // 更新UI
            document.getElementById('levelInfo').textContent = `第 ${gameState.level} 关 / 10 (${cfg.difficulty})`;
            updateTimerDisplay();
            
            // 生成电线数据
            generateWiresData(cfg.wires);
            
            // 生成提示
            generateHints();
            
            // 重置按钮
            document.getElementById('confirmBtn').disabled = true;
            document.querySelectorAll('.wire-btn').forEach(b => b.classList.remove('selected'));
            
            // 隐藏结果弹窗
            document.getElementById('resultPopup').style.display = 'none';
            
            // 开始计时
            startTimer();
        }

        function generateWiresData(count) {
            const colorKeys = Object.keys(COLORS);
            const shuffled = [...colorKeys].sort(() => Math.random() - 0.5).slice(0, count);
            gameState.wires = shuffled.map((color, idx) => ({
                color, idx, isCorrect: idx === Math.floor(Math.random() * count)
            }));
            gameState.correctWire = gameState.wires.findIndex(w => w.isCorrect);
            
            // 更新3D
            generate3DWires(gameState.wires);
            
            // 更新UI按钮(仅哑巴可见)
            const container = document.getElementById('muteControl');
            container.innerHTML = '';
            gameState.wires.forEach((w, i) => {
                const btn = document.createElement('button');
                btn.className = 'wire-btn';
                btn.style.backgroundColor = COLORS[w.color];
                btn.textContent = i + 1;
                btn.onclick = () => selectWire(i);
                container.appendChild(btn);
            });
        }

        function generateHints() {
            const idx = gameState.correctWire;
            const total = gameState.wires.length;
            const targetColor = COLOR_NAMES[gameState.wires[idx].color];
            let blindHint = '', deafHint = '';
            
            // 根据关卡难度生成不同提示
            if (gameState.level <= 3) {
                blindHint = `📍 正确序号:第 ${idx + 1} 根\n🎨 颜色:${targetColor}`;
            } else if (gameState.level <= 6) {
                const n1 = Math.floor(Math.random() * 5) + 1;
                blindHint = `🧮 计算:${n1} × ${idx + 1} ÷ ${n1} = ?\n结果就是序号!\n🎨 颜色:${targetColor}`;
            } else if (gameState.level <= 9) {
                const parity = (idx + 1) % 2 === 0 ? '偶数' : '奇数';
                blindHint = `🔐 序号是 ${parity}\n🔢 序号 + 3 = ${idx + 3}\n🎨 颜色:${targetColor}`;
            } else {
                const parity = (idx + 1) % 2 === 0 ? '偶数' : '奇数';
                const exclude = gameState.wires.filter((_, i) => i !== idx).map(w => COLOR_NAMES[w.color]).join('、');
                blindHint = `☠️ 三重线索:\n1️⃣ 序号是 ${parity}\n2️⃣ 颜色:${targetColor}\n3️⃣ 不是:${exclude}`;
            }
            
            // 耳聋:仅电线顺序
            deafHint = gameState.wires.map((w, i) => `${i+1}.${COLOR_NAMES[w.color]}`).join('\n');
            
            document.getElementById('blindHint').textContent = blindHint;
            document.getElementById('deafHint').textContent = deafHint;
        }

        function selectWire(idx) {
            if (!gameState.isRunning || gameState.role !== 'mute') return;
            gameState.selectedWire = idx;
            document.querySelectorAll('.wire-btn').forEach((b, i) => {
                b.classList.toggle('selected', i === idx);
            });
            document.getElementById('confirmBtn').disabled = false;
        }

        function confirmCut() {
            if (!gameState.isRunning || gameState.selectedWire === null) return;
            gameState.isRunning = false;
            clearInterval(gameState.timerInterval);
            
            const isSuccess = gameState.selectedWire === gameState.correctWire;
            showResult(isSuccess);
        }

        function showResult(success) {
            const popup = document.getElementById('resultPopup');
            const box = document.getElementById('resultBox');
            box.className = 'result-box ' + (success ? 'success' : 'fail');
            document.getElementById('resultEmoji').textContent = success ? '✅' : '💥';
            document.getElementById('resultTitle').textContent = success ? '拆弹成功!' : '炸弹爆炸!';
            document.getElementById('resultDesc').textContent = success 
                ? `第${gameState.level}关完成!准备迎接下一个挑战。` 
                : `剪错了电线!正确答案是第${gameState.correctWire + 1}根,${COLOR_NAMES[gameState.wires[gameState.correctWire].color]}。`;
            document.getElementById('nextBtn').style.display = success && gameState.level < 10 ? 'inline-block' : 'none';
            popup.style.display = 'flex';
        }

        function startTimer() {
            gameState.timerInterval = setInterval(() => {
                gameState.timeLeft--;
                updateTimerDisplay();
                if (gameState.timeLeft <= 0) {
                    gameState.isRunning = false;
                    clearInterval(gameState.timerInterval);
                    showResult(false);
                }
            }, 1000);
        }

        function updateTimerDisplay() {
            const box = document.getElementById('timerBox');
            box.textContent = gameState.timeLeft;
            box.classList.remove('warning', 'danger');
            if (gameState.timeLeft <= 20) box.classList.add('warning');
            if (gameState.timeLeft <= 10) box.classList.add('danger');
        }

        function nextLevel() {
            gameState.level++;
            loadLevel();
        }

        function restartLevel() {
            loadLevel();
        }

        function backToMenu() {
            if (gameState.timerInterval) clearInterval(gameState.timerInterval);
            document.getElementById('gameUI').style.display = 'none';
            document.getElementById('resultPopup').style.display = 'none';
            document.getElementById('startScreen').style.display = 'flex';
            document.body.classList.remove('mask-blind', 'mask-deaf', 'mask-mute');
            gameState.level = 1;
        }
    </script>
</body>
</html>

Game Source: 💣 3D拆弹三人组 - 随机身份

Creator: FlashPhoenix67

Libraries: none

Complexity: complex (534 lines, 27.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 ARCADELAB header at the top with "remix_of: 3d-flashphoenix67" to link back to the original. Then publish at arcadelab.ai/publish.