🎮ArcadeLab

ENHYPEN · 大学ABO · 结缘寻雨

by BlazeStar26
415 lines18.7 KB
▶ Play
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=yes">
    <title>ENHYPEN · 大学ABO · 结缘寻雨</title>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }
        body {
            background: #f7f3ee;
            font-family: 'Segoe UI', 'Helvetica Neue', sans-serif;
            color: #2d2a24;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            padding: 16px;
        }
        .game-container {
            max-width: 600px;
            width: 100%;
            background: #fffaf7;
            border-radius: 32px;
            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.08), 0 8px 16px rgba(0, 0, 0, 0.06);
            overflow: hidden;
            padding: 24px 20px 28px;
            transition: all 0.2s;
            border: 1px solid #ede6df;
        }
        h1 {
            font-size: 22px;
            font-weight: 600;
            letter-spacing: 1px;
            color: #3a2e28;
            text-align: center;
            margin-bottom: 6px;
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 8px;
        }
        .subhead {
            text-align: center;
            font-size: 13px;
            color: #8e7b6e;
            border-bottom: 1px dashed #e0d6ce;
            padding-bottom: 16px;
            margin-bottom: 16px;
            letter-spacing: 0.3px;
        }
        .character-grid {
            display: flex;
            flex-wrap: wrap;
            gap: 8px;
            justify-content: center;
            margin-bottom: 18px;
        }
        .char-tag {
            background: #eee7e1;
            border-radius: 40px;
            padding: 6px 14px;
            font-size: 12px;
            font-weight: 500;
            color: #4d3e35;
            border: 1px solid #ddd2c9;
            transition: all 0.15s;
            cursor: default;
        }
        .char-tag.active {
            background: #dacfc6;
            border-color: #b8a69a;
            color: #1f1a16;
        }
        .story-screen {
            background: #fcf8f5;
            border-radius: 20px;
            padding: 18px 16px 12px;
            min-height: 200px;
            border: 1px solid #e8dfd8;
            box-shadow: inset 0 2px 4px rgba(0,0,0,0.02);
            margin-bottom: 18px;
        }
        .story-text {
            font-size: 15px;
            line-height: 1.6;
            color: #2e2822;
            white-space: pre-wrap;
            word-break: break-word;
        }
        .story-text .highlight {
            color: #b45f3b;
            font-weight: 500;
        }
        .story-text .muted {
            color: #7a6b5f;
            font-size: 14px;
        }
        .story-text .tag {
            display: inline-block;
            background: #e3d9d0;
            border-radius: 12px;
            padding: 0 10px;
            font-size: 12px;
            color: #3d332b;
            margin-right: 4px;
        }
        .choices {
            display: flex;
            flex-direction: column;
            gap: 10px;
            margin-top: 12px;
        }
        .choice-btn {
            background: #f3ede8;
            border: 1px solid #ddd2c9;
            border-radius: 40px;
            padding: 12px 18px;
            font-size: 15px;
            font-weight: 500;
            color: #2d2620;
            text-align: left;
            transition: all 0.15s;
            cursor: pointer;
            box-shadow: 0 2px 4px rgba(0,0,0,0.02);
            line-height: 1.4;
        }
        .choice-btn:hover, .choice-btn:active {
            background: #e5d9d0;
            border-color: #b8a396;
            transform: scale(0.99);
        }
        .choice-btn:disabled {
            opacity: 0.5;
            pointer-events: none;
            filter: grayscale(0.3);
        }
        .info-bar {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-top: 14px;
            font-size: 13px;
            color: #7a6b5f;
            border-top: 1px solid #ede6df;
            padding-top: 14px;
        }
        .info-bar span {
            background: #f3ede8;
            padding: 4px 14px;
            border-radius: 30px;
            border: 1px solid #e0d6ce;
        }
        .reset-btn {
            background: none;
            border: 1px solid #d5c8be;
            border-radius: 30px;
            padding: 6px 18px;
            font-size: 13px;
            color: #5b4d42;
            cursor: pointer;
            transition: 0.1s;
        }
        .reset-btn:hover {
            background: #e8dfd8;
        }
        .footer-note {
            text-align: center;
            font-size: 12px;
            color: #b3a397;
            margin-top: 12px;
            letter-spacing: 0.2px;
        }
        .badge {
            background: #dacfc6;
            border-radius: 30px;
            padding: 2px 12px;
            font-size: 11px;
            font-weight: 600;
            color: #3f332b;
            display: inline-block;
        }
        @media (max-width: 480px) {
            .game-container { padding: 18px 14px; }
            .story-text { font-size: 14px; }
            .choice-btn { font-size: 14px; padding: 10px 14px; }
        }
    </style>
</head>
<body>
<div class="game-container" id="app">
    <h1>🌸 ENHYPEN · 大学ABO</h1>
    <div class="subhead">结缘 · 寻雨 · 破镜重圆 · 双向暗恋 · 欢喜冤家</div>

    <!-- 角色标签 -->
    <div class="character-grid">
        <span class="char-tag active">🐕 载伦</span>
        <span class="char-tag active">🐈 羲承</span>
        <span class="char-tag active">🐈‍⬛ 知妤</span>
        <span class="char-tag active">🔥 综星</span>
        <span class="char-tag active">🐱 祯元</span>
        <span class="char-tag active">❄️ 成训</span>
        <span class="char-tag active">🍑 善禹</span>
        <span class="char-tag active">🦊 西村力</span>
    </div>

    <!-- 剧情展示 -->
    <div class="story-screen" id="storyScreen">
        <div class="story-text" id="storyText">
            <span class="tag">📖 序章</span><br>
            大二上学期,校园的银杏开始泛黄。<br>
            沈载伦从澳洲转学来的第一天,就在音乐系楼下看见了那个瘦削的背影。<br>
            他追上去,却听见电话里传来一声软糯的“妈妈”。<br>
            ——那是李羲承,和他分开两年的前男友,独自抚养着他们的女儿。
        </div>
    </div>

    <!-- 选项区 -->
    <div class="choices" id="choicesContainer">
        <button class="choice-btn" data-choice="0">💔 主CP · 破镜重圆 · 带球跑</button>
        <button class="choice-btn" data-choice="1">🔥 朴综星 × 梁祯元 · 双向暗恋</button>
        <button class="choice-btn" data-choice="2">❄️ 朴成训 × 金善禹 · 欢喜冤家</button>
        <button class="choice-btn" data-choice="3">🦊 西村力 · 旁观者清</button>
    </div>

    <!-- 信息栏 -->
    <div class="info-bar">
        <span id="sceneLabel">🏷️ 结缘 · 重逢</span>
        <button class="reset-btn" id="resetBtn">↺ 重置</button>
    </div>
    <div class="footer-note">点击选项展开剧情 · 每个选择揭示不同CP的片段</div>
</div>

<script>
    (function() {
        // ---------- 角色/剧情数据库 ----------
        const STORIES = {
            // 主CP ① 沈载伦 × 李羲承
            cp1: [
                {
                    label: '💔 破镜重圆 · 重逢',
                    text: `【沈载伦 × 李羲承】\n\n载伦转学第一天,在校园里认出了羲承的背影。\n他追了三条街,看见羲承从幼儿园接走一个孩子——\n那个孩子,和他长得太像了。\n\n“你问过我吗?你问过我愿不愿意吗?”\n载伦的声音在发抖。\n羲承没有回头,只是把知妤抱得更紧了一些。\n\n<span class="muted">——终身标记的齿痕还留在后颈,那是他两年来从未触碰的伤疤。</span>`
                },
                {
                    label: '🍼 李知妤 · 爸爸?',
                    text: `【李知妤 · 2岁】\n\n“妈咪!”知妤指着载伦,歪着脑袋。\n羲承蹲下来,轻声说:“知妤,叫……叔叔。”\n\n知妤盯着载伦看了很久,忽然伸手抓住他的手指。\n“……par……pa?”\n\n载伦的眼泪瞬间掉了下来。\n羲承别过脸,指甲掐进掌心。\n\n<span class="muted">——那个被他藏在中间的名字,终于有人叫了出来。</span>`
                },
                {
                    label: '🌊 终身标记 · 夜话',
                    text: `【终身标记 · 两年后】\n\n夜深了,知妤睡着后,羲承在厨房热牛奶。\n载伦靠在门框上,声音沙哑:\n“为什么不告诉我?”\n\n“告诉你什么?”羲承没有转身,“告诉你之后呢?你回澳洲,我留下来,然后呢?”\n\n“然后我留下。”载伦走近,“我留下,你留下,我们三个人一起。”\n\n羲承的手顿住了。\n牛奶溢出来,烫红了指尖。`
                }
            ],
            // 主CP ② 朴综星 × 梁祯元
            cp2: [
                {
                    label: '🔥 双向暗恋 · 初雪',
                    text: `【朴综星 × 梁祯元】\n\n初雪那天,综星和祯元一起去买鲫鱼饼。\n祯元呼着白气说:“哥,你最近总是和我一起吃饭。”\n\n综星别过脸:“……刚好路过。”\n祯元低头笑,酒窝若隐若现:“那……下次也一起吧。”\n\n两个人并肩走在雪里,谁都没有说出口。\n但彼此都知道,那是什么意思。\n\n<span class="muted">——所有人都看得出来,只有他们自己觉得藏得很好。</span>`
                },
                {
                    label: '🎧 守护天使 · 直播',
                    text: `【守护天使 · 直播后】\n\n祯元在wvs直播,综星留言:“今天跳舞辛苦了。”\n祯元念出来,笑着说:“jay哥来了?要不要来我房间?”\n\n综星秒回:“忙着呢。”\n但三分钟后,他端着热巧克力出现在祯元门口。\n\n“你不是说忙着吗?”祯元眼睛弯弯。\n“……刚好路过便利店。”综星的耳朵红了。`
                },
                {
                    label: '🌙 不敢开口的推拉',
                    text: `【互相觉得对方不可能喜欢自己】\n\n综星对祯元好:默默做,不解释。\n祯元对综星好:默默做,也不解释。\n\n“jay哥今天穿了白色——好看。”\n祯元说完就跑,综星在原地愣了三秒。\n\n“……他说好看。”综星对着手机自言自语。\n然后他把那件白色卫衣穿了一整个星期。`
                }
            ],
            // 主CP ③ 朴成训 × 金善禹
            cp3: [
                {
                    label: '❄️ 欢喜冤家 · 最烦的人',
                    text: `【朴成训 × 金善禹】\n\n“金善禹你能不能安静点。”\n“朴成训你能不能多说点话。”\n\n善禹做搞怪表情,成训一脸嫌弃,但眼睛一直在看。\n善禹撒娇说“哥帮我拿一下”,成训嘴上说“烦死了”,手已经伸了过去。\n\n所有人都知道成训对善禹不一样。\n只有成训不承认。\n\n<span class="muted">——最烦的人,也是最先想到的人。</span>`
                },
                {
                    label: '⛸️ 花滑 · 偷偷来看',
                    text: `【花滑比赛 · 偷偷来看】\n\n成训在冰场上旋转,余光瞥见最后一排有个熟悉的身影。\n善禹戴着帽子,缩在角落,手里举着应援牌。\n\n“不是说今天有课吗?”成训赛后发消息。\n“路过而已……你滑得还行吧。”善禹秒回。\n\n成训盯着屏幕笑了。\n——那是他第一次在比赛后笑。`
                },
                {
                    label: '🍑 易感期 · 热可可',
                    text: `【易感期 · 热可可】\n\n成训易感期到了,把自己关在练习室。\n善禹推开门,把热可可放在他手边。\n\n“我只是路过。”善禹说。\n“你每次都路过。”成训的声音有点哑。\n\n善禹没说话,坐在他旁边。\n两个人沉默地喝完了一杯热可可。\n\n——从那天起,成训的易感期变得没那么难熬了。`
                }
            ],
            // 副线 西村力
            cp4: [
                {
                    label: '🦊 西村力 · 旁观者清',
                    text: `【西村力 · 稳定器】\n\n“哥,你们不累吗……算了当我没问。”\n\n作为Beta,西村力闻不到信息素,却把三对CP的推拉看得最清楚。\n成训和善禹吵架时,他在旁边默默递水。\n综星和祯元互相偷看时,他假装没看见。\n\n“尼叔叔!”知妤张开手。\n西村力把知妤抱起来,叹了口气:\n“你比他们省心多了。”\n\n<span class="muted">——不靠信息素,也能建立深刻的连接。</span>`
                },
                {
                    label: '💃 舞蹈 · 专注',
                    text: `【舞蹈练习室 · 专注】\n\n西村力一个人练到深夜。\n祯元路过,敲了敲门:“还不回去?”\n\n“哥你先走吧,我再练一会儿。”\n西村力擦了擦汗,继续对着镜子抠动作。\n\n他的世界很简单:舞蹈、舞台、还有这些烦人的哥哥们。\n——虽然他们真的很烦,但他从来没想过要离开。`
                }
            ]
        };

        // ---------- 状态 ----------
        let currentCp = 'cp1';        // cp1 / cp2 / cp3 / cp4
        let currentIndex = 0;         // 当前cp下的剧情索引
        let history = [];            // 简单记录

        const storyTextEl = document.getElementById('storyText');
        const sceneLabelEl = document.getElementById('sceneLabel');
        const choicesContainer = document.getElementById('choicesContainer');
        const resetBtn = document.getElementById('resetBtn');

        // 渲染剧情
        function renderStory() {
            const cpData = STORIES[currentCp];
            if (!cpData || cpData.length === 0) {
                storyTextEl.innerHTML = '💭 故事还在酝酿中……';
                return;
            }
            // 循环索引
            if (currentIndex >= cpData.length) currentIndex = 0;
            const entry = cpData[currentIndex];
            storyTextEl.innerHTML = entry.text;
            sceneLabelEl.textContent = `🏷️ ${entry.label}`;
        }

        // 更新选项按钮(根据当前cp显示不同的选项组合)
        function updateChoices() {
            // 清除所有按钮
            while (choicesContainer.firstChild) {
                choicesContainer.removeChild(choicesContainer.firstChild);
            }

            // 根据 currentCp 构建选项
            const choiceMap = {
                'cp1': [
                    { label: '💔 破镜重圆 · 重逢', value: 'cp1', index: 0 },
                    { label: '🍼 李知妤 · 爸爸?', value: 'cp1', index: 1 },
                    { label: '🌊 终身标记 · 夜话', value: 'cp1', index: 2 },
                ],
                'cp2': [
                    { label: '🔥 双向暗恋 · 初雪', value: 'cp2', index: 0 },
                    { label: '🎧 守护天使 · 直播', value: 'cp2', index: 1 },
                    { label: '🌙 不敢开口的推拉', value: 'cp2', index: 2 },
                ],
                'cp3': [
                    { label: '❄️ 欢喜冤家 · 最烦的人', value: 'cp3', index: 0 },
                    { label: '⛸️ 花滑 · 偷偷来看', value: 'cp3', index: 1 },
                    { label: '🍑 易感期 · 热可可', value: 'cp3', index: 2 },
                ],
                'cp4': [
                    { label: '🦊 西村力 · 旁观者清', value: 'cp4', index: 0 },
                    { label: '💃 舞蹈 · 专注', value: 'cp4', index: 1 },
                ]
            };

            const options = choiceMap[currentCp] || choiceMap['cp1'];
            options.forEach(opt => {
                const btn = document.createElement('button');
                btn.className = 'choice-btn';
                btn.textContent = opt.label;
                btn.dataset.cp = opt.value;
                btn.dataset.index = opt.index;
                btn.addEventListener('click', function(e) {
                    const cp = this.dataset.cp;
                    const idx = parseInt(this.dataset.index, 10);
                    if (cp && !isNaN(idx)) {
                        currentCp = cp;
                        currentIndex = idx;
                        renderStory();
                        updateChoices(); // 刷新选项高亮
                        // 高亮当前选项(简单处理:滚动到顶部)
                        window.scrollTo({ top: 0, behavior: 'smooth' });
                    }
                });
                choicesContainer.appendChild(btn);
            });

            // 添加一个"随机"彩蛋选项 (额外)
            const extraBtn = document.createElement('button');
            extraBtn.className = 'choice-btn';
            extraBtn.textContent = '🎲 随机片段 · 全员混剪';
            extraBtn.addEventListener('click', function() {
                // 随机选择一个cp和片段
                const cpKeys = ['cp1', 'cp2', 'cp3', 'cp4'];
                const randomCp = cpKeys[Math.floor(Math.random() * cpKeys.length)];
                const cpData = STORIES[randomCp];
                if (cpData && cpData.length > 0) {
                    const randomIdx = Math.floor(Math.random() * cpData.length);
                    currentCp = randomCp;
                    currentIndex = randomIdx;
                    renderStory();
                    updateChoices();
                }
            });
            choicesContainer.appendChild(extraBtn);
        }

        // 重置到默认 (主CP 重逢)
        function resetToDefault() {
            currentCp = 'cp1';
            currentIndex = 0;
            renderStory();
            updateChoices();
        }

        // 初始化
        resetBtn.addEventListener('click', resetToDefault);

        // 额外:点击故事区域也可随机(但保留,不需要)
        // 启动
        resetToDefault();

        // 监听窗口 resize 无额外操作
        console.log('🌸 ENHYPEN ABO 视觉小说已加载');
    })();
</script>
</body>
</html>

Game Source: ENHYPEN · 大学ABO · 结缘寻雨

Creator: BlazeStar26

Libraries: none

Complexity: complex (415 lines, 18.7 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: enhypen-abo-blazestar26-mr9gkjt1" to link back to the original. Then publish at arcadelab.ai/publish.