🎮ArcadeLab

Monday爱豆生活 · 角色扮演

by ThunderPenguin58
452 lines16.5 KB
▶ Play
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <title>Monday爱豆生活 · 角色扮演</title>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
            font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
        }
        body {
            background: #0b0b0f;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            padding: 16px;
        }
        .app {
            max-width: 420px;
            width: 100%;
            background: #14141c;
            border-radius: 36px;
            padding: 20px 16px 16px;
            box-shadow: 0 20px 40px rgba(0,0,0,0.8);
            border: 1px solid #2a2a35;
            min-height: 700px;
            display: flex;
            flex-direction: column;
        }
        .status {
            display: flex;
            justify-content: space-between;
            color: #8888a0;
            font-size: 12px;
            padding-bottom: 12px;
            border-bottom: 1px solid #22222e;
            margin-bottom: 16px;
        }
        .scene-box {
            background: #181822;
            border-radius: 24px;
            padding: 18px 16px;
            flex: 1;
            min-height: 300px;
            border: 1px solid #2b2b3a;
            display: flex;
            flex-direction: column;
        }
        .scene-text {
            color: #e8e8f0;
            font-size: 15px;
            line-height: 1.7;
            white-space: pre-wrap;
            word-break: break-word;
            flex: 1;
        }
        .scene-text .highlight {
            color: #b8a5ff;
            font-weight: 500;
        }
        .scene-text .system {
            color: #7a8aaa;
            font-size: 13px;
        }
        .options {
            margin-top: 20px;
            display: flex;
            flex-direction: column;
            gap: 10px;
        }
        .option-btn {
            background: #252536;
            border: 1px solid #3a3a52;
            border-radius: 40px;
            padding: 14px 18px;
            color: #d0d0e8;
            font-size: 15px;
            font-weight: 500;
            text-align: left;
            cursor: pointer;
            transition: 0.2s;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        .option-btn:active {
            background: #3a3a5a;
            transform: scale(0.97);
        }
        .option-btn .key {
            background: #3d3d5a;
            border-radius: 30px;
            padding: 2px 14px;
            font-size: 13px;
            color: #b0b0d0;
        }
        .option-btn .label {
            flex: 1;
        }
        .reset-area {
            margin-top: 16px;
            display: flex;
            gap: 10px;
        }
        .reset-btn {
            background: #2a2a3e;
            border: none;
            padding: 10px 20px;
            border-radius: 40px;
            color: #b0b0c8;
            font-size: 14px;
            cursor: pointer;
            flex: 1;
            text-align: center;
        }
        .reset-btn:active {
            background: #3d3d58;
        }
        .member-tag {
            display: inline-block;
            background: #2f2f4a;
            padding: 2px 16px;
            border-radius: 30px;
            font-size: 13px;
            color: #c8c8e8;
            margin-bottom: 8px;
        }
        .hidden {
            display: none !important;
        }
        .flex-center {
            display: flex;
            justify-content: center;
            align-items: center;
            gap: 10px;
        }
    </style>
</head>
<body>
<div class="app" id="app">
    <div class="status">
        <span>📍 岳城 · JYJZ</span>
        <span id="memberDisplay">🎭 未选择</span>
    </div>

    <div class="scene-box" id="sceneBox">
        <div class="scene-text" id="sceneText">
            <span class="system">▶ 欢迎来到《Monday爱豆生活》</span>
            <br><br>
            请选择你要扮演的成员,开始你的偶像人生。
        </div>
        <div class="options" id="optionsContainer">
            <!-- 动态生成选项 -->
        </div>
    </div>

    <div class="reset-area">
        <button class="reset-btn" id="resetBtn">⟳ 重新开始</button>
        <button class="reset-btn" id="statusBtn" style="flex:0.6;">📊 数值</button>
    </div>
</div>

<script>
    // ============================================================
    //  核心:角色扮演叙事引擎
    //  每个场景 = { id, text, options: [ { label, next, effect? } ] }
    //  玩家选择后推进剧情,数值变化,触发分支。
    // ============================================================

    // ---------- 全局状态 ----------
    let state = {
        member: null,          // '季灿' | '余升' | '纪澜沅' | '祝舟'
        scene: 'start',
        // 数值 (简版)
        popularity: 50,
        pressure: 20,
        blackScore: 5,
        loveProgress: 0,      // 对官配CP的好感度
        groupIntimacy: 40,
        week: 1,
        // 标记
        flags: {}
    };

    // ---------- 场景库 ----------
    const scenes = {};

    // ----- 初始选择 -----
    scenes.start = {
        id: 'start',
        text: `【岳城 · JYJZ 练习生大楼】
        你站在公司门口,手里握着练习生合约。
        今天是决定命运的一天——你要以谁的身份,踏入这条偶像之路?

        ${state.member ? `当前已选:${state.member}` : '选择你的角色:'}`,
        options: [
            { label: '🐱 季灿 (Dawn) · 队长/门面', next: 'intro_jican' },
            { label: '🐏 余升 (Yooseung) · 主舞/ACE', next: 'intro_yusheng' },
            { label: '🐹 纪澜沅 (Reawon) · 主唱/综艺', next: 'intro_jilanyuan' },
            { label: '🦊 祝舟 (Poison) · 主Rap/忙内', next: 'intro_zhuzhou' }
        ]
    };

    // ----- 成员专属导入 -----
    scenes.intro_jican = {
        id: 'intro_jican',
        text: `【季灿 · 06年 水瓶座】
        你叫季灿,艺名Dawn,是团里的大哥。
        家里对你当练习生一直反对,但你倔强地来了。
        高中同学纪澜沅也在这里——你没想到他也通过了面试。

        “喂,你也来了?” 纪澜沅笑着拍你肩膀。

        🎯 当前官配CP:季灿 × 纪澜沅 (灿澜)`,
        options: [
            { label: '“嗯,一起加油吧。” (温和回应)', next: 'common_practice', effect: () => { state.loveProgress += 5; } },
            { label: '“别跟我套近乎。” (嘴硬傲娇)', next: 'common_practice', effect: () => { state.loveProgress += 2; state.pressure += 5; } },
        ]
    };
    scenes.intro_yusheng = {
        id: 'intro_yusheng',
        text: `【余升 · 06年 处女座】
        你叫余升,艺名Yooseung,团里的二哥。
        家里父亲酗酒,母亲卧病,你为了赚药钱被星探发现。
        你总是照顾别人,却很少被人照顾。

        练习室里,祝舟正对着镜子练Rap,你递过去一瓶水。
        “……谢了。”他接过去,没看你。

        🎯 当前官配CP:余升 × 祝舟 (升舟)`,
        options: [
            { label: '“别太拼,注意身体。” (温柔关心)', next: 'common_practice', effect: () => { state.loveProgress += 5; } },
            { label: '“下次别让我等。” (暗爽闷骚)', next: 'common_practice', effect: () => { state.loveProgress += 3; } },
        ]
    };
    scenes.intro_jilanyuan = {
        id: 'intro_jilanyuan',
        text: `【纪澜沅 · 07年 射手座】
        你叫纪澜沅,艺名Reawon,团里的三哥。
        你陪高中同学季灿来面试,结果自己也被选上了。
        你性格开朗自来熟,很快就和所有人打成一片。

        季灿站在走廊尽头,你冲他喊:“季灿!晚上一起吃饭?”
        他别过脸去:“……随便。”

        🎯 当前官配CP:季灿 × 纪澜沅 (灿澜)`,
        options: [
            { label: '“那就这么定了!” (热情主动)', next: 'common_practice', effect: () => { state.loveProgress += 5; } },
            { label: '“你脸红什么?” (逗他)', next: 'common_practice', effect: () => { state.loveProgress += 4; state.pressure += 3; } },
        ]
    };
    scenes.intro_zhuzhou = {
        id: 'intro_zhuzhou',
        text: `【祝舟 · 08年 水瓶座】
        你叫祝舟,艺名Poison,团里最小的忙内。
        家里有钱但关系冷淡,你和父母吵架后离家出走。
        被星探骗来公司,结果真的当了练习生。

        余升递给你一瓶水,你接过没看他。
        “……别管我。”你低声说。

        🎯 当前官配CP:余升 × 祝舟 (升舟)`,
        options: [
            { label: '“……谢谢。” (别扭但接受)', next: 'common_practice', effect: () => { state.loveProgress += 5; } },
            { label: '“我不需要你照顾。” (嘴硬)', next: 'common_practice', effect: () => { state.loveProgress += 2; state.pressure += 5; } },
        ]
    };

    // ----- 通用练习生阶段 -----
    scenes.common_practice = {
        id: 'common_practice',
        text: `【练习生日常 · 第${() => state.week}周】
        你和其他成员一起在练习室挥汗如雨。
        月末评价临近,每个人都绷紧了神经。

        ${state.member},你现在的状态:
        · 人气 ${state.popularity}  · 压力 ${state.pressure}
        · 黑粉值 ${state.blackScore}  · 团体亲密度 ${state.groupIntimacy}

        今天你打算怎么做?`,
        options: [
            { label: '💪 加练到深夜 (提升实力,压力上升)', next: 'event_night', effect: () => { state.pressure += 10; state.popularity += 3; } },
            { label: '🍵 和成员们一起点外卖 (提升亲密度)', next: 'event_eat', effect: () => { state.groupIntimacy += 8; state.popularity += 2; } },
            { label: '📱 偷偷刷SNS看看舆论 (了解粉圈)', next: 'event_sns', effect: () => { state.blackScore += 2; state.pressure += 5; } },
            { label: '💬 找官配CP单独聊聊 (感情线)', next: 'event_cp', effect: () => { state.loveProgress += 8; } },
        ]
    };

    // ----- 事件分支 -----
    scenes.event_night = {
        id: 'event_night',
        text: `【深夜练习室】
        你一个人留在练习室,镜子里映出疲惫但坚定的脸。
        突然,门被推开——

        ${state.member === '季灿' || state.member === '纪澜沅' ? '纪澜沅' : '余升'} 端着两杯热牛奶走进来。
        “就知道你还在。” 他/她把牛奶放在你手边。

        💡 压力 +10,人气 +3
        ❤️ 官配好感度小幅上升`,
        options: [
            { label: '“谢了。” (默默喝掉)', next: 'common_practice', effect: () => { state.loveProgress += 3; } },
            { label: '“你也还没睡?” (聊起来)', next: 'common_practice', effect: () => { state.loveProgress += 5; state.groupIntimacy += 3; } },
        ]
    };
    scenes.event_eat = {
        id: 'event_eat',
        text: `【宿舍客厅】
        你们四个人围坐在一起吃炸鸡。
        祝舟难得没有摆臭脸,余升笑着给他递纸巾。
        季灿和纪澜沅在旁边斗嘴。

        “你吃的是我的鸡腿!”
        “写你名字了?”

        💛 团体亲密度 +8,人气 +2`,
        options: [
            { label: '加入斗嘴 (活跃气氛)', next: 'common_practice', effect: () => { state.groupIntimacy += 5; } },
            { label: '安静看着他们 (微笑)', next: 'common_practice', effect: () => { state.loveProgress += 2; } },
        ]
    };
    scenes.event_sns = {
        id: 'event_sns',
        text: `【SNS 舆论】
        你刷到了关于自己的帖子——
        “${state.member} 是不是资源咖啊?空降出道位?”
        评论区吵成一片。

        ⚠️ 黑粉值 +2,压力 +5

        你要怎么回应?`,
        options: [
            { label: '无视,继续努力 (隐忍)', next: 'common_practice', effect: () => { state.pressure += 3; } },
            { label: '发一条隐晦的微博反击 (争议)', next: 'common_practice', effect: () => { state.blackScore += 5; state.popularity += 5; } },
        ]
    };
    scenes.event_cp = {
        id: 'event_cp',
        text: `【天台 · 黄昏】
        你约了官配CP单独见面。
        ${state.member === '季灿' || state.member === '纪澜沅' ? '纪澜沅' : '余升'} 靠在栏杆上,风吹乱头发。

        “叫我来干嘛?”
        “……就想跟你待一会儿。”

        ❤️ 官配好感度 +8

        这一刻,心跳有点快。`,
        options: [
            { label: '“走吧,回去练习了。” (克制)', next: 'common_practice', effect: () => { state.loveProgress += 3; } },
            { label: '“你头发乱了。” (伸手整理)', next: 'common_practice', effect: () => { state.loveProgress += 8; state.popularity += 3; } },
        ]
    };

    // ---------- 渲染引擎 ----------
    function render() {
        const sceneId = state.scene;
        const scene = scenes[sceneId];
        if (!scene) {
            document.getElementById('sceneText').innerHTML = `<span class="system">⚠️ 剧情加载错误,请重新开始。</span>`;
            document.getElementById('optionsContainer').innerHTML = '';
            return;
        }

        // 更新成员显示
        document.getElementById('memberDisplay').textContent = state.member ? `🎭 ${state.member}` : '🎭 未选择';

        // 处理动态文本中的函数
        let text = scene.text;
        if (typeof text === 'function') text = text();

        // 渲染文本
        document.getElementById('sceneText').innerHTML = text.replace(/\n/g, '<br>');

        // 渲染选项
        const container = document.getElementById('optionsContainer');
        container.innerHTML = '';
        scene.options.forEach((opt, index) => {
            const btn = document.createElement('div');
            btn.className = 'option-btn';
            // 判断是否可用 (简单条件)
            const isAvailable = true;
            if (!isAvailable) {
                btn.style.opacity = '0.4';
                btn.style.pointerEvents = 'none';
            }
            const keyMap = ['①', '②', '③', '④'];
            btn.innerHTML = `
                <span class="key">${keyMap[index] || '·'}</span>
                <span class="label">${opt.label}</span>
            `;
            btn.addEventListener('click', () => {
                // 执行效果
                if (opt.effect) opt.effect();
                // 跳转
                if (opt.next) {
                    state.scene = opt.next;
                    // 自动推进周次(简易)
                    if (state.scene === 'common_practice') state.week += 1;
                    render();
                }
            });
            container.appendChild(btn);
        });
    }

    // ---------- 重置 ----------
    function resetGame() {
        state = {
            member: null,
            scene: 'start',
            popularity: 50,
            pressure: 20,
            blackScore: 5,
            loveProgress: 0,
            groupIntimacy: 40,
            week: 1,
            flags: {}
        };
        // 重置成员选择
        render();
    }

    // ---------- 数值查看 (简单弹窗) ----------
    function showStatus() {
        alert(
            `📊 ${state.member || '未选择'} 的当前数值\n` +
            `━━━━━━━━━━━━━━\n` +
            `❤️ 官配好感度 : ${state.loveProgress}\n` +
            `👥 团体亲密度 : ${state.groupIntimacy}\n` +
            `🔥 人气值      : ${state.popularity}\n` +
            `😰 压力值      : ${state.pressure}\n` +
            `🖤 黑粉值      : ${state.blackScore}\n` +
            `📆 当前周次    : 第 ${state.week} 周\n` +
            `━━━━━━━━━━━━━━\n` +
            `💡 压力过高可能触发负面事件!`
        );
    }

    // ---------- 初始化 ----------
    document.getElementById('resetBtn').addEventListener('click', resetGame);
    document.getElementById('statusBtn').addEventListener('click', showStatus);

    // 首次渲染
    resetGame();
</script>
</body>
</html>

Game Source: Monday爱豆生活 · 角色扮演

Creator: ThunderPenguin58

Libraries: none

Complexity: complex (452 lines, 16.5 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: monday-thunderpenguin58-mskwfvaz" to link back to the original. Then publish at arcadelab.ai/publish.