一、任务概述

项目的开发任务是构建一个完整的游戏叙事系统前端,包含世界选择、角色创建、主对话和结局展示四大核心界面。目标是为玩家提供沉浸式的穿书体验,让每个选择都影响剧情走向和最终结局。此前我已经基本完成各个界面的实现,此次博客记录的工作內容主要是我针对各个界面进行功能完善和体验优化。

二、世界选择界面完善

2.1 原有问题

原有世界选择界面功能较为基础,仅支持四个世界观的选择和跳转,缺少预览功能和视觉反馈。

2.2 完善内容

(1)视觉增强

添加了背景装饰光晕效果,三个彩色球体使用radial-gradient渐变和blur滤镜,营造梦幻的视觉氛围。卡片采用毛玻璃效果(backdrop-filter: blur(10px)),选中状态添加边框高亮和脉冲动画。

(2)世界预览功能

实现了鼠标悬停300ms后显示详细预览浮层,包含场景数量、角色数量、主线剧情数、可达成结局数等信息。预览浮层位置会根据屏幕边界自动调整,避免超出可视区域。

// 预览浮层位置自适应
if (this.previewPosition.x + 380 > window.innerWidth) {
  this.previewPosition.x = rect.left - 400;
}
if (this.previewPosition.y + 400 > window.innerHeight) {
  this.previewPosition.y = window.innerHeight - 420;
}

(3)交互增强

  • 选中动画:卡片选中时播放脉冲效果

  • 已选择世界指示器:顶部显示当前选中的世界

  • 底部操作栏:确认选择后跳转,支持重置选择

  • 加载过渡动画:点击确认后显示加载遮罩

如下图所示:增加预览功能,悬浮窗展示详细信息。

三、角色创建界面完善

3.1 原有问题

角色创建界面表单字段较多,用户需要完成大量选择后才能生成剧情,缺少步骤引导和实时反馈。

3.2 完善内容

(1)步骤式表单设计

将原本的长表单拆分为三个步骤:基础信息 → 角色自定义 → 生成故事。每个步骤独立验证,只有当前步骤完成后才能进入下一步。

nextStep() {
  if (this.currentStep === 1 && !this.isBasicInfoValid) {
    this.showValidationMessage('请填写完整的角色名称和身份选择');
    return;
  }
  if (this.currentStep === 2 && !this.isCustomizeValid) {
    this.showValidationMessage('请完成天赋、性格和入世缘由的选择');
    return;
  }
  this.currentStep++;
}

如下图所示:将长表单进行拆分,步骤指引更加清晰明确。

(2)属性点数分配优化

基础属性采用点数分配机制,总点数为15点,玩家可以自由分配到力量、敏捷、智力、魅力、幸运五个属性上。属性值变化时实时更新进度条,剩余点数不足时禁用增加按钮。

(3)天赋选择限制

天赋最多选择3项,达到上限后其他天赋卡片自动禁用并显示半透明效果。已选择的天赋在底部汇总显示。

(4)身份差异化效果

四种身份(主角、配角、反派、路人)拥有不同的初始属性和特殊能力:

身份 初始效果 特殊能力
主角 气运+10 关键剧情额外选择
配角 人缘+10 更容易获得好感
反派 谋略+10 额外行动机会
路人 自由+10 更多剧情分支

(5)生成进度模拟

点击生成剧情后,显示进度条和状态文字("正在编织命运之网..."、"正在编写角色背景..."、"正在构建人物关系网..."),增强等待体验。

(6)入场剧情展示

生成的入场剧情使用打字机效果展示,支持一键复制到剪贴板。

四、主对话界面完善

4.1 原有问题

主对话界面缺少实时通信机制,消息发送依赖HTTP请求,无法接收AI角色的自主推进消息。

4.2 完善内容

(1)WebSocket实时通信

实现了完整的WebSocket连接管理器,包含连接建立、心跳保活、断线重连等机制。

// 心跳保活
startHeartbeat() {
  this.heartbeatInterval = setInterval(() => {
    if (this.ws?.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify({ type: 'ping', timestamp: Date.now() }));
    }
  }, 30000);
}

// 指数退避重连
reconnectWebSocket() {
  if (this.reconnectAttempts >= this.maxReconnectAttempts) return;
  const delay = 3000 * Math.pow(2, this.reconnectAttempts);
  setTimeout(() => this.initWebSocket(), delay);
}

(2)连接状态指示器

右上角显示实时连接状态(连接中/已连接/断开),断开时提供重连按钮。

(3)消息增强功能

  • 表情选择器:20个常用表情,点击添加到输入框

  • 字符计数器:实时显示输入长度,超过450字变黄色,500字变红色

  • 正在输入指示器:三个跳动圆点,模拟角色正在输入的效果

(4)聊天记录导出

支持将完整对话历史导出为JSON文件,包含游戏信息、角色关系、剧情进度等数据。

(5)状态变化动画

关系值变化时显示浮动数字(+/-),并配有淡出动画。数值变化时背景色闪烁提示。

(6)结局系统集成

剧情进度达到100%时自动显示结局按钮,点击后跳转到结局展示页面。

如下图为主对话界面。

五、结局展示界面完善

5.1 原有问题

结局文本与世界观和角色羁绊的关联度不够紧密,缺乏个性化体验。

5.2 完善内容

(1)个性化结局生成

结局文本根据实际游戏数据动态生成,包括:

  • 高羁绊角色(≥70)在结局中被特别提及

  • 低羁绊敌对者的影响被描述

  • 隐藏角色的揭示进度影响结局类型

generatePersonalizedEndingText() {
  const highBondChars = this.allCharacters.filter(c => c.relationship >= 70);
  const lowBondChars = this.allCharacters.filter(c => c.relationship <= 30);
  const topAlly = highBondChars.find(c => c.type === 'ally');
  const topRival = lowBondChars.find(c => c.type === 'rival');
  
  // 根据世界类型和角色羁绊生成个性化结局
  const worldSpecificEndings = {
    '古代宫廷': { ... },
    '修仙世界': { ... },
    // ...
  };
}

(2)结局类型判定

根据平均羁绊值、高羁绊角色数量、隐藏角色揭示进度自动判定结局类型(good/bad/hidden/normal)。

(3)成就系统

成就根据实际游戏进度判定解锁状态,包含完成度环形进度条和稀有成就金色标识。

(4)角色羁绊可视化

  • 排序功能:按羁绊值/名称排序

  • 筛选功能:按盟友/敌对/隐藏角色筛选

  • 进度条颜色:高羁绊红色、中等橙色、低羁绊蓝色

(5)数据回顾图表

  • 羁绊演变趋势图:展示八阶段羁绊值变化

  • 剧情推进曲线:展示五阶段剧情进度

  • 角色关系网络:力导向图展示玩家与角色的关系网络,支持拖拽缩放

(6)打字机效果优化

增加了标点符号停顿(句号200ms,逗号60ms),使阅读节奏更自然。同时添加阅读进度条,实时显示阅读进度。

六、技术要点总结

模块 关键技术 主要完善内容
世界选择 CSS Grid、悬停预览 预览浮层、选中动画、边界检测
角色创建 步骤表单、点数分配 三步引导、属性分配、进度模拟
主对话 WebSocket、心跳保活 实时通信、表情选择、记录导出
结局展示 ECharts、个性化生成 羁绊关联成就、关系网络图、打字机优化

七、遇到的问题及解决方案

问题描述

在测试过程中发现,结局页面的结局文本角色羁绊数据所对应的世界观不一致。

具体表现

  • 世界观设定为「修仙世界」,但结局文本却显示「古代宫廷」的内容

  • 角色羁绊列表中出现了与当前世界观不匹配的角色(如修仙世界出现沈清辞、慕容璟等宫廷角色)

  • 从旧存档加载时,世界观切换后数据未正确更新

根本原因分析

1. 世界观映射不完整
原有代码只支持英文关键词映射(如 courtancient),缺少中文变体的支持,导致 '古代''宫廷''修仙' 等输入无法正确识别。

2. 角色数据与世界观脱钩
角色数据是独立从 localStorage 加载的,没有与当前选择的世界观进行绑定验证。当存档中的世界观与当前不一致时,仍然加载了旧的角色数据。

3. 存档校验机制缺失
加载存档时,没有检查存档中保存的世界观与当前世界观是否一致,导致世界观切换后数据混乱。

4. 结局文本生成的回退逻辑问题
当世界观匹配失败时,代码直接回退到「古代宫廷」的结局文本,而不是给出警告或自动修正。

具体修复方案

方案一:建立世界观规范化映射表

创建一个强大的名称映射函数,能够将各种输入变体统一转换为标准世界观名称。支持的输入包括:

  • 中文全称:'古代宫廷''修仙世界''现代校园''末世生存'

  • 中文简称:'古代''宫廷''修仙''校园''末世'

  • 英文关键词:'court''ancient''cultivation''xianxia''school''apocalypse'

这样无论上层传入什么样的命名格式,都能正确识别。

方案二:为每种世界观配置专属角色库

为四种世界观分别创建独立的角色配置数据库,每个角色都包含:名称、身份、头像、初始羁绊值、类型、背景故事、性格特点。

方案三:添加存档校验与自动修复机制

在加载游戏数据时,增加以下校验流程:

  1. 存档级校验:比较存档中的世界观与当前世界观是否一致

  2. 角色级校验:通过角色名称集合快速验证是否与当前世界观匹配

  3. 自动修复:当检测到不匹配时,自动使用当前世界观的默认角色配置

  4. 日志记录:在控制台输出详细的修复日志,便于追踪问题

这样既能保证数据一致性,又不会让用户感知到修复过程。

方案四:完善结局文本生成器

为每种世界观独立配置完整的结局文本库,包括四种结局类型:

  • 天命所归(Good Ending):达成完美结局,成就非凡

  • 宿命之殇(Bad Ending):走向悲剧,留下遗憾

  • 暗涌奇缘(Hidden Ending):揭示隐藏真相,获得特殊结局

  • 凡尘一梦(Normal Ending):平凡但温馨的普通结局

结局文本会根据实际角色羁绊数据动态插入角色名称,使每个玩家的结局都具有独特性。

通过本次完善,四大核心界面在功能完整性、交互流畅度和视觉沉浸感方面都有了显著提升,为玩家提供了更加完整的穿书游戏体验。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐