月影·妖宴 — ENHYPEN 同人
by BlazeStar26704 lines27.3 KB
```html
<!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=no" />
<title>月影·妖宴 — ENHYPEN 同人</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;700;900&display=swap');
:root {
--bg: #0b0808;
--card: #1a1212;
--border: #3d2222;
--gold: #c89b6b;
--gold-dim: #8a6a44;
--text: #eeddcc;
--text-dim: #aa8877;
--red: #b34a4a;
--shadow: rgba(180, 80, 80, 0.15);
}
body {
background: var(--bg);
color: var(--text);
font-family: 'Noto Serif SC', 'Times New Roman', serif;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 16px;
background-image: radial-gradient(ellipse at 30% 20%, #1f0f0f 0%, #0b0808 70%);
}
#app {
width: 100%;
max-width: 520px;
margin: 0 auto;
position: relative;
}
.container {
background: var(--card);
border: 1px solid var(--border);
border-radius: 28px;
padding: 28px 24px 24px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.8), inset 0 0 80px rgba(80, 30, 30, 0.08);
backdrop-filter: blur(4px);
min-height: 520px;
display: flex;
flex-direction: column;
transition: opacity 0.3s ease;
position: relative;
}
/* 装饰线 */
.container::before {
content: '';
position: absolute;
top: -1px;
left: 30%;
right: 30%;
height: 2px;
background: linear-gradient(90deg, transparent, var(--gold), transparent);
opacity: 0.4;
}
/* 标题区 */
.header {
text-align: center;
padding-bottom: 16px;
border-bottom: 1px solid rgba(200, 155, 107, 0.15);
margin-bottom: 18px;
flex-shrink: 0;
}
.header .title {
font-size: 20px;
font-weight: 900;
letter-spacing: 6px;
color: var(--gold);
text-shadow: 0 0 30px rgba(200, 155, 107, 0.1);
}
.header .sub {
font-size: 12px;
color: var(--text-dim);
letter-spacing: 2px;
margin-top: 4px;
}
.header .chapter-tag {
display: inline-block;
margin-top: 8px;
font-size: 11px;
background: rgba(200, 155, 107, 0.12);
border: 1px solid rgba(200, 155, 107, 0.2);
padding: 2px 16px;
border-radius: 20px;
color: var(--gold-dim);
letter-spacing: 1px;
}
/* 内容区 */
.content {
flex: 1;
padding: 8px 0 16px;
min-height: 200px;
display: flex;
flex-direction: column;
gap: 12px;
}
.story-text {
font-size: 15px;
line-height: 1.9;
color: var(--text);
white-space: pre-wrap;
word-break: break-word;
letter-spacing: 0.4px;
}
.story-text .highlight {
color: var(--gold);
font-weight: 700;
}
.story-text .red {
color: var(--red);
}
.story-text .dim {
color: var(--text-dim);
font-size: 13px;
}
.story-text .italic {
font-style: italic;
color: var(--gold-dim);
}
/* 角色标签 */
.char-label {
display: inline-block;
font-size: 12px;
font-weight: 700;
color: var(--gold);
background: rgba(200, 155, 107, 0.08);
border-left: 2px solid var(--gold);
padding: 2px 12px 2px 10px;
border-radius: 0 12px 12px 0;
margin-bottom: 6px;
letter-spacing: 1px;
}
/* 选项区 */
.choices {
display: flex;
flex-direction: column;
gap: 10px;
margin-top: 12px;
padding-top: 14px;
border-top: 1px solid rgba(200, 155, 107, 0.08);
flex-shrink: 0;
}
.choice-btn {
background: rgba(200, 155, 107, 0.04);
border: 1px solid rgba(200, 155, 107, 0.15);
border-radius: 16px;
padding: 14px 18px;
color: var(--text);
font-size: 14px;
font-family: inherit;
cursor: pointer;
transition: all 0.25s ease;
text-align: left;
letter-spacing: 0.4px;
line-height: 1.4;
position: relative;
overflow: hidden;
}
.choice-btn:hover {
background: rgba(200, 155, 107, 0.08);
border-color: var(--gold-dim);
transform: translateX(4px);
box-shadow: 0 0 30px rgba(200, 155, 107, 0.03);
}
.choice-btn:active {
transform: scale(0.97);
}
.choice-btn .label {
display: inline-block;
font-size: 11px;
color: var(--gold-dim);
margin-right: 10px;
font-weight: 700;
}
/* 结局特殊样式 */
.ending-badge {
text-align: center;
font-size: 13px;
color: var(--gold);
letter-spacing: 4px;
padding: 12px 0;
border-top: 1px solid rgba(200, 155, 107, 0.1);
border-bottom: 1px solid rgba(200, 155, 107, 0.1);
margin: 8px 0;
}
/* 底部 */
.footer {
margin-top: 14px;
text-align: center;
font-size: 10px;
color: var(--text-dim);
opacity: 0.4;
letter-spacing: 1px;
flex-shrink: 0;
}
/* 滚动 */
.scroll-area {
max-height: 440px;
overflow-y: auto;
padding-right: 4px;
}
.scroll-area::-webkit-scrollbar {
width: 3px;
}
.scroll-area::-webkit-scrollbar-track {
background: transparent;
}
.scroll-area::-webkit-scrollbar-thumb {
background: var(--gold-dim);
border-radius: 10px;
}
/* 动画 */
.fade-in {
animation: fadeIn 0.45s ease forwards;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(12px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 响应式 */
@media (max-width: 460px) {
.container {
padding: 20px 16px 18px;
border-radius: 20px;
}
.story-text {
font-size: 14px;
line-height: 1.8;
}
.choice-btn {
padding: 12px 14px;
font-size: 13px;
}
.header .title {
font-size: 17px;
letter-spacing: 4px;
}
}
/* 小标签装饰 */
.ornament {
text-align: center;
font-size: 10px;
color: var(--gold-dim);
opacity: 0.3;
letter-spacing: 8px;
margin: 4px 0;
}
</style>
</head>
<body>
<div id="app">
<div class="container" id="mainContainer">
<!-- header -->
<div class="header">
<div class="title">✦ 月影 · 妖宴 ✦</div>
<div class="sub">— ENHYPEN 同人 | 蛇魅之约 —</div>
<div class="chapter-tag" id="chapterTag">序章</div>
</div>
<!-- content -->
<div class="content scroll-area" id="contentArea">
<div id="storyDisplay" class="story-text fade-in">
<span class="char-label">🐍 月影咖啡馆</span>
雨夜,首尔,大学路尽头。<br />
梁祯元正擦拭着咖啡杯,窗外的雨丝斜斜地划过玻璃。<br />
老板沈载伦瘫在吧台后,一副被吸干了精气的模样。<br />
<span class="dim">“又被那魅魔找上门了?”</span> 祯元头也不抬。<br />
<span class="dim">“别提了……那家伙,上来就骑……”</span> 载伦有气无力。<br />
而此刻,在街角的阴影里,一条黑色的小蛇正蜷缩在积水旁,浑身是伤。<br />
命运的丝线,在雨夜中悄然缠绕。
</div>
<div id="choicesContainer" class="choices">
<!-- 由js动态渲染 -->
</div>
</div>
<div class="ornament">· · ·</div>
<div class="footer">✦ 选择你的命运 ✦</div>
</div>
</div>
<script>
// ============================================================
// 剧情数据 — 包含所有节点、选择、结局
// ============================================================
const STORY = {
// -------- 序章 --------
'prologue': {
id: 'prologue',
tag: '序章 · 雨夜',
char: '🐍 月影咖啡馆',
text: `雨夜,首尔,大学路尽头。
梁祯元正擦拭着咖啡杯,窗外的雨丝斜斜地划过玻璃。
老板沈载伦瘫在吧台后,一副被吸干了精气的模样。
<span class="dim">“又被那魅魔找上门了?”</span> 祯元头也不抬。
<span class="dim">“别提了……那家伙,上来就骑……”</span> 载伦有气无力。
而此刻,在街角的阴影里,一条黑色的小蛇正蜷缩在积水旁,浑身是伤。
命运的丝线,在雨夜中悄然缠绕。
<span class="italic">—— 你选择跟随谁的命运? ——</span>`,
choices: [
{ label: 'A', text: '🐱 梁祯元 · 结缘篇 — 救下小蛇,开启同居', next: 'jieyuan_1' },
{ label: 'B', text: '☕ 沈载伦 · 载伦篇 — 被魅魔缠上的咖啡馆主', next: 'zailun_1' },
{ label: 'C', text: '🦊 金善禹 · 善禹篇 — 跟踪那个叫朴成训的男人', next: 'shanyu_1' }
]
},
// ============================================================
// 结缘篇 — 朴综星 × 梁祯元
// ============================================================
'jieyuan_1': {
id: 'jieyuan_1',
tag: '结缘篇 · 初遇',
char: '🐱 梁祯元',
text: `下班已是深夜,雨小了些。
梁祯元撑伞走过街角,忽然被什么东西绊了一下。
低头一看——是一条黑色的小蛇,鳞片在路灯下泛着幽光,似乎受了伤。
<span class="dim">“……蛇?”</span>
他蹲下身,犹豫片刻,还是轻轻将小蛇捧起。
那蛇微微抬头,琥珀色的竖瞳看了他一眼,便虚弱地垂下。
梁祯元将它揣进怀里,带回了自己的出租屋。
他不知道,这条蛇,是山脚下修炼百年的蛇妖——<span class="highlight">朴综星</span>。`,
choices: [
{ label: 'A', text: '❤️ 悉心照料小蛇', next: 'jieyuan_2' },
{ label: 'B', text: '💭 好奇地观察它的鳞片', next: 'jieyuan_2' }
]
},
'jieyuan_2': {
id: 'jieyuan_2',
tag: '结缘篇 · 同栖',
char: '🐱 梁祯元',
text: `几天后,小蛇恢复了精神,开始在家里游走。
梁祯元给它取名“元宝”,每天下班回来都会跟它说话。
直到那个夜晚,梁祯元洗完澡出来,发现床上躺着一个人——
黑发,琥珀色的眼睛,赤裸的上身,腰间缠着一条蛇尾。
<span class="red">“你……!?”</span>
<span class="highlight">“别怕,我是朴综星。”</span> 他声音低沉,带着山野的凉意。
<span class="highlight">“你救了我,我会报答你。”</span>
梁祯元的脸瞬间红透,他从未见过这样的男人——危险,又莫名地吸引人。`,
choices: [
{ label: 'A', text: '💕 接受他的“报答”', next: 'jieyuan_3' },
{ label: 'B', text: '😳 慌乱地让他穿好衣服', next: 'jieyuan_3' }
]
},
'jieyuan_3': {
id: 'jieyuan_3',
tag: '结缘篇 · 交缠',
char: '🐍 朴综星 × 🐱 梁祯元',
text: `那一夜,朴综星化为人形,将梁祯元压在身下。
蛇妖的体温偏凉,却让祯元浑身发烫。
<span class="dim">“别怕,我会很温柔。”</span> 朴综星吻着他的后颈。
当那两根粗长的性器同时进入时,梁祯元叫出了声——
<span class="red">“啊……!两个……都进来了……”</span>
朴综星低笑,缓缓抽送,前后夹击的快感让祯元几乎失神。
精液灌满了他的小腹,多的从缝隙溢出,淫靡的水声在房间里回荡。
<span class="italic">“太多了……综星……我兜不住了……”</span>
梁祯元羞耻地捂住脸,身体却诚实地绞紧。`,
choices: [
{ label: 'A', text: '🔥 继续深入 — 捅破子宫', next: 'jieyuan_4' },
{ label: 'B', text: '💦 高潮失禁 — 彻底沉沦', next: 'jieyuan_4' }
]
},
'jieyuan_4': {
id: 'jieyuan_4',
tag: '结缘篇 · 深渊',
char: '🐍 朴综星 × 🐱 梁祯元',
text: `朴综星的动作越来越猛,蛇尾缠住祯元的腰,将他钉死在身下。
龟头狠狠顶开宫颈,<span class="red">“噗嗤”</span>一声,整根没入子宫。
<span class="red">“啊啊——!综星……子宫……被捅穿了……!”</span>
梁祯元仰头弓背,淫水混着精液从穴口喷涌而出,床单湿了一大片。
朴综星吻去他眼角的泪,低哑道:<span class="highlight">“怀上我的种吧,祯元。”</span>
此后,梁祯元的肚子一天天大了起来。
他羞耻地发现自己开始泌乳,乳尖又胀又痒。
朴综星每晚都会吮吸他的胸口,将乳汁吞下,然后再次贯穿他。
<span class="italic">“……综星,别吸了……好奇怪……”</span>
<span class="highlight">“甜的,我喜欢。”</span> 蛇妖的竖瞳里满是占有欲。`,
choices: [
{ label: 'A', text: '🤰 孕期play — 肚子越来越大', next: 'jieyuan_5' },
{ label: 'B', text: '🍼 吃奶play — 乳汁横流', next: 'jieyuan_5' }
]
},
'jieyuan_5': {
id: 'jieyuan_5',
tag: '结缘篇 · 终章',
char: '🐍 朴综星 × 🐱 梁祯元',
text: `孕期的梁祯元变得格外敏感,朴综星几乎夜夜都要他。
蛇妖的精液滋养着腹中的胎儿,也让他愈发离不开综星的怀抱。
某个清晨,祯元在综星怀里醒来,感觉小腹微微抽动。
<span class="highlight">“综星……他动了。”</span>
朴综星将手覆上他隆起的腹部,眼中是化不开的温柔。
<span class="gold">—— 结缘 · 生生世世 ——</span>
<span class="dim">“你救了我,我用一生来还。”</span>
<span class="dim">“我才不要你‘还’……我要你永远都在。”</span>
<span class="italic">❤️ 结缘篇 · 圆满 ❤️</span>`,
isEnd: true,
choices: [
{ label: '🔄', text: '重头开始', next: 'prologue' }
]
},
// ============================================================
// 载伦篇 — 沈载伦 × 李羲承
// ============================================================
'zailun_1': {
id: 'zailun_1',
tag: '载伦篇 · 突袭',
char: '☕ 沈载伦',
text: `沈载伦刚关上咖啡馆的门,就被一股力量按在了墙上。
一个红发男人骑在他腰间,眼神凶戾,尾巴在身后甩动。
<span class="red">“你就是沈载伦?”</span>
<span class="dim">“……魅魔?”</span> 载伦懵逼了。
<span class="highlight">“我叫李羲承,你的阳气很香。”</span>
说着,他直接撕开了载伦的衬衫,跨坐上去。
<span class="red">“等等——!这他妈是性侵——!”</span>
但李羲承已经扶着他的性器坐了下去,紧致湿热的内壁瞬间绞紧。
<span class="italic">“……好大……怎么这么……长……”</span>
魅魔咬住下唇,一边骂一边耸动腰肢。
<span class="italic">“你动啊……难受死了……!”</span>
沈载伦两眼一闭,差点享福去了。`,
choices: [
{ label: 'A', text: '😈 反客为主 — 狠狠操他', next: 'zailun_2' },
{ label: 'B', text: '😵 放弃抵抗 — 任由摆布', next: 'zailun_2' }
]
},
'zailun_2': {
id: 'zailun_2',
tag: '载伦篇 · 沉沦',
char: '☕ 沈载伦 × 🦇 李羲承',
text: `沈载伦忍无可忍,翻身将魅魔压在身下。
粗长的性器整根没入,李羲承发出一声惊喘。
<span class="red">“你……!谁让你动的……!”</span>
载伦掐着他的腰猛干,每一下都顶到最深处。
<span class="highlight">“……太大了……要坏掉了……”</span>
魅魔的尾巴缠上载伦的腰,嘴上骂着,身体却诚实地收缩。
那晚之后,李羲承隔三差五就来“拜访”。
每次做完都会晕过去,流着口水,脸上还带着高潮的余韵。
<span class="italic">“……沈载伦……你的尺寸……我很满意……”</span>
魅魔红着脸,小声嘟囔。`,
choices: [
{ label: 'A', text: '💞 接受魅魔的依赖', next: 'zailun_3' },
{ label: 'B', text: '🔥 更加粗暴地占有他', next: 'zailun_3' }
]
},
'zailun_3': {
id: 'zailun_3',
tag: '载伦篇 · 终章',
char: '☕ 沈载伦 × 🦇 李羲承',
text: `李羲承渐渐不再只是来“采补”。
他会赖在咖啡馆不走,趴在吧台上看着载伦做咖啡。
尾巴尖偷偷勾住载伦的手指。
<span class="highlight">“……我好像……有点喜欢你了。”</span>
魅魔别过脸,耳朵尖红透。
沈载伦愣了一下,然后笑了。
<span class="dim">“那就别走了,我的咖啡馆,缺个老板娘。”</span>
<span class="gold">—— 载伦 · 魅惑之恋 ——</span>
<span class="italic">❤️ 载伦篇 · 圆满 ❤️</span>`,
isEnd: true,
choices: [
{ label: '🔄', text: '重头开始', next: 'prologue' }
]
},
// ============================================================
// 善禹篇 — 金善禹 × 朴成训
// ============================================================
'shanyu_1': {
id: 'shanyu_1',
tag: '善禹篇 · 猎物',
char: '🦊 金善禹',
text: `金善禹是只魅魔,但他的业绩惨淡——一个男人的精气都没采到。
直到那天,他在大学门口看到了<span class="highlight">朴成训</span>。
那人穿着白衬衫,清冷如月,光是站在那里就让金善禹腿软。
<span class="italic">“……太他妈帅了……光是看着就好空虚……”</span>
金善禹开始跟踪他,偷拍他的照片。
回到住处,他对着照片自慰,用手指插到自己高潮,却依然不够。
<span class="red">“想要……想要真的……想要他狠狠地贯穿我……”</span>
他决定,一定要勾引朴成训,破了自己的“处子之身”。`,
choices: [
{ label: 'A', text: '📸 继续跟踪偷拍', next: 'shanyu_2' },
{ label: 'B', text: '💋 直接上前搭讪', next: 'shanyu_2' }
]
},
'shanyu_2': {
id: 'shanyu_2',
tag: '善禹篇 · 勾引',
char: '🦊 金善禹 × 🧊 朴成训',
text: `金善禹找了个机会,在朴成训常去的图书馆“偶遇”。
他故意把书掉在地上,弯腰时露出纤细的腰肢和臀缝。
朴成训低头看他,眼神冷淡。
<span class="dim">“……你跟着我很久了。”</span>
金善禹心里一惊,却扬起一个魅惑的笑。
<span class="highlight">“被你发现了……那,要惩罚我吗?”</span>
朴成训沉默片刻,忽然捏住他的下巴。
<span class="red">“魅魔?你身上的味道,藏不住。”</span>
金善禹的心跳几乎停止——他暴露了。`,
choices: [
{ label: 'A', text: '🔥 主动献身 — 求他占有', next: 'shanyu_3' },
{ label: 'B', text: '😨 惊慌逃跑 — 却被抓回', next: 'shanyu_3' }
]
},
'shanyu_3': {
id: 'shanyu_3',
tag: '善禹篇 · 终章',
char: '🦊 金善禹 × 🧊 朴成训',
text: `朴成训将他按在图书馆的角落里,手指探入他的后穴。
<span class="red">“……啊……成训……别……”</span>
金善禹浑身颤抖,却不由自主地夹紧。
<span class="highlight">“不是你要我惩罚你吗?”</span> 朴成训的声音依旧清冷。
他解开裤子,将自己的性器抵在穴口,猛地贯穿。
金善禹尖叫着高潮了,淫水顺着大腿流下。
朴成训掐着他的腰,一下比一下更重。
<span class="italic">“……魅魔……也不过如此……”</span>
但朴成训的眼底,却燃起了从未有过的欲望。
此后,金善禹成了朴成训的“专属魅魔”。
他再也不用去跟踪偷拍,因为那个人,每天都会来找他。
<span class="gold">—— 善禹 · 驯服之爱 ——</span>
<span class="italic">❤️ 善禹篇 · 圆满 ❤️</span>`,
isEnd: true,
choices: [
{ label: '🔄', text: '重头开始', next: 'prologue' }
]
}
};
// ============================================================
// 游戏引擎
// ============================================================
let currentNodeId = 'prologue';
let history = [];
function renderNode(nodeId) {
const node = STORY[nodeId];
if (!node) {
// fallback
currentNodeId = 'prologue';
return renderNode('prologue');
}
// 更新 header
document.getElementById('chapterTag').textContent = node.tag || '—';
// 更新故事文本
const display = document.getElementById('storyDisplay');
const charLabel = node.char ? `<span class="char-label">${node.char}</span>` : '';
display.innerHTML = `<div class="fade-in">${charLabel}<br />${node.text}</div>`;
// 更新选项
const choicesContainer = document.getElementById('choicesContainer');
choicesContainer.innerHTML = '';
if (node.choices && node.choices.length > 0) {
node.choices.forEach((choice, index) => {
const btn = document.createElement('button');
btn.className = 'choice-btn';
const label = choice.label || String.fromCharCode(65 + index);
btn.innerHTML = `<span class="label">${label}</span> ${choice.text}`;
btn.addEventListener('click', () => {
if (choice.next) {
currentNodeId = choice.next;
renderNode(currentNodeId);
// 滚动到顶部
document.querySelector('.scroll-area').scrollTop = 0;
}
});
choicesContainer.appendChild(btn);
});
} else {
// 没有选项时显示结束占位
const placeholder = document.createElement('div');
placeholder.style.textAlign = 'center';
placeholder.style.padding = '12px 0';
placeholder.style.color = 'var(--text-dim)';
placeholder.style.fontSize = '13px';
placeholder.textContent = '✦ 故事暂告一段落 ✦';
choicesContainer.appendChild(placeholder);
}
// 记录历史
history.push(nodeId);
if (history.length > 50) history.shift();
// 重绘后重新触发淡入
const el = document.querySelector('.fade-in');
if (el) {
el.style.animation = 'none';
requestAnimationFrame(() => {
el.style.animation = 'fadeIn 0.45s ease forwards';
});
}
}
// ============================================================
// 启动
// ============================================================
document.addEventListener('DOMContentLoaded', () => {
renderNode('prologue');
});
// 暴露重启函数(方便调试)
window.restart = () => {
history = [];
currentNodeId = 'prologue';
renderNode('prologue');
};
console.log('✦ 月影·妖宴 ✦ ENHYPEN 同人互动小说已加载');
console.log('💡 三条故事线:结缘篇 · 载伦篇 · 善禹篇');
</script>
</body>
</html>
```Game Source: 月影·妖宴 — ENHYPEN 同人
Creator: BlazeStar26
Libraries: none
Complexity: complex (704 lines, 27.3 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-blazestar26-mr9fw7b5" to link back to the original. Then publish at arcadelab.ai/publish.