AI群演请就位—个人博客(八)
经过这么多周的努力,我们小组的创新实训项目主要功能已经基本实现。而我负责的工作,主要就是针对我们所实现的项目对前端进行编程设计。为了更好的切合我们项目的主题以及带来更好的游戏体验,这周我对前端页面进行了统一的升级改进,并且连接后端对游玩体验进行了测试。
页面全面改进详解
游戏启动页(WorldSelect.vue )
这是用户进入游戏的第一印象,我将其设计为一个具有沉浸感的开屏页面。

设计亮点:
-
游戏LOGO动画:“渡厄峰”三字使用渐变金色,配合浮动动画和光晕效果
-
毛玻璃故事卡片:半透明背景+模糊效果,展示世界观简介
-
背景音乐系统:支持播放/暂停,音量可调,设置自动保存
-
设置弹窗:可调节音乐音量、音效音量、文字速度和画面效果
技术难点:
-
浏览器音频自动播放策略:现代浏览器禁止未经用户交互的音频自动播放,我通过在
<audio>标签上同时设置autoplay和muted属性,并在首次用户交互时取消静音来解决 -
云雾动画性能:使用CSS
transform而非position实现平移,利用GPU加速,确保动画流畅 -
响应式布局:手机端按钮变为横向排列,音乐控制按钮简化显示
实现效果:
用户打开游戏后,首先看到精美的启动画面,背景音乐尝试自动播放(若被阻止则静音等待用户点击),点击“开始新的旅程”跳转到角色创建页,如果之前玩过游戏并且有存档时点击“继续未竟之途”则加载存档直接进入游戏。
角色创建页(CharacterCreate.vue)
这个页面让玩家从四个角色中选择一个,每个角色都有独特的背景故事。

四个可选角色:
| 角色ID | 名称 | 身份 | 心厄形态 | 开场物品 |
|---|---|---|---|---|
| hua_jianke | 花间客 | 女剑客 | 黑衣仇人 | 染血的残剑穗 |
| liu_jianqing | 柳见青 | 药师 | 病弱弟弟 | 旧药方 |
| yunchang | 云裳 | 刺客 | 被害小女孩 | 褪色小风筝 |
| he_buyu | 何不语 | 盲厨 | 背叛他的女子 | 断弦残谱 |
设计亮点:
-
角色卡片网格:四列网格布局,卡片悬停有上浮和光效扫过动画
-
选中状态特效:选中卡片有紫色渐变边框、光晕阴影和右上角“✓ 已选择”标记
-
详情区域:选中角色后右侧展开详细档案,包含角色立绘、背景故事、心厄形态、初始物品、专属线索、角色目标、性格标签
-
BGM系统:独立的角色选择页面背景音乐,与启动页共享音乐设置
-
加载遮罩:确认选择后显示加载动画,模拟“编织命运之网”的沉浸感
技术难点:
-
立绘图片加载:图片加载失败时自动降级显示emoji头像
-
角色数据传递:通过localStorage保存选中角色,跳转到游戏页面后读取
-
后端初始化调用:选择角色后调用
/api/chat/init接口,传递角色ID、模型名称和温度参数
实现效果:
玩家点击角色卡片查看详细信息,确认选择后系统调用后端初始化游戏会话,生成入场剧情后进入游戏主界面。
游戏主界面(GameView.vue)
这是游戏的核心界面,采用三栏深色玻璃态布局设计。


左侧角色信息区:
-
角色立绘卡片:圆形立绘头像,心厄值>50时显示红色脉冲光晕特效
-
角色属性面板:生命值(❤️)和心厄侵蚀度(🌑)进度条,心厄值过高时文字变红
-
当前位置面板:场景名称带淡入淡出切换动画
-
背包简览:显示前3个物品,超出显示“+N 更多”
-
当前任务简览:显示前2个未完成任务及完成状态
中间对话区:
-
消息气泡:用户消息靠右显示紫蓝渐变背景,AI消息靠左显示
-
旁白消息:使用斜体样式,背景更透明,区分剧情叙述
-
正在输入指示器:三点跳动动画 + “正在编织命运...”文字
-
快捷短语按钮:询问、调查、对话、观察、探索、思考
-
清除对话按钮:一键清空对话记录
右侧功能按钮区:
-
竖列按钮设计:任务、剧情、线索、角色、背包、存档、设置、重置
-
任务角标:未完成任务数量红色角标
-
线索角标:新线索获得时橙色角标+按钮闪烁动画
-
弹出面板:点击按钮从右侧滑出详情面板
弹出面板功能:
-
任务面板:从后端
quest_flags动态生成任务列表,显示任务名称和提示,自动同步完成状态 -
剧情面板:环形进度条显示整体进度,里程碑节点展示
-
线索面板:显示已获得线索,新线索带“新”标记和闪烁动画
-
角色面板:显示NPC名称、身份、信任值进度条,点击可快速对话
-
背包面板:展示所有持有物品
存档/读档系统:
-
3个独立存档槽,支持保存和加载
-
自动存档功能(可开关),每60秒自动保存
-
存档信息包含场景位置、保存时间
通知系统:
-
线索获得时弹出通知并闪烁线索按钮
-
任务完成时弹出通知
-
通知4秒后自动消失
技术难点:
-
WebSocket实时通信:实现消息实时收发,断线自动重连,心跳保活
-
任务系统联动:任务列表从
questFlags动态生成,完成后自动更新 -
线索通知:监听
known_clues数组变化,比较新旧值判断新线索 -
心厄值特效:立绘外围红色脉冲动画,属性文字变红
-
场景切换动画:场景名称变化时淡入淡出过渡
实现效果:
玩家输入行动或对话,通过WebSocket发送到后端,AI响应后实时显示在对话区。任务完成、线索获得时会有通知提示,游戏进度自动保存。
结局页面(EndingPage.vue)


根据玩家的游戏进度展示个性化结局,与主界面保持统一的深色玻璃态风格。
核心功能:
-
四种结局类型:
-
good(天命所归):击败照影雾魇后触发,圆满结局
-
normal(凡尘一梦):面对心厄投影但未击败,普通结局
-
hidden(暗涌奇缘):接触心厄但未面对投影,隐藏结局
-
bad(宿命之殇):未完成任何关键任务,悲剧结局
-
-
结局文本打字机效果:结局文字逐字显示,句号等标点处自然停顿
-
任务完成总结:显示五个主线任务的完成状态
-
NPC关系总结:从
questFlags读取信任值,用信任圆环可视化,根据信任值生成关系描述 -
成就系统:7个成就,根据任务完成情况自动解锁
与后端联动:
-
从
gameState.world.quest_flags读取任务完成状态 -
从
gameState.npcs读取NPC信任值 -
根据玩家选择的角色生成个性化结局文案
-
游戏时长从
gameStartTime计算
设计亮点:
-
打字机效果:逐字显示,中英文标点差异化停顿,增强沉浸感
-
信任圆环:使用CSS
conic-gradient实现圆形进度条 -
成就卡片:解锁成就高亮显示,稀有成就特殊背景
-
分享功能:支持复制结局文案和保存结局图片(html2canvas)
-
BGM系统:独立的结局页面背景音乐
实现效果:
游戏结束后,系统根据任务完成情况自动判断结局类型,逐字显示结局故事,展示任务总结、NPC羁绊和已解锁成就,玩家可以分享结局或重新开始游戏。
部分重要功能实现
任务系统与后端联动
任务系统是游戏的核心玩法之一。我设计了一个动态任务列表,从后端的quest_flags实时生成:
// 任务映射关系
const questMapping = [
{ flag: 'found_mist_source', name: '调查雾气来源', hint: '询问清尘子或调查白雾' },
{ flag: 'asked_about_mist', name: '询问心厄', hint: '与清尘子交谈' },
{ flag: 'touched_heart_affliction', name: '接触心厄', hint: '走入白雾深处' },
{ flag: 'faced_personal_shadow', name: '面对心厄投影', hint: '面对自己的心厄投影' },
{ flag: 'defeated_shadow_mist', name: '击败照影雾魇', hint: '击败照影雾魇' }
]
任务完成时会自动弹出通知,任务按钮上的角标也会实时更新。
通知系统
为了让用户及时了解游戏中的重要事件,我实现了一个全局通知系统:
-
线索获得通知:当获得新线索时,右上角弹出通知,线索按钮闪烁
-
任务完成通知:当任务完成时,弹出成功通知
-
存档成功通知:保存游戏后弹出确认通知
音效与背景音乐
为了增强沉浸感,我实现了背景音乐和音效系统:
-
启动页和游戏内统一背景音乐
-
音乐控制按钮(播放/暂停)
-
音量调节滑块
遇到的问题与解决方案
问题一:开屏剧情打字机效果
问题描述
游戏启动后需要播放一段开屏剧情,逐字显示文字,营造沉浸感。但简单的逐字显示存在以下问题:
-
中英文混合时显示不流畅
-
标点符号处没有停顿,显得生硬
-
用户无法跳过或加速
-
长文本时滚动不同步
解决方案
我设计了一个带有智能停顿的打字机系统:
核心思路:
-
根据字符类型动态调整打字速度
-
中文标点处增加停顿时间
-
支持用户点击跳过或加速
实现细节:
-
字符类型识别:判断每个字符的类型,中文句号、感叹号、问号等标点处增加200ms停顿,逗号、顿号等处增加60ms停顿,普通字符使用40ms基础速度。
-
段落管理:将开屏文本按段落拆分,用户点击“下一节”时才继续显示下一段,避免一次性显示过多内容。
-
跳过功能:用户点击“跳过剧情”按钮时,清除定时器并直接显示全部文本,方便老玩家快速进入游戏。
-
滚动跟随:每显示完一段文字,自动滚动到底部,确保最新内容始终可见。
遇到的问题:
-
初始实现时,段落切换时打字机状态没有重置,导致新段落直接显示全部内容。通过在切换段落时重置索引和定时器解决了这个问题。
问题二:背景音乐自动播放被阻止
问题描述
现代浏览器(Chrome、Safari等)出于用户体验考虑,默认阻止音频的自动播放。当用户打开游戏时,背景音乐无法自动播放,需要在控制台看到错误信息:
DOMException: play() failed because the user didn't interact with the document first.
解决方案
核心思路:浏览器允许自动播放的条件是用户已经与页面进行过交互。因此,我采取了以下策略:
-
尝试自动播放:页面加载时仍然尝试调用
audio.play(),如果成功则正常播放;如果被阻止,静默失败并设置播放状态为暂停。 -
首次交互激活:在用户首次点击页面任意位置(如“开始游戏”按钮)时,调用
audio.play()激活音频。这是最可靠的方案。 -
音乐控制按钮:在页面右下角添加音乐控制按钮,用户可以手动开启/关闭音乐。按钮状态实时显示当前播放状态。
-
音量设置持久化:将用户的音量设置保存到localStorage,下次进入游戏时自动恢复。
遇到的问题:
-
部分浏览器在用户交互后仍需要短暂延迟才能播放音频,通过将播放调用放在用户点击事件的回调中解决。
-
页面跳转后音频状态丢失,通过在Vuex中保存音乐状态并在路由切换时恢复解决。
问题三:进度条不更新,任务列表停滞不前
在我进行《渡厄峰》游戏测试过程中,我发现了一个严重影响游戏体验的问题:玩家完成第一章后,游戏界面的右侧剧情进度显示为100%,但第二章开启后进度条不再更新,任务列表也停滞不前。
| 问题层面 | 具体原因 |
|---|---|
| 进度计算 | 进度计算逻辑只考虑了第一章5个任务,没有根据当前章节动态调整 |
| 任务列表 | 任务列表只在初始化时生成,不会根据章节变化更新 |
| 数据读取 | 前端没有从 branch_progress 读取支线任务数据 |
核心思路
-
任务列表动态化:根据当前章节(第一章/第二章/第三章)显示不同的任务列表
-
进度计算动态化:根据当前章节计算对应的进度百分比
-
数据源统一:任务完成状态直接从
questFlags和branchProgress读取
第一步:增加章节状态判断
chapter1Completed() {
return this.questFlags.defeated_shadow_mist === true
},
chapter2Unlocked() {
return this.questFlags?.chapter_2_unlocked || false
},
chapter3Unlocked() {
return this.questFlags?.chapter_3_unlocked || false
},
第二步:动态生成任务列表
dynamicQuests() {
// 第一章任务配置
const chapter1Quests = [
{ flag: 'found_mist_source', name: '调查雾气来源', hint: '...' },
// ... 其他4个任务
]
// 第二章支线任务(从 branch_progress 读取)
const branchProgress = this.questFlags.branch_progress || {}
const chapter2Quests = [
{ id: 'blood_letter', name: '山下血书', completed: branchProgress.blood_letter?.completed },
// ... 其他3个支线
]
// 第三章任务
const chapter3Quests = [
{ id: 'mind_realm', name: '不二观心境', completed: this.questFlags.mind_realm_entered },
// ... 其他2个任务
]
// 根据章节返回对应任务
if (this.chapter3Unlocked) return chapter3Quests
if (this.chapter2Unlocked && this.chapter1Completed) return chapter2Quests
return chapter1Quests
},
第三步:动态计算进度
computedProgress() {
// 第三章进度
if (this.chapter3Unlocked) {
const total = 3
const completed = [/* 第三章完成标志 */].filter(Boolean).length
return Math.floor((completed / total) * 100)
}
// 第二章进度(基于支线完成数量)
if (this.chapter2Unlocked && this.chapter1Completed) {
const total = 4
const completed = this.completedBranchCount
return Math.floor((completed / total) * 100)
}
// 第一章进度
const total = 5
const completed = this.completedQuestCount
return Math.floor((completed / total) * 100)
}
}
最终修改后进入第二章后任务列表和剧情进度都会更新。


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



所有评论(0)