欢迎光临
我们一直在努力

【西游劫:第一篇】前言

西游劫(Journey to the West Tribulation)

在这里插入图片描述

第一章:概述

《西游劫》是一款以大语言模型(LLM)为核心的西游记题材文字冒险 MUD 游戏。它并非传统意义上的 MUD —— 那些依赖固定逻辑和预定义选项的游戏;相反,它做了一次大胆的“引擎替换”:将原本由代码硬编码的“世界反应规则”,交给大模型自由生成,再通过服务端的精准提示约束,让自由的输出依然服务于游戏的可控性与可玩性。

一句话:传统 MUD 像一本题库,你选 A 就到第 5 页;《西游劫》像一位会讲故事的说书人,你描述想做什么,他根据西游世界观和你的状态,即兴演绎出合理且有趣的结局,同时保证角色属性、道具、任务不会乱套。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

第二章:技术栈全景

项目严格构建于现代化全栈框架之上,分层清晰,选型克制。

#mermaid-svg-LQammsCYRfqJn7XQ{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-LQammsCYRfqJn7XQ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LQammsCYRfqJn7XQ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LQammsCYRfqJn7XQ .error-icon{fill:#552222;}#mermaid-svg-LQammsCYRfqJn7XQ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LQammsCYRfqJn7XQ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LQammsCYRfqJn7XQ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LQammsCYRfqJn7XQ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LQammsCYRfqJn7XQ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LQammsCYRfqJn7XQ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LQammsCYRfqJn7XQ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LQammsCYRfqJn7XQ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LQammsCYRfqJn7XQ .marker.cross{stroke:#333333;}#mermaid-svg-LQammsCYRfqJn7XQ svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LQammsCYRfqJn7XQ p{margin:0;}#mermaid-svg-LQammsCYRfqJn7XQ .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-LQammsCYRfqJn7XQ .cluster-label text{fill:#333;}#mermaid-svg-LQammsCYRfqJn7XQ .cluster-label span{color:#333;}#mermaid-svg-LQammsCYRfqJn7XQ .cluster-label span p{background-color:transparent;}#mermaid-svg-LQammsCYRfqJn7XQ .label text,#mermaid-svg-LQammsCYRfqJn7XQ span{fill:#333;color:#333;}#mermaid-svg-LQammsCYRfqJn7XQ .node rect,#mermaid-svg-LQammsCYRfqJn7XQ .node circle,#mermaid-svg-LQammsCYRfqJn7XQ .node ellipse,#mermaid-svg-LQammsCYRfqJn7XQ .node polygon,#mermaid-svg-LQammsCYRfqJn7XQ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-LQammsCYRfqJn7XQ .rough-node .label text,#mermaid-svg-LQammsCYRfqJn7XQ .node .label text,#mermaid-svg-LQammsCYRfqJn7XQ .image-shape .label,#mermaid-svg-LQammsCYRfqJn7XQ .icon-shape .label{text-anchor:middle;}#mermaid-svg-LQammsCYRfqJn7XQ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-LQammsCYRfqJn7XQ .rough-node .label,#mermaid-svg-LQammsCYRfqJn7XQ .node .label,#mermaid-svg-LQammsCYRfqJn7XQ .image-shape .label,#mermaid-svg-LQammsCYRfqJn7XQ .icon-shape .label{text-align:center;}#mermaid-svg-LQammsCYRfqJn7XQ .node.clickable{cursor:pointer;}#mermaid-svg-LQammsCYRfqJn7XQ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-LQammsCYRfqJn7XQ .arrowheadPath{fill:#333333;}#mermaid-svg-LQammsCYRfqJn7XQ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-LQammsCYRfqJn7XQ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-LQammsCYRfqJn7XQ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LQammsCYRfqJn7XQ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-LQammsCYRfqJn7XQ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LQammsCYRfqJn7XQ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-LQammsCYRfqJn7XQ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-LQammsCYRfqJn7XQ .cluster text{fill:#333;}#mermaid-svg-LQammsCYRfqJn7XQ .cluster span{color:#333;}#mermaid-svg-LQammsCYRfqJn7XQ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-LQammsCYRfqJn7XQ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-LQammsCYRfqJn7XQ rect.text{fill:none;stroke-width:0;}#mermaid-svg-LQammsCYRfqJn7XQ .icon-shape,#mermaid-svg-LQammsCYRfqJn7XQ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LQammsCYRfqJn7XQ .icon-shape p,#mermaid-svg-LQammsCYRfqJn7XQ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-LQammsCYRfqJn7XQ .icon-shape .label rect,#mermaid-svg-LQammsCYRfqJn7XQ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LQammsCYRfqJn7XQ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-LQammsCYRfqJn7XQ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-LQammsCYRfqJn7XQ :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

AI层

后端

前端

Next.js 16 App Router

React 19

Tailwind CSS 4 + shadcn/ui

Framer Motion 动画

LocalStorage 持久化

API Routes /api/game/*

Prisma 6 ORM

SQLite 数据库

ZAI SDK

大模型 API

  • 框架层:Next.js 16 (App Router) + React 19,享受服务端组件与客户端组件的灵活分工。
  • 样式层:Tailwind CSS 4 + shadcn/ui 组件库(基于 Radix 的弹窗、抽屉、气泡等),快速构建沉浸式游戏界面。
  • 状态与动画层:React Hooks(useState/useRef/useCallback/useMemo)管理本地交互状态,Framer Motion 实现打字机效果、屏幕震动、页面转场等增强叙事氛围的动画。
  • 数据层:Prisma 6 作为 ORM,搭配 SQLite(db/custom.db),轻量但完整地存储游戏存档、背包、NPC 关系、任务、消息记录。
  • AI 接入:ZAI SDK(z-ai-web-dev-sdk)统一封装大模型调用,屏蔽不同模型商的差异。
  • 持久化缓存:LocalStorage 存储成就、地图探索记录、用户笔记、设置、本地进度,与服务端数据互为补充。

第三章:三层架构详解

整个系统分为三个逻辑层,各司其职,形成“叙事生成 — 状态同步 — 体验呈现”的闭环。

#mermaid-svg-Is3EcnyMnsLGCGDf{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Is3EcnyMnsLGCGDf .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Is3EcnyMnsLGCGDf .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Is3EcnyMnsLGCGDf .error-icon{fill:#552222;}#mermaid-svg-Is3EcnyMnsLGCGDf .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Is3EcnyMnsLGCGDf .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Is3EcnyMnsLGCGDf .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Is3EcnyMnsLGCGDf .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Is3EcnyMnsLGCGDf .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Is3EcnyMnsLGCGDf .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Is3EcnyMnsLGCGDf .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Is3EcnyMnsLGCGDf .marker{fill:#666;stroke:#666;}#mermaid-svg-Is3EcnyMnsLGCGDf .marker.cross{stroke:#666;}#mermaid-svg-Is3EcnyMnsLGCGDf svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Is3EcnyMnsLGCGDf p{margin:0;}#mermaid-svg-Is3EcnyMnsLGCGDf .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Is3EcnyMnsLGCGDf .cluster-label text{fill:#333;}#mermaid-svg-Is3EcnyMnsLGCGDf .cluster-label span{color:#333;}#mermaid-svg-Is3EcnyMnsLGCGDf .cluster-label span p{background-color:transparent;}#mermaid-svg-Is3EcnyMnsLGCGDf .label text,#mermaid-svg-Is3EcnyMnsLGCGDf span{fill:#333;color:#333;}#mermaid-svg-Is3EcnyMnsLGCGDf .node rect,#mermaid-svg-Is3EcnyMnsLGCGDf .node circle,#mermaid-svg-Is3EcnyMnsLGCGDf .node ellipse,#mermaid-svg-Is3EcnyMnsLGCGDf .node polygon,#mermaid-svg-Is3EcnyMnsLGCGDf .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Is3EcnyMnsLGCGDf .rough-node .label text,#mermaid-svg-Is3EcnyMnsLGCGDf .node .label text,#mermaid-svg-Is3EcnyMnsLGCGDf .image-shape .label,#mermaid-svg-Is3EcnyMnsLGCGDf .icon-shape .label{text-anchor:middle;}#mermaid-svg-Is3EcnyMnsLGCGDf .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Is3EcnyMnsLGCGDf .rough-node .label,#mermaid-svg-Is3EcnyMnsLGCGDf .node .label,#mermaid-svg-Is3EcnyMnsLGCGDf .image-shape .label,#mermaid-svg-Is3EcnyMnsLGCGDf .icon-shape .label{text-align:center;}#mermaid-svg-Is3EcnyMnsLGCGDf .node.clickable{cursor:pointer;}#mermaid-svg-Is3EcnyMnsLGCGDf .root .anchor path{fill:#666!important;stroke-width:0;stroke:#666;}#mermaid-svg-Is3EcnyMnsLGCGDf .arrowheadPath{fill:#333333;}#mermaid-svg-Is3EcnyMnsLGCGDf .edgePath .path{stroke:#666;stroke-width:2.0px;}#mermaid-svg-Is3EcnyMnsLGCGDf .flowchart-link{stroke:#666;fill:none;}#mermaid-svg-Is3EcnyMnsLGCGDf .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Is3EcnyMnsLGCGDf .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Is3EcnyMnsLGCGDf .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Is3EcnyMnsLGCGDf .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Is3EcnyMnsLGCGDf .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Is3EcnyMnsLGCGDf .cluster text{fill:#333;}#mermaid-svg-Is3EcnyMnsLGCGDf .cluster span{color:#333;}#mermaid-svg-Is3EcnyMnsLGCGDf div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Is3EcnyMnsLGCGDf .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Is3EcnyMnsLGCGDf rect.text{fill:none;stroke-width:0;}#mermaid-svg-Is3EcnyMnsLGCGDf .icon-shape,#mermaid-svg-Is3EcnyMnsLGCGDf .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Is3EcnyMnsLGCGDf .icon-shape p,#mermaid-svg-Is3EcnyMnsLGCGDf .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Is3EcnyMnsLGCGDf .icon-shape .label rect,#mermaid-svg-Is3EcnyMnsLGCGDf .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Is3EcnyMnsLGCGDf .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Is3EcnyMnsLGCGDf .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Is3EcnyMnsLGCGDf :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}#mermaid-svg-Is3EcnyMnsLGCGDf .clientStyle>*{fill:#E3F2FD!important;stroke:#1976D2!important;stroke-width:2px!important;color:#000!important;font-weight:bold!important;}#mermaid-svg-Is3EcnyMnsLGCGDf .clientStyle span{fill:#E3F2FD!important;stroke:#1976D2!important;stroke-width:2px!important;color:#000!important;font-weight:bold!important;}#mermaid-svg-Is3EcnyMnsLGCGDf .clientStyle tspan{fill:#000!important;}#mermaid-svg-Is3EcnyMnsLGCGDf .apiStyle>*{fill:#FFF8E1!important;stroke:#FF8F00!important;stroke-width:2px!important;color:#000!important;font-weight:bold!important;}#mermaid-svg-Is3EcnyMnsLGCGDf .apiStyle span{fill:#FFF8E1!important;stroke:#FF8F00!important;stroke-width:2px!important;color:#000!important;font-weight:bold!important;}#mermaid-svg-Is3EcnyMnsLGCGDf .apiStyle tspan{fill:#000!important;}#mermaid-svg-Is3EcnyMnsLGCGDf .engineStyle>*{fill:#E8F5E9!important;stroke:#388E3C!important;stroke-width:2px!important;color:#000!important;font-weight:bold!important;}#mermaid-svg-Is3EcnyMnsLGCGDf .engineStyle span{fill:#E8F5E9!important;stroke:#388E3C!important;stroke-width:2px!important;color:#000!important;font-weight:bold!important;}#mermaid-svg-Is3EcnyMnsLGCGDf .engineStyle tspan{fill:#000!important;}#mermaid-svg-Is3EcnyMnsLGCGDf .storageStyle>*{fill:#FCE4EC!important;stroke:#C2185B!important;stroke-width:2px!important;color:#000!important;font-weight:bold!important;}#mermaid-svg-Is3EcnyMnsLGCGDf .storageStyle span{fill:#FCE4EC!important;stroke:#C2185B!important;stroke-width:2px!important;color:#000!important;font-weight:bold!important;}#mermaid-svg-Is3EcnyMnsLGCGDf .storageStyle tspan{fill:#000!important;}#mermaid-svg-Is3EcnyMnsLGCGDf .stateStyle>*{fill:#F3E5F5!important;stroke:#7B1FA2!important;stroke-width:2px!important;color:#000!important;font-weight:bold!important;}#mermaid-svg-Is3EcnyMnsLGCGDf .stateStyle span{fill:#F3E5F5!important;stroke:#7B1FA2!important;stroke-width:2px!important;color:#000!important;font-weight:bold!important;}#mermaid-svg-Is3EcnyMnsLGCGDf .stateStyle tspan{fill:#000!important;}

🧠 AI叙事引擎 – 服务端

🌐 游戏API – 服务端

🖥️ 交互界面 – 客户端

用户动作

执行指令

解析响应

同步状态

获取状态

持久化数据

更新UI

触发新动作

💬 自然语言输入框

📜 叙事渲染区

🎒 功能模块(背包 / 技能 / 地图 / 成就)

💾 LocalStorage 缓存

/api/game/init

/api/game/action

/api/game/state

/api/game/message

/api/game/saves

🌍 World / Player 状态

📝 Prompt 组装

🤖 LLM 调用 & 响应解析

🗄️ Prisma 持久化

3.1 Tier 1 —— AI 叙事引擎(服务端核心)

文件位置:/src/lib/game-engine.ts

核心职责:

  • 状态管理:维护当前世界的世界观、NPC 状态、玩家属性(生命、法力、修为等)。
  • Prompt 工程:根据玩家历史行动、当前场景、角色状态,动态组装发给大模型的提示词。提示词中包含:
    • 西游记世界观背景与风格约束(如“不要出现现代物品”)。
    • 玩家状态摘要(生命值、背包物品、当前任务)。
    • 输出格式要求(如必须返回 JSON,包含叙事文本、属性变化、道具得失等)。
  • LLM 调用:通过 ZAI SDK 发送请求,支持流式(SSE)与非流式响应。
  • 响应解析:将大模型返回的自然语言或 JSON 解析为结构化数据(例如:{ narrative: "…", hpDelta: -5, gainItem: "金丹" })。
  • 持久化:调用 Prisma 更新数据库中的 GameSave、Inventory、NPC 关系、任务进度等。

为什么叫“叙事引擎”?因为大模型承担了“游戏规则计算 + 剧情生成”的双重角色,而引擎层负责把它“驯化”成一个可靠、可回溯的游戏逻辑核心。

3.2 Tier 2 —— 游戏 API(前后端通道)

路径:/src/app/api/game/{init, action, state, message, saves}

核心职责:

  • 参数校验与鉴权(确保请求合法)。
  • 调用 Tier 1 引擎的不同功能(初始化游戏、执行玩家动作、获取当前状态、获取消息历史、管理存档)。
  • 返回统一格式的 JSON 或 SSE(Server-Sent Events)流。
  • 对于 action 接口,由于 LLM 生成叙事需要时间,采用 SSE 逐步将“叙事文本 chunk”推送到前端,提升用户体验(不用等待完整响应)。

3.3 Tier 3 —— 交互界面(客户端体验层)

主文件:/src/app/page.tsx + /components/game/*.tsx

核心职责:

  • 输入与输出:提供自然语言输入框,用户输入“我跳上筋斗云,朝火焰山飞去”这类指令,实时展示 AI 生成的叙事结果。
  • 辅助面板:背包、技能、地图、成就、音效控制等,全部以独立组件形式存在,通过全局状态与游戏核心交互。
  • 动画与反馈:打字机效果逐字显示叙事文本,屏幕震动模拟打斗场景,页面转场增强沉浸感。
  • 本地缓存同步:将用户设置、已解锁成就、地图探索进度等非关键但频繁读写的数据存入 LocalStorage,减少服务端请求,实现离线可用(部分功能)。

第四章:数据流向 —— 一次完整玩家操作的生命周期

理解《西游劫》最好的方式,就是跟踪一次用户输入的完整旅程。

LocalStoragePrisma + SQLiteLLMgame-engine.ts/api/game/actionClientUIUserLocalStoragePrisma + SQLiteLLMgame-engine.ts/api/game/actionClientUIUser#mermaid-svg-yZPLdhbqfu5Vthqa{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-yZPLdhbqfu5Vthqa .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yZPLdhbqfu5Vthqa .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yZPLdhbqfu5Vthqa .error-icon{fill:#552222;}#mermaid-svg-yZPLdhbqfu5Vthqa .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yZPLdhbqfu5Vthqa .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yZPLdhbqfu5Vthqa .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yZPLdhbqfu5Vthqa .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yZPLdhbqfu5Vthqa .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yZPLdhbqfu5Vthqa .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yZPLdhbqfu5Vthqa .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yZPLdhbqfu5Vthqa .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yZPLdhbqfu5Vthqa .marker.cross{stroke:#333333;}#mermaid-svg-yZPLdhbqfu5Vthqa svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yZPLdhbqfu5Vthqa p{margin:0;}#mermaid-svg-yZPLdhbqfu5Vthqa .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-yZPLdhbqfu5Vthqa text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-yZPLdhbqfu5Vthqa .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-yZPLdhbqfu5Vthqa .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-yZPLdhbqfu5Vthqa .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-yZPLdhbqfu5Vthqa .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-yZPLdhbqfu5Vthqa #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-yZPLdhbqfu5Vthqa .sequenceNumber{fill:white;}#mermaid-svg-yZPLdhbqfu5Vthqa #sequencenumber{fill:#333;}#mermaid-svg-yZPLdhbqfu5Vthqa #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-yZPLdhbqfu5Vthqa .messageText{fill:#333;stroke:none;}#mermaid-svg-yZPLdhbqfu5Vthqa .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-yZPLdhbqfu5Vthqa .labelText,#mermaid-svg-yZPLdhbqfu5Vthqa .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-yZPLdhbqfu5Vthqa .loopText,#mermaid-svg-yZPLdhbqfu5Vthqa .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-yZPLdhbqfu5Vthqa .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-yZPLdhbqfu5Vthqa .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-yZPLdhbqfu5Vthqa .noteText,#mermaid-svg-yZPLdhbqfu5Vthqa .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-yZPLdhbqfu5Vthqa .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-yZPLdhbqfu5Vthqa .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-yZPLdhbqfu5Vthqa .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-yZPLdhbqfu5Vthqa .actorPopupMenu{position:absolute;}#mermaid-svg-yZPLdhbqfu5Vthqa .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-yZPLdhbqfu5Vthqa .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-yZPLdhbqfu5Vthqa .actor-man circle,#mermaid-svg-yZPLdhbqfu5Vthqa line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-yZPLdhbqfu5Vthqa :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}loop[SSE 流式响应]输入“我要用芭蕉扇熄灭火焰山”POST { gameSaveId, action, llmConfig }processActionStream(saveId, action)读取当前游戏状态(生命、背包、NPC等)返回状态对象组装 Prompt(状态+动作+西游规则+输出格式)通过 ZAI SDK 发起流式请求文本块(chunk)转发 chunk通过 SSE 推送 chunk逐步渲染叙事文本(打字机效果)最终完整响应(含结构化数据)解析响应(HP变化、道具得失、任务更新)写入更新(新的 HP、背包、消息记录)发送 done 事件,包含完整状态快照SSE 事件: done + 最终状态一次性更新所有UI面板(背包、状态等)同步本地可持久化数据(成就、地图等)显示完整叙事和更新后的游戏界面

关键步骤解读:

  • 用户输入:自由文本,无需选择固定指令。
  • API 接收:携带存档 ID 和当前动作,调用引擎的流式处理方法。
  • 引擎加载状态:从数据库读取该存档的所有相关信息,确保 LLM “知道”玩家是谁、有什么、在哪里。
  • Prompt 组装:将状态、动作、世界观约束、输出格式要求合并成一条精心设计的提示语。这是控制游戏质量的核心环节。
  • LLM 流式生成:大模型边思考边输出,引擎实时转发每个文本块。
  • 前端逐步渲染:用户看到叙事像打字一样出现,无需等待漫长生成。
  • 最终解析与落库:LLM 输出完整后,引擎从中提取出结构化变更(如扣血、得宝),更新数据库,保证游戏数据一致。
  • 一次性刷新 UI:收到 done 事件后,前端用最新状态一次性重绘所有面板,避免频繁闪烁。
  • 本地缓存同步:将成就、地图探索等用户进度存入 LocalStorage,下次启动时可快速恢复部分界面状态。
  • 第五章:说明

    设计点解决的问题带来的价值
    LLM 替代硬编码规则 传统 MUD 的剧情和反应有限,玩久了可预测 无限可能性,每次行动都新鲜,真正“开放叙事”
    服务端 Prompt 约束 LLM 可能胡说八道或脱离西游风格 保证输出在游戏框架内,不超纲(例如不会突然出现激光枪)
    SSE 流式返回 LLM 生成较慢(数秒),用户焦虑 提升感知速度,打字机效果本身也增强叙事沉浸感
    结构化解析 + 数据库 LLM 输出不稳定,可能遗漏属性变更 通过解析层保证即使 LLM 忘了扣血,后端也能补上或修正,确保游戏公平
    本地 + 服务端双存储 频繁读写服务端压力大,且部分数据(如本地笔记)无需上云 性能优化 + 部分离线可用 + 降低服务器成本
    Next.js App Router 统一前后端 TypeScript 生态,API 路由简单 全栈类型安全,开发效率高

    结语

    《西游劫》不是简单地在聊天框上套了个游戏皮肤,而是通过三层架构重新定义了“AI 原生游戏”的基础模式:LLM 提供无限的叙事生成能力,服务端引擎用提示和解析赋予它规则性,前端则负责将这种生成式体验包装成传统 MUD 玩家熟悉的界面与反馈。这种架构不仅适用于西游记题材,稍加修改 Prompt 和世界观数据,就能快速衍生出《封神劫》《克苏鲁劫》等新游戏。

    如果你是一名开发者,理解了这个数据流向和分层职责,就已经掌握了扩展或调试该项目的核心钥匙。

    赞(0)
    未经允许不得转载:171主机测评 » 【西游劫:第一篇】前言
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址