diff --git a/research/00-charter.md b/research/00-charter.md new file mode 100644 index 00000000..7e4b5e9f --- /dev/null +++ b/research/00-charter.md @@ -0,0 +1,77 @@ +# 纯音频游戏交互设计研究章程(Research Charter) + +> 状态:进行中 | 启动日期:2026-08-30 | 本文档是研究项目的总入口与裁定记录。 + +## 1. 问题定义 + +玩家试玩本项目 6 款纯音频游戏时的真实反馈: + +- **不知道自己处于什么状态**:在菜单里?在战斗中?等待输入还是在播剧情? +- **不知道能做什么、该做什么**:6 种手势在当前状态下分别意味着什么? +- **出错后不知道为什么错、怎么纠正**,于是「玩不进去,马上就放弃」。 + +根因假设:纯音频游戏缺失视觉游戏的「常驻信息层」(画面/HUD 一直在告诉玩家状态),我们只做了**事件层**反馈(发生某事→播某音),没有做**状态层**反馈。研究目标就是把「状态层」的音频等价物找出来,并形成可复用的方法论。 + +## 2. 研究问题(RQ) + +| # | 研究问题 | 对应产物 | +|---|---|---| +| RQ1 | 优秀音频游戏(学界/商业/盲人社区)如何让玩家保持状态感知?有哪些被验证的模式? | 01-literature/01 | +| RQ2 | 声音如何承载结构化信息(状态/选项/空间/进度)?earcon/音效/语音的分工与参数边界? | 01-literature/02 | +| RQ3 | 视障玩家(音频游戏的资深用户群)已形成哪些交互惯例与期望? | 01-literature/03 | +| RQ4 | 怎样的引导与反馈节奏能让新玩家度过头 5 分钟不弃坑(心流/FTUE/留存)? | 01-literature/04 | +| RQ5 | 不同使用场景(睡前/通勤/摸鱼)与人群(学生/视障/白领/工人)对交互设计提出什么不同约束? | 01-literature/05 | +| RQ6 | 如何把 RQ1-5 综合成可操作的方法论(能直接推导出设计决策)? | 02-methodology | +| RQ7 | 方法论如何落地为本项目 6 款游戏的具体交互方案(按人设×场景×游戏类型给多套方案)? | 03-schemes | +| RQ8 | 交互方案实现后,「普通玩家」是否认可?(多人设玩家代理试玩闭环) | 04-playtests | + +## 3. 方法 + +``` +文献调研(5 路并行 agent) + ↓ +方法论《纯音频游戏交互设计方法论》——原则 + 决策规则 + 反模式 + ↓ +交互方案(全局听觉语言 + 分游戏方案 + 人设×场景适配矩阵) + ↓ +实现(引擎交互层 + 6 游戏接入,试玩测试全绿) + ↓ +玩家代理试玩:事件流转写(audio event log)+ 多人设 agent 读流写心得 + ↓ 不认可 → 回到「交互方案」修订 + 认可 → 结题 +``` + +**多人设玩家代理**(步骤 6/7 的人设 × 场景矩阵): + +| 人设 | 场景 | 关键约束 | +|---|---|---| +| 时间充裕的大学生 | 宿舍躺床、戴耳机、愿意深玩 | 期待深度与沉浸,讨厌说教 | +| 视障玩家 | 日常,资深读屏/音频游戏经验 | 对听觉惯例极挑剔,是「专业评委」 | +| 时间紧张的白领 | 通勤地铁(嘈杂)、上班摸鱼(怕出声、会被打断) | 3 分钟一局、可随时中断续玩、安静可玩 | +| 工人(体力劳动) | 下班后疲惫、睡前放松 | 低认知负荷、容错高、即时正反馈 | + +**试玩代理的感官替代说明(诚实声明)**:agent 无法真正「听」音频。试玩 harness 把游戏对玩家输出的**全部音频事件流**(何时播了什么语音/音效/BGM 切换/震动、语义是什么、持续多久)转写成时间轴日志,玩家 agent 以此重构「我每秒钟知道什么、被要求做什么」。这有效评测的是**信息流与状态感知**(即本次研究核心痛点),但**不能**评测音色美感、响度舒适度、空间音频定位精度——这些仍需真机人类听测(见 roadmap §4,不在本研究闭环内)。 + +## 4. 成功标准(结题门槛) + +1. 6 款游戏无头试玩测试全绿(回归保护)。 +2. 玩家代理闭环:4 个人设中**至少 3 个**明确「愿意继续玩」,且无人设存在 P0 级状态混淆问题(不知道自己在哪/该做什么/为何失败)。 +3. 产出可复用方法论文档:给出**多套**(而非单一)方案,并能按「目标用户 × 场景 × 游戏类型」推导选择。 +4. 全部新语音台词遵守资产管线规范(voice-ids 文档 → gen_voice_dual.py → 终检)。 + +## 5. 产物清单 + +| 产物 | 路径 | +|---|---| +| 本章程 | research/00-charter.md | +| 5 份文献调研报告 | research/01-literature/01~05 | +| 方法论 | research/02-methodology/methodology.md | +| 交互方案 | research/03-schemes/ | +| 玩家代理试玩记录与迭代 | research/04-playtests/ | +| 研究总结 | research/05-summary.md | + +## 6. 边界与不做的事 + +- 不改 `docs/design/` 下的历史裁定记录(round*-review),新裁定写本研究目录。 +- 不重做 6 款游戏的玩法核心(本研究只动「交互/反馈/引导/状态传达」层)。 +- 不追求真机听感验证(保持既有 roadmap §4 的人类听测流程)。 diff --git a/research/01-literature/01-audio-games-sota.md b/research/01-literature/01-audio-games-sota.md new file mode 100644 index 00000000..81c51c2c --- /dev/null +++ b/research/01-literature/01-audio-games-sota.md @@ -0,0 +1,324 @@ +# 音频游戏设计现状与代表作调研(RQ1:状态感知) + +> 项目:纯音频手机网页游戏交互设计研究(SoundGame) +> 报告编号:01-literature / 01 +> 调研日期:2026-08-30 +> 调研方法:英文检索为主,覆盖 GDC Vault 演讲、开发者 postmortem、访谈、媒体评测、视障社区(AFB AccessWorld、AppleVis、audiogames.net)与学术论文。凡未找到一手资料之处均已标注。 + +--- + +## ① 研究问题 + +**RQ1:优秀音频游戏如何让玩家保持状态感知?有哪些被验证的设计模式?** + +子问题拆解: +1. 音频游戏要求玩家实时知道哪些状态(位置 / 朝向 / 威胁方位与距离 / 自身生命与资源 / 当前可做的动作 / 目标进度)? +2. 这些状态分别通过什么通道呈现(双耳声像、音色语义、语音播报、触觉震动、旁白)? +3. 头几分钟如何建立玩家的"听觉操作模型"(教学)? +4. 玩家失败后如何归因与补救(纠错设计)? +5. 哪些做法被评论和社区反复批评(负模式)? + +本报告结论服务于:屏幕只有封面图、全音频 + 震动、6 手势输入的 HTML5 手机网页游戏。 + +--- + +## ② 逐作案例拆解 + +### 2.1 Papa Sangre(Somethin' Else,iOS,2010)——"用耳朵看"的第一人称音频游戏 + +**基本事实**:全球首款宣称"全动态双耳音频"的商业手游,25 个关卡,恐怖叙事(到死亡之国拯救被 Papa Sangre 绑走的朋友)。自研 Papa Engine,将单声道录音实时渲染为双耳定位声。开发约 1 年,核心团队 6 人,音效 1600+ 条(续作数据)。2013 年后下架、引擎开源。 + +1. **核心玩法与信息结构**:每关在黑暗地形中收集音符、躲避会"闻到你/听到你"的怪物(如 snufflehogs)。玩家需实时知道:自己面朝哪个方向、目标声源在哪、怪物离自己多近、脚下的地面材质(会暴露脚步声)。 +2. **状态感知手段**: + - 移动 = 左右脚两个按钮交替点击(慢点 = 走,快点 = 跑);转动 = 屏幕上方一个可滑动的"罗盘拨盘",转动直到目标声"听起来在正前方",再朝它走。 + - 距离感完全靠声音响度与双耳声像收敛;指引靠风铃类音效(chimes),"仔细听能听出远近"(Ars Technica)。 + - 怪物用吼叫/嗅探声预警,且地形不同脚步声不同——玩家与怪物通过"声音暴露"互相定位。 + - 每关开场有旁白"解释你的周围环境和你该避开什么"(TouchArcade 原文:"wonderfully narrated before the start of each level, explaining your surroundings")。 +3. **教学/引导**:第 1 关("In the Dark")由一个引导角色("fluttery watery thing")用台词教学:"在这个地下世界一片漆黑,你什么也看不见""你必须学会用耳朵去看""走向光"。 +4. **空间信息**:HRTF 双耳实时渲染;Ars Technica 引述制作人 Paul Bennun:成功双耳音频"比任何屏幕都更接近沉浸现实"。开发者承认部分人 HRTF 个体差异大、定位效果打折。 +5. **失败与纠错**:被怪物抓住即失败重来,检查点为关卡制(25 关小体量)。未见详细的一手参数。 +6. **被批评的点**:TouchArcade 只给 3 星——"需要特定心态才能享受,更多是'真奇妙'而非'真好玩'";部分玩家抱怨"就是把自己对准声音然后走过去",玩法单薄;虚拟摇杆/踏步操作被部分用户嫌"fussy";有玩家"怕到无法继续玩";另被学界批评:主角固定为男性呻吟音效、"用耳朵看"台词默认了明眼人视角(Sounding Out! Blog)。盲人 playtester 与明眼人水平差距极大——"VoiceOver 用户会踢爆你的屁股"(Bennun),说明音频技能需要分层难度。 + +**来源**: +- Ars Technica 一手访谈:https://arstechnica.com/gaming/2011/01/scared-of-the-dark-a-look-at-the-audio-game-papa-sangre/ +- TouchArcade 评测:https://toucharcade.com/2011/01/26/papa-sangre-review-a-clever-binaural-audio-game-without-graphics/ +- Sounding Out! 学术分析:https://soundstudiesblog.com/2013/10/28/papa-sangre-immersion-and-audio-games/ +- 引擎开源(AppleVis):https://www.applevis.com/blog/papa-sangre-other-audio-games-somethin-else-be-discontinued-their-game-engine-made-open-source + +--- + +### 2.2 The Nightjar(Somethin' Else,iOS,2011,旁白:Benedict Cumberbatch) + +**基本事实**:Papa Sangre 精神续作,废弃飞船逃生,全双耳音频,约 2 小时流程。 + +1. **核心玩法与信息结构**:沿飞船通道逃向出口。玩家需要知道:面朝方向、通道走向、出口面板声("faint beeps of access panels")、致命幽灵的距离。 +2. **状态感知手段**:操控极简——"两块光桥表示你的左右脚、一个旋转拨盘作罗盘"(TouchArcade)。危险与路径信息重叠设计:"越接近危险,也就越接近真正的出口",随逼近新声源浮现。两个旁白声音互相矛盾(飞船电脑 vs Cumberbatch 的引导者),"信任那个救过你的声音"——用叙事制造状态判断的张力。 +3. **教学/引导**:前几幕即教学;评测者承认"I failed a small number of early acts before I confidently connected to the UI"——失败本身是校准过程。 +4. **空间信息**:Papa Engine 双耳渲染;出口"救命的一声 ding"需要声像精确定位。 +5. **失败与纠错**:声像判断错 = 被幽灵抓 = 重来该幕;"如果感觉幽灵在咬你的脚跟,它真的就在"(声画一致的忠实度)。 +6. **被批评的点**:后半段难度陡增;评测者"在需要沉稳的时刻不断自我怀疑"——双耳定位个体差异导致的不确定性是劝退点;Guardian 肯定氛围但流程短。 + +**来源**: +- TouchArcade 评测:https://toucharcade.com/2013/05/03/the-nightjar-review-an-impressive-auditory-maze-of-fright/ +- Guardian 评测:https://www.theguardian.com/technology/2011/may/22/nightjar-ipad-iphone-game-review +- New Yorker(含 Somethin' Else 系列背景):https://www.newyorker.com/tech/annals-of-technology/a-video-game-that-you-cant-even-see + +--- + +### 2.3 A Blind Legend(Dowino × France Culture,iOS/Android/PC,2015)——与本项目最接近的标杆 + +**基本事实**:免费下载 + 内购复活;盲剑客 Edward Blake 携女儿 Louise 寻妻。零画面(官方定位"video-less game")。开发者 postmortem(Aymeric Lamboley 博客):约 1 年半开发,5 关,130MB 音频,5000+ 条音频剪辑,使用 3Dception(Two Big Ears)双耳引擎。 + +1. **核心玩法与信息结构**:走路 / 转向 / 战斗(挥剑、格挡)。玩家需知道:行进方向(跟不跟着 Louise)、敌人数量与各自方位、出剑时机、自身血量。 +2. **状态感知手段**(一手资料最丰富): + - **引导员角色 Louise**:用台词描述环境、指路、报敌人方位,且**随时可以让她重复指令**(AFB 评测确认)。 + - **双通道语音分离**:菜单/操作指令用 TTS 合成音,剧情用人声录音——玩家永远不会把"系统提示"误当"角色说话"。 + - **心跳声 = 血量**;战斗开始时非动作用低通滤波压低(战斗中只留下相关声音),躲进盾牌后整体音色变成"水下/闷住"(AFB:"It sounded like everything was happening under water")——**用全频段音色变化表达自身姿态状态**。 + - 战斗设计妥协(postmortem 原话):最多同时 4 个敌人、固定在 4 个方向攻击,这样玩家不需要精确定位每个敌人;战斗变成"在正确时机出剑"的节奏问题——**用约束敌人数量来换取方位感知的可靠性**。 + - 屏幕并非全黑:有云雾/剑光/受击时屏幕闪白,加上振动——全部可选,但默认开启。postmortem 明言:**"对大多数人来说黑屏 = 崩溃"**,所以屏幕上必须显示点什么。 +3. **教学/引导**:内置教学关 + Louise 可重复指令 + TTS 念操作说明。 +4. **空间信息**:双耳渲染 + 脚步/刀剑声方位 + Louise 口头报方位双保险。 +5. **失败与纠错**:多命制,命耗尽后几分钟后自动恢复(AFB:"multiple lives… regenerate after a few minutes");战斗失败可反复尝试;评测者仍在一场战斗卡关放弃——说明"时机型战斗 + 纯音频归因困难"仍是流失点。 +6. **被批评的点**:格挡(组合手势)"第一遍通关都没搞懂怎么用"(Metaphors and Moonlight)——组合手势必须强教学;法英翻译生硬("discard your fingers from the screen");内购页出现"If you are blind, ask someone to help you"被 AFB 点名批评;某场战斗不可通过(bug)。 + +**来源**: +- 开发者 postmortem(一手):http://www.aymericlamboley.fr/blog/a-blind-legend/ +- AFB AccessWorld 评测(视障视角):https://afb.org/aw/17/3/15351 +- Prime Gaming 访谈:https://primegaming.blog/dowino-on-making-games-for-change-and-their-video-less-game-a-blind-legend-f5a66c0db2ae +- Metaphors and Moonlight 评测:https://metaphorsandmoonlight.com/game-review-a-blind-legend-by-dowino/ + +--- + +### 2.4 Dark Echo(RAC7,iOS/Android/PC,2015)——声音可视化:把"声音"变成玩家能操作的对象 + +**基本事实**:Ludum Dare 26 极简主题 jam 作品(原型名 You Must Escape,第 2 名)扩展而成,两人团队(Jesse Ringrose 编程、Jason Ennis 图形/音频)。 + +1. **核心玩法与信息结构**:黑屏上只有你的脚印。走/拍手发出声波,声波沿地形反弹、短暂勾出墙壁与陷阱。玩家需要知道:地形轮廓、敌人(红色乱线 = 敌人脚步/异响)位置、自己的噪音水平(噪音引来敌人)。 +2. **状态感知手段**: + - **声音既是输入又是显示**:每一步都产生可见声波 = 位置自我确认 + 地形探测,一举两得。 + - 敌人"以红色狂乱线条"只在其发出声音时显形——**敌人状态用专属音色+专属视觉符号绑定**。 + - 水面溅水声"吸引附近所有敌人"——噪音水平本身是被管理的资源。 +3. **教学/引导**:刻意反教程。开发者明言讨厌手游式"手指点哪里都替你标好",只给单词级文字提示(第一个敌人出现时打一个"Run!")。因 jam 起家、机制单一人人秒懂,可以承受这种极端做法——**只有当输入-反馈闭环 < 1 秒时可省略教程**。 +4. **空间信息**:声波回波几何 = 距离与轮廓;立体声定位敌人。 +5. **失败与纠错**:死亡即时重来(单关短),死因可听(你最后的脚步/水声引来敌人),归因链路清晰。 +6. **被批评的点**:恐怖压力导致部分玩家放弃(开发者自己也承认"irrational fear"是刻意放大);关卡后期靠试错;2025 年 RAC7 已将游戏下架(Techmeme 报道)。 + +**来源**: +- 开发者访谈(Animal New York):https://animalnewyork.com/2015/03/06/making-dark-echo-minimalist-game-echolocation-fear/ +- 设计分析(Game Developer):https://www.gamedeveloper.com/design/what-dark-echo-do-that-you-should-do-in-your-game-either +- TouchArcade 评测:https://toucharcade.com/2015/02/11/dark-echo-review/ + +--- + +### 2.5 Blind Drive(Lo-Fi People,2021;GDC 2022 Audio Summit 演讲)——音频反应游戏的工程化范本 + +**基本事实**:黑色喜剧街机竞速:被蒙眼绑在车流中逆行,通过手机听筒里的绑匪电话指令开车。两键操控(左/右变道),27 关。获 GANG "最佳独立游戏音效设计"提名;GDC 2022 Audio Summit 演讲 "Designing Audio Based Game Mechanics"(Giori Politi)。 + +1. **核心玩法与信息结构**:玩家只需判断"威胁从左还是右来 + 什么时候打方向"。需要的状态:各车道车辆方位与距离、自身生命(3 次受击 = 回检查点)、关卡目标(撞警车/冰淇淋车回血等黑色喜剧规则)。 +2. **状态感知手段**(一手资料非常具体): + - **三层空间音频管线**:引擎/普通车辆/对话用预渲染 HRTF(DearVR Pro + 在开发者自己车里录的脉冲响应);Foley 用人头录音(dummy head);直升机、警车、枪手等动态威胁才用实时空间化——**按"可预测性"分配渲染预算**。 + - **主角自己的声音永远 mono、从不移动**——"像从你脑子内部发出",作为稳定的 POV 参照系。 + - **受击状态 = 全局混音变化**:被神风炸弹击中后"一切声音变模糊 + 耳内出现高频鸣响"(失聪模拟)——状态改变不用图标,用耳朵直接感受。 + - **混音分总线管理**:环境 / 外部车声 / 内部车声(基本不动,保持锚点)/ 敌人 / 受击音各自独立总线,保证"重要游戏信息在任何时刻清晰"。 + - FMOD 双向通信:音频数据反向驱动动画与**震动反馈**——震动跟随声音事件,天然同步。 + - **蓝牙耳机延迟补偿**:设置里可"把整个游戏机制的 timing 整体前移",因为约一半手游玩家用蓝牙耳机——把反应窗口还给玩家。 +3. **教学/引导**:每关开场对白既推进广播剧剧情、又必须"解释玩家接下来要做什么"(对白 = 关卡教程)。playtest 后立了条铁律:**凡是需要长时间解释的机制一律砍掉**,游戏必须 "fast and snappy"。 +4. **空间信息**:左/右二选一即可玩——刻意把连续方位问题降维成二元判断;距离以威胁逼近的时间窗表达。 +5. **失败与纠错**:3 命后回检查点,但"checkpoints are generous and plentiful"(TheSixthAxis),重启即时;失败原因在耳机里可听清(喇叭从哪边逼近)。 +6. **被批评的点**:压力过大——playtest 玩家"出汗、脸红、头晕、摘耳机"(开发者访谈原话);通关仅 2~3 小时(评测扣分点);没耳机没法玩(天然门槛);**难度技能差异极大且与游戏经验无关**:"硬核音乐家觉得极难,65 岁从没玩过游戏的女性轻松过关"——开发者自己都无法预测难度,这是音频游戏的普遍难题。 + +**来源**: +- A Sound Effect 深度访谈(一手):https://www.asoundeffect.com/blind-drive-sound/ +- Game Developer 开发访谈(一手):https://www.gamedeveloper.com/audio/creating-i-blind-drive-i-an-audio-sensory-driving-game-experienced-through-sound +- GDC 2022 演讲页:https://gdcvault.com/play/1028001/Audio-Summit-Designing-Audio-Based +- TheSixthAxis 评测:https://www.thesixthaxis.com/2021/03/17/blind-drive-review/ +- WIRED 预览:https://www.wired.com/story/blind-drive-review/ + +--- + +### 2.6 BlindSide(Aaron Rasmussen / Mr. Roboto,2012)——"写实声学失败"的关键教训 + +**基本事实**:无画面音频冒险(PC/iOS),New Yorker 报道。先建 3D 模型再转译成音频,1000+ 音效。iOS 版用机身陀螺仪:玩家转身 = 游戏内转身(评测者撞到真实家具)。 + +关键一手发现: +- 主角 Case 撞墙后会**大声自报方位**:"The door is to my left, the kitchen is to my right"——用角色台词直接播报空间关系。 +- 环境声标定:面朝开窗 = 双耳都有车流声;转向后车流声集中到左耳——环境声就是罗盘。 +- **最重要的负结果**:开发者最初做了物理写实的头部遮挡滤波,playtest 中玩家"在立体声耳机上根本听不出前后区别",最终**夸大头部对高频的遮挡效应**才可用。原话:"we had to exaggerate the effect of your head blocking high-frequency sounds behind you."——写实 ≠ 可读,可读性优先。 +- 难题定位:Astolfi 称最大挑战是"真实感与可玩性的比例",尤其"分辨声源在身后还是身前"。 +- 明眼玩家与盲玩家差异:盲玩家通常通关更快。 + +**来源**:New Yorker:https://www.newyorker.com/tech/annals-of-technology/a-video-game-that-you-cant-even-see + +--- + +### 2.7 Shades of Doom(GMA Games,Windows,2000 年代)——视障社区 FPS 的"信息播报系统"教科书 + +**基本事实**:面向盲人的第一人称射击,被誉为最早的音频 FPS 之一;GMA Games(盲人开发者 David Greenwood);5 档难度、9 个区域;DirectSound 3D,最多 32 路同时音效。 + +**可操作的状态感知设计**(50 Years of Text Games 回顾 + 官方页): +- **通道口用"风声"报方向**:每个方向的风声音色不同——"不同罗盘方向有不同的风"。 +- **脚步回声报空间**:某方向有开阔空间时,脚步回声在该侧耳朵更响;**即将撞墙前回声会先变化**——预告性反馈。 +- **夜视镜声呐**:ping 频率随怪物距离加快;怪物与面朝方向夹角越小**音调越高**;正对目标时播放"lock-on"音,确认开枪必中——**连续参数映射(角度→音高、距离→节奏)**。 +- **EVA 语音系统 = 游戏内读屏**:用语音报敌人类别、血量、房间尺寸与距离(英尺)。 +- 可给已探索房间打编号标记,甚至把地图输出到盲文打印机——**空间记忆外置**。 +- 设计哲学(Greenwood):"每个声音都是刻意的、充满信息的";批评早期游戏"几乎不用声音传递信息"。 + +**对本项目(3x3 密室逃脱)的启示**:房间编号语音标记、开口处风声、贴墙回声预警、lock-on 确认音——全部可直接移植。 + +**来源**: +- 官方页:https://www.gmagames.com/sod.html +- 50 Years of Text Games 回顾(一手细节):https://if50.substack.com/p/2005-shades-of-doom +- AFB AccessWorld 怀旧评测:https://afb.org/aw/21/12/17336 + +--- + +### 2.8 Three-D Velocity(BPC Programs / Munawar Bijani,Windows,~2012)——语音副驾驶 + 语音雷达 + +**基本事实**:盲人战斗飞行模拟;完全自发声(不依赖读屏器);有训练模式、任务模式、竞速/死斗/自动驾驶模式,支持力反馈与飞行摇杆。 + +状态感知手段(GitHub README 一手): +- **RIO(雷达拦截官)语音副驾驶**:任务中实时给关键反馈,如提示"翻滚躲导弹"。 +- **雷达用真人语音读出周边信息**;独立的武器雷达列出所有来袭导弹。 +- 听觉十字准星(auditory cross-hairs)锁定敌机与跑道。 +- 导弹呼啸、航炮开火、敌机掠过的方位声全部由真人配音系统冗余确认。 + +**启示**:复杂多资源状态(飞行仪表)用"专属语音角色持续播报关键变化"解决——对应本项目的旁白/解说角色。 + +**来源**:GitHub(一手):https://github.com/munawarb/Three-D-Velocity + +--- + +### 2.9 视障社区其他经典(audiogames.net 系) + +- **Sarah and the Castle of Witchcraft and Wizardry**(PCS Games,GMA 引擎,Windows):第一人称动作冒险,约 13 小时流程;学界(Lund University 等)评价其"导航音效运用极佳"。具体导航机制未找到一手描述,以下为推断:立体声方位 + 语音念出物品/敌人,属 GMA 引擎惯用做法。来源:https://blindhelp.net/software/Sarah-and-the-Castle-of-Witchcraft-and-Wizardry +- **Judgement Day**(Windows):audiogames.net 评价为"可能是功能最全的太空侵略者类游戏""音频游戏中最有野心的项目之一"。多维声像(方位×距离×高度)+ 语音播报武器/弹药。详细参数未找到一手资料,标注为推断。来源:http://fog.audiogames.net/db.php?action=view&id=judgementday +- **Crazy Party**(Pragma,Windows,免费):130+ 小游戏、13 个世界、8 种语言,社区"我最爱的音频游戏";每分钟级的小游戏 = 单规则快循环,失败即时重试。2024 年起开发停滞(Black Screen Gaming 专题)。来源:http://pragmapragma.free.fr/crazy-party/ 、https://blog.blackscreengaming.com/audio-games/what-happened-to-crazy-party/02/03/2024/ +- **EchoVis 系列**(波兰 Techfield,iOS/Android,2018 起):EchoVis Street(立体声车流中过马路)、EchoVis Game(回声定位教学)、EchoVis Quiz(听力敏感度训练)——单一听觉技能 + 立即反馈的"小关卡"结构,至今仍在更新,是 2020 年代视障社区手游的活样本。来源:https://play.google.com/store/apps/details?id=pl.com.tt.echovis.street + +--- + +### 2.10 其他音频主导产品(互动音频剧 / 声音解谜 / 2024–2026 新动态) + +- **Alt-Frequencies**(Accidental Queens × ARTE,2018):时间循环广播解谜——电台每 **3 分钟**重置,玩家录制片段再投放到别的电台。把"时间"变成可录制/回放的操作对象;有 Alexa 语音版。对"节奏跟随/记忆复现"类玩法的启示:给玩家一段可反复听的小片段作为操作单元。来源:http://accidentalqueens.com/press/alt-frequencies/ +- **Earplay**(美国):语音输入的互动广播剧平台(Alexa/Google Assistant),玩家用说话推动剧情;White Wolf/Paradox 曾合作。证明"语音 = 输入"在音频剧品类可行,但对 6 手势项目参考有限。来源:https://earplay.com/press/ 、https://www.gamedeveloper.com/audio/why-veteran-game-devs-are-now-creating-interactive-audio-dramas +- **RidePods**(2025-09,iOS):用 AirPods 头部动作 + 反向工程的空间音频硬件做体感摩托车竞速(The Verge / MacRumors / Tom's Hardware 报道)。信号:耳机的头部追踪传感器开始成为音频游戏输入。来源:https://www.theverge.com/news/787396/ride-pods-race-with-head-apple-airpods-spatial-audio-motion-controls +- **Audemy**(2024–,audemy.org):面向盲人的 AI 生成音频游戏平台,代表"AI TTS 降本"后的音频游戏供给扩张。来源:https://audemy.org/ +- 2017–2018 年学界跟进:Garcia & Neris《Design Guidelines for Audio Games》提出 50 条指南(9 款游戏案例验证);同一团队 2018 年《Fair Play》提出 33 条无障碍音频游戏指南;Borges & Campos 2017《"I'm Blind, Can I Play?"》给出 audiogame 开发建议清单。来源见 ④。 + +--- + +## ③ 横向综合:15 条被验证的设计模式 + +> 格式:模式名 → 做法(参数级)→ 来源作品与出处 → 对本项目的启示。置信度:★=一手开发者资料确认;☆=评测/社区多方一致。 + +**P1. 语音引导员角色:环境、方向、下一步动作由一个"角色"持续播报,且指令必须可随时重听** ★ +A Blind Legend 的 Louise("可随时让她重复指令")、TDV 的 RIO、The Nightjar 的 Cumberbatch、Papa Sangre 的开场引导。启示:为 6 款游戏设计统一的"引导者"声线(如武侠 RPG 的师兄),关键指令("上滑翻墙")在玩家闲置 3~5 秒未操作时自动复述一次(复述机制为一手确认;自动复述的时限为本项目建议参数)。 + +**P2. 系统音与叙事音分离:TTS 念指令/菜单,人声演剧情** ★ +A Blind Legend:菜单与操作说明用合成音,剧情用配音,玩家不会混淆"谁在对我说话"。启示:所有 6 款游戏共用一套 TTS"系统声"做状态播报与手势确认,剧情/BGM 完全不让渡该音色。 + +**P3. 事件前置音(预警窗口):威胁声必须先于命中出现,且逼近过程连续可闻** ★ +Blind Drive:车辆喇叭/引擎按方位逼近、受击前有完整时间窗;TDV:导弹呼啸 + RIO 语音提示"翻滚"。Shades of Doom:撞墙前脚步回声先变化。启示:每个危险事件设定"预警音 → 判定"的时间窗(Blind Drive 未公布具体秒数,建议本项目从 1.5~2 秒起调),预警音强度随距离连续上升。 + +**P4. 方位编码降维:把连续方位问题压到二元(左/右)或四元(前/后/左/右)** ★ +Blind Drive 只要求判断左右再按键,因此可以做到"听得出、按得快";A Blind Legend 战斗把敌人限制在 4 个固定方向、最多 4 个同时攻击,让双耳定位必然可靠。启示:陨石闪避的方位只做左/右(或前/后左右 4 象限),且同屏威胁 ≤ 4;超出时用语音播报"三点钟方向"兜底。 + +**P5. 渲染预算按"动态性"分层:静态用预渲染 HRTF,只有不可预测的威胁用实时空间化** ★ +Blind Drive 三层管线(预渲染 HRTF / 人头录音 / 实时空间化)。启示:HTML5 网页端算力与一致性都受限——固定环境声直接用双耳素材(甚至真实录音),只有敌人/移动物体做实时 panning,稳定性远比全实时渲染重要。 + +**P6. 写实声学不可读:主动夸张化** ★ +BlindSide:物理正确的头部遮挡滤波玩家听不出来,必须夸大高频遮蔽;A Blind Legend:战斗中把无关声音整体低通压低。启示:前后方位差、距离衰减曲线都要比物理值夸张一档;前后区分可用"闷(后)/亮(前)"的滤波对比而非仅 ITD。 + +**P7. 状态变化 = 全局混音/音色签名变化,而不是提示音** ★ +Blind Drive 受击后全声场模糊 + 耳鸣音;A Blind Legend 举盾 = 水下闷声、心跳 = 低血量。启示:低血量、剩余次数不足、倒计时逼近等状态各绑定一个"全局滤镜签名"(低通、耳鸣、心跳叠加 BGM),让玩家"耳朵里整体感觉不对"即知道状态变了。 + +**P8. 玩家自身的声音是固定锚点:主角呼吸/心跳/自言自语永远居中 mono 不移动** ★ +Blind Drive 主角人声永不空间化;BlindSide 主角撞墙后自报方位。启示:给玩家一个恒定的"自我声"(呼吸声或角色低语),所有空间声以它为原点;碰撞/出错时由它说出方位话术("墙在我右边")。 + +**P9. 每关开场旁白 = 地形 + 威胁 + 目标三要素,60 秒内讲完** ★ +Papa Sangre 每关前旁白解释环境与要避开的怪物(评测确认);Blind Drive 每关对白 intro 同时是玩法说明。启示:6 款游戏统一"关卡开场播报模板":这里是哪(场景音垫底)→ 你要做什么(目标)→ 危险是什么(威胁音色预览)。威胁音色预览尤其重要——先听到"教学版"威胁声,再在实战中遇到。 + +**P10. 教学铁律:需要解释超过一句话的机制直接砍掉** ★ +Blind Drive playtest 后的硬规则("ideas requiring long explanations were cut");对照反例:A Blind Legend 的格挡组合手势没教会玩家,整周目没用上(评测实锤)。启示:6 手势中每个手势在每款游戏里只绑一个主动作;任何需要组合/长按变体的机制要么重做要么删除。 + +**P11. 失败归因链路可听化 + 宽容检查点** ★ +Blind Drive:3 命 + "generous and plentiful"检查点 + 即时重启;A Blind Legend:多命、几分钟后自动恢复;Dark Echo:死亡原因(你自己的噪音)在死前 2 秒内可听。启示:每次失败后 1 句语音归因("刚才左边的车喇叭太近了"),检查点粒度 ≤ 1 分钟;失败→重试必须 ≤ 2 秒。 + +**P12. 触觉跟随音频事件走,且与"可选视觉最小化"并行** ★ +Blind Drive 用 FMOD 音频数据驱动震动;A Blind Legend 屏幕闪光 + 振动全部可选但默认开。启示:受击/成功/方位(左/右可分别用左右侧震动强弱)三事件接手机 vibration API;屏幕保留封面图 + 极简状态角标(生命、进度),既防"黑屏 = 闪退"误解又不泄题。 + +**P13. 屏幕上必须永远显示点什么:黑屏会被当成崩溃** ★ +A Blind Legend postmortem 原话("对大多数人来说,黑屏 = 崩溃")。启示:本项目"只有封面图"的约束下,封面图上必须叠加呼吸感动效/进度点/生命图标,证明"游戏活着"。 + +**P14. 蓝牙耳机延迟补偿必须是设置项** ★ +Blind Drive 提供"整体 timing 前移"选项,理由:约一半移动玩家用蓝牙耳机。启示:HTML5 + 手机 + 蓝牙 = 音频输出延迟不可控;节奏跟随与陨石闪避两作必须提供校准流程(听一声→点按→测偏移)或至少 3 档延迟补偿。 + +**P15. 听觉技能方差极大且不可预测:难度必须自适应或可调** ★ +Blind Drive playtest:硬核游戏音乐家卡关、65 岁非玩家轻松通过;Papa Sangre:盲测者远强于明眼测试者。启示:上线前用"听方位测试关"(3 次判断左右)给玩家定档,动态调整预警窗口时长(如 2.0s / 1.5s / 1.0s 三档),而不是让所有玩家吃同一套反应窗口。 + +**补充(★ 级、可并入 P4/P14 使用)**:Shades of Doom 的"连续参数映射"——夹角→音高、距离→ping 节奏、方向→风声音色,是 3x3 密室逃脱最直接可抄的参数表(含用语音报"房间编号 + 英尺距离"的做法)。 + +**负模式清单(被评论反复批评,勿踩)**: +- 纯音频"时机型战斗"无视觉辅助归因 → A Blind Legend 卡关弃游(AFB + Moonlight 双评测); +- 组合手势教学失败 → A Blind Legend 格挡; +- 转向操作(拨盘)校准成本高 → The Nightjar / Papa Sangre 前期失败与"自我怀疑"; +- 双耳定位个体差异未做校准 → Papa Sangre 部分玩家"感受不到 3D"; +- 恐怖压力不加调节 → Blind Drive 摘耳机、Dark Echo 弃坑; +- 强迫耳机但无替代方案提示 → Blind Drive 评测扣分点(本项目场景玩家必戴耳机,风险转移为"没戴耳机进游戏"需入口检测提示)。 + +--- + +## ④ 参考来源列表 + +**开发者一手资料 / GDC** +1. A Sound Effect — Behind Blind Drive's Essential Game Audio(Ian Garic 访谈):https://www.asoundeffect.com/blind-drive-sound/ +2. Game Developer — Creating Blind Drive:https://www.gamedeveloper.com/audio/creating-i-blind-drive-i-an-audio-sensory-driving-game-experienced-through-sound +3. GDC 2022 Audio Summit — Designing Audio Based Game Mechanics(Giori Politi, Lo-Fi People):https://gdcvault.com/play/1028001/Audio-Summit-Designing-Audio-Based +4. Aymeric Lamboley — A Blind Legend postmortem:http://www.aymericlamboley.fr/blog/a-blind-legend/ +5. Animal New York — Making Dark Echo(RAC7 访谈):https://animalnewyork.com/2015/03/06/making-dark-echo-minimalist-game-echolocation-fear/ +6. Ars Technica — Scared of the dark(Paul Bennun 访谈):https://arstechnica.com/gaming/2011/01/scared-of-the-dark-a-look-at-the-audio-game-papa-sangre/ +7. Nick Ryan(Papa Sangre/The Nightjar 音频总监)博客:https://www.nickryanmusic.com/blog/papa-sangre-3d-audio-iphone-game +8. Prime Gaming — DOWiNO 访谈:https://primegaming.blog/dowino-on-making-games-for-change-and-their-video-less-game-a-blind-legend-f5a66c0db2ae +9. Three-D Velocity GitHub(BPC Programs):https://github.com/munawarb/Three-D-Velocity +10. GMA Games — Shades of Doom 官方页:https://www.gmagames.com/sod.html +11. Crazy Party 官方页(Pragma):http://pragmapragma.free.fr/crazy-party/ + +**评测与媒体分析** +12. TouchArcade — Papa Sangre 评测:https://toucharcade.com/2011/01/26/papa-sangre-review-a-clever-binaural-audio-game-without-graphics/ +13. TouchArcade — The Nightjar 评测:https://toucharcade.com/2013/05/03/the-nightjar-review-an-impressive-auditory-maze-of-fright/ +14. The Guardian — The Nightjar 评测:https://www.theguardian.com/technology/2011/may/22/nightjar-ipad-iphone-game-review +15. The New Yorker — A Video Game That You Can't Even See(BlindSide):https://www.newyorker.com/tech/annals-of-technology/a-video-game-that-you-cant-even-see +16. TheSixthAxis — Blind Drive 评测:https://www.thesixthaxis.com/2021/03/17/blind-drive-review/ +17. WIRED — Blind Drive 预览:https://www.wired.com/story/blind-drive-review/ +18. Game Developer — What Dark Echo does that you should do:https://www.gamedeveloper.com/design/what-dark-echo-do-that-you-should-do-in-your-game-either +19. Metaphors and Moonlight — A Blind Legend 评测:https://metaphorsandmoonlight.com/game-review-a-blind-legend-by-dowino/ + +**视障社区 / 无障碍视角** +20. AFB AccessWorld — A Blind Legend 评测:https://afb.org/aw/17/3/15351 +21. AFB AccessWorld — Shades of Doom 怀旧评测:https://afb.org/aw/21/12/17336 +22. AFB AccessWorld — Blindness Accessibility Deep Dive:https://afb.org/aw/fall2023/Blindness-Accessibility-in-Video-Games-A-Deep-Dive +23. AppleVis — Somethin' Else 音频游戏下架与引擎开源:https://www.applevis.com/blog/papa-sangre-other-audio-games-somethin-else-be-discontinued-their-game-engine-made-open-source +24. Blind Help Project — Sarah and the Castle of Witchcraft and Wizardry:https://blindhelp.net/software/Sarah-and-the-Castle-of-Witchcraft-and-Wizardry +25. audiogames.net 数据库 — Judgement Day:http://fog.audiogames.net/db.php?action=view&id=judgementday +26. Black Screen Gaming — What Happened to Crazy Party?:https://blog.blackscreengaming.com/audio-games/what-happened-to-crazy-party/02/03/2024/ +27. EchoVis Street(Google Play,Techfield):https://play.google.com/store/apps/details?id=pl.com.tt.echovis.street + +**学术论文 / 设计指南** +28. Garcia & Neris (2013). Design Guidelines for Audio Games. HCII 2013, Springer, pp.229–238(50 条指南):https://link.springer.com/chapter/10.1007/978-3-642-39262-7_26 (全文:https://www.academia.edu/61440259/Design_Guidelines_for_Audio_Games) +29. Garcia et al. (2018). Fair Play: A Guidelines Proposal for the Development of Accessible Audiogames(33 条指南):https://www.researchgate.net/publication/325620762_Fair_Play_A_Guidelines_Proposal_for_the_Development_of_Accessible_Audiogames_for_Visually_Impaired_Users +30. Borges & Campos (2017). "I'm Blind, Can I Play?" Recommendations for the Development of Audiogames. HCII 2017:https://www.researchgate.net/publication/317183424_I'm_Blind_Can_I_Play_Recommendations_for_the_Development_of_Audiogames +31. Aaron A. Reed — 50 Years of Text Games: Shades of Doom(音频设计细节):https://if50.substack.com/p/2005-shades-of-doom +32. Audiokinetic — Blind Accessibility in Interactive Entertainment:https://www.audiokinetic.com/en/community/blog/blind-accessibility-in-interactive-entertainment (正文 403,仅目录,见 AFB #22 替代) + +**2024–2026 新动态** +33. The Verge — RidePods(AirPods 体感音频竞速,2025):https://www.theverge.com/news/787396/ride-pods-race-with-head-apple-airpods-spatial-audio-motion-controls +34. Audemy(AI 音频游戏平台):https://audemy.org/ +35. Access-Ability — 2025 Video Game Accessibility Recap:https://access-ability.uk/2025/12/05/2025-video-game-accessibility-recap/ + +--- +### 未找到一手资料、以上报告中为推断的内容(汇总) +- Papa Sangre 的死亡/重生具体规则与检查点参数; +- The Nightjar 的具体预警时间窗数值; +- Judgement Day 与 Sarah 系列的具体空间播报参数(机制描述基于 audiogames.net 词条与 GMA 引擎惯例推断); +- 各作双耳定位的 ITD/ILD 具体数值(各家引擎均为专有实现); +- GDC 2022 Blind Drive 演讲全文(Vault 需订阅,本报告以两篇一手访谈替代)。 diff --git a/research/01-literature/03-accessibility-blind-gaming.md b/research/01-literature/03-accessibility-blind-gaming.md new file mode 100644 index 00000000..42a1f04e --- /dev/null +++ b/research/01-literature/03-accessibility-blind-gaming.md @@ -0,0 +1,247 @@ +# RQ3 调研报告:视障玩家的交互惯例与纯听觉界面中的状态感知 + +> 项目:纯音频 HTML5 手机游戏交互设计研究(无画面,音频+震动,6 种手势:上下左右滑/单击/双击+长按) +> 研究问题(RQ3):**视障玩家已形成哪些交互惯例与期望?资深视障玩家如何在纯听觉界面里保持状态感知?** +> 调研时间:2026-08。方法:WebSearch/WebFetch 英文一手来源(指南原文、玩家社区博客与评论、读屏官方文档、同行评审论文)。 +> 标注约定:凡未能直接核验一手原文、由二手转述或合理推论得出的内容,均标注【推断】。 + +--- + +## ① 研究问题 + +视障(盲/低视力,下称 BLV)玩家是纯音频游戏最资深的用户群,30 多年来围绕读屏(VoiceOver/TalkBack/NVDA)和音频游戏(audiogames)已经形成一套稳定的、近乎"肌肉记忆"的交互惯例。本报告回答两个子问题: + +- **RQ3a**:这些惯例具体是什么(手势语义、语音规则、菜单结构、声音编码)?参数是什么? +- **RQ3b**:资深 BLV 玩家在无画面条件下靠什么保持"我在哪、我处于什么状态、下一步能做什么"的状态感知(state awareness)? + +核心论点:新玩家流失的根源(不知道自己处于什么状态、不知道手势含义)在 BLV 玩家社区早有成熟解法——**"探索-激活分离"的读屏手势范式 + 全局状态播报键(status/where-am-I key)+ 可打断的自朗读(self-voicing)+ 阈值化状态播报 + 分层声音编码**。这些应被视为本项目的"行业标准"基线。 + +--- + +## ② 分主题发现 + +### 2.1 主流游戏无障碍指南中的音频/听觉条目 + +**Game Accessibility Guidelines(gameaccessibilityguidelines.com)**——业界引用最广的游戏无障碍清单(Ian Hamilton、AbleGamers 等联合维护,2012 年至今,获多个奖项),按 Basic / Intermediate / Advanced 三级组织: + +| 条目(原文要点) | 级别 | 对本项目的含义 | +|---|---|---| +| Ensure screen reader support, including menus & installers(含移动端读屏支持) | Basic | 菜单/安装/设置必须可被 VoiceOver/TalkBack 读出 | +| Provide pre-recorded voiceovers for all text(自朗读/预录语音读出全部文本) | Basic | 指南明确指出:BLV 玩家常把读屏与"挫败体验"关联,**偏爱游戏内置 self-voicing**;技术上比读屏支持更容易实现 | +| Use distinct sound / music design for all objects and events | Basic | 玩家用"角色动作声/招式声/环境底噪"作为方位与事件判断依据,环境声是定位锚点 | +| Provide separate volume controls / mutes for effects, speech, music | Basic(听觉)/ Intermediate(视觉) | 语音、音效、音乐分轨音量——语音轨可独占提升,音效可降噪底 | +| Provide a stereo/mono toggle | Basic | 单声道兼容(外放/单耳用户) | +| Provide a pingable sonar-style audio map(声呐式可触发音图) | Advanced | 按需触发"周围有什么、在哪个方向"的播报,复杂环境可导航的关键 | +| Simulate binaural recording(双耳/空间音频) | Advanced | 方位感来源 | +| Ensure important audio-conveyed info is replicated in text/visuals(如被攻击方向) | Intermediate | 反向冗余:音频信息也要留文字/日志通道 | +| Provide an audio description track | Advanced | 过场/剧情的口述影像 | + +来源: +- 全清单:https://gameaccessibilityguidelines.com/full-list/ +- 读屏支持条目:https://gameaccessibilityguidelines.com/ensure-screenreader-support-including-menus-installers/ +- 移动端读屏:https://gameaccessibilityguidelines.com/ensure-screenreader-support-for-mobile-devices/ +- 自朗读:https://gameaccessibilityguidelines.com/provide-pre-recorded-voiceovers-for-all-text-including-menus-and-installers/ +- 声音区分设计:https://gameaccessibilityguidelines.com/use-distinct-sound-music-design-for-all-objects-and-events/ +- 声呐音图:https://gameaccessibilityguidelines.com/provide-a-pingable-sonar-style-audio-map/ + +**AbleGamers**:核心产出是 APX(Accessible Player Experiences)工具包,强调把音频线索、输入替代纳入"玩家体验层"设计而非事后补丁。其参与维护的 gameaccessibilityguidelines 为上述条目背书。 +- https://ablegamers.org/ ;APX:https://accessibleplayerexp.com/ 【APX 具体条目未逐条核验,推断与指南一致】 + +**RNIB(英国皇家盲人协会)**:"Design for Every Gamer" 开发者指南 + 2018 年前后与高校合作的无障碍游戏研究。核心结论(引自引用该报告的论文):**"Audio-based solutions are most desired by blind and visually impaired users"——音频方案是 BLV 用户最想要的**。RNIB 还与 Activision 合作研究 BLV 玩家的社交游戏收益(2026)。 +- https://www.rnib.org.uk/living-with-sight-loss/assistive-aids-and-technology/tv-audio-and-gaming/design-for-every-gamer/ +- 引用页(Huddersfield 论文 PDF):https://pure.hud.ac.uk/files/113755847/17_Final_thesis.pdf +- Activision×RNIB 研究:https://research.activision.com/publications/2026/Video_games_positive_impact_blind_and_partially_sighted + +**W3C**:澄清一个常见误解——W3C **没有**专门的游戏无障碍标准("WAEX"应为误记)。相关文件是: +- UAAG 2.0(User Agent Accessibility Guidelines,W3C Working Group Note):读屏/媒体播放器如何暴露信息,https://www.w3.org/TR/UAAG20/ +- W3C Mobile Accessibility WCAG Extension(移动无障碍扩展):其中明确记录了平台手势惯例——**"VoiceOver reserves the double tap to activate an item"(双击=激活是系统保留语义)**,并指出 explore-by-touch 单独使用不充分:**用户会在不知情的情况下漏掉内容**(所以必须有显式的"读全部/重听"通道)。http://w3c.github.io/Mobile-A11y-Extension/ +- XR Accessibility User Requirements (XAUR):空间音频、非视觉反馈的 XR 需求,可类推到纯音频游戏。https://www.w3.org/TR/xaur/ +- IGDA Game Accessibility SIG 指南亦推荐 self-voicing(把屏幕文本转语音的能力):https://igda-gasig.org/get-involved/sig-initiatives/resources-for-game-developers/sig-guidelines/ + +**GDC / 3A 实践(The Last of Us Part II)**: +- Naughty Dog 演讲 "The Accessibility in The Last of Us Part II: A 3 Year Journey"(Emilia Schatz & Matthew Gallant,GDC 2021 版本于 YouTube 可看):60+ 项无障碍设置。 +- 关键设计:**Traversal & Combat Audio Cues**——把常用动作/敌人动作映射为"易识别的声音标签",战斗中用**语音标签(speech tags,如喊" Above / 手雷 / 侧面")+ 震动**标注敌人位置与动作,使全盲玩家可通关;菜单内置 TTS 且**语速可调**。官方页:https://www.playstation.com/en-us/games/the-last-of-us-part-ii/accessibility/ +- 全盲玩家实测评论(证实可无视觉通关):Game Accessibility Nexus:https://www.gameaccessibilitynexus.com/blog/2020/06/12/blind-low-vision-game-review-the-last-of-us-part-ii/ ;Can I Play That?(无障碍游戏媒体):https://caniplaythat.com/ +- 音频中间件视角(Audiokinetic,"声呐式回声定位音效是标注目标方向的最常见做法"):https://www.audiokinetic.com/en/community/blog/blind-accessibility-in-interactive-entertainment/ + +### 2.2 视障玩家社区的实测经验(最恨什么、最看重什么) + +**The Blind Nerd(盲人玩家博客)的音频游戏设计要点**(一手玩家视角): +- **在标题画面加载出来之前**就要有旁白宣告"如何开启语音/如何操作"——把可用性宣告放在最前面,而不是藏在设置里; +- 菜单不发声 = 不可玩:某游戏(Blind Love)存读档菜单静音,作者**干脆不敢存档**;另一例中菜单移动只有"咔哒声、不念条目名",直接判死; +- 走路/移动要用**雷达/信标**:接近目标时哔声变响变密;要有**非脚步声的移动反馈**(脚步声在混响环境里听起来像原地踏步); +- 空场景要用人群环境声填满,否则"死城"感;要给玩家角色本身配音(不只是 NPC); +- 教程要讲透:作者是"反复被 boss 打死后在菜单里乱按"才发现还能买技能——教程欠账导致错误归因; +- 不要把"无障碍"等同于"黑屏纯音频":保留低视力支持(放大、反色、TTS 菜单)。 +- 来源:https://theblindnerdblog.wordpress.com/tag/blind-gaming/ + +**AudioGames.net / audiogames.net 生态**(音频游戏最大社区与数据库,论坛 forum.audiogames.net 搜索引擎收录差,以下为数据库与镜像可核验部分): +- 数据库经典高分作品:《Swamp》(音频射击):多种**雷达模式**(扫左侧/右侧、像盲杖一样前方来回扫、扫身后、连续全扫)+ 区域名称播报 + **信标**(越接近目标哔声间隔越短)+ 全键位可重映射;http://w.audiogames.net/db.php?action=view&id=Swamp +- 《A Hero's Call》《Manamon》《The Vale》:被社区与 AFB 反复引用为"好音频游戏"范本(见 2.4)。 +- 社区抱怨高频词(由玩家博客、论坛镜像与评论归纳【推断】:未知等待(加载/对手回合无声音)、静默死局(不知道卡住还是游戏坏了)、无法打断的长语音、方位不清、菜单不发声)。 +- "What Makes a Good Audio Game?"(盲人开发者 Talon,2026-01,Games for Blind Gamers jam 特邀文章,转贴于 Reddit):系统总结好音频游戏标准,涉及等待与静默问题。原文 Reddit 页被 403 拦截未全文核验【推断,二手】:https://www.reddit.com/r/disabledgamers/comments/1qlqixf/what_makes_a_good_audio_game_by_talon_games_for/ + +**CHI 2025《How Users Who are Blind or Low Vision Play Mobile Games》**(32 名中国资深 BLV 手游玩家访谈,26 盲 + 6 低视力;一手实证,对本项目最重要): +- BLV 专属手游已形成**标准化手势**:**双击=确认、滑动=导航、列表式菜单、内置焦点系统**——与读屏惯例同构; +- **状态感知是最大痛点**:战斗要同时追踪技能、位置、血量,P7:"多个音频通道重叠时,会导致信息过载"→ 需要**音频通道分层(关键信息 vs 环境信息)与优先级排序**; +- 触屏的"**不知道自己不知道什么**"问题:看不见的屏幕区域没有音频/触觉线索;出现 `` 之类的未标注元素时,P3 说"每一个都像在提醒我是个盲人"; +- **反馈断层导致失败不可归因**:P18"音频线索不完整时,玩家可能毫无预兆地死亡,却不明白为什么失败"; +- **过度简化的歧视感**:P30 已彻底退出 BLV 游戏:"BLV 游戏把 BLV 玩家当白痴,只给极简单的游戏"——纯音频不等于低龄化; +- 玩家自发策略:靠脚步声/音乐变化/环境声做空间感知;低视力玩家把手机举到眼前 10 cm;社区流媒体主(7000+ 粉)做插件和教程互相传帮带; +- 设计建议(作者方):从第一天内置读屏/焦点导航;**默认开无障碍模式、可一键退出**;音频分层通道;提供"盲人模式/明眼人模式"双态。 +- 来源:https://arxiv.org/html/2502.09866v1 + +### 2.3 读屏交互惯例 → 游戏手势设计的迁移 + +iOS VoiceOver / Android TalkBack 的手势词汇表(官方与 W3C 文档确认,全球数百万 BLV 用户的肌肉记忆): + +| 手势 | VoiceOver/TalkBack 语义 | 迁移建议 | +|---|---|---| +| 单指拖动/触摸 | 探索(explore by touch):念出手指下元素 | 单击=聚焦+播报,**不执行** | +| **双击(任意位置)** | 激活聚焦项("VoiceOver reserves the double tap") | 双击=确认/执行,全游戏统一 | +| 单指左右滑动 | 焦点在元素间移动 | 选项切换(上/下滑或左/右滑逐项播报) | +| 单指上下滑动 | 随 rotor 模式:切元素类型/调值 | 模式切换或参数增减 | +| 两指旋转 | rotor:按标题/链接/语速等维度导航;Perkins:**可直接调速** | 我们的"双击+长按组合/长按"可承载类似维度切换【本项目手势集无 rotor,需用长按菜单替代,推断】 | +| 两指轻点 | 暂停/继续朗读 | 语音暂停 | +| 两指双击(Magic Tap) | 执行最重要动作 | 可映射为"播报状态" | +| 两指 Z 字滑动 | Escape/返回 | 返回上级 | + +关键研究佐证: +- W3C Mobile A11y Extension 明文记录双击激活惯例,并警告 explore-by-touch 会漏内容(需"读全部"补充):http://w3c.github.io/Mobile-A11y-Extension/ +- W3C Mobile A11y Task Force 会议记录:"one click to focus, double-click to activate" 为标准模式:https://www.w3.org/2015/11/12-mobile-a11y-minutes.html +- 盲人可及性专家 Jonathan Mosen 对手势不一致的批评:平台间手势不一致直接摧毁肌肉记忆(他因 TalkBack 早期手势不稳而买外接键盘):https://mosen.org/why-i-want-android-accessibility-to-succeed/ +- CHI'25 中国 BLV 手游研究实证:本地 BLV 游戏已把"双击确认、滑动导航、列表菜单"作为事实标准:https://arxiv.org/html/2502.09866v1 +- rotor 与标题导航(AFB / Perkins / Apple 官方):https://afb.org/blindness-and-low-vision/using-technology/cell-phones-tablets-mobile/apple-ios-iphone-and-ipad-2 ;https://www.perkins.org/resource/voiceover-rotor-options-idevices/ ;https://support.apple.com/guide/voiceover/voiceover-rotor-mchlp2719/mac +- 读屏器自身的"Where am I?"命令(NVDA 桌面惯例,Enter 数字键盘):https://download.nvaccess.org/releases/2026.1.1/documentation/userGuide.html + +**结论(惯例迁移原则)**:凡手机上已存在的手势语义,游戏中沿用即"零学习成本";与之冲突的语义 = 主动制造挫败。**探索(聚焦播报)与激活(双击确认)分离**是第一惯例。 + +### 2.4 资深 BLV 玩家的"状态感知"技术 + +**(a)声音分类学**(Friberg & Gärdenfors 2004,音频游戏声音五分类,被后续研究广泛引用):avatar(自己)/ object(物体)/ character(他人)/ ornamental(装饰氛围)/ instruction(指令与状态)声音。纯音频游戏必须保持该分类的音色一致性。 +- https://www.semanticscholar.org/paper/Audio-games%3A-new-perspectives-on-game-audio-Friberg-G%C3%A4rdenfors/4c31eafc8865962a83c419f5eab0b97f57493d81 ;综述见 https://gamestudies.org/1301/articles/oldenburg_sonic_mechanics + +**(b)三属性空间编码**(AFB AccessWorld 深度文章,一手工程指南): +- **方向**=声像 pan(左右);**距离**=音量;**高度/前后**=音高;身后的声音做闷化/滤波处理以示区分; +- 视觉上无声的对象(收集品、悬崖、机关)配**人工音**(哔声/铃声),本身有声的对象(门、床、水)配**自然音**——《Manamon》惯例:墙与角色用人工音、家具用自然音;《The Vale》战斗全靠自然声+空间音频; +- 不要给已有声音的对象再加提示音(火堆无需再标);危险物可在"还差一步"时才加提示。 +- 来源:https://afb.org/aw/fall2023/Blindness-Accessibility-in-Video-Games-A-Deep-Dive + +**(c)雷达/信标/声呐**: +- 《Swamp》雷达四模式 + 信标"哔声间隔随距离缩短"(见 2.2);声呐 ping 是 3D 游戏标注目标方向的最常见手段(gameaccessibilityguidelines Advanced 条目;Audiokinetic 工程博客)。 +- 混响作为信息通道:AES 2023 系统综述确认**早期反射与混响衰减让 BVI 用户推断房间大小、声源距离与自位置**——混响不是氛围,是导航数据:https://micalab.org/publications/051/aes2023.pdf ;回声定位训练游戏 EchoExplorer:https://dl.acm.org/doi/full/10.1145/3676557 +- 导航技能训练实证:Sánchez et al. 2010(音频游戏显著提升 BLV 青少年 O&M 导航技能):https://pmc.ncbi.nlm.nih.gov/articles/PMC4259046/ + +**(d)听觉 HUD = status key 惯例**(对本项目最直接可用): +- AFB 文章给出的标准做法:**专用按键按需播报** HUD 数据——直觉键位"H=Health 血量、S=Score 分数、T=Time 时间"(《Hearthstone Access》按手位排布);控制器按键不够时,**给最重要的一个信息留快捷键,其余放进可暂停菜单**; +- **被动阈值播报**:血量在 75% / 50% / 25% / 15% / 10% 等节点自动播报——玩家不需要主动查询也知道状态拐点; +- 出现大段说明文字后要能**一键重听**; +- 《Swamp》等音频游戏与 Godot 盲用插件 **Lantern** 均内置 **"where am I" 键 + 方位概览(directional survey)**:https://www.reddit.com/r/blindgamers/ ; +- 街导应用 StreetReaderAI 的共设计结果同样是"Where am I? / What am I facing?"快捷键:https://arxiv.org/html/2508.08524v4 + +**(e)TTS 语速参数(资深用户开极快语速的数据)**: +- Bragg et al. 2021(ACM TACCESS,大规模听速率研究):**过半盲人参与者的 iOS 语速设为 51–100 档 ≈ 250–780 WPM**,远高于默认;先天/资深盲与后天失明分化(后者偏好接近人声的 ~150-200 WPM):https://dl.acm.org/doi/fullHtml/10.1145/3461700 +- Choi et al. 2020 "Nobody Speaks that Fast!":视障用户在 **500 WPM 下仍能获取 ≥50% 信息**:https://dasomchoi.com/papers/Nobody.pdf +- WebAIM 实务基准:资深读屏用户常调到 **300+ WPM**:https://webaim.org/【数值转引自上述综述与搜索结果,推断】 +- 含义:TTS/语音语速**必须可调且上限要高**(≥4 倍速),并记住设置;新玩家默认 1.0–1.3x。 + +### 2.5 学术研究脉络(音频游戏可玩性与 BLV 玩家) + +| 文献 | 关键发现 | +|---|---| +| Yuan, Folmer & Harris 2011, *Game Accessibility: A Survey*, Universal Access in the Information Society 10(1) | 盲人玩主流游戏的两大结构性障碍:**无法接收反馈**、**无法确定游戏对自己操作的响应**——即"状态感知"缺失的学术表述。https://www.researchgate.net/publication/220606739_Game_accessibility_A_survey | +| Yuan & Folmer 2008, *Blind Hero*(ASSETS'08) | 用触觉震动轨替代视觉轨使 Guitar Hero 可盲玩——音频+震动冗余编码的先例。https://dl.acm.org/doi/10.1145/1414470.1414481 【DOI 转引,推断】 | +| Westin 2005, *Game Not Over: Accessibility Issues in Video Games*(UAHCI) | 最早系统提出游戏无障碍议题的论文之一。https://www.academia.edu/585823/Game_not_over_Accessibility_issues_in_video_games | +| Friberg & Gärdenfors 2004, *Audio Games: New Perspectives on Game Audio*(ACE'04) | 声音五分类;音频游戏叙事与指令需专用声音类型。 | +| Röber & Masuch 2005, *Leaving the Screen*(ICAD'05) | 纯音频交互摆脱屏幕的交互模型(空间化听觉界面)。https://www.academia.edu/89942862/Leaving_The_Screen_New_Perspectives_In_Audio_Only_Gaming | +| Araújo-Façanha et al., *Mobile Audio Games Accessibility Evaluation for Users Who Are Blind* | 对移动音频游戏做启发式评估,提出 **10 条移动音频游戏设计建议** 与评估量表(全文被反爬虫拦截,仅确认存在与主题【推断,细节未核验】)。https://www.researchgate.net/publication/317183103_Mobile_Audio_Games_Accessibility_Evaluation_for_Users_Who_Are_Blind | +| *Exploring Audio Game Design with Visually Impaired Players*(ACM 2021) | 与视障玩家共设计音频游戏的评估维度(反馈、声音设计、可玩性)。https://dl.acm.org/doi/pdf/10.1145/3478384.3478410 【PDF 拉取失败,二手转述,推断】 | +| *Improving UI Design of Mobile Audio Games Based on AC*(Teikyo Univ.) | 用玩家行为日志分析改进移动音频游戏 UI。https://pure.teikyo.jp/en/publications/improving-user-interface-design-of-mobile-audio-games-based-on-ac/ | +| Mangiron & Larreina-Morales(盲人玩家偏好调查;Larreina-Morales 2024 游戏口述影像, Universal Access in the Information Society) | BLV 玩家对音频描述、音频线索的偏好实证。https://link.springer.com/article/10.1007/s10209-023-01036-4 ;演讲视频 https://www.youtube.com/watch?v=ui77xh_rY1M | +| CHI'25 中国 BLV 手游研究(同 2.2) | 状态过载、失败不可归因、反过度简化、双通道模式。https://arxiv.org/html/2502.09866v1 | + +### 2.6 可跳过语音、打断与"重试体验" + +- **语音必须可打断**(AFB 工程指南原文:语音"either by a key press or when a user moves from one item to another"必须被打断,否则导航卡死):任意按键/焦点移动即打断当前播报,是新条目播报的前提。https://afb.org/aw/fall2023/Blindness-Accessibility-in-Video-Games-A-Deep-Dive +- **跳过是可及性特性**:从业者综述把"allowing players to skip frustrating content"列为可及性要点:https://medium.com/@ryannealewallace/the-quest-for-great-gaming-accessibility-3cb2f1b75ec1 +- **跳过粒度**:玩家投诉"跳过一句结果跳过整段对话"的机制设计(Steam 讨论串):https://steamcommunity.com/app/427290/discussions/0/1696049513767276016/ ——逐句跳过 > 整段跳过;盲人向 VN《Real Sound: Echoing Sky》提供"跳过已读文本 + 自动播放":https://lemmasoft.renai.us/forums/viewtopic.php?t=68205 【一手论坛贴,细节为转述,推断】 +- **重试体验与失败归因**: + - CHI'25 P18:线索不足 → "毫无预兆死亡且不知为何失败"——**失败不可归因是 BLV 玩家弃游的强预测因素**; + - AFB:阈值播报血量让死亡"有预告";失败后应有明确的"死因 + 纠正提示"语音; + - The Blind Nerd:教程欠债 → 靠"反复死于 boss + 乱翻菜单"补课,是最差的纠错循环; + - 宽容性检查点/单次失误不清进度是通用游戏 UX 共识(从业者文章【推断】)。 + +--- + +## ③ 对本项目的可操作规则清单(15 条) + +针对本项目约束:HTML5 手机、无画面、音频+震动、6 手势(上/下/左/右滑、单击、双击+长按)、6 款游戏。 + +1. **探索-激活分离**:单击(或滑动)只做"聚焦/预览"并播报名称与含义;**双击才执行**——VoiceOver/TalkBack 系统保留语义,资深玩家零学习成本。6 种手势中不要让"单击"承担激活职责。 +2. **全局"我在哪/我有什么"手势(status key)**:用"长按"实现:任意时刻长按 → 依次播报 当前游戏名 / 阶段与回合 / 生命与关键资源 / 距上次目标的方位 / **当前可用的手势清单**。这是音频游戏三十年沉淀的 "where am I" 键惯例(Swamp、Lantern、NVDA 同源)。 +3. **开场 3 秒内宣告自救入口**:启动音后立即播报"双击确认,长按听状态,下滑听教程"——把可用性宣告放在一切之前(标题画面之前宣告 self-voicing 的社区惯例)。 +4. **所有语音可打断**:任何输入或游戏事件立即截断当前播报;不允许不可打断的旁白/教程长语音;两指轻点=暂停朗读(读屏惯例)。 +5. **逐句跳过 + 重听键**:长语音支持逐句快进(不是整段跳过);已播报的重要信息(规则提示、任务文本)可单手势重听一遍。 +6. **语速可调 1.0x–4.0x 并记忆**:资深 BLV 用户常听 250–780 WPM(Bragg 2021);默认 1.0–1.3x,设置入口放在首次引导里;TTS 语速也应可通过连续手势微调(模拟 rotor 调速)。 +7. **被动阈值播报**:生命/时间/资源在 75/50/25/15/10% 节点自动短促播报(配独立音色+震动),杜绝"突然死亡";危急阈值(<15%)切换为持续脉动音。 +8. **失败必须可归因**:死亡/失败后 ≤2 秒内播报"死因 + 下一次动作建议"(如"你被左侧飞来的障碍击中——下次向右滑躲避"),随后一键重试,重试不重放已读引导。 +9. **方位双编码 + 兼容单声道**:方向=pan(左右),前后/高低=音高或滤波闷化,距离=音量渐变或信标间隔缩短;提供单声道开关,单声道下方位改为语音标签("左!""三点钟方向")或音色差异。 +10. **每个对象/事件一个独特音色**,按 avatar/object/character/instruction 分类保持一致(Friberg & Gärdenfors 分类学);同类事件跨 6 款游戏复用同一音色词汇表,切换游戏时先播报"当前游戏 + 本作手势含义表"。 +11. **绝无静默死局**:任何等待(加载、思考、AI 回合)>3 秒必须有进度音/环境声/心跳脉冲,且等待期间允许查询状态;等待结束有明确的"轮到你了"提示音。 +12. **菜单=列表导航**:左右滑逐项播报(聚焦)、双击确认;提供"从头读全部选项"手势(弥补 explore-by-touch 会漏内容,W3C 警告);每项聚焦时附一句用法提示,提示可关闭。 +13. **音频通道分层防过载**:关键事件(危险、回合、状态拐点)> 指令播报 > 环境氛围,三个优先级用音量域+音色域区分;同屏并发 ≤2 条语音,其余排队或降级为短音效(CHI'25 信息过载发现)。 +14. **不因纯音频而过度简化**:保留游戏深度,用分层音频而不是删机制回应复杂度(社区强烈反感"把盲人当白痴"的简单化);难度分级 + 可调时限(回合制可关倒计时压力)。 +15. **与系统读屏共存**:HTML5 全部 UI 文本带 ARIA 标签,VoiceOver/TalkBack 用户可直接以系统读屏玩菜单层;游戏层内置 self-voicing 与系统读屏互斥(防止双声道重复播报),启动时自动检测并询问。 + +--- + +## ④ 参考来源列表 + +**指南与行业标准** +1. Game Accessibility Guidelines(全清单及各条目页):https://gameaccessibilityguidelines.com/full-list/ +2. AbleGamers / APX:https://ablegamers.org/ ;https://accessibleplayerexp.com/ +3. RNIB Design for Every Gamer:https://www.rnib.org.uk/living-with-sight-loss/assistive-aids-and-technology/tv-audio-and-gaming/design-for-every-gamer/ +4. W3C Mobile Accessibility WCAG Extension(双击激活惯例、explore-by-touch 局限):http://w3c.github.io/Mobile-A11y-Extension/ +5. W3C UAAG 2.0(Note):https://www.w3.org/TR/UAAG20/ ;W3C XAUR:https://www.w3.org/TR/xaur/ +6. IGDA GASIG 指南:https://igda-gasig.org/get-involved/sig-initiatives/resources-for-game-developers/sig-guidelines/ +7. PlayStation,TLOU Part II 官方无障碍页:https://www.playstation.com/en-us/games/the-last-of-us-part-ii/accessibility/ + +**社区一手经验** +8. The Blind Nerd 博客(blind gaming 标签):https://theblindnerdblog.wordpress.com/tag/blind-gaming/ +9. AudioGames.net(社区门户/数据库):http://fog.audiogames.net/ ;Swamp 数据库页:http://w.audiogames.net/db.php?action=view&id=Swamp +10. Game Accessibility Nexus,TLOU2 全盲通关评论:https://www.gameaccessibilitynexus.com/blog/2020/06/12/blind-low-vision-game-review-the-last-of-us-part-ii/ +11. Can I Play That?(无障碍游戏媒体):https://caniplaythat.com/ +12. Audiokinetic,Blind Accessibility in Interactive Entertainment:https://www.audiokinetic.com/en/community/blog/blind-accessibility-in-interactive-entertainment/ +13. r/blindgamers(Lantern Godot 插件,"where am I" 键):https://www.reddit.com/r/blindgamers/ +14. Jonathan Mosen,读屏手势肌肉记忆评论:https://mosen.org/why-i-want-android-accessibility-to-succeed/ + +**读屏惯例官方文档** +15. Apple VoiceOver rotor:https://support.apple.com/guide/voiceover/voiceover-rotor-mchlp2719/mac +16. AFB,iOS VoiceOver/rotor 教程:https://afb.org/blindness-and-low-vision/using-technology/cell-phones-tablets-mobile/apple-ios-iphone-and-ipad-2 +17. Perkins,VoiceOver rotor 选项(含调速):https://www.perkins.org/resource/voiceover-rotor-options-idevices/ +18. NVDA 用户指南(Where-am-I 命令):https://download.nvaccess.org/releases/2026.1.1/documentation/userGuide.html +19. W3C Mobile A11y TF 会议记录(focus→double-click 模式):https://www.w3.org/2015/11/12-mobile-a11y-minutes.html + +**学术文献** +20. Yuan, Folmer & Harris (2011). Game Accessibility: A Survey. UAIS 10(1). https://www.researchgate.net/publication/220606739_Game_accessibility_A_survey +21. Yuan & Folmer (2008). Blind Hero: Enabling Guitar Hero for the Visually Impaired. ASSETS'08. https://dl.acm.org/doi/10.1145/1414470.1414481 +22. Westin (2005). Game Not Over: Accessibility Issues in Video Games. UAHCI. https://www.academia.edu/585823/Game_not_over_Accessibility_issues_in_video_games +23. Friberg & Gärdenfors (2004). Audio Games: New Perspectives on Game Audio. ACE'04. https://www.semanticscholar.org/paper/4c31eafc8865962a83c419f5eab0b97f57493d81 +24. Röber & Masuch (2005). Leaving the Screen: New Perspectives in Audio-Only Gaming. ICAD'05. https://www.academia.edu/89942862/Leaving_The_Screen_New_Perspectives_In_Audio_Only_Gaming +25. Araújo-Façanha et al. Mobile Audio Games Accessibility Evaluation for Users Who Are Blind. https://www.researchgate.net/publication/317183103_Mobile_Audio_Games_Accessibility_Evaluation_for_Users_Who_Are_Blind +26. How Users Who are Blind or Low Vision Play Mobile Games (CHI 2025). https://arxiv.org/html/2502.09866v1 +27. Bragg et al. (2021). A Large Inclusive Study of Human Listening Rates. ACM TACCESS. https://dl.acm.org/doi/fullHtml/10.1145/3461700 +28. Choi et al. (2020). Nobody Speaks that Fast! https://dasomchoi.com/papers/Nobody.pdf +29. AFB AccessWorld (2023). Blindness Accessibility in Video Games: A Deep Dive. https://afb.org/aw/fall2023/Blindness-Accessibility-in-Video-Games-A-Deep-Dive +30. Sánchez et al. (2010). Enhancing Navigation Skills through Audio Gaming. https://pmc.ncbi.nlm.nih.gov/articles/PMC4259046/ +31. AES (2023). 系统综述:Reverberation and Accessibility for BVI People. https://micalab.org/publications/051/aes2023.pdf +32. Larreina-Morales (2024). Audio Description in Video Games. UAIS. https://link.springer.com/article/10.1007/s10209-023-01036-4 +33. Exploring Audio Game Design with Visually Impaired Players (ACM 2021). https://dl.acm.org/doi/pdf/10.1145/3478384.3478410 +34. StreetReaderAI (2025). https://arxiv.org/html/2508.08524v4 +35. Talon (2026). What Makes a Good Audio Game?(经 r/disabledgamers 转贴)https://www.reddit.com/r/disabledgamers/comments/1qlqixf/what_makes_a_good_audio_game_by_talon_games_for/ + +**二手/实务(佐证)** +36. ReadSpeaker 关于 RNIB 游戏无障碍研究:https://www.readspeaker.com/blog/video-game-accessibility-rnib/ +37. GDC,The Accessibility in The Last of Us Part II(Schatz & Gallant,YouTube):https://www.youtube.com/watch?v=5HDdino-umA +38. Ren'Py self-voicing 指南(V 键惯例):https://orangecarnation.neocities.org/guides/renpy_tts +39. Medium,The Quest for Great Gaming Accessibility(跳过=可及性):https://medium.com/@ryannealewallace/the-quest-for-great-gaming-accessibility-3cb2f1b75ec1 diff --git a/research/01-literature/04-onboarding-flow-retention.md b/research/01-literature/04-onboarding-flow-retention.md new file mode 100644 index 00000000..edfd122f --- /dev/null +++ b/research/01-literature/04-onboarding-flow-retention.md @@ -0,0 +1,223 @@ +# RQ4 调研报告:引导/新手体验(FTUE)、心流与反馈节奏——如何让新玩家度过头 5 分钟不弃坑(无画面纯音频条件) + +- 项目:纯音频手机网页游戏(音频+震动,6 种手势),单局较短;模式:回合制 RPG、互动广播剧、密室逃脱、记忆复现、节奏跟随、方位闪避 +- 研究问题(RQ4):怎样的引导与反馈节奏能让新玩家度过头 5 分钟不弃坑?如何在无画面条件下实现? +- 调研时间:2026-08;方法:WebSearch / WebFetch(英文一手来源为主) +- 说明:查不到一手来源的结论均标注"(推断)"。用户指定的 "DeltaEros" 来源经多轮检索无法找到(疑为 F2P 设计师 Ethan Levy / FamousAspect 相关内容的误记,其 FTUE 分析见 Game Developer 作者页,见来源 [S12]),相关论点改用可验证来源支撑。 + +--- + +## ① 研究问题 + +新玩家在头几分钟处于"高流失、低容忍、零信任"状态:他们不知道自己处于什么状态(state clarity)、不知道该做什么(goal clarity)、不确定自己能否做到(self-efficacy)。本研究问题聚焦三个子问题: + +1. **时机**:首次可玩交互、首个目标、首次成功各应出现在第几秒/分钟? +2. **节奏**:反馈延迟上限、正反馈频率、失败后的反馈内容应如何设计? +3. **通道**:以上全部信息在"无画面、只有音频+震动"的条件下如何传达? + +--- + +## ② 分主题发现 + +### 2.1 FTUE 研究与实践:流失有多快、发生在哪 + +**留存基准(GameAnalytics,Q1'24 至 2026 报告)** +- 全体手游中位数:**D1 ≈ 22–23%,D7 ≈ 4%,D28 ≈ 0.85%**;顶尖游戏为 **D1 40% / D7 15% / D28 6.5%**("40/15/6.5"经验值)[S1][S2][S3] +- 头 24 小时内约 **73%** 的玩家流失,首因是"教学过长"与"早期难度陡增" [S4] +- Warframe 数据(Hodent 引用):**约 20% 的玩家在 FTUE 期间(首 1 小时)永久流失** [S5] +- 个案:有开发者复盘发现**只有约 50% 玩家完成教学,最大流失点在第一个任务** [S6] + +**"Time to Fun"(TTF)基准数字** +- 手网页/手游玩家要求**打开后 60 秒内**获得真实互动,Steam 玩家也只多容忍一点;大量下载玩家**到不了第 10 分钟** [S7] +- 可玩广告研究:**<10 秒**的 time-to-fun 才能保证理解与完成率 [S8];优秀游戏被要求做到 **≈5 秒**(roguelite 深度文,推断性较强)[S9] +- "You Only Get 9 Seconds":SW: Galaxy of Heroes 把 time-to-fun 从"数分钟"压到**秒级**作为核心 FTUE 策略 [S10] +- 经验法则:**首个可输入交互 <60s;首个明确目标 <30s;首次"赢" <第 3 分钟;第 10 分钟前埋下未闭环钩子** [S7] +- 投资人侧经验值:**约每 60 秒一个多巴胺时刻**(Lumikai,推断性质的行业口诀)[S9] + +**首局三大杀手** [S7]:① UI/信息过载;② 首个目标不清晰(玩家要的是"现在做什么"不是世界观);③ 首次输入太慢(每一秒闲置都在邀请退出)。 + +**权威教学原则(Hodent《The Gamer's Brain》GDC16/17,最重要的可操作数字来源)** [S5] +- 工作记忆 5±2 项,**学习态同屏/同段最多 3 个新信息项**(含"不熟悉的操作"本身也算一项) +- **在玩家能行动的时刻教**(learn by doing),加载页文字最多讲 3 件事、多讲"为什么"少讲"怎么按" +- **间隔重复 + 变换情境**(静止目标→移动→遮挡→边躲边打)对抗遗忘;约 20 分钟后就需要 recall 提醒 +- **学习期绝不惩罚**:Fortnite alpha 数据显示新手期挣扎/死亡的玩家留存显著更低 +- "先展示锁,再给钥匙":先让玩家看到被锁定的内容,之后的解锁奖励才有动机意义 +- FTUE 最佳实践综述:尽快进入核心循环、最小化早期摩擦、教学可跳过、用观察(而非问卷)验证玩家是否真的懂了 [S11][S12][S13] + +### 2.2 心流(Csikszentmihalyi)在游戏中的操作化 + +- **GameFlow 模型(Sweetser & Wyeth 2005)**把心流拆成 8 要素:专注、挑战、技能、控制、**清晰目标、即时反馈**、沉浸、社交;至今 200+ 应用(GameFlow 2020 综述)[S14][S15] +- Cowley et al. 2008 提出用游戏机制+玩家模型**自动逼近挑战-技能平衡**(运行时调整)[S16] +- Jenova Chen《Flow in Games》:用**动态难度调整(DDA)**把玩家维持在心流通道,允许玩家自选强度 [S17] +- 实证:感知挑战-技能平衡 → 心流 → "想继续玩"的冲动(复杂手游样本)[S18];挑战-技能平衡、控制感、专注三要素最能代表游戏心流 [S19] +- **对无画面游戏的含义(推断)**:心流三件套——清晰目标、即时反馈、控制感——必须全部迁移到听觉/触觉通道:目标用语音播报+可重听;反馈用音效+震动(≤100ms);控制感来自"每个输入都有确定、可预期的声音响应"+"失败可归因于自己而非系统"。 + +### 2.3 引导模式分类与适用条件 + +| 模式 | 做法 | 适用条件 | 来源 | +|---|---|---|---| +| 交互式教学(learn by doing) | 在第一次真实操作中教,边玩边学 | 一切情况的默认首选;尤其操作类 | [S5][S20] | +| 隐形教学(invisible tutorial) | 教学融入正常玩法,玩家意识不到 | 机制可被关卡/情境自然强制时 | [S20](Berbece, GDC Europe 2016) | +| Prime–Teach–Observe | 先暗示→再教→观察验证 | 引入全新机制(我们的 6 手势属此类) | [S21] | +| 渐进披露 | 只暴露当前需要的功能 | 功能多、认知负荷高的产品 | [S5][S22] | +| 安全练习区 | 零惩罚沙盒试手势 | 全新输入方式(音频手势正是) | [S5](学习期不惩罚) | +| 首次失败兜底 | 首败无损/自动重试/降难 | 早期会话 | [S5](Fortnite 数据) | +| 上下文提示(contextual hint) | 卡住 N 秒后触发,不定时弹窗 | 玩家已可自主行动后 | [S5][S23] | +| 可跳过教学 | 任何提示可跳过;老手免打扰 | 所有玩家(很多人会跳) | [S11][S23] | + +- 反面证据:玩家会跳过教学,然后因为没学到而怪游戏 [S23];教学弹窗式"Press A to skip"是被 industry 复盘最多的反模式 [S20]。 +- 互动广播剧/语音叙事特例:**Earplay 的做法是把"可能性空间"刻意收窄**——语音/手势可选项少而明确,玩家不需要画面也能知道"此刻我能做什么" [S24]。 + +### 2.4 反馈设计:延迟、频率、Juice、失败归因 + +**延迟上限** +- Nielsen 经典三阈值:**0.1s = 感觉即时的上限**;1s = 思维流不断(可察觉延迟,需过渡反馈);10s = 注意力极限(需进度提示)[S25] +- 游戏手感文献普遍要求输入→可感知响应 ≤100ms(与 Nielsen 0.1s 一致;Game Feel / Swink 体系,推断综合) +- 网页/移动端还需扣掉触控与音频延迟预算:Web Audio 调度+预解码是达标的工程前提(推断) + +**正反馈频率与强化节奏** +- 变率强化(variable ratio)是最强的部分强化schedule,多巴胺在"预期"时释放而非仅奖励时 [S26][S27];但**新手期应先用固定、可预期的奖励建立控制感**,再引入变率(行为学习原理+玩家为中心的变率schedule研究)[S28] +- 行业口诀:每 30–60 秒一个明确奖励/高潮点(Lumikai"每 60 秒一次多巴胺"+ TTF 文献,推断综合)[S9] + +**"Juice it or lose it" 流派**(Jonasson & Purho, 2012) +- 核心句:"**A juicy game feels alive and responds to everything you do**";以最小输入换最大输出,把简单反馈分层叠加(音效、震动、动画…)[S29] +- 实证支持:juiciness 提升好奇心与动机(CHI 2024)[S30];动作 RPG 中 juice 显著改善体验评分 [S31] +- **音频版 juice(推断)**:每次触摸都有确认音+轻震(即使无效输入也用"错误音"响应,绝不静默);事件层(命中/受伤)+状态层(血量/进度的持续音床)+庆祝层(胜利 jingle)三层并行。 + +**失败归因反馈** +- 游戏的优势恰是"安全地失败并从中学习"(failing up:失败信号促进学习动机)[S32];好失败设计 = 明确原因 + 可改进路径,而非单纯惩罚 [S33][S34] +- 具体要求(推断综合 [S5][S32]):失败结算须回答三问——**为什么输(归因)、差多少(量化差距)、下次怎么办(一条可执行建议)**;重试入口零延迟。 + +### 2.5 状态清晰度(state clarity):迷失类型 × 听觉对策 + +玩家迷失成因可分四类(分类框架为推断综合,依据 Hodent 对"困惑=目标不清+反馈不足+认知过载"的归因 [S5] 与 3D 游戏空间定向研究 [S35]): + +| 迷失类型 | 玩家的内心问题 | 听觉/触觉对策(推断+部分来源) | +|---|---|---| +| 空间迷失 | "我在哪/敌人在哪" | 双耳声像 pan+距离混响(Papa Sangre 以双耳音频实现全游戏导航 [S36]);方位闪避用声道位置=威胁方位;震动强度=距离 | +| 目标迷失 | "我现在该做什么" | 开局一句话目标;随时可重听当前目标(专用手势唤起语音提示);Earplay 式收窄可选项 [S24] | +| 进度迷失 | "还有多远/进行到哪" | 进度音床(音乐段落推进=关卡推进;Dark Echo 用声音可见化降低学习曲线的思路 [S37]);章节 tick 音;结算语音报进度 | +| 能力迷失 | "为什么失败/我该用什么" | 失败即归因语音(见 2.4);错误输入给出"错误音+名称提示"而非静默;每个手势绑定独占音色 | + +- 音频游戏可用性研究的一致结论:**清晰、一致的音频线索 + 渐进式机制引入**是视障玩家可用性的关键 [S38][S39];盲玩家依赖听觉+触觉双通道感知环境 [S40][S41] +- 震动设计原则(Apple HIG / Android 官方):触觉是**补充通道**,用平台预置纹样起步、节制使用以省电,强度可随游戏事件缩放 [S42][S43] + +### 2.6 微会话设计:3–5 分钟一局 + +- 长会话本身是流失原因之一(GameAnalytics"16 Reasons":**session 太长**位列流失原因前茅——对短局设计是利好)[S44] +- 单局结构(推断综合 [S7]):**10s 内可操作的开头 → 难度爬升的中段 → 高潮 → 15–30s 结算(正反馈+归因+钩子)**;首个"赢"须出现在第 3 分钟前 +- 断点续玩(interruptibility):玩家随时可能杀进程;恢复时间必须秒级且保留局内进度;音频游戏没有"瞄一眼屏幕"的恢复手段,故需要**开局语音回顾("上次你打到…")**(推断) +- 会话结尾钩子:**Zeigarnik 效应**——未完成任务被记住的程度远高于已完成(有文献称高达 90%),"开环"制造持续张力,是留存循环的标准心理机制 [S45][S46];第 10 分钟前埋钩 [S7] +- 奖励发放时机(推断):把奖励放在**下一局开头**(回来就领),与开环共同构成"回来理由"。 + +### 2.7 弃坑研究:Top 原因与音频游戏特有因素 + +**通用 Top 原因**(多来源交叉): +1. 游戏开场/介绍差(GameAnalytics 列为第 1 位)[S44] +2. 教学过长、过度解释 [S4][S6] +3. 早期难度陡增、学习期被惩罚 [S4][S5] +4. 首个目标不清晰、"不知道自己在干嘛" [S7] +5. 会话太长/节奏拖沓 [S44] +6. 玩家跳过教学后迷路 [S23] + +**音频游戏特有因素**(定性证据为主,部分推断): +- 双耳空间线索需要**耳机**且需几分钟学习;Papa Sangre 强制耳机+极简控制来压低学习曲线 [S36] +- 纯听觉工作记忆负荷高(无画面可"回看",信息一旦播过就没了)→ 与 Hodent 3 项限制叠加后,音频版预算应更紧(推断) +- 听觉疲劳:持续专注听音比看画面更易疲劳,会话应更短(推断) +- 音频游戏 usability 研究显示:线索不一致、机制引入过快是主要失败原因 [S38][S39] + +### 2.8 自我效能:早期"我能行"时刻 + +- Bandura 四来源按效力排序:**亲历的掌握体验(mastery experience)> 替代体验 > 言语说服 > 生理情绪状态** [S47][S48] +- 游戏设计映射:"掌握体验就是赢的体验,而赢本来就是游戏的核心构成"——《Cognitive Behavioral Game Design》[S49] +- 设计技巧(综合 [S5][S7][S49]): + - 前 3 分钟内安排**保送式首次胜利**(几乎不可能失败的引导局) + - 教学=第一次掌握体验:把手势校准/试音做成 mini-game(推断) + - 替代体验:开局用"示范音频"演示一次成功循环(听一遍别人怎么做)[S47] + - 言语说服:结算时具体化表扬("你在 0.4 秒内反应过来了")优于空泛"真棒"(推断) + - 生理状态:紧张段落用音乐强度管理焦虑,避免新手把"心跳快"归因为"我做不到"(推断) + +--- + +## ③ 对本项目的可操作规则清单(无画面纯音频条件) + +1. **TTF ≤ 15 秒**:打开网页 → 戴耳机提示/校准(≤8s,本身做成第一个 mini-game)→ 15 秒内完成第一次有效手势并获得声音确认。所有登录/授权/设置后置到第 2 局之后。(依据:<10s 可玩广告基准 [S8]、9 秒论 [S10]、<60s 首输入 [S7]) +2. **首目标 ≤30 秒**:一句 ≤10 个字的语音目标 + 一个可听的目标音效;同一时刻最多 **3 个**听觉信息项(含新操作本身)。([S5][S7]) +3. **首胜 ≤3 分钟**:第 1 局为保送局(参数放宽到几乎不可失败),保证一次完整的"行动→反馈→赢"循环。([S7][S49]) +4. **学习期零惩罚**:前 2 次失败不扣任何东西、自动降难(反应窗口放宽/提示加强)——连续 2 次失败触发 DDA;第 3 次起才进入真实规则。([S5][S17]) +5. **输入确认 ≤100ms**:每次触摸(包括无效手势)100ms 内给出确认音+轻震,绝不静默;结果性反馈 ≤1s。([S25][S29]) +6. **三层音频 Juice**:确认层(每次输入)、事件层(命中/受伤/拾取,音色互相远离)、状态层(血量/危险用音乐强度与音床明暗编码)。震动作补充通道,强度随事件缩放。([S29][S30][S42][S43]) +7. **6 手势 = 6 个可聚类区分的音色 + 6 种震动纹理**,且"手势名"有一个 1 字语音标签;错误输入报名("那是横扫")而非仅报错。([S38][S39],推断) +8. **教学寄生在局内、≤90 秒、永远可跳过**:用 Prime(预听示范)→ Teach(首局中一次执行)→ Observe(后续局自然复现)结构;同一手势在 10 分钟内于 2–3 个不同情境复现(间隔重复)。([S5][S20][S21]) +9. **上下文提示延迟触发**:卡住/无输入 3–5 秒后才给提示(先音效提醒、再语音),绝不定时弹语音打断节奏。([S5][S23],秒数为推断) +10. **四类迷失各配一个听觉对策**:空间=双耳 pan+混响距离;目标=专用手势随时重听当前目标;进度=音乐段落化推进+章节 tick;能力=失败归因语音。(2.5 节) +11. **失败结算 ≤15 秒、必答三问**:为什么输(具体行为,"你在左声道威胁出现时用了防御")、差多少("差 2 点血/慢了 0.3 秒")、下次一条建议;随后"再来一次"零延迟(≤2s)。前 3 次失败时归因语音额外温和(归因于策略而非能力)。([S32][S33][S5]) +12. **3–5 分钟单局标准结构**:≤10s 可操作开局 → 中段单峰爬升 → 末段高潮(音乐+震动加强)→ 15–30s 结算。每 30–60 秒安排一个明确奖励/高潮点;新手期用固定可预期奖励,第 2 局起引入变率小奖励。([S7][S9][S26][S28]) +13. **断点续玩**:任意时刻可杀进程;重进 ≤5 秒回到可玩状态,保留局内进度;开局 5 秒语音回顾"上次你到哪、现在该做什么"。([S44]反证 + 推断) +14. **会话结尾开环钩子**:结算语音必须包含一个未完成项("钥匙还差半把/下一层有人在等你")+ 下一局开头发放奖励;第 5 分钟前绝不让玩家处于"无事可做"状态。([S45][S46][S7]) +15. **FTUE 漏斗逐步埋点并作为验收指标**:首交互率(≤15s)、首胜率(≤3min)、教学完成率、每步流失位置——第一个任务的流失通常最大,需单独看。([S6][S1])目标参照:D1 ≥30%(高于中位数 22–23%,低于顶级 40%)。([S1][S2]) + +--- + +## ④ 参考来源列表 + +**FTUE / 留存基准** +- [S1] GameAnalytics — Reducing User Churn(40/15/6.5): https://www.gameanalytics.com/blog/reducing-user-churn +- [S2] GameAnalytics Q1'24 Benchmarks(D1 22.91% / D7 4.2% / D28 0.85%): https://gamedevreports.substack.com/p/gameanalytics-benchmarks-in-mobile ;2026 报告: https://www.gameanalytics.com/reports/2026-mobile-pc-gaming-benchmarks ;分位数: https://appagent.com/blog/mobile-game-retention-benchmarks/ ;genre 级: https://business.mistplay.com/resources/mobile-game-retention-benchmarks +- [S3] GameAnalytics — 16 Reasons Why Players Are Leaving Your Game: https://www.gameanalytics.com/blog/16-reasons-players-leaving-game +- [S4] Adrian Crook & Associates — Churn Prevention(73%/24h): https://adriancrook.com/churn-prevention-strategies-mobile-games/ +- [S5] Celia Hodent — The Gamer's Brain: UX of Onboarding(GDC16 文字版): https://celiahodent.com/gamers-brain-ux-onboarding/ ;GDC Vault: https://www.gdcvault.com/play/1023231/The-Gamer-s-Brain-Part +- [S6] Roblox DevForum — 教学完成率 ~50%、首任务流失最大: https://devforum.roblox.com/t/why-are-half-the-people-leaving-my-game-before-they-finish-the-tutorial-and-how-can-i-improve-engagementsession-time/3483410 +- [S7] Medium (Block Bastards) — Your Indie Game Isn't Failing. Its First 10 Minutes Are(<60s/30s/3min 数字): https://medium.com/block-bastards/your-indie-game-isnt-failing-its-first-10-minutes-are-187d4aeac6b3 +- [S8] PlayableMaker — 可玩广告 time-to-fun <10s: https://playablemaker.com/top-ad-engagement-tips-for-mobile-game-marketers/ +- [S9] roguelite TTF≈5s(推断性强): https://medium.com/@icodewithben/ ;Lumikai "每 60 秒多巴胺"见 segwise/lumikai 行业综述(转引) +- [S10] Player Driven — You Only Get 9 Seconds: https://playerdriven.io/blog/you-only-get-9-seconds-why-onboarding-defines-success-in-games-and-beyond +- [S11] Game Developer — Best practices for a successful FTUE: https://www.gamedeveloper.com/design/best-practices-for-a-successful-ftue-first-time-user-experience- +- [S12] Ethan Levy (FamousAspect) — League of Legends and the top of funnel imperative for F2P: https://www.gamedeveloper.com/business/league-of-legends-and-the-top-of-funnel-imperative-for-f2p (注:用户提到的 "DeltaEros" 来源未能找到) +- [S13] GDC Vault — The Sticky Science of New User Experiences: https://gdcvault.com/play/1019769/The-Sticky-Science-of-New + +**心流** +- [S14] Sweetser & Wyeth 2005 — GameFlow: https://www.researchgate.net/publication/220686347_GameFlow_A_Model_for_Evaluating_Player_Enjoyment_in_Games +- [S15] Sweetser et al. — GameFlow 2020(15 年综述): https://dl.acm.org/doi/10.1145/3441000.3441048 +- [S16] Cowley et al. 2008 — Toward an understanding of flow in video games: https://dl.acm.org/doi/10.1145/1371216.1371223 +- [S17] Jenova Chen — Flow in Games(DDA): https://www.jenovachen.com/flowingames/introduction.htm +- [S18] 挑战-技能平衡与"想继续玩"(PMC): https://pmc.ncbi.nlm.nih.gov/articles/PMC8943660/ +- [S19] Frontiers in Psychology 2018 — Flow and Immersion in Video Games: https://www.frontiersin.org/journals/psychology/articles/10.3389/fpsyg.2018.01682/full + +**引导模式** +- [S20] Nicolae Berbece — This is a Talk About Tutorials, Press "A" to Skip(GDC Europe 2016): https://gdcvault.com/play/1023845/This-is-a-Talk-About ;视频: https://www.youtube.com/watch?v=VM1pV_6IE34 +- [S21] GDC Vault — Prime, Teach, Observe: Tutorializing Innovative Mechanics: https://gdcvault.com/play/1020512/Prime-Teach-Observe-Tutorializing-Innovative +- [S22] UX Collective — Zelda BotW onboarding 拆解: https://uxdesign.cc/using-video-games-to-learn-about-product-onboarding-15e3d431ae79 +- [S23] r/gamedesign — 玩家跳过教学的行为模式: https://www.reddit.com/r/gamedesign/comments/1uinl96/ + +**反馈设计** +- [S25] Jakob Nielsen — Response Time Limits(0.1/1/10s): https://www.nngroup.com/articles/response-times-3-important-limits/ +- [S26] Engineered highs: reward variability & frequency(多巴胺/变率): https://www.sciencedirect.com/science/article/pii/S0306460323000217 ;变率schedule原理: https://www.verywellmind.com/what-is-a-variable-ratio-schedule-2796012 +- [S28] Player-centered Positive Reinforcement to Schedule In-game Rewards: https://journal.seriousgamessociety.org/index.php/IJSG/article/view/47 +- [S29] Jonasson & Purho — Juice it or lose it(GDC2012): https://www.youtube.com/watch?v=Fy0aCDmgnxg +- [S30] CHI 2024 — How does Juicy Game Feedback Motivate?: https://dl.acm.org/doi/fullHtml/10.1145/3613904.3642656 +- [S31] The effects of juiciness in an action RPG: https://www.sciencedirect.com/science/article/pii/S1875952118300879 +- [S32] Failing up: How failure in a game environment promotes learning: https://www.sciencedirect.com/science/article/abs/pii/S1871187117301682 +- [S33] UMD HCI Lab — Designing Feedback & Failure in Videogames: https://medium.com/hcil-at-umd/designing-feedback-failure-in-videogames-55b99d5b1ad1 +- [S34] Scoping Review of Failure States in Game-Based Learning: https://digitalcommons.odu.edu/cgi/viewcontent.cgi?article=1181&context=stemps_fac_pubs + +**状态清晰度 / 音频游戏** +- [S35] ACM — Where am I? Design Pointers for Enhanced Spatial Orientation in 3D Games: https://dl.acm.org/doi/full/10.1145/3723498.3723826 +- [S36] Papa Sangre(双耳音频、强制耳机): https://en.wikipedia.org/wiki/Papa_Sangre ;设计分析: https://arstechnica.com/gaming/2011/01/scared-of-the-dark-a-look-at-the-audio-game-papa-sangre/ ;学术: https://eprints.bournemouth.ac.uk/29332/ +- [S37] Game Developer — What Dark Echo does that you should do: https://www.gamedeveloper.com/design/what-dark-echo-do-that-you-should-do-in-your-game-either +- [S38] Araújo et al. 2017 — Mobile Audio Games Accessibility Evaluation for Users Who Are Blind: https://www.researchgate.net/publication/317183103_Mobile_Audio_Games_Accessibility_Evaluation_for_Users_Who_Are_Blind +- [S39] Springer 2024 — Game Accessibility for Visually Impaired People: A Review: https://link.springer.com/article/10.1007/s00500-024-09827-4 +- [S40] DiGRA — Audio-Game Co-Design: https://dl.digra.org/index.php/dl/article/download/1922/1921/1918 +- [S41] IJPREMS — 空间音频+触觉的游戏框架: https://www.ijprems.com/ijprems-paper/an-audiodriven-gaming-framework-for-visually-impaired--players-using-spatial-audio-and-haptic-feedback ;Audio Game Hub: https://play.google.com/store/apps/details?id=com.AUT.AudioGameHub +- [S24] Engadget — Earplay 语音游戏设计(收窄可能性空间): https://www.engadget.com/2017-06-23-voice-based-gaming.html +- [S42] Apple HIG — Playing Haptics: https://developer.apple.com/design/human-interface-guidelines/playing-haptics +- [S43] Android — Haptics Design Principles: https://developer.android.com/develop/ui/views/haptics/haptics-principles + +**微会话 / 钩子 / 自我效能** +- [S44] 见 [S3](session 太长为流失原因) +- [S45] Zeigarnik effect: https://en.wikipedia.org/wiki/Zeigarnik_effect +- [S46] Yu-kai Chou — Zeigarnik Effect(开环张力): https://yukaichou.com/behavioral-analysis/zeigarnik-effect-incomplete-tasks-memory-tension/ ;会话结束行为研究(UCT 论文): https://pubs.cs.uct.ac.za/id/eprint/1248/1/Thesis.pdf +- [S47] Yu-kai Chou — Bandura 自我效能四来源: https://yukaichou.com/behavioral-analysis/self-efficacy-theory-bandura-belief-ability/ ;原理: https://www.simplypsychology.org/self-efficacy.html +- [S48] Robertson Cooper — Four Sources of Self-Efficacy: https://www.robertsoncooper.com/insights/the-four-sources-of-self-efficacy-you-draw-on-every-day/ +- [S49] Cognitive Behavioral Game Design: A Unified Model(PMC): https://pmc.ncbi.nlm.nih.gov/articles/PMC3910127/ +- [S50] Yu-kai Chou — Onboarding: Win Users in the First 5 Minutes: https://yukaichou.com/gamification-analysis/onboarding-design-gamification-first-five-minutes/ diff --git a/research/01-literature/05-context-scenario-design.md b/research/01-literature/05-context-scenario-design.md new file mode 100644 index 00000000..316b0f66 --- /dev/null +++ b/research/01-literature/05-context-scenario-design.md @@ -0,0 +1,260 @@ +# 05 场景化/情境化交互设计与音频优先产品的用户研究(RQ5) + +> 状态:完成 | 调研日期:2026-08-30 | 对应章程 RQ5 +> RQ5:不同使用场景(睡前/通勤/摸鱼/下班疲惫)与人群(学生/视障/白领/工人)对纯音频游戏交互提出什么不同约束?如何据此给出多套交互方案? +> 方法:WebSearch/WebFetch 桌面调研,英文一手来源为主。搜不到一手来源处明确标注「推断」。 + +--- + +## ① 研究问题 + +本项目是手机网页纯音频游戏(无画面、音频+震动、6 种手势、单局短),面向 4 类人设 × 4 类场景。RQ5 要回答: + +1. **场景侧**:移动游戏真实发生在哪些场景?各场景的注意力、噪声、社会、生理约束分别是什么,有无量化证据? +2. **产品侧**:已被验证的音频优先产品(播客/睡眠/车载)在「免视、免手、可中断、噪声环境」下沉淀了哪些交互模式? +3. **人群侧**:不同人群(熟练度、时间预算、认知资源)对同一套音频交互的期望差异有无研究支撑? +4. **框架侧**:有没有可直接复用的「情境→设计约束」分析框架? +5. **综合**:据此为本项目推导出**多套**(而非单一)交互方案的方向性建议。 + +--- + +## ② 分主题发现 + +### 2.1 移动游戏场景分布:床是第一场景,「在家」远多于「在路上」 + +| 数据点 | 数值 | 来源 | +|---|---|---| +| MocoSpace 调查(1.5 万美国手游玩家,2012):在家玩 | 96% 每天至少一次 | [TechCrunch](https://techcrunch.com/2012/03/22/home-is-where-the-mobile-game-is-96-play-games-in-the-house-53-in-bed/) | +| 在床上玩(最常见地点) | **53%**(Max FM 调查为 61%) | 同上;[Max FM](https://max1073.com.au/articles/people-play-mobile-games-in-bed/) | +| 在厕所玩 | 5%(MocoSpace)~ 29%(Max FM),口径差异极大 | 同上 | +| 通勤/公共交通上玩 | **20%**(YouGov 2025 美国调查);9%(Max FM 澳洲) | [YouGov Reality Checks](https://yougov.com/en-us/articles/52890-reality-checks-talkshow-mobile-game-download-habits-andre-gualda) | +| 外出时(排队/候诊)玩 | 83% 至少偶尔 | TechCrunch(同上) | + +**结论**:手游的主战场是「家」(床/沙发),通勤是第二梯队;「床上玩」是绝对多数场景,这直接支持本项目把「睡前」当一等公民场景。单次时长:行业基准为手游中位单局 **4–6 分钟**,头部 25% 游戏 8–10 分钟;每日 4–6 次微会话、日总时长中位约 22 分钟(GameAnalytics 基准)、美国用户日均 33 分钟(Flurry)([Icon Era 统计汇编](https://icon-era.com/statistics/average-gaming-session-length-by-age-group/))。→ 本项目「单局 1–5 分钟」的假设与行业中位吻合,天然就是 micro-session 形态。 + +### 2.2 打断频率与恢复成本:被打断是常态,恢复是隐性成本 + +- 经典研究(Gloria Mark 等,UC Irvine):被打断后完全回到原任务平均需 **23 分 15 秒**,82% 的被打断工作当天会续上([综述](https://addyo.substack.com/p/it-takes-23-mins-to-recover-after);原文 Mark et al., "The Cost of Interrupted Work")。 +- 打断存在**速度-准确率权衡**:恢复 lag 越短,出错越多([PubMed](https://pubmed.ncbi.nlm.nih.gov/23795978/))。→ 对游戏设计的含义:**强制即时恢复(回来直接续打)会放大出错与挫败;恢复时应给「低风险缓冲期」**。 +- 职场打断频率:84.2% 上班族每小时被手机打断 1–3 次,30% 达 5 次以上;员工日均个人手机使用约 60 分钟(Screen Education 调查,见 [cyberloafing 汇总](https://www.myshyft.com/blog/interruption-science-scheduling/)及下文 2.7)。 +- → **摸鱼场景的核心约束不是「玩多久」而是「随时会被叫走」**:恢复成本必须由游戏承担(自动存档、回来先口头重述局面),而不是让玩家记。 + +### 2.3 Micro-session 游戏设计实践(单局 1–5 分钟怎么设计中断与续玩) + +- 行业实践共识(无单一一手论文,多来源交叉):**「灵活会话」设计**——把长流程切成可独立完成的微循环,任何时刻退出都不损失进度([Mobile Free To Play: Flexible Sessions](https://mobilefreetoplay.com/mobile-session-design-flexible-sessions-2/)、[Design The Game: Micro-Sessions](https://www.designthegame.com/learning/tutorial/micro-sessions-engaging-on-the-go-players))。 +- **建模玩家时间**:把玩家日程中的「碎片缝」作为设计对象,提供 30 秒/3 分钟/10 分钟多档目标([UX Collective: Modeling Player's Time](https://uxdesign.cc/modeling-players-time-e2c69b2eef47))。 +- 体力/生命值机制的另一面:它既是付费墙也是**天然停机点**,替玩家解决「该停了」的自控问题([GameRefinery](https://www.gamerefinery.com/3-things-to-know-about-session-length-restriction-when-designing-a-free2play-game/))。 +- 学术方向:「disengagement-friendly game design」开始出现——主动设计「友好退出/再进入」,降低中断的心理成本([ACM 2025](https://dl.acm.org/doi/10.1145/3772318.3790564))。 +- → 归纳出 micro-session 三件套(**推断**,由上述来源综合):①单局闭环小且完整;②任意时刻可无损暂停/退出,回来有「局面复述」;③重进入口零摩擦(一击即续播)。 + +### 2.4 音频优先产品的场景 UX:已被验证的免视模式 + +**播客/有声书(通勤与家务场景的成熟答案)**: + +| 模式 | 具体做法 | 来源 | +|---|---|---| +| 精确续播 | 重进 App 自动恢复到上次的精确位置,无需书签操作;每档节目记忆独立设置 | [Pocket Casts](https://apps.apple.com/ro/app/pocket-casts-podcast-player/id414834813)、[Podtastic(per-podcast 设置)](https://apps.apple.com/us/app/podtastic/id6761050924) | +| 变速 | 0.5x–3x 连续可调,老用户常态 1.5x+ | Pocket Casts(同上) | +| 跳过静音 | Smart Speed/剪静音;静音门限可配置(−60 至 −20 dB) | [Overcast](https://overcast.fm/)、[AppleVis 论坛(阈值配置)](https://applevis.com/forum/ios-ipados/seeking-testers-my-new-ios-macos-podcast-app?page=1) | +| 响度自适应 | Overcast Voice Boost 2:按广播级 LUFS 感知响度算法做动态归一+真峰值限制器,明确卖点是「在嘈杂车里也听得清」 | [overcast.fm](https://overcast.fm/)、[Marco Arment 技术说明](https://marco.org/2020/01/31/voiceboost2) | +| 睡眠定时器 | 全员标配、入口常驻播放器;有用户仅因睡眠定时器 UI 更好而换 App | [Apple Podcasts 重设计案例](https://uxdesign.cc/fixing-things-that-bug-you-or-redesigning-the-apple-podcast-app-6d438a7b4a78)、[TidBITS 讨论](https://talk.tidbits.com/t/do-you-use-it-podcast-apps/27148?page=3) | + +**睡眠音频产品(Calm/潮汐/白噪音)**:深夜 UI 一致走向**暗色低对比 + 极简夜间交互**——内容即界面(Sleepcasts/自然声/睡前故事),播放页控件极少,默认防误触;「内容音频化、操作最少化」是被验证的睡前形态([Calm](https://www.calm.com/)、[Headspace](https://www.headspace.com/)、[冥想类 App UI 案例研究](https://gummble.com/blog/best-meditation-app-designs-2026))。 + +**驾车/CarPlay(免视安全约束的法规锚点)**: +- NHTSA 驾驶分心指南:单次视线离开道路 **≤2 秒**、单任务总视/手操作 **≤12 秒**;CarPlay 设计(语音优先、大目标、少文本)即按此收敛([Apple CarPlay 开发者](https://developer.apple.com/carplay/)、[DesignCode: Designing for CarPlay](https://designcode.io/ui-design-handbook-designing-for-carplay/))。 +- NN Group:「好的**一维音频界面**设计既服务盲人用户,也服务驾驶等『眼睛忙』情境」——**situational impairment 把无障碍设计变成通用设计**([NN Group: Alternative Interfaces for Accessibility](https://www.nngroup.com/articles/alternative-interfaces-for-accessibility/))。 +- → 提炼出免视交互通用法则(**推断**,综合上述来源):①任何一条语音指令/反馈必须能在 **≤2 秒注意力窗口**内被理解;②单次交互只做一个决定;③关键信息冗余编码(语音+音色+震动);④一切操作可被一句话撤销/重听。 + +### 2.5 环境噪声与语音可懂度:地铁是「压力测试环境」 + +**噪声量级**: +- 纽约地铁平均 **80–90 dBA**([PMC](https://pmc.ncbi.nlm.nih.gov/articles/PMC6302728/));MTA 站台均值 81.1 dBA、峰值 90.2 dBA([AJPH](https://ajph.aphapublications.org/doi/full/10.2105/AJPH.2008.138297));车内 74–81 dB([Hearing Health Foundation](https://hearinghealthfoundation.org/subway));港铁报告区间 80–112 dB([Harvard](https://dash.harvard.edu/entities/publication/fd5e76ac-8511-4e7b-9d69-2eab31f67137))。 +- 记住一个数:**地铁环境≈80 dBA 本底 + 突发尖峰**,耳机内 SNR 常年在 **0–10 dB** 之间摆动。 + +**SNR 与可懂度**: +- SNR −5~0 dB 时语音可懂度崩塌;自然语音在噪声中的可懂度可从 71.7% 跌到 22.8%([Kim et al. 2009, PMC](https://pmc.ncbi.nlm.nih.gov/articles/PMC2757424/);JASA Express Letters,转引自搜索结果)。 +- 工程经验:<15 dB SNR 就需要整套噪声鲁棒处理(VAD、降噪、动态响度)([Forasoft](https://www.forasoft.com/blog/article/speech-recognition-accuracy-noisy-environments))。 +- 地铁站台广播可懂度差的根因=高噪声+长混响,普通 SNR 标准在地铁站失效([SSRN 论文](https://papers.ssrn.com/sol3/Delivery.cfm/4015e7b5-0278-4aa0-b841-1c4dee512535-MECA.pdf?abstractid=5339289))。 + +**「一遍听不清怎么办」的已有做法**: +- 响度自适应(Voice Boost 式 LUFS 归一)是播客端被验证的产品级答案(见 2.4)。 +- 语速维度:正常语音 120–180 wpm;视障资深用户经训练可听 500+ wpm,但**新手与普通用户在噪声下应降速而非提速**——加速会进一步压缩掩蔽间隙([Bragg et al. 2021 听速大样本研究](https://dl.acm.org/doi/fullHtml/10.1145/3461700))(后半句为**推断**)。 +- 重听:读屏工具普遍提供「重复最后一句」指令,说明**重听必须是零成本一级操作**(读屏通用实践,具体手势因系统而异——通用实践/推断)。 +- → 设计对策(**推断**,由上述证据综合):关键信息默认**两遍式播报**(一遍原样+一遍关键值);任何时刻一键重听;噪声环境下自动降语速+提响度+拉长语句间隙。 + +### 2.6 社会约束场景:纯震动玩法可行吗? + +**震动语言的表达上限(关键参数)**: +- 信息论视角:单个震动刺激实际可传递约 **2–3 bit**(≈4–8 个完全可辨选项);序列化呈现可叠加。触觉通信的最优传输率约 **7.9 bit/s**,且在「每刺激 3 bit」的编码下取得([Tan, Reed & Durlach, IEEE ToH 2010](https://engineering.purdue.edu/~hongtan/pubs/PDFfiles/J45_TanReedDurlach_ToH2010.pdf))。 +- 可学习词表规模:实用场景下用户经训练可稳定掌握 **约 10–25 个震动模式**;用节奏×频率×幅度参数化可做出 **84 个可辨触觉图标**([Boulos et al., Springer](https://dl.acm.org/doi/10.1007/978-3-540-69057-3_24));运动 App 的时序震动模式集在实验室辨识别率 96%、真实场景 88.7%(ActiVibe, AVI 2018,转引自检索汇总)。 +- 注意资源上限:同时呈现的触觉刺激超过 **约 4 个**后判断力骤降([Gallace, Tan & Spence 2007](https://engineering.purdue.edu/~hongtan/pubs/PDFfiles/J30_GallaceTanSpence_PnP2007b.pdf))→ **震动必须串行、低频次、只编码「状态变化」而非连续数据流**。 +- 认知负荷下的可用性:用户在专注其他任务时仍能学会识别小规模触觉图标集,但学习速度显著变慢([Chan & MacLean, UBC](https://www.cs.ubc.ca/labs/spin/sites/default/files/local_pdfs/Learning_and_identifying_haptic_icons_under_workload.pdf))——支持「摸鱼模式只保留 3–6 个震动语义」。 +- 盲聋人群的震动语言先例:Mobile Lorm Glove(Lorm 触觉字母手机化)、Tactile Board(文本/语音→震动符号实时转译)([arXiv 2205.04802](https://arxiv.org/pdf/2205.04802))、Neosensory Buzz(声音→ wrist 震动模式)([Deafpedia 概述](https://deafpedia.org/visual-tactile-technology-for-deaf-people/))。→ **震动承载一门「小语言」已被多次验证,但词表都是几十个以内且需学习期**。 + +**单手/不看屏**: +- 真实持机观察(n=1333):**49% 单手、36% 托持、15% 双手**;**75% 的触控由拇指完成**([Hoober, UX Matters 2013](https://www.uxmatters.com/mt/archives/2013/02/how-do-users-really-hold-mobile-devices.php))。→ 6 种手势若全部单手拇指可达,覆盖近半真实使用姿势;躺床姿势(屏幕朝上/朝侧)进一步要求**手势不依赖屏幕坐标**——这恰是纯音频手势的天然优势(**推断**)。 +- 静音可行性:手机震动本身近乎无声,但网页游戏若保留任何提示音需默认静音+仅震动;音效泄漏与 TTS 在安静办公室的清晰度是主要风险(**推断**,无直接研究)。 + +### 2.7 人群差异:场景画像的行为证据 + +**摸鱼/白领(cyberloafing 研究)**: +- 92–96% 员工在工作日使用个人手机;60–80% 承认 cyberloafing;日均约 60 分钟(低自报口径)~2 小时(高口径);动机依次为愉悦 79%、放松 77%、无聊 71%([Screen Education/Zippia/OFO 调查汇总](https://www.myshyft.com/blog/interruption-science-scheduling/)、[Vouchercloud 2019](https://www.vouchercloud.com/resources/office-worker-productivity))。 +- **恢复视角**(重要反直觉):短暂的网页浏览比午餐/锻炼更「回血」,适度摸鱼提升后续专注(recovery theory,South University 等汇总,同上来源)。→ 摸鱼游戏的价值主张应是「3 分钟回血」,而非「沉浸世界」。 + +**视障玩家(专业用户群)**: +- CHI 2025《How Users Who are Blind or Low Vision Play Mobile Games》:**优先选择与读屏兼容的游戏**,读屏适配决定其游戏选择([ACM](https://dl.acm.org/doi/10.1145/3706598.3714205))。 +- 音频游戏设计指南(分析 9 款音频游戏提炼 **50 条指南**):空间音频、一致的听觉词汇、清晰的「等待输入」信号是核心([Design Guidelines for Audio Games](https://www.researchgate.net/publication/296643157_Design_Guidelines_for_Audio_Games))。 +- 行业深访:要用尽声音的一切属性(音高/音色/响度/尤其**空间定位**)传信息([AFB AccessWorld](https://afb.org/aw/fall2023/Blindness-Accessibility-in-Video-Games-A-Deep-Dive))。 +- 听速:资深读屏用户 400–600+ wpm、偏好更「机械但高速不失真」的语音;新手贴近 150–180 wpm 自然语音([Bragg et al. 2021](https://dl.acm.org/doi/fullHtml/10.1145/3461700))→ **同一游戏需要可调语速,且默认值因人群而异**。 + +**学生/时间充裕者**:Newzoo 分群(casual/midcore/core)显示年轻玩家动机偏向「与朋友完成任务、竞争、社交」与长线成长([Newzoo Global Gamer Study](https://newzoo.com/products/global-gamer-study/)、[2024 参与度报告摘要](https://gamedevreports.substack.com/p/newzoo-how-people-engage-with-games))。直接针对「大学生音频游戏偏好」的一手数据未检索到——**推断**:会话预算大、可接受 10 分钟+沉浸局与成长系统,对重复说教敏感。 + +**工人/体力劳动者**: +- 疲劳与无聊**预测**更多手机使用(客观传感数据)([ResearchGate: Fatigue, Boredom and Objectively Measured Smartphone Use at Work](https://www.researchgate.net/publication/353085835_Fatigue_boredom_and_objectively_measured_smartphone_use_at_work))。 +- 蓝/白领可用性痛点研究:移动优先、低数字素养人群需要**极简流程、低认知负荷**([Jansen et al. 2025, ACM](https://dl.acm.org/doi/full/10.1145/3750069.3750390));低文化程度用户界面设计研究同向([Microsoft Research](https://www.microsoft.com/en-us/research/publication/designing-mobile-interfaces-for-novice-and-low-literacy-users/))。 +- 触控疲劳:长时间触屏操作本身产生肌肉疲劳([ACM 2025](https://dl.acm.org/abs/10.1007/978-3-031-92707-2_14))→ 下班疲惫场景应**减少每局操作次数**。 +- 未检索到「蓝领手游偏好」专门行业报告——「偏好简单规则与即时反馈」这一人设假设目前由上述可用性文献**间接支撑(推断)**。 + +### 2.8 情境化框架:可直接借用的两个模型 + +**Context-aware computing(Dey & Abowd)**: +- 定义:**「上下文是任何可用于刻画实体情境的信息」**(位置、身份、活动、时间);「若系统利用上下文为用户提供相关信息/服务,且相关性取决于用户任务,则它是上下文感知的」([Dey 2001, PDF](http://www.cs.umd.edu/class/spring2018/cmsc818G/files/contextdey.pdf)、[Dey & Abowd, HCI Journal 2001](https://dl.acm.org/doi/abs/10.1207/s15327051hci16234_02))。 +- → 对本项目:**手机网页拿不到精细传感器上下文,但可以用「入口选择/首局试探」做轻量上下文**:让玩家(或首次体验模式)声明场景档位,游戏据此切换交互参数包。这是把 context-awareness 降维成「场景预设 profile」的可行路径(**推断**)。 + +**Microsoft 包容设计:permanent / temporary / situational(情境性损伤)**: +- 官方框架([microsoft.com/design/inclusive](https://www.microsoft.com/design/inclusive/)):同一功能约束有三种来源——永久(独臂/盲/聋)、暂时(手臂打石膏/白内障/耳部感染)、**情境**(抱婴儿单手抱机/强光下看屏/酒吧嘈杂中听不清)。 +- → 核心推论:**为视障用户设计的免视交互,就是为通勤、摸鱼、睡前所有「情境性失明/失聪」时刻设计的交互**(与 NN Group 结论互证,见 2.4)。这使 RQ3(视障惯例)的成果可以直接复用到 RQ5 的场景方案里。 + +### 2.9 睡前场景特殊性:低负荷、零光线、可入睡 + +- **睡眠惰性(sleep inertia)**:刚醒来认知最差,典型持续 **15–30 分钟**、极端 15–120 分钟,决策能力受影响最明显([ScienceDirect Topics](https://www.sciencedirect.com/topics/medicine-and-dentistry/sleep-inertia)、[PLOS ONE](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0079688))→ 不仅「睡前犯困」,**早晨睁眼躺床也是认知低谷**;两端的共同设计答案是「低记忆负荷+高容错」。 +- 手机在床使用的实证:影响入睡潜伏期、心率与 HRV([PMC9643910](https://pmc.ncbi.nlm.nih.gov/articles/PMC9643910/));大学生 **70.1% 关灯后仍玩手机**、关灯后平均 38.5 分钟([Nature Sci Rep](https://www.nature.com/articles/s41598-026-42454-7));睡前看屏者睡眠质量差的比例高 33%([SleepEducation.org](https://sleepeducation.org/screen-time-and-sleep-what-new-studies-reveal/));蓝光抑制褪黑素([Brain Communications](https://academic.oup.com/braincomms/article/6/3/fcae173/7675955)),但也有综述认为影响仅约 9 分钟延迟([BBC Future](https://www.bbc.com/future/article/20260407-the-blue-light-from-your-phone-isnt-ruining-your-sleep))。 +- → 对纯音频游戏:**无画面是睡前场景的结构性优势**(零蓝光、暗处可用),但音量敏感(同枕他人/室友)+困倦认知下降是硬约束;「帮人入睡后不吵人」的睡眠定时器是睡眠音频品类标配(2.4),纯音频游戏也应提供「定时软退出」。 + +--- + +## ③ 场景→设计约束映射表 + +> 四个目标场景 × 关键约束(附证据强度)× 交互对策。证据强度:【实】有一手研究/产品实证;【推】推断。 + +| 场景 | 关键约束 | 证据 | 交互对策 | +|---|---|---|---| +| **睡前躺床**(占比最高的手游场景,53–61% 在床上玩) | ① 音量敏感(同室他人/浅眠)② 零视觉本来满足,但屏幕亮度/蓝光需为零 ③ 困倦→工作记忆下降,记不住复杂规则 ④ 想玩到睡着→需要「软着陆」退出 ⑤ 躺姿单手、拇指操作 | 【实】2.1/2.9 | 暗黑模式常驻+屏幕常暗(无画面即优势);默认低音量曲线+人声为主;单局规则 ≤3 条、无长链状态记忆;内置睡眠定时器(如 10/20 分钟后柔和收尾);每局结束播一句「晚安式」低刺激收束音;手势全部单手拇指可达 | +| **地铁通勤**(约 20% 用户在公共交通玩;80–90 dBA 噪声、SNR 0–10 dB) | ① TTS 可懂度崩塌风险 ② 站到站的 3–8 分钟碎片窗口+到站打断 ③ 单手+可能站着晃动 ④ 噪声中自感音量过大伤耳 | 【实】2.2/2.5 | 响度自适应(LUFS 归一+动态提亮人声频段);关键信息两遍式播报+一键重听(零成本重听手势);到站铃声/打断后回来先播「局面复述」再继续;单局按 3 分钟设计,站间可完成整数局;降语速、拉长语句间隙;提供「本站模式」短局变体 | +| **上班摸鱼**(92–96% 员工工时用手机;84% 每小时被打断 1–3 次;怕出声) | ① 绝对静音(TTS/音效可能外泄)② 随时被叫走→30 秒级中断 ③ 屏幕需可瞬间藏匿(.alt-tab 心理模型)④ 短时回血定位而非沉浸 | 【实】2.2/2.7 | 「纯震动模式」:仅 3–6 个震动语义(开始/正确/错误/等待输入/结算),串行低频次(同发 ≤4 是上限);自动暂停零损失、回来一句话复述局面;单手拇指完成全部 6 手势;单局 ≤3 分钟、可中途放弃不计失败;无长激励音效 | +| **下班疲惫放松**(疲劳预测更多手机使用;触控操作本身致疲劳) | ① 认知资源低:学新规则成本高 ② 容错要求高,惩罚性失败劝退 ③ 需要即时正反馈回血 ④ 可能边做家务边听(耳机可能不戴) | 【实】2.7 | 规则复用已知手势(不引入新手势);失败降级为「再来一次」而非重头;正反馈前置(前 30 秒内必有一次明确成功反馈);免耳机可玩(扬声器模式语音更慢更响);每局操作次数压缩(少而重的反馈,避免连续高频触控) | + +--- + +## ④ 人群→设计偏好映射表 + +| 人设 | 关键证据/推断 | 交互偏好 | 设计对策 | +|---|---|---|---| +| **视障玩家**(专业评委) | 【实】读屏兼容是选游戏首要标准(CHI 2025);听速 400–600+ wpm;期望空间音频与一致听觉词汇;50 条音频游戏指南 | 高信息密度、高速语音、严谨一致的听觉语言;反感「为健全人降智」的简化和过度提示 | 提供语速 1x–3x 可调(默认偏快);完整空间音频信息;手势/音色词汇与读屏惯例对齐;绝不抢读屏焦点;邀请其「挑错」的心智模型 | +| **时间充裕的大学生** | 【推】由 Newzoo 年轻玩家动机(社交/竞争/成长)+ 长 session 分群间接支撑 | 愿意深玩:期待沉浸感、成长曲线、可钻研深度;讨厌说教与手把手引导 | 保留完整状态层+成长系统;允许跳过教程直达硬核模式;提供可探索的深度机制(连击/排行);引导做成可跳过的一句话而非连续课程 | +| **时间紧张的白领** | 【实】cyberloafing 数据:日均 60 分钟、每小时被打断;摸鱼动机=放松回血 | 即时满足、3 分钟一局、随时中断续玩、静音可玩、零学习成本 | 见③摸鱼列:震动模式+自动暂停+局面复述;即时小结算(每局都有收获感);无需登录/设置即可玩 | +| **工人(体力劳动)** | 【推】由疲劳→更多手机使用、低认知负荷界面、触控疲劳等文献间接支撑;无直接「蓝领手游偏好」一手报告 | 简单规则、即时正反馈、高容错、少操作 | 每局规则 ≤2 条且开局口播;失败不惩罚(无「游戏结束」重挫音,改为鼓励+重试);大粒度反馈(成功/失败二值为主,少灰色评价);操作频次低 | + +--- + +## ⑤ 对本项目的可操作建议(多套方案方向) + +### 5.1 先立「全局基线」:所有场景共享的最小状态层 + +证据(2.4/2.5/2.6)收敛出四条任何场景都不该违背的底线,作为多方案公共内核: + +1. **任意时刻可无损暂停,恢复时先播一句局面复述**(被打断是常态,恢复成本游戏承担)。 +2. **零成本重听**:重听最后一条指令必须是单手势一级操作;关键信息默认两遍式(一遍完整+一遍关键值)。 +3. **听觉词汇全局一致**:同一语义永远同一音色/earcon/震动模式,跨游戏复用(视障社区的硬期望)。 +4. **语音参数可调**:语速(0.8x–2x,视障档至 3x)与响度(LUFS 归一基线)是全局设置而非各游戏散装实现。 + +### 5.2 四套场景方案(同一内核,四个参数包) + +| 方案 | 名称 | 核心参数差异 | 一句话定位 | +|---|---|---|---| +| A | **通勤·噪声鲁棒版** | 语速 0.9x+句间停顿加大;响度自适应提亮;关键信息两遍式;单局 3 分钟、到站可弃局;手势全部单手拇指 | 「在 85 分贝里也玩得下去」 | +| B | **摸鱼·静默震动版** | 全静音,仅震动语言(≤6 个语义、串行播报);自动暂停无感续玩;单手完成;单局 ≤3 分钟、随时弃 | 「领导走过来 0.5 秒切走,回来一句话接上」 | +| C | **睡前·助眠低负版** | 低音量曲线+暖音色;常暗常静;睡眠定时器;规则 ≤3 条;失败即鼓励;收束音低刺激 | 「玩着玩着能安心睡着」 | +| D | **下班·轻回血版** | 免耳机扬声器模式;即时正反馈前置;容错拉满;每局操作次数最少 | 「累成狗也能赢一局」 | + +关键取舍说明:A 与 B 冲突最大(一个要「响」,一个要「无声」),**不应做成自动切换,而应做成入口显式选择 + 记忆上次选择**——因为手机网页拿不到可靠上下文传感器(2.8 的 context-awareness 降维方案)。C 与 D 可共享「低认知负荷」底层,仅音色/收束策略不同。 + +### 5.3 按人群的调优旋钮(在场景方案之上叠加) + +- **视障档**:语速上限 3x、完整空间信息、严格读屏协作(不抢焦点、语义标签完整)——RQ3 的惯例清单直接作为该档验收标准。 +- **学生档**:保留成长系统与深度机制,引导全部可跳过。 +- **白领档**:默认即方案 B;结算即时化(每局都有「+1 进步」口播)。 +- **工人档**:每局新信息量为零(只复用已学手势);反馈二值化。 + +### 5.4 需要用试玩验证的风险假设(带入 RQ8) + +1. 纯震动玩法的信息带宽是否够(理论上限 2–3 bit/刺激,需实测玩家在摸鱼分心状态下能否分辨 6 个语义——Chan & MacLean 显示分心会显著拖慢学习)。 +2. 两遍式播报在低速语音下是否会拖节奏(通勤版需 A/B 检验)。 +3. 「局面复述」的一句话是否真能重建状态感知(这是章程核心痛点在场景维度的检验点)。 +4. 睡眠定时器与「软着陆」是否提升「愿意再玩」而非只提升「关掉」。 + +--- + +## ⑥ 参考来源列表 + +**场景分布与碎片化** +- TechCrunch — MocoSpace 手游场景调查(96% 在家/53% 在床): https://techcrunch.com/2012/03/22/home-is-where-the-mobile-game-is-96-play-games-in-the-house-53-in-bed/ +- YouGov Reality Checks(20% 通勤玩): https://yougov.com/en-us/articles/52890-reality-checks-talkshow-mobile-game-download-habits-andre-gualda +- Max FM 调查(61% 床/29% 厕所/9% 通勤): https://max1073.com.au/articles/people-play-mobile-games-in-bed/ +- Icon Era 手游会话长度统计汇编: https://icon-era.com/statistics/average-gaming-session-length-by-age-group/ +- Addy Osmani 打断恢复成本综述(23min15s): https://addyo.substack.com/p/it-takes-23-mins-to-recover-after +- 速度-准确率权衡(恢复 lag 研究): https://pubmed.ncbi.nlm.nih.gov/23795978/ + +**Micro-session 设计** +- Mobile Free To Play — Flexible Sessions: https://mobilefreetoplay.com/mobile-session-design-flexible-sessions-2/ +- Design The Game — Micro-Sessions: https://www.designthegame.com/learning/tutorial/micro-sessions-engaging-on-the-go-players +- UX Collective — Modeling Player's Time: https://uxdesign.cc/modeling-players-time-e2c69b2eef47 +- GameRefinery — Session-Length Restriction(体力值=停机点): https://www.gamerefinery.com/3-things-to-know-about-session-length-restriction-when-designing-a-free2play-game/ +- ACM — Disengagement-Friendly Game Design: https://dl.acm.org/doi/10.1145/3772318.3790564 + +**音频优先产品场景 UX** +- Pocket Casts(0.5x–3x 变速/剪静音): https://apps.apple.com/ro/app/pocket-casts-podcast-player/id414834813 +- Podtastic(per-podcast 音频偏好): https://apps.apple.com/us/app/podtastic/id6761050924 +- Overcast(Voice Boost LUFS 响度归一/Smart Speed): https://overcast.fm/ ;技术说明: https://marco.org/2020/01/31/voiceboost2 +- Apple Podcasts 重设计(睡眠定时器入口): https://uxdesign.cc/fixing-things-that-bug-you-or-redesigning-the-apple-podcast-app-6d438a7b4a78 +- Calm: https://www.calm.com/ ;Headspace: https://www.headspace.com/ +- 冥想/睡眠 App UI 案例研究: https://gummble.com/blog/best-meditation-app-designs-2026 +- Apple CarPlay 开发者页: https://developer.apple.com/carplay/ ;DesignCode CarPlay 设计: https://designcode.io/ui-design-handbook-designing-for-carplay/ +- NN Group — Alternative Interfaces for Accessibility(一维音频设计服务「眼睛忙」场景): https://www.nngroup.com/articles/alternative-interfaces-for-accessibility/ +- Oakley — Designing Eyes-Free Interaction: http://www.whereveriam.org/work/etri/HAID07_Oakley.pdf + +**噪声与语音可懂度** +- NYC 地铁噪声 80–90 dBA: https://pmc.ncbi.nlm.nih.gov/articles/PMC6302728/ +- AJPH — MTA 站台噪声实测: https://ajph.aphapublications.org/doi/full/10.2105/AJPH.2008.138297 +- Hearing Health Foundation — 车内噪声: https://hearinghealthfoundation.org/subway +- Harvard — 港铁噪声评估: https://dash.harvard.edu/entities/publication/fd5e76ac-8511-4e7b-9d69-2eab31f67137 +- Kim et al. 2009 — 噪声中语音可懂度增强算法: https://pmc.ncbi.nlm.nih.gov/articles/PMC2757424/ +- Forasoft — 噪声环境语音识别 SNR 工程阈值: https://www.forasoft.com/blog/article/speech-recognition-accuracy-noisy-environments +- SSRN — 地铁站台广播可懂度与混响: https://papers.ssrn.com/sol3/Delivery.cfm/4015e7b5-0278-4aa0-b841-1c4dee512535-MECA.pdf?abstractid=5339289 +- Bragg et al. — 大样本听速研究(读屏用户 500+ wpm): https://dl.acm.org/doi/fullHtml/10.1145/3461700 + +**震动/触觉语言与单手** +- Tan, Reed & Durlach — 触觉信息传输率(7.9 bit/s @ 3bit/刺激): https://engineering.purdue.edu/~hongtan/pubs/PDFfiles/J45_TanReedDurlach_ToH2010.pdf +- Boulos et al. — 节奏化 84 个触觉图标: https://dl.acm.org/doi/10.1007/978-3-540-69057-3_24 +- Gallace, Tan & Spence — 触觉同时感知上限(约 4 个): https://engineering.purdue.edu/~hongtan/pubs/PDFfiles/J30_GallaceTanSpence_PnP2007b.pdf +- Chan & MacLean — 认知负荷下学习触觉图标: https://www.cs.ubc.ca/labs/spin/sites/default/files/local_pdfs/Learning_and_identifying_haptic_icons_under_workload.pdf +- Kutner & Hadžidedić — 盲聋震动通信(Tactile Board): https://arxiv.org/pdf/2205.04802 +- Neosensory Buzz(声音→震动): https://deafpedia.org/visual-tactile-technology-for-deaf-people/ +- Hoober — 真实持机观察(49% 单手/75% 拇指): https://www.uxmatters.com/mt/archives/2013/02/how-do-users-really-hold-mobile-devices.php + +**人群差异** +- ACM CHI 2025 — 视障/低视力用户如何玩手游: https://dl.acm.org/doi/10.1145/3706598.3714205 +- Design Guidelines for Audio Games(50 条指南): https://www.researchgate.net/publication/296643157_Design_Guidelines_for_Audio_Games +- AFB AccessWorld — 盲人游戏可及性深访: https://afb.org/aw/fall2023/Blindness-Accessibility-in-Video-Games-A-Deep-Dive +- Newzoo Global Gamer Study: https://newzoo.com/products/global-gamer-study/ ;2024 参与度摘要: https://gamedevreports.substack.com/p/newzoo-how-people-engage-with-games +- Cyberloafing 数据汇总(Screen Education 等): https://www.myshyft.com/blog/interruption-science-scheduling/ +- 疲劳/无聊→更多工作时段手机使用: https://www.researchgate.net/publication/353085835_Fatigue_boredom_and_objectively_measured_smartphone_use_at_work +- Jansen et al. 2025 — 蓝领/白领移动可用性痛点: https://dl.acm.org/doi/full/10.1145/3750069.3750390 +- Microsoft Research — 低文化程度用户移动界面设计: https://www.microsoft.com/en-us/research/publication/designing-mobile-interfaces-for-novice-and-low-literacy-users/ + +**框架与睡前** +- Dey — Context 定义与 context-aware computing: http://www.cs.umd.edu/class/spring2018/cmsc818G/files/contextdey.pdf ;Dey & Abowd Context Toolkit: https://dl.acm.org/doi/abs/10.1207/s15327051hci16234_02 +- Microsoft Inclusive Design(permanent/temporary/situational): https://www.microsoft.com/design/inclusive/ +- ScienceDirect — Sleep Inertia 综述(15–120 min): https://www.sciencedirect.com/topics/medicine-and-dentistry/sleep-inertia ;PLOS ONE 晨间睡眠惰性: https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0079688 +- 手机在床使用与睡眠(HRV): https://pmc.ncbi.nlm.nih.gov/articles/PMC9643910/ ;大学生关灯玩手机数据: https://www.nature.com/articles/s41598-026-42454-7 ;睡前屏幕与睡眠质量: https://sleepeducation.org/screen-time-and-sleep-what-new-studies-reveal/ diff --git a/research/03-schemes/game-inventory.md b/research/03-schemes/game-inventory.md new file mode 100644 index 00000000..78e917ab --- /dev/null +++ b/research/03-schemes/game-inventory.md @@ -0,0 +1,383 @@ +# 六款游戏交互接线清单(「向导交互层」接入前置调研) + +> 调研方法:逐行阅读 `web/engine/{game,gesture,audio,haptics}.js` 与 6 款 `web//game.js` 全文。 +> 所有行号均指 `web//game.js`(engine 文件显式标注 `engine/xxx.js:行号`)。以代码为准;与文件头注释/设计文档不一致处已注明。 +> 调研日期:2026-08-30。工作区版本(未提交改动以实际文件为准)。 + +--- + +## 0. 引擎公共事实(先读,后文引用) + +- 手势集合:`'up'|'down'|'left'|'right'|'tap'|'doubletap'`,另有 `'longpress'|'longpressend'`(gesture.js:5-7)。**tap 回调有 ~300ms 延迟**(双击窗口,engine/gesture.js:11-13、161-166)——即时反馈必须用滑动/双击,rhythm/space/rpg 均做了补偿。 +- 手势识别震动由 gesture.js 内置:滑动→`swipe`、tap/doubletap→`confirm`(engine/gesture.js:144、155、164);语义震动(error/success/warning/hit/beat 等)由游戏层自行调 `vibrate()`。 +- audio 三层:`bgm/`(循环+交叉淡化)、`voice/`(单通道,播 BGM duck 到 20%;`onComplete` 仅自然播完触发,**被打断不触发**)、`sfx/`(即发即弃可叠加)(engine/audio.js:4-11、184-186)。`skipVoice()` = 截断当前句并**触发其 onComplete**(链继续),`stopVoice()` = 作废整条链(engine/audio.js:216-244)。 +- 长按 = 旁白临时 1.7 倍速,audio.js 全局监听 window 事件,游戏零改动(engine/audio.js:97-101、448-458)。rhythm 文件头注明 main/tut 应豁免但引擎无 per-game 开关,属已知限制(rhythm/game.js:36-38)。 +- **`audio._voice` 是私有字段**,无公开"是否有对白在播"查询 API;simon:131-140、escape:328、rhythm:472-476、space:646-648、rpg:1054 都直接读它做"单击跳句"的语境判定——向导层若改引擎应把它转正。 +- 语音链通行写法:各游戏都有自己的 `_speak(ids, onDone)`(session/runId 令牌守卫)+ `_speakGuarded`(看门狗兜底)变体;storyline 例外,用 `playSeq` + 30s 单句看门狗。 +- `Game` 基类(engine/game.js:18-42):`onGesture/start/stop`。`StateMachineGame`(engine/game.js:66-106)**6 款游戏无一使用**,全部直接继承 `Game`、自管状态字段。 + +--- + +## 1. storyline《声命线》(web/storyline/game.js,340 行) + +### 1.1 状态模型 +- 类 `StorylineGame extends Game`(:84)。**手动状态字段,非状态机基类**。 +- 字段(:87-101):`mode: 'STORY'|'MENU'`(:76);`nodeId`(剧情节点 id,NODES 表 :31-68 共 32 节点);`voicePlaying`(链播放中);`currentVoiceId`;`promptPlaying`(当前句是抉择提示 `voice/p\d*`,正则 :82);`choiceArmed`(提示音播完、可左右抉择);`pendingChoice`(提示音播放中缓存的抉择);`awaitingRestart`(结局播完);`seqToken`(语音链作废令牌);剧情标记 `companion/knowTrap/betrayed`。 +- 流转驱动:**语音 onComplete 链 + 手势**。`playNode`→`playSeq`(:175-196, 230-261)串行播完→`onNodeSeqDone`(:214-227)置 `choiceArmed/awaitingRestart` 或静默等 tap;`choose`(:263-273)驱动跳节点;无任何游戏逻辑定时器(只有语音看门狗)。 + +### 1.2 等待输入点清单 +| # | 状态/条件 | 玩家该做什么 | 此刻声音 | 位置 | +|---|---|---|---|---| +| W1 | 叙事节点链播完(`voicePlaying=false`、`node.next≠null`) | tap=继续下一节点;doubletap=重听本节点;up=帮助;down=菜单。**left/right 静默忽略**(:137 prompt==null return) | 完全静默(仅 `bgm/dark_drone` 循环垫底,:107) | :214-227("否则等待单击继续" :226),tap 分支 :130 | +| W2 | 选择节点提示音播完(`choiceArmed=true`,p1~p8 共 8 个节点) | left/right=抉择。**tap 无效**(选择节点 `next==null`,:130 判空) | 静默 | :217-222、:137-141 | +| W3 | 结局播完(`awaitingRestart=true`,e1~e4) | tap=重开 | 静默 | :224、:126 | +| W4 | 菜单(`mode=MENU`) | left=重开;right/tap=关闭;up=帮助;doubletap=重听菜单语音。**down 无绑定** | `bgm/menu`(:304)+ `voice/menu` 播完即静默 | :151-171 | +| W5 | (特殊)提示音播放中滑 left/right | 不生效,**缓存进 `pendingChoice`**,播完自动执行(缓冲,非忽略) | voice/p* 播放中 | :139、:218-222 | + +### 1.3 播放内容但不接受输入的时刻 +- 节点语音链播放中(`playSeq` :230-261):tap=跳过当前句(`skipVoice`,**`promptPlaying` 时不可跳**,盲玩公平,:128-129);doubletap=打断重听(:198-211);up/down 随时可用。 +- 引导句 `voice/skip_hint`(首局 n00 后追加,:188-191)、彩蛋 `e1_child`(:193)随链播放,可跳。 +- 输入行为总述:**从不报错**,不匹配的手势一律静默 return(:130-141 各分支)。 + +### 1.4 错误路径清单 +- **无"错误"概念**:无效手势(非选择节点滑 left/right、选择节点按 tap、菜单按 down)全部静默忽略,无震动、无音效、无语音。代码中无一处 `vibrate('error')`。 +- 唯一"负反馈"是结局本身的剧情音效(e3 `sfx/radio_static` :66、e4 `sfx/struggle` :67)。 +- **无纠错性语音**(也不需要传统意义的纠错,但"无效手势零反馈"对盲玩家等于手势没发出去)。 + +### 1.5 已有帮助/状态播报 +- up = `playHelpAndResume`(:284-297):`seqToken++` 作废当前链 → 播 `voice/help` + `voice/status1..3`(按 `actOf` :331-339 分幕)→ **自动重播当前剧情节点**。这是全游戏唯一的状态播报,内容是"第几幕",不含节点级进度。 +- 菜单内 up 同函数(`backToMenu=true`,:160-162)。 +- 无卡关看门狗:某节点静默等 tap 永远不会超时(除 :245-250 的 30s 单句语音资产缺失看门狗)。 + +### 1.6 超时/定时器 +| 定时器 | 时长 | 后果 | 位置 | +|---|---|---|---| +| 单句语音看门狗 `VOICE_WATCHDOG_MS` | 30s | 视为资产缺失,自动续链下一句 | :79、:245-250 | +| (无其他定时器;无卡关/保护/倒计时) | | | | + +### 1.7 向导层接入点建议 +1. **状态播报**:向导层劫持 `playSeq`(:230)即可掌握全部旁白时机;"你现在的进度"语音可在 `onNodeSeqDone`(:214)后追加(在 voice 链尾部排队,不与 p* 提示冲突——p* 是链的末句,播完即 W2,向导层应避免在此追加,见下)。 +2. **轮到你提示**:W1(叙事节点播完)在 `onNodeSeqDone` :226 分支插"轻触继续"提示(现状完全静默,是全 6 款中最盲的等待点)。W2 不可插语音(会破坏"提示音播完即可选"的契约),可改用**震动**(`vibrate('confirm')`)标记 `choiceArmed=true`(:217)。 +3. **静默看门狗**:W1/W2/W3 均无超时。建议在 `onNodeSeqDone`(:214)挂 N 秒无手势→重播 `voice/help+status`(复用 `playHelpAndResume` :284)。W3 同理(`awaitingRestart` 置位点 :224)。 +4. **纠错反馈**:`onStoryGesture`(:121)各静默 return 处(:137 等)加轻震动(`swipe` 之外的语义提示)或一句 `voice/` 提示,成本极低。 + +--- + +## 2. simon《音序回响》(web/simon/game.js,547 行) + +### 2.1 状态模型 +- 类 `SimonGame extends Game`(:66)。 +- `phase` 枚举(:69):`idle|tutorial|announce|playback|input|roundend|gameover|menu`。辅助字段:`round`(序列长 = round+1)、`inputIdx`、`chances`(重听机会,初始 1、每 4 轮 +1、上限 2,:73)、教学字段 `teachIdx/teachAwait/teachErrs`(:76-78)、`_menuIdx`、`_session`(会话令牌)、`_timers`(:80-82)。 +- 流转驱动:**定时器 + onComplete 链 + 手势**。教学:`_teachStep`(:151-175)语音链播完→播音色→900ms→`t_try`→播完或 1.5s 兜底→`teachAwait=true` 等手势;对局:`_nextRound`(:236-259)→announce 语音(2.5s 兜底)→`_playSequence`(:290-319)定时器驱动的序列演示→400ms→`confirm` 震→第 1 轮 `your_turn` 语音→`_toInput`(:321)等输入。 + +### 2.2 等待输入点清单 +| # | 状态/条件 | 玩家该做什么 | 此刻声音 | 位置 | +|---|---|---|---|---| +| W1 | tutorial `teachAwait=true` | 做当前教的手势(6 个逐一);down=跳过教学(教 down 时除外,:180 上下文判定) | 静默(t_try 播完后) | :151-175、:177-216 | +| W2 | `phase='input'` | 按序重复序列手势;doubletap 在"非期望双击"时=主动重听(耗机会,:329-332) | **完全静默**(对局全程无 BGM,文件头 :7-9);进入时仅 `confirm` 震 + 第 1 轮 `voice/your_turn` | :321-324、:302-315 | +| W3 | `gameover` 播报链播完 | tap=重开;up=规则;down=菜单 | `bgm/menu` vol0.3(起播后 ~2650ms 淡入,:418-422) | :109-113 | +| W4 | `menu` | tap=循环项;doubletap=确认;up=规则。**down 无绑定** | `bgm/menu` | :449-462 | + +**W2 无任何超时**:玩家不动则永远静默等下去(无看门狗)——向导层最大价值点之一。 + +### 2.3 播放内容但不接受输入的时刻 +- `announce`(轮次整句 `round_01..round_20`/`round_more`,:245-256):**所有手势静默忽略**(:117-119 default 分支,裁定见 :118 注释"纯聆听阶段手势静默忽略");2.5s 兜底直接进 playback。 +- `playback`(序列演示,每音 `beat` 震,间隔 `max(420, 700-(round-1)*26)`ms,:285-319):同样全部忽略(含第 1 轮 your_turn 期间)。 +- `roundend`(答对/答错后的播报链,`_speakGuarded` 10s):忽略;播完自动 `_nextRound` 或重播序列。 +- 旁白跳过:`_tapSkipsVoice`(:131-140)按 phase 白名单(tutorial 非等待期/announce/roundend/gameover 可跳;**teachAwait 期 tap=答题、playback/input 期不跳、menu 单击是菜单语义**)。 + +### 2.4 错误路径清单 +- 教学做错(:205-215):`vibrate('error')` + `voice/t_wrong_`;**同一步错满 3 次**:`vibrate('warning')` + `voice/t_blunt_`(更直白描述)并计数清零。→ 已有纠错语音且带升级。 +- input 做错(`_wrongAnswer` :377-391):有机会→`error` 震 + 300ms 后 `warning` 震 + `voice/retry_use`(+归零时 `chances_out`)→ 自动重播同一序列(`phase='roundend'`)。无机会→`_gameOver`(:393-423):`error` 震、300ms 后 `hit` 震、700ms 后 `sfx/gameover`、1400ms 后播 `gameover+score_band+new_record+replay+rules_prompt` 链。 +- 重听无机会(:344-349):`error` 震 + `voice/chances_out`。 +- 对局输入错误无"该做什么"级纠错语音(retry_use 只说"再试一次",不重复期望手势——靠重播序列弥补)。 + +### 2.5 已有帮助/状态播报 +- gameover up / menu up = `_speakRules`(:435-437):`voice/rules + voice/rules_prompt`。**tutorial 与对局中无帮助手势**(up/down 在 input 是序列手势)。 +- 状态播报:每轮 `round_XX` 整句(主动播)、成绩 `score_band1..6`(结算)、机会变动 `chance_plus/chances_out`——播报文化完整。 +- 对局无卡关计时器(等输入无限等,见 2.2)。 + +### 2.6 超时/定时器 +| 定时器 | 时长 | 后果 | 位置 | +|---|---|---|---| +| 开场进教学延迟 | 500ms | `_runTutorial` | :92 | +| `t_try` 缺失兜底 | 1.5s | 直接 `teachAwait=true` | :169-171 | +| 教学跳过(down)兜底 | 4s | `_beginGame` | :185 | +| announce 兜底 | 2.5s | 直接 `_playSequence` | :258 | +| 序列末音→"轮到你" | 400ms | `confirm` 震 + 第 1 轮 your_turn | :315、:304 | +| your_turn 兜底 | 2.5s | 直接 `_toInput` | :311 | +| roundend→下一轮 | 300ms | `_nextRound` | :373 | +| `_wrongAnswer` warning 震 | 300ms 后 | 第二段震动 | :382 | +| gameover 各段 | 300/700/1400/2650ms | hit 震/gameover 音/语音链/menu pad | :404-422 | +| `_speakGuarded` 默认 | 10s | 语音缺失也推进链回调 | :518-528 | +| 教学收尾 t7 链兜底 | 12s | `_beginGame` | :201 | + +### 2.7 向导层接入点建议 +1. **静默看门狗(最优先)**:`_toInput`(:321)挂计时——N 秒无输入先播提示再自动重听(复用 `_relisten` :344 逻辑但可免机会扣减或改为无限次提示);`gameover` 链播完(:413 `_speak(ids, null)` 的 null 回调处)同理。 +2. **轮到你提示泛化**:`_playSequence` :304 的 `confirm` 震 + :306 `your_turn`(仅第 1 轮)——向导层把"轮到你"语音做成低打扰版(震型升级或每 K 轮播一次)只需改这两行。 +3. **状态播报**:`phase` 字段完备,向导层可直接读;劫持 `_speak`(:502)即可统一插播。 +4. **菜单缺口**:对局中(input/playback)无菜单呼出路径,唯一退出是故意答错到 gameover——向导层或需一个不与 6 手势冲突的呼出方案(长按已全局占用为快进,engine/gesture.js:14-19)。 +5. `audio._voice` 私有读(:131-140)应随引擎转正。 + +--- + +## 3. escape《暗室》(web/escape/game.js,672 行) + +### 3.1 状态模型 +- 类 `EscapeGame extends Game`(:76)。`Phase` 枚举(:36-42):`REOPEN|GUIDE|PLAY|ENDING|MENU`。 +- 字段(:86-110):坐标 `x,y`(3x3)、谜题旗标 `hasKey/hasFuse/cabinetOpen/powerOn`、`visited`、`guideStep 0..7/guideSwipes/guideErrs/_guideBusy`、卡关 `_lastProgressAt/_stuckShown(L1|L2|L3)/_lastL3At`、`_voiceSkippable`、`_menuReturn/_menuIdx`、`_session`。 +- 流转驱动:**手势为主 + 语音 onComplete 链**。start 按存档进 REOPEN 或 GUIDE(:121-128);GUIDE 由 `_advance`(:176-194)语音播完回调推进 guideStep;PLAY 是自由探索无严格状态;谜题链阶段由派生函数 `_stage()`(:454-459:key→cabinet→box→gate)给出。 + +### 3.2 等待输入点清单 +| # | 状态/条件 | 玩家该做什么 | 此刻声音 | 位置 | +|---|---|---|---|---| +| W1 | REOPEN:`reopen_prompt` 播完(**不可跳**) | tap=直接开始;up=重听引导。左右滑/双击静默忽略 | 静默(`bgm/drone` 垫底,:120) | :134-137 | +| W2 | GUIDE 各步:推进语音播完(`_guideBusy=false`) | 做该步手势(tap/滑动×2/左/下/tap/双击) | 静默 | `_advance` :180-187,`_onGuideGesture` :196-256 | +| W3 | PLAY 常态 | 四向移动/tap 检查/doubletap 用物 | `amb_*` 环境音(进房自动播,:370-372)+ `bgm/drone` | `_onPlayGesture` :318-336 | +| W4 | PLAY:voice 播放中 | **滑动移动不受阻**(无全局 gate);仅 tap 分流:可跳句=skip,不可跳句=**忽略**(:328-331 注释解释了为何不触发检查) | voice | :324-332 | +| W5 | ENDING:结算链播完(或 30s 兜底) | tap=重开;down=菜单 | `bgm/menu` vol0.5(`_startEndingBgm` :577-581) | :144-147 | +| W6 | MENU | tap=循环;doubletap=确认;up=操作说明;down=关闭 | `bgm/menu` | :524-539 | +| W7 | GUIDE G7:g7_goal 播放中 | 手势忽略(等 `_advance` onDone 进 PLAY) | voice | :253-254 | + +### 3.3 播放内容但不接受输入的时刻 +- 引导推进链(`_speak(..., {skippable:false})`,:192):`_guideBusy=true` 期**下滑以外的手势一律忽略**(:199-200);下滑随时可跳过引导(G4 除外——G4 答案就是下滑,:197-199)。 +- 关键获得句不可跳:`found_key`(:390)、`unlock_cabinet`(:422)、`fix_box`(:431)、逃脱结算链(:570-571)、L3 带路链(:489)、`guide_skip`(:268)。 +- 可跳句:`room_*` 首到描述、`start_room`、`empty_*`、检查描述、`wall`、L1/L2 提示。 +- PLAY 期**没有缓冲**:voice 中滑动手势立即生效(移动与语音并行),tap 按可跳性分流。 + +### 3.4 错误路径清单 +- 撞墙(`_move` :341-346):`sfx/wall` + `vibrate('error')` + `voice/wall`(**每次都播**,:344 注释"取消一次性限制")。 +- 引导做错(`_guideWrong` :278-288):`vibrate('error')` + `guide_wrong_`(方向错)/`guide_wrong_gesture`(手势类型错);**错满 3 次**:`warning` 震 + `guide_blunt_` 直白重述(仅方向步有 blunt)。→ 完整纠错语音 + 升级。 +- 双击无可用目标(`_useItem` :435-443):`error` 震 + 播 `use_fail`(关键房间)/背包句 `inv_*` + **主动追加当前阶段 L2 明示** `stuck__2`。→ 已有"告诉玩家该去哪"级纠错。 +- **纠错性语音:全 6 款中最完备**(wrong/blunt/stuck 三级 + nav 带路)。 + +### 3.5 已有帮助/状态播报 +- **PLAY 中无帮助手势**(四向/tap/doubletap 全被占用,上滑=向北走)。状态查询只能靠:tap 重播环境音+描述(:375-409)、doubletap 兜底播报背包+L2(:435-443)。 +- MENU up = `voice/help_ops`(:529-530)。 +- **三级卡关看门狗**(`_checkStuck` :479-500,每 5s 轮询 :463-466;进展事件 `_progressEvent` :475-477 重置):60s L1 `stuck_ask+stuck__1`(暗示);120s L2 `stuck__2`(明示);180s L3 `stuck__3` + 按坐标实时算路 `nav_*`,此后**每 60s 重复**(:485-490)。全部 `warning` 震;L3 不可跳。 + +### 3.6 超时/定时器 +| 定时器 | 时长 | 后果 | 位置 | +|---|---|---|---| +| 卡关轮询 | setInterval 5s | 见 3.5 | :465 | +| L1/L2/L3 阈值 | 60s/120s/180s,L3 重复 60s | 提示/明示/带路 | :483-499 | +| 检查描述延迟 | 800ms | 先环境音后描述 | :379-381 | +| 引导推进看门狗 | 20s | 语音缺失也切步(带 `guideStep===fromStep` 防误触发) | :188-190 | +| 跳过引导兜底 | 5s | `_enterPlay` | :270 | +| 逃脱结算 pad 兜底 | 30s | `_startEndingBgm` | :573 | + +### 3.7 向导层接入点建议 +1. **三级卡关即现成的静默看门狗骨架**:向导层接管 `_checkStuck`(:479)或把阈值/级别改由向导层配置;`_progressEvent`(:475)就是标准的"重置看门狗"钩子。 +2. **轮到你提示**:W1/W2 播完即静默,可在 `_advance` done(:180-187)和 REOPEN(:126)后加轻提示;PLAY 是开放探索不需要。 +3. **帮助缺口**:PLAY 无帮助手势——向导层的"状态播报"可挂到向导专属入口(如连续 N 次撞墙后主动播 `nav`),不必新增手势。 +4. `_voiceSkippable`(:96、:642-645)是全项目最干净的"可跳性"封装,向导层插播语音时应复用该机制决定自己的句子可否被打断。 + +--- + +## 4. rhythm《节拍行者》(web/rhythm/game.js,767 行) + +### 4.1 状态模型 +- 类 `RhythmGame extends Game`(:133)。`phase` 枚举(:136):`idle|intro|tut|select|main|menu|end`。 +- 字段:`_runId`(作废令牌)、`_timer`(40ms 调度泵句柄)、`_sched`(领奏音符绝对时刻)、`_timed`(mid_song 等定时动作)、`_cues`(应答期望 `{gesture, expected, judged, result, phrase}`)、`_bgmSrc/_bgmT0`(手动 BGM 网格)、`_tutIdx/_tutFails/_tutAttempts`、`_menuIdx/_pauseAt/_bgmOffset`、`_phaseEnd`(实例字段,constructor 未声明,:308/:421 赋值)。 +- 流转驱动:**AudioContext 时钟绝对排程 + 40ms 泵(`_pump` :239-268)+ 手势**。无 setTimeout 链播(语音仍走 onComplete `_speak`)。全部节拍按 `ctx.currentTime` 预排(LOOKAHEAD 0.6s,:46)。 + +### 4.2 等待输入点清单 +| # | 状态/条件 | 玩家该做什么 | 此刻声音 | 位置 | +|---|---|---|---|---| +| W1 | tut 应答小节(领奏后 4 拍,`cue.expected`±GOOD) | 按谱跟打(T1 单音→T2 左右→T3 三音) | 领奏音已停,`bgm/track90` 循环 | `_tutLead` :290-310 | +| W2 | select 常态 | 左右换曲/tap 确认(未解锁播 `song_locked`)/up=规则/down=回大厅 | `bgm/menu` + 选项播报 | :366-384 | +| W3 | main 每个 cue 应答窗口(expected±0.25s) | 对应乐器手势 | 领奏 1 小节后 4 拍空窗 + 曲目 BGM | `_onMainGesture` :495-527 | +| W4 | main 长空档(restAfter 休止小节) | 无期望输入(可自由演奏/下滑呼菜单) | BGM | 谱面 :61-116 | +| W5 | end 结算链播完 | tap=同曲再来;right=下一首/locked/最后一首播 `voice/restart`;down=回大厅 | `bgm/menu`(链播完淡入,:679) | :452-459 | +| W6 | menu | tap=循环(resume/lobby 两项);doubletap=确认;up=帮助;down=恢复 | **静默**(模态暂停、断点续播不叠 pad) | :569-608 | +| W7 | intro(welcome 播放中) | **只收 tap 跳旁白**,其余全忽略 | voice + 6s 后起的 track90 | :461-463、:173 | + +**注意**:main 阶段"轮到你"无任何显式信号——领奏→应答的切换只靠 BGM 网格与 4 拍静默空窗自悟(对比 simon 有 confirm 震+your_turn、rpg 有 turn_player 标点)。向导层第二价值点。 + +### 4.3 播放内容但不接受输入的时刻 +- intro:非 tap 手势全部忽略(:461-463)。 +- tut/select/end:tap=逐句跳过(`_trySkipVoice` :472-476),其余手势按阶段语义处理(tut 中会记尝试 :479-493——**教学领奏期的手势不是忽略而是全量记录进评估**)。 +- main:**永不跳语音**(mid_song 不可跳裁定,:447 注释);所有手势按演奏判定——窗口内错手势=Miss(:518-520),窗口外=自由演奏发声不判定(:514-517)。 + +### 4.4 错误路径清单 +- Miss(窗口内错手势/超时缺失):**不播乐器音**(错过=没出声)+ `vibrate('error')`(:548-556);超时判定在泵里 :258-263(tap 余量 TAP_DELAY+0.08,其余 0.05s)。**无任何语音反馈**——对局期纠错全靠震,方向都不提示。→ 向导层最该补的位置。 +- 教学评估失败(`_tutEvaluate` :313-354):`error` 震 + 分类纠错语音:手势错=`retry_gesture`、过早=`retry_early`、过晚=`retry_late`、没出手=`retry_listen`(:347-353);**同一步失败 2 次 `retry_skip` 自动跳过**(:335-346)。 +- 未解锁曲 tap:`voice/song_locked`(:373-377)。 +- 不掉血不中断(文件头 :15,"歌照唱完")。 + +### 4.5 已有帮助/状态播报 +- select up = `voice/rules`(:381-383);menu up = `rules + settings_hint`(:585-587)。**main 中无帮助**(下滑被菜单折中占用,:498-501:仅当无悬置/临近 down 音符时下滑才呼菜单,`_downNotePending` :530-534)。 +- 状态播报:无"你打到第几乐句"类播报(节奏游戏特性,可理解);结算链完整(`grade_s..c`+`new_best_combo`+unlock+`restart`)。 + +### 4.6 超时/定时器 +| 定时器 | 时长 | 后果 | 位置 | +|---|---|---|---| +| 调度泵 | setInterval 40ms | 排程音符/Miss 判定/乐句结束 | :270-273 | +| `_speakGuarded` | 默认 10s;welcome 8s | 语音缺失兜底推进 | :756-766、:174 | +| 开场 BGM 延迟 | 6.0s(教学)/1.0s(正式) | 网格起点 | :173、:400 | +| tap 判定补偿 | -0.30s | 手势时刻修正 | :483、:504 | +| `_phaseEnd` | 末 cue + 0.25 + 0.3 + 0.4/0.5s | 教学/曲目结束 | :308、:421 | +| 暂停平移 | resumeAt=now+0.1s | 全部绝对时刻 shift(断点续播) | :595-608 | +| 结算 BGM 淡出 | 0.6s ramp/700ms stop | 曲目 BGM 收 | :634-643 | + +**注意**:`_finish` 的结算链用 `_speak`(无看门狗,:679)——`grade_*` 等语音资产若缺失,`bgm/menu` 永远不会淡入(W5 永远纯静默等待)。这是与 space `_gameOver` 同款的代码事实缺口。 + +### 4.7 向导层接入点建议 +1. **对局纠错语音**:`_applyMiss`(:548)加连续 N 次 Miss 触发一次 `voice/` 提示(素材可参考教学 `retry_gesture`);插播通道建议复用 `play('voice/…', {queue:true})`(engine/audio.js:186)避免顶掉 mid_song。 +2. **轮到你提示**:在泵里检测"首个未判定 cue 进入窗口"(`_pump` :244 附近可取 `_cues` 首个 `!judged`),首乐句播一次 `your_turn` 型提示;或谱面排程时向 `_timed` 推入(:414-418 旁已有 mid_song 先例)。 +3. **结算链补看门狗**:`_finish` :679 `_speak`→`_speakGuarded`(守卫里起 `bgm/menu`)。 +4. **状态播报**:select/end 已够;main 中向导层若要插播必须走 `queue:true` 且避开 `_downNotePending` 类判定干扰。 + +--- + +## 5. space《盲航》(web/space/game.js,698 行) + +### 5.1 状态模型 +- 类 `SpaceGame extends Game`(:88)。`phase` 枚举(:91):`idle|ask|drill|playing|feature|menu|over`。 +- 字段(:97-116):`hits/dodges/runStart/protectionUntil/_protectAnnounced/swipes[]`(滑动手势环形缓冲)、`obstacles`(Set,`{dir, impactAt}`)、`drillOb/drillIdx/drillFails`、`shieldUpUntil/shieldReadyAt/boostUntil/boostReadyAt`、`boostIntroDone/shieldIntroDone/featureKind`、`_menuIdx`、`_session`。 +- 流转驱动:**纯 setTimeout(`_after` :679-687,全部带 session 守卫)+ 手势**。首局 D0-D5 演练(`_startDrill` :178);对局 `_startRun`(:268-281)排三个一次性定时器:20s 单击引入、45s 双击引入、60s 保护期结束宣告;刷怪自递归 `_scheduleSpawn`(:423-431)。 + +### 5.2 等待输入点清单 +| # | 状态/条件 | 玩家该做什么 | 此刻声音 | 位置 | +|---|---|---|---|---| +| W1 | ask:`second_run_ask` 播完 | tap=直接出发;up=重听演练。其余静默忽略 | 静默(无 BGM) | :131-134、:150-153 | +| W2 | drill:每步 `drill_*` 旁白播完→演练陨石逼近 4.5s | 同向滑动拨开(D1 左/D2 右/D3 上/D4 下) | `whoosh_`(语音先、音效后不叠放,:203 注释) | `_nextDrill` :191-204、`_spawnDrillOb` :206-214 | +| W3 | drill:无 drillOb(旁白/反馈播放中) | down=跳过演练;tap=跳句;**其余忽略** | voice | :217-223 | +| W4 | playing 常态 | 持续同向闪避;tap=加速(20s 引入后);doubletap=护盾(45s 引入后);down=无下方陨石时呼菜单(:295-301 折中) | `bgm/engine` + whoosh + 两档 alarm | `_onPlayGesture` :287-324 | +| W5 | feature:引入句播完后 8s 内 | 做 tap(boost 教学)或 doubletap(shield 教学);其他手势忽略等超时 | 静默(刷怪暂停、陨石清空,:347-349) | `_beginFeature` :339-352、`_onFeatureGesture` :354-374 | +| W6 | menu | tap=循环(resume/lobby/help 三项);doubletap=确认;up=帮助;down=恢复 | `bgm/menu` 300ms 快切 | :526-540 | +| W7 | over:结算链播完 | tap=再飞(voice 中 tap=跳句,:167-170);down=回大厅 | `bgm/menu`(链播完淡入,:573-575) | :166-172 | + +### 5.3 播放内容但不接受输入的时刻 +- 演练旁白(`_speakGuarded` 链)、`feat_boost/feat_shield` 引入句、对局归因句 `hit_*`/`protect_*`、里程碑 `ms_*`、结算链:播放中 tap=跳句(:221、:305、:357、文件头 :23-25),其余手势按上文 W3/W5 分流。 +- playing 中**滑动闪避从不被 voice 阻塞**(:290-293 无 gate)。 +- feature 期其他手势"忽略,等超时自动继续"(:359 注释)。 + +### 5.4 错误路径清单 +- 演练做错/超时(`_drillFail` :243-256):`vibrate('error')` + `voice/drill_retry_`(当场重教重演);**失败 2 次 `drill_moveon` 自动带过**不卡流程。 +- 保护期被撞(`_resolve` 第 4 级 :485-490):`sfx/shield_block` + `warning` 震 + `voice/protect_`(归因:哪边来的、你该怎么拨)。 +- 正常被撞(:492-501):`sfx/hit` + `hit` 震 + `voice/hit_`;第 2 次追加 `hit_last`;第 3 次坠毁 `_gameOver`(:556-577):`error` 震、300ms 后 `hit` 震、`sfx/crash`、1200ms 后结算链 `time_1..4 + new_record + dodge_1..4 + restart_hint`。 +- **纠错性语音:归因式**(告诉方位)而非指令式("向左滑")——演练期有指令式(drill_retry 说反了方向语义吗?见语音资产,代码只按 dir 选 id)。 +- **注意**:`_gameOver` 结算链 `_speak(ids, ...)` 无看门狗(:573-575)——`time_*` 资产缺失则 `bgm/menu` 永不淡入。 + +### 5.5 已有帮助/状态播报 +- menu up / menu 第三项 = `help_recap + settings_hint`(:530-532、:538)。**playing 中无帮助手势**(手势全是闪避)。 +- 状态播报:保护期结束宣告 `protect_end`(:409-415,含 `_rearmRunTimers` :389-405 的暂停补偿补播);护盾充能完毕 `shield_ready`+`pickup` 震(:327-334);里程碑 10/25/50/100(:80、:504-512);受击次数走 `hit_last`。状态可辨识性对局内良好。 + +### 5.6 超时/定时器(全项目最多) +| 定时器 | 时长 | 后果 | 位置 | +|---|---|---|---| +| 保护期 | 60s | 撞击不掉血;结束播 `protect_end`+`warning` 震 | :56、:275-280、:409-415 | +| 单击/双击引入 | 第 20s/45s | 暂停刷怪进 feature | :60-61、:278-279 | +| feature 等待上限 | 8s | 不做也继续(`_endFeature`) | :62、:351 | +| 刷怪间隔 | 保护期 4000ms;之后 3200→1200ms(120s 爬满) | `_scheduleSpawn` 自递归 | :57-58、:67、:423-431 | +| 逼近时长 | 保护期/演练 4000/4500ms;之后 2800→1800ms | 撞击判定点 | :57-59、:436 | +| 警报两档 | 撞击前 1000ms/500ms | `alarm` vol0.5→1 + `danger` 震×2 | :50、:442-453 | +| 闪避窗口/宽限 | 1500ms / 250ms | `_resolve` 匹配 swipes | :48-49、:469-471 | +| 护盾 | 持续 6s / 充能 30s(完毕播报) | | :51-52、:327-334 | +| 加速 | 持续 1.8s / 冷却 3s | | :53-54 | +| 演练陨石 | 4500ms 超时=做错 | `_resolveDrill` | :59、:213、:238-241 | +| 坠毁结算延迟 | 1200ms | 爆炸声后开口 | :567 | +| `_speakGuarded` | 默认 10s | 演练/收尾链兜底 | :667-677 | + +### 5.7 向导层接入点建议 +1. **死亡教学升级**:`_resolve` :492-501 的 `hit_` 已含方位,向导层可在 60s 内第 2 次同向被撞时把归因句升级为指令句("左边的来了就向左滑"),插入点即 :498-500 的 ids 组装处。 +2. **静默看门狗**:对局是连续流不需要;drill/feature 已有超时。唯一缺口是 ask(W1)——`second_run_ask` 播完后静默,可加提示或超时直接出发。 +3. **结算链补看门狗**:`_gameOver` :573 `_speak`→`_speakGuarded`(守卫里起 `bgm/menu`),照抄 `_escape` :573 的兜底写法。 +4. `_voiceBusy`(:646-648)是项目里最干净的 `_voice` 读取封装,可作向导层判断"此刻能否插播"的基准。 + +--- + +## 6. rpg《剑与声》(web/rpg/game.js,1105 行) + +### 6.1 状态模型 +- 类 `RpgGame extends Game`(:115)。`phase` 枚举(:118):`idle|ask|intro|explore|shop|battle|menu|over`。**`over` 从未被赋值**(仅 :241 default 注释提及),预留态;`idle` 仅构造后瞬态。 +- 战斗内部二级状态机 `this._battle.state`(:543-561 赋初值):`B_START → PLAYER_SELECT → PLAYER_EXECUTE → CHECK_ENEMY_DEAD → ENEMY_TELEGRAPH → ENEMY_RESOLVE → VICTORY|DEFEAT|FLED|FLEE_FAIL`;另有 `teachStage: 'menu'|'attack'|'parry'|'defend'|null`(四步强制教学 :556)、`tier`(难度档 :559、:567-573)。 +- 其他字段:`scene/optIdx/visited/flags/player/chapters/stats`、`_shopIdx/_menuIdx`、`_ambSrc`(手动环境音循环 :961-982)、`_session`。 +- 流转驱动:**手势 + 语音 onComplete 链 + setTimeout(`_after` :1091)**。探索 `_enterScene`(:251-279)→desc 链→遭遇检查(:282-305)→`_speakOption` 报当前选项;战斗由 `_playerSelect`(:600)与 `_enemyTelegraph`(:770)交替推进。 + +### 6.2 等待输入点清单 +| # | 状态/条件 | 玩家该做什么 | 此刻声音 | 位置 | +|---|---|---|---|---| +| W1 | ask:`sys_continue_ask` 播完 | tap=继续存档;right=新游戏。其余忽略 | **静默**(此时未进任何场景音乐,:167-179 无 bgm 调用) | :224-227 | +| W2 | explore:desc 链播完→当前选项名 `opt_*` 播完 | 左右=切选项(切一个播一个);tap=确认;doubletap=重听 desc+选项;up=状态链;down=菜单 | `amb_*` 常开 + `bgm/village|explore`(:945-949),选项名播完即静默 | `_speakOption` :307-312、`_onExploreGesture` :314-336 | +| W3 | shop:价格句播完 | 左右=切/tap=买/down=离开/up=状态 | 同上 | :451-464 | +| W4 | battle `PLAYER_SELECT`:`turn_player` 音 + 650ms 后 `cmd_<指令名>` 播完 | 左右=切指令(切一个播一个);tap=执行;up=敌我血量;down=逃跑 | `bgm/battle|boss`,cmd 播完即静默 | `_playerSelect` :600-612、:654-666 | +| W5 | battle `ENEMY_TELEGRAPH`:前摇窗口(tier 1.0/1.25/1.5/1.8s + 听风剑 +0.3s) | **doubletap=格挡**(窗口内);其他手势=`error` 震留在窗口 | 前摇音 `tel_*`(Boss 二阶段 1.2 倍速)+ `beat` 震开窗标识 | `_enemyTelegraph` :770-781、:667-678 | +| W6 | menu | 左右=切(RPG 豁免:菜单与探索同构,文件头 :31-33);tap=确认;up=帮助;down=关闭 | `bgm/menu`(amb 不停,:498) | :509-528 | +| W7 | intro/over | **不收任何手势**(:241 default) | voice 链 | :241 | + +- 教学等待点:T0(teachStage='menu',左右切 2 次过关 :658-659)、T1(命中一次 :709-712)、T2(格挡或受击均通过 :819-825)、T3(防御一次 :717-721)——每步都有 8s/16s 看门狗(见 6.6)。 + +### 6.3 播放内容但不接受输入的时刻 +- intro 链(`intro_1..3+skip_hint+sys_new_game`,:198-201):完全不收手势。 +- explore 的 desc/NPC/事件链:tap=跳句(`_voicePlaying()` :324、:1054),**左右切选项/up/down 不被 voice 阻塞**(无全局 gate)——即播 desc 时也能盲切选项(切了会重播 `opt_*` 顶掉 desc)。 +- 战斗:**tap 永不跳语音**(PLAYER_SELECT 中 tap=执行指令 :660-661);文件头 :24-26 声明 `cmd_*` 与 `tut_b*` 不可跳,代码事实上战斗中根本没有跳过路径。 +- 战斗结算链(victory/defeat/ch1_end):`PLAYER_EXECUTE/ENEMY_RESOLVE` 等状态"其他战斗状态:手势忽略"(:679 注释)。 + +### 6.4 错误路径清单 +- 技能无蓝:`btl_nomp` → 4s 后回 PLAYER_SELECT(:688-691);无药:`btl_noitem`(:692-695)。→ 告知型纠错。 +- 逃跑:不可逃战 `error` 震 + `btl_noflee`(:839-844);Lv≥3 逃跑 70%,失败 `btl_flee_fail` → 敌方一个可格挡的前摇回合(:848-856)。 +- **格挡窗口内做错手势:仅 `vibrate('error')`,无语音**(:675-677)——窗口一过就挨打。教学战有 `tut_b2`(:779),非教学战零提示。→ 向导层价值点。 +- 受击:`sfx/hurt` + `hit` 震(:810-811);血量降档:`warning` 震 + `st_hp_low/mid`(:829-832,仅降档才播);战败:`hit`+`error` 震 + `btl_lose+btl_lose_hint` → 回村重生(:886-904)。 +- 格挡成功:`sfx/parry` + `confirm` 震(:672-673,即时回调规避 tap 300ms 延迟)。 +- 纠错性语音:教学战完整(tut_b0..b6 + 看门狗重播);常规战斗靠 `cmd_*` 循环播报即事实上的纠错。 + +### 6.5 已有帮助/状态播报 +- explore/battle/shop up = `_speakStatus`(:431-447):探索 5 句链(lv/hp/gold/weapon/armor,全部分档整句),战斗 2 句(己方+敌方血量档位);血量 low 附 `warning` 震。**全 6 款最完整的状态播报**。 +- menu 帮助 = `help_explore + help_battle + settings_hint`(:521-524)。 +- 战斗回合标点:`sfx/turn_player`(≤0.4s)→650ms 间隙→`cmd_*`(:604-611 注释"听觉标点");前摇开窗 `beat` 震(:778)。 +- 教学看门狗(`_armTeachWatchdog` :630-649):8s 无操作重播一次提示(tut_b0/b3/b6),16s 仍无进展**兜底自动推进**教学步;parry 步不兜底(前摇自然结算)。 +- **探索/常规战斗无卡关计时器**:PLAYER_SELECT 挂机永远等(敌不打你);`_speakGuarded` 全部是语音资产缺失兜底而非卡关逻辑。 + +### 6.6 超时/定时器 +| 定时器 | 时长 | 后果 | 位置 | +|---|---|---|---| +| intro 链兜底 | 30s | 进村 | :201 | +| desc 链兜底 | 20s | 存档→遭遇→报选项 | :278 | +| 战斗开场链兜底 | 60s | `_playerSelect` | :597 | +| 教学提示重播 | 8s | 重播 tut_b0/b3/b6 一次 | :634-638 | +| 教学兜底推进 | 16s | 自动进下一步 | :639-648 | +| 教学步链兜底 | 8s | `_playerSelect`/`_enemyTelegraph` | :619-622 | +| nomp/noitem 回合 | 4s | 回 PLAYER_SELECT | :689、:693 | +| turn_player→cmd | 650ms | 播指令名 | :607 | +| 敌亡链/连战 | 10s | `_nextEnemy`/`_victory` | :748 | +| half/phase2 链 | 8s | `_enemyTelegraph` | :759、:763 | +| 血量降档链 | 5s | 下一回合 | :831 | +| flee 两分支 | 6s | 结束/前摇 | :852、:855 | +| victory/defeat/ch1_end | 15s/15s/15s | 收尾 | :883、:893、:936 | +| 格挡窗口 | 1.0/1.25/1.5/1.8s(+0.3 剑) | 到点 `_enemyResolve` 挨打 | :559、:775-780 | + +### 6.7 向导层接入点建议 +1. **常规战斗静默看门狗**:`_playerSelect`(:600)挂"教学式"看门狗——非教学战 N 秒无手势重播 `cmd_<当前指令>`(照抄 `_armTeachWatchdog` :630 的 8s 重播模式,去掉 16s 强推)。这是把现成机制推广,改动最小。 +2. **格挡窗口纠错语音**:`_onBattleGesture` :675-677 的 else 分支(现仅 error 震)加节流语音(如 `voice/` "现在是双击")——注意窗口只有 ~1s,语音应走 queue 且短,或仅震动升级(`warning`)。 +3. **轮到你提示**:`turn_player` 标点已是范本;向导层可统一在 `_playerSelect`(:600)后追加播报型钩子。 +4. **状态播报**:`_speakStatus`(:431)即向导层"状态播报"的内容源,接法 = 向导层主动调用即可。 +5. `phase`+`_battle.state` 双层状态完备,向导层可精确知道"该做什么手势"(PLAYER_SELECT=指令循环,TELEGRAPH=doubletap),适合生成通用提示语。 + +--- + +## 7. 全局观察 + +### 7.1 对比表 + +| 维度 | storyline | simon | escape | rhythm | space | rpg | +|---|---|---|---|---|---|---| +| **等待输入时的静默处理** | ★☆☆ W1/W2/W3 全静默无信号、无超时;仅 BGM 垫 | ★★★★ input 前 confirm 震+第1轮 your_turn;但 W2 无限静默等 | ★★★☆ W1/W2 静默;PLAY 有 amb 常开可接受 | ★☆☆ main 无任何"轮到你"信号,全靠 BGM 网格自悟;end 链无看门狗 | ★★★☆ 连续流无轮次问题;ask/feature 有超时兜底 | ★★★★★ turn_player 标点+650ms+cmd 播报,是范本 | +| **错误反馈完整性** | ☆☆☆ 无效手势零反馈(无震无音无语音) | ★★★★ 教学纠错+3次 blunt 升级;对局 retry_use 自动重播 | ★★★★★ wrong/blunt/stuck 三级+nav 带路,全项目最完备 | ★★☆ 教学好(4 类归因+2次跳过);**对局 Miss 仅 error 震无任何语音** | ★★★★ 演练 retry+2次 moveon;对局归因式 protect_*/hit_* | ★★★★ nomp/noitem/noflee/教学看门狗齐全;**格挡窗口错手势仅震动** | +| **状态可辨识性** | ★★☆ 仅手动 up 查"第几幕";节点级不可知;无效手势无法分辨"没收到" | ★★★★ 每轮整句报数+机会播报+分段成绩;但对局无菜单可退 | ★★★★★ REOPEN/引导/三级卡关+amb/BGM 双层+进展重置,可辨识性最强 | ★★☆ 无对局进度播报;结算链完整;教学结束不可知(挂机停在 tut 静默等) | ★★★★ 保护期宣告/护盾就绪/里程碑/两档警报齐备 | ★★★★★ 四状态 BGM+turn 标点+上滑状态链;phase/state 双层机读友好 | +| **卡关/静默看门狗** | 无(仅 30s 资产兜底) | 无对局看门狗(最需要) | ★★★ 三级 60/120/180s+L3 循环 | 无(教学靠 _phaseEnd) | 无(feature 8s 除外) | ★★ 教学 8s/16s(非教学无) | +| **"轮到你"显式提示** | 无 | 震+首轮语音 | 无(开放探索不需) | 无 | 无(连续流不需) | sfx 标点(最好) | +| **单击跳句 gate 实现** | 自查 promptPlaying | `_tapSkipsVoice` 白名单 | `_voiceSkippable` 封装(最干净) | `_trySkipVoice` | `_voiceBusy` | `_voicePlaying` | + +### 7.2 结论(谁最好、谁最薄弱) + +- **错误反馈最完备:escape**(wrong→blunt 升级 + stuck 三级 + nav 带路,且全部语音化);**最薄弱:storyline**(无效手势零反馈——对剧情游戏可辩护,但盲玩家无法分辨"手势没识别"与"这里没这个手势"),其次 **rhythm 对局期**(Miss 无声无语,只有 error 震)与 **rpg 格挡窗口**(1s 决胜窗口内做错只有震动)。 +- **等待输入静默处理最好:rpg**(turn_player+cmd 名构成完整"轮到你+你可选什么"信号链);**最薄弱:rhythm main**(领奏→应答切换零显式信号)与 **storyline W1**(静默即等待);**simon input 是最危险的静默等待**(完全无 BGM、无超时、玩家挂机则永久卡住)。 +- **状态可辨识性最好:escape**(被动三级提示 + 主动 doubletap 兜底播报)与 **rpg**(双层状态 + 状态链);**最薄弱:storyline**(只有幕级播报)。 +- **向导层的四个统一钩子落点**(所有游戏都已具备,接法成本低): + 1. 语音插播通道:各游戏 `_speak`(storyline 用 `playSeq`)+ 引擎 `queue:true`(engine/audio.js:186); + 2. "轮到你"注入点:storyline `onNodeSeqDone`:214 / simon `_toInput`:321 / escape `_advance` done:180 / rhythm `_pump` 首 cue:244 / space `_startRun` 首刷怪前:277 / rpg `_playerSelect`:600; + 3. 静默看门狗模板:escape `_checkStuck`:479(轮询+进展重置+级别集合)与 rpg `_armTeachWatchdog`:630(N 秒重播+2N 兜底推进)两套现成范式,向导层统一实现后逐游戏替换; + 4. 纠错语音注入点:simon :205-215 / escape `_guideWrong`:278 / space `_drillFail`:243 / rhythm `_tutEvaluate`:347 与 `_applyMiss`:548 / rpg :675-677。 +- **引擎侧两件待办**(向导层前置):`audio._voice` 转为公开只读 API(5 处私有读);`skipVoice` 语义与 `_speakGuarded` 看门狗模式可下沉进引擎统一提供。另注意 rhythm `_finish`:679 与 space `_gameOver`:573 的结算链**无看门狗**,语音资产缺失会导致结算 BGM 永不淡入——接入向导层时应一并修复。 diff --git a/research/04-playtests/transcripts/storyline.md b/research/04-playtests/transcripts/storyline.md new file mode 100644 index 00000000..193dc122 --- /dev/null +++ b/research/04-playtests/transcripts/storyline.md @@ -0,0 +1,103 @@ +# 试玩转写:《storyline》 + +> 本文件是「玩家感知日志」:一位新手玩家的整局体验转写。语音列出了玩家听到的每句话全文, +> 音效/BGM/震动按发生时间列出。「静默」段 = 玩家什么也听不到。手势是剧本注入的(模拟真人手部动作), +> 非最优操作:包含犹豫、误操作与乱试。语音时长按语速估算(±20%),仅供节奏参考。 +t+ 0.0s (玩家点开游戏,轻触屏幕开始) +t+ 0.0s ♫ BGM 切换 → bgm/dark_drone +t+ 0.0s ▶ 语音:「大停电后的第三十天,城市陷入彻底的黑暗。没有电,没有网络,只有收音机里偶尔闪过的沙沙声,像垂死者的呼吸。你是林晚,一名前急救员。在这个故事里,你用声音活下去。请记住:单击屏幕,继续剧情;双击,重听上一句;向上滑,听你的状态和帮助;向下滑,呼出菜单。当我说“请选择”的时候,向左滑,或者向右滑,做出你的决定。选择一旦做出,就无法回头。现在,单击屏幕,睁开眼睛。」 +t+ 2.1s ▶ 语音:「单击可跳过旁白。」 +t+ 4.2s 【状态】等待中(BGM=bgm/dark_drone) +t+ 4.2s ♪ 音效 sfx/heartbeat +t+ 4.2s ▶ 语音:「后脑一阵钝痛,嘴里全是铁锈味。你在废弃的地铁站里醒来,四周黑得像沉在水底。背包还压在身下,手电筒却不知去向。远处滴水的声音,一下,一下,像某种倒计时。」 +t+ 6.4s 【状态】等待中(BGM=bgm/dark_drone) +t+ 6.4s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 6.4s ⚠ 资产缺失 voice/female/n02_linwan.ogg → 玩家此刻听到的是静默 +t+ 6.4s ⚠ 资产缺失 voice/female/n02_linwan.m4a → 玩家此刻听到的是静默 +t+ 6.4s ⚠ 资产缺失 voice/female/n02_linwan.mp3 → 玩家此刻听到的是静默 +t+ 6.4s ⚠ 资产缺失 voice/female/n02_linwan.wav → 玩家此刻听到的是静默 +t+ 8.5s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 10.6s 【状态】等待中(BGM=bgm/dark_drone) +t+ 10.6s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 12.7s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 14.8s 【状态】等待中(BGM=bgm/dark_drone) +t+ 14.8s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 17.0s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 19.1s 【状态】等待中(BGM=bgm/dark_drone) +t+ 19.1s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 21.2s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 23.3s 【状态】等待中(BGM=bgm/dark_drone) +t+ 23.3s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 25.4s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 27.6s 【状态】等待中(BGM=bgm/dark_drone) +t+ 27.6s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 29.7s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 31.8s 【状态】等待中(BGM=bgm/dark_drone) +t+ 31.8s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 33.9s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 36.0s 【状态】等待中(BGM=bgm/dark_drone) +t+ 36.0s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 38.2s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 40.3s 【状态】等待中(BGM=bgm/dark_drone) +t+ 40.3s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 42.4s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 44.5s 【状态】等待中(BGM=bgm/dark_drone) +t+ 44.5s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 46.6s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 48.8s 【状态】等待中(BGM=bgm/dark_drone) +t+ 48.8s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 50.9s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 53.0s 【状态】等待中(BGM=bgm/dark_drone) +t+ 53.0s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 55.1s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 57.2s 【状态】等待中(BGM=bgm/dark_drone) +t+ 57.2s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 59.4s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 61.5s 【状态】等待中(BGM=bgm/dark_drone) +t+ 61.5s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 63.6s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 65.7s 【状态】等待中(BGM=bgm/dark_drone) +t+ 65.7s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 67.8s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 70.0s 【状态】等待中(BGM=bgm/dark_drone) +t+ 70.0s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 72.1s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 74.2s 【状态】等待中(BGM=bgm/dark_drone) +t+ 74.2s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 76.3s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 78.4s 【状态】等待中(BGM=bgm/dark_drone) +t+ 78.4s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 80.6s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 82.7s 【状态】等待中(BGM=bgm/dark_drone) +t+ 82.7s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 84.8s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 86.9s 【状态】等待中(BGM=bgm/dark_drone) +t+ 86.9s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 89.0s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 91.2s 【状态】等待中(BGM=bgm/dark_drone) +t+ 91.2s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 93.3s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 95.4s 【状态】等待中(BGM=bgm/dark_drone) +t+ 95.4s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 97.5s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 99.6s 【状态】等待中(BGM=bgm/dark_drone) +t+ 99.6s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 101.8s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 103.9s 【状态】等待中(BGM=bgm/dark_drone) +t+ 103.9s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 106.0s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 108.1s 【状态】等待中(BGM=bgm/dark_drone) +t+ 108.1s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 110.2s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 112.4s 【状态】等待中(BGM=bgm/dark_drone) +t+ 112.4s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 114.5s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 116.6s 【状态】等待中(BGM=bgm/dark_drone) +t+ 116.6s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 118.7s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 120.8s 【状态】等待中(BGM=bgm/dark_drone) +t+ 120.8s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 123.0s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 +t+ 125.1s 【状态】等待中(BGM=bgm/dark_drone) +t+ 125.1s ▶ 语音 voice/n02_linwan(无台词表文本) +t+ 127.2s ▶ 语音:「请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。」 diff --git a/tools/extract_voice_text.py b/tools/extract_voice_text.py new file mode 100644 index 00000000..528a2861 --- /dev/null +++ b/tools/extract_voice_text.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +"""从 tools/gen_voice_dual.py 台词表提取 id -> 台词全文 映射,输出 JSON。 + +供试玩转写 harness(web/harness/)把语音播放事件转写成人类可读文本。 +台词表是唯一事实源:新台词先改进 gen_voice_dual.py,再跑本脚本刷新 JSON。 + +用法:.venv-tts/bin/python tools/extract_voice_text.py +输出:web/harness/voice_text.json {"game": {"id": "全文", ...}} +""" +import ast +import json +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parent.parent +sys.path.insert(0, str(ROOT / "tools")) + +import gen_voice_dual as gvd # noqa: E402 + +out = {} +for game, lines in gvd.GAMES.items(): + table = {} + for fid, _ins, text in lines: + if fid in table: + raise SystemExit(f"重复 id:{game}/{fid}") + table[fid] = text + out[game] = table + + +def parse_legacy(py_path: Path) -> dict: + """AST 解析旧版 gen_voice.py:提取 ('id', ("Speaker", "instruct"), "text") 元组。 + 不能 import——这些脚本顶层直接执行生成。""" + tree = ast.parse(py_path.read_text(encoding="utf-8")) + found = {} + for node in ast.walk(tree): + if not isinstance(node, ast.Tuple) or len(node.elts) != 3: + continue + a, _b, c = node.elts + if (isinstance(a, ast.Constant) and isinstance(a.value, str) + and isinstance(c, ast.Constant) and isinstance(c.value, str) + and len(c.value) >= 2): + found[a.value] = c.value + return found + + +# 旧 flavor 脚本补齐角色台词(storyline 林晚等、escape 角色音);主表优先,不覆盖 +for game, legacy in [("storyline", ROOT / "app/src/storyline/gen/gen_voice.py"), + ("escape", ROOT / "app/src/escape/gen/gen_voice.py")]: + for fid, text in parse_legacy(legacy).items(): + out[game].setdefault(fid, text) + +dest = ROOT / "web" / "harness" / "voice_text.json" +dest.parent.mkdir(parents=True, exist_ok=True) +dest.write_text(json.dumps(out, ensure_ascii=False, indent=1), encoding="utf-8") +total = sum(len(v) for v in out.values()) +print(f"OK {dest.relative_to(ROOT)} games={len(out)} lines={total}") diff --git a/web/harness/mock.mjs b/web/harness/mock.mjs new file mode 100644 index 00000000..bfadd16e --- /dev/null +++ b/web/harness/mock.mjs @@ -0,0 +1,169 @@ +/** + * 无头试玩 mock 层(转写 harness 专用,逻辑对齐各游戏 test/playtest.mjs 的 mock)。 + * + * 提供:虚拟时钟(setTimeout/clearTimeout/performance.now)、假 AudioContext、 + * 读真实资产目录的 fetch(记录 404)、navigator.vibrate 记录、window 事件。 + * 每个 Node 进程只 install 一次(patch 全局)。 + */ +import fs from 'node:fs'; +import path from 'node:path'; +import url from 'node:url'; + +const VOICE_TEXT = JSON.parse( + fs.readFileSync(path.join(path.dirname(url.fileURLToPath(import.meta.url)), 'voice_text.json'), 'utf8'), +); + +// 中文 TTS 正常语速 ≈ 4.5 字/秒 + 起止余量;无文本 sfx 0.35s;bgm 90s +function estimateDuration(gameName, url) { + const m = String(url).match(/audio\/(voice|sfx|bgm)\/([^/?]+?)\.\w+$/); + if (!m) return 2.0; + const [, layer, id] = m; + if (layer === 'bgm') return 90; + if (layer === 'sfx') return 0.35; + const t = (VOICE_TEXT[gameName] || {})[id] || (VOICE_TEXT[gameName] || {})[id.replace(/^(male|female)\//, '')]; + return t ? Math.max(0.8, t.length / 4.5 + 0.4) : 2.0; +} + +export function installMock(gameDir) { + const gameName = path.basename(gameDir); + const realLog = console.log.bind(console); + let now = 0; // 虚拟毫秒 + let timerSeq = 1; + const timers = new Map(); + const realSetImmediate = setImmediate; + + globalThis.setTimeout = (cb, ms = 0, ...args) => { + const id = timerSeq++; + timers.set(id, { fireAt: now + Math.max(0, Number(ms) || 0), cb, args }); + return id; + }; + globalThis.clearTimeout = (id) => { timers.delete(id); }; + globalThis.clearInterval = (id) => { timers.delete(id); }; + globalThis.setInterval = globalThis.setTimeout; // 转写场景无真实 interval 语义需求 + Object.defineProperty(globalThis, 'performance', { value: { now: () => now }, configurable: true }); + + async function flush(rounds = 8) { + for (let i = 0; i < rounds; i++) await new Promise((r) => realSetImmediate(r)); + } + + async function advance(cond = null) { + for (let n = 0; n < 200000; n++) { + await flush(2); + if (cond && cond()) return 'cond'; + let nextId = -1; let nextAt = Infinity; + for (const [id, t] of timers) if (t.fireAt < nextAt) { nextAt = t.fireAt; nextId = id; } + if (nextId < 0) return 'idle'; + now = nextAt; + const t = timers.get(nextId); + timers.delete(nextId); + t.cb(...t.args); + } + throw new Error('虚拟时钟定时器超上限(疑似死循环)'); + } + const idle = () => advance(null); + + const winListeners = new Map(); + globalThis.window = { + addEventListener: (type, fn) => { + if (!winListeners.has(type)) winListeners.set(type, []); + winListeners.get(type).push(fn); + }, + AudioContext: null, + }; + const fireWindowEvent = (type) => { for (const fn of winListeners.get(type) || []) fn(); }; + + const storageData = new Map(); + globalThis.localStorage = { + getItem: (k) => (storageData.has(k) ? storageData.get(k) : null), + setItem: (k, v) => { storageData.set(k, String(v)); }, + removeItem: (k) => { storageData.delete(k); }, + }; + + const vibrateLog = []; + Object.defineProperty(globalThis, 'navigator', { + value: { vibrate: (...a) => { vibrateLog.push({ pattern: a[0], t: now }); return true; } }, + configurable: true, + }); + + class MockParam { + constructor(v = 1) { this.value = v; } + setValueAtTime() {} + linearRampToValueAtTime() {} + cancelScheduledValues() {} + } + class MockGainNode { + constructor() { this.gain = new MockParam(); } + connect() {} + disconnect() {} + } + class MockOscillator { + constructor() { + this.type = 'sine'; this.frequency = new MockParam(); + this.connect = () => {}; this.start = () => {}; this.stop = () => {}; + } + } + class MockAudioContext { + constructor() { + this.state = 'running'; this.currentTime = 0; this.destination = {}; + this.sampleRate = 44100; + } + createGain() { return new MockGainNode(); } + createOscillator() { return new MockOscillator(); } + createDynamicsCompressor() { + const n = new MockGainNode(); + n.threshold = new MockParam(); n.ratio = new MockParam(); + n.attack = new MockParam(); n.release = new MockParam(); + return n; + } + createBufferSource() { + return { + buffer: null, loop: false, playbackRate: new MockParam(), + connect() {}, start() {}, stop() {}, + }; + } + createScriptProcessor() { return { connect() {}, disconnect() {}, onaudioprocess: null }; } + decodeAudioData() { + return Promise.resolve({ + duration: estimateDuration(gameName, lastFetched), + numberOfChannels: 1, sampleRate: 44100, + getChannelData: () => new Float32Array(16), + }); + } + resume() { this.state = 'running'; return Promise.resolve(); } + } + globalThis.window.AudioContext = MockAudioContext; + + // 静默引擎日志;fetch 记录 404(= 玩家此刻听到静默,转写时如实标注) + console.error = () => {}; + console.warn = () => {}; + console.log = () => {}; + + const requestedUrls = []; + const missingAssets = []; + const fetchedLog = []; // { url, ok } 全量记录,供回退判定 + let lastFetched = null; + globalThis.fetch = async (u) => { + const s = String(u); + requestedUrls.push(s); + lastFetched = s; + const p = path.join(gameDir, decodeURIComponent(s)); + if (!fs.existsSync(p)) { + missingAssets.push({ url: s, t: now }); + fetchedLog.push({ url: s, ok: false }); + return { ok: false, status: 404, arrayBuffer: async () => new ArrayBuffer(0) }; + } + const data = fs.readFileSync(p); + fetchedLog.push({ url: s, ok: true }); + return { + ok: true, status: 200, + arrayBuffer: async () => data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength), + }; + }; + + return { + get now() { return now; }, + flush, advance, idle, fireWindowEvent, + vibrateLog, requestedUrls, missingAssets, fetchedLog, + realLog, + }; +} diff --git a/web/harness/transcribe.mjs b/web/harness/transcribe.mjs new file mode 100644 index 00000000..5b3e30a0 --- /dev/null +++ b/web/harness/transcribe.mjs @@ -0,0 +1,202 @@ +#!/usr/bin/env node +/** + * 玩家感知转写器:把一局游戏对玩家输出的「全部可感知事件」转写成时间轴日志。 + * + * 产物是给人设玩家 agent 读的「玩家视角剧本」:每一句语音(含全文)、每个音效、 + * 每次 BGM 切换、每次震动、每段静默等待、每次资产缺失(玩家听到的静默), + * 加上脚本注入的玩家手势。人无法听音频,但信息流(何时知道什么、何时轮到自己) + * 在这份日志里与真实听感一一对应(语音时长按文本长度估算,非精确)。 + * + * 用法:tools/node/bin/node web/harness/transcribe.mjs [--out ] + * 会话剧本:web/harness/sessions/.mjs(describe(game) + session(ctx)), + * 无剧本时退化为「新手乱试」通用策略。 + */ +import fs from 'node:fs'; +import path from 'node:path'; +import url from 'node:url'; +import { installMock } from './mock.mjs'; + +const HARNESS_DIR = path.dirname(url.fileURLToPath(import.meta.url)); +const WEB_DIR = path.resolve(HARNESS_DIR, '..'); +const GAME_NAME = process.argv[2]; +if (!GAME_NAME || !fs.existsSync(path.join(WEB_DIR, GAME_NAME, 'game.js'))) { + console.error('用法: node transcribe.mjs [--out ]'); + process.exit(2); +} +const GAME_DIR = path.join(WEB_DIR, GAME_NAME); +const argOf = (k, dflt) => { + const i = process.argv.indexOf(k); + return i > -1 && process.argv[i + 1] ? process.argv[i + 1] : dflt; +}; +const OUT = argOf('--out', path.resolve(WEB_DIR, '..', `research/04-playtests/transcripts/${GAME_NAME}.md`)); + +const VOICE_TEXT = JSON.parse(fs.readFileSync(path.join(HARNESS_DIR, 'voice_text.json'), 'utf8')); +const textOf = (id) => { + const table = VOICE_TEXT[GAME_NAME] || {}; + return table[id.replace(/^voice\//, '')] || null; +}; + +// 中文 TTS 正常语速 ≈ 4.5 字/秒,留 0.4s 起止余量;无文本(sfx)0.35s;bgm 90s +const estimateDuration = (id) => { + if (id.startsWith('bgm/')) return 90; + const t = textOf(id); + if (!t) return id.startsWith('voice/') ? 2.0 : 0.35; + return Math.max(0.8, t.length / 4.5 + 0.4); +}; + +const CLASS_NAME = { + storyline: 'StorylineGame', escape: 'EscapeGame', simon: 'SimonGame', + rhythm: 'RhythmGame', space: 'SpaceGame', rpg: 'RpgGame', +}[GAME_NAME]; + +const mock = installMock(GAME_DIR); +const { realLog } = mock; + +// ---------------------------------------------------------------- 转写流 + +const lines = []; +const fmtT = () => `t+${(mock.now / 1000).toFixed(1).padStart(6)}s`; +const push = (s) => lines.push(`${fmtT()} ${s}`); +const HAPTIC_NAME = { + '[20]': 'confirm(轻点确认)', '[60,40,60]': 'error(做错了:两连短震)', + '[100]': 'success(成功长震)', '[30,50,30,50,30]': 'warning(警告三连震)', + '[10]': 'swipe(滑动识别)', '[40,100,40]': 'heartbeat(心跳/倒计时)', + '[15]': 'pickup(获得)', '[80]': 'hit(受击重震)', '[8]': 'beat(节拍点)', + '[25,40,25,40,25]': 'danger(危险逼近)', +}; +const hapticName = (p) => HAPTIC_NAME[JSON.stringify(p)] || `自定义震型 ${JSON.stringify(p)}`; + +// ---------------------------------------------------------------- 装载引擎与游戏 + +const { WebAudioEngine } = await import('../engine/audio.js'); +const { settings } = await import('../engine/settings.js'); +const { [CLASS_NAME]: GameClass } = await import(`../${GAME_NAME}/game.js`); + +let pending = []; // 本次驱动步内产生的感知事件(排序后落盘) +let lastBgm = null; + +function capture(audio) { + const orig = audio.play.bind(audio); + audio.play = (id, opts) => { + const isVoice = id.startsWith('voice/'); + const t = textOf(id); + if (id.startsWith('bgm/')) { + if (id !== lastBgm) { + lastBgm = id; + pending.push(`${fmtT()} ♫ BGM 切换 → ${id}${opts?.fadeMs ? `(淡入 ${opts.fadeMs}ms)` : ''}`); + } + } else if (isVoice) { + pending.push(t + ? `${fmtT()} ▶ 语音:「${t}」` + : `${fmtT()} ▶ 语音 voice/${id.slice(6)}(无台词表文本)`); + } else { + pending.push(`${fmtT()} ♪ 音效 ${id}`); + } + return orig(id, opts); + }; +} + +function drain() { + for (const m of mock.vibrateLog.splice(0)) { + pending.push(`${fmtT()} 〰 震动:${hapticName(m.pattern)}`); + } + // 引擎按 ogg→m4a→mp3→wav、性别目录→平铺 逐个探测;只有全部路径都 404, + // 玩家才是真的什么都没听到(角色音探测性别目录 404 后平铺成功属正常回退) + for (const m of mock.missingAssets.splice(0)) { + const key = m.url.replace(/^audio\//, '').replace(/\.\w+$/, '').replace(/^voice\/(male|female)\//, 'voice/'); + const everOk = mock.fetchedLog.some((f) => f.ok + && f.url.replace(/^audio\//, '').replace(/\.\w+$/, '').replace(/^voice\/(male|female)\//, 'voice/') === key); + if (!everOk) pending.push(`${fmtT()} ⚠ 资产缺失 ${key} → 玩家此刻听到的是静默`); + } + pending.sort((a, b) => parseFloat(a.match(/t\+(\s*)(\d+)/)?.[2] ?? 0) - parseFloat(b.match(/t\+(\s*)(\d+)/)?.[2] ?? 0)); + lines.push(...pending); + pending = []; +} + +// ---------------------------------------------------------------- 驱动 API + +const voiceBusy = (audio) => audio._voice !== null; + +async function step(audio, game, fn) { + fn(); + await mock.flush(); + drain(); +} + +function makeCtx(audio, game, describe) { + const ctx = { + game, audio, settings, + gesture: async (g) => { game.onGesture(g); await mock.flush(); drain(); }, + waitIdle: async () => { await mock.advance(null); drain(); }, + waitVirtual: async (ms) => { + const target = mock.now + ms; + await mock.advance(() => mock.now >= target); + drain(); + }, + waitCond: async (cond) => { await mock.advance(cond); drain(); }, + voiceBusy: () => voiceBusy(audio), + note: (s) => { lines.push(`\n#### 【玩家动作】${s}\n`); }, + status: (tag) => { + const d = describe ? describe(game) : ''; + const v = voiceBusy(audio) ? '语音播放中' : (audio._bgm ? `BGM=${audio._bgm?.id ?? '无'}` : '无 BGM'); + lines.push(`${fmtT()} 【状态】${tag || ''}${d ? ` ${d}` : ''}(${v})`); + }, + silence: (sec, why) => { + lines.push(`${fmtT()} ……… 静默 ${sec}s${why ? `(${why})` : ',游戏在等待玩家输入'} ………`); + }, + }; + return ctx; +} + +// ---------------------------------------------------------------- 会话 + +const sessionMod = fs.existsSync(path.join(HARNESS_DIR, 'sessions', `${GAME_NAME}.mjs`)) + ? await import(`./sessions/${GAME_NAME}.mjs`) : null; + +const header = [ + `# 试玩转写:《${GAME_NAME}》`, + '', + `> 本文件是「玩家感知日志」:一位新手玩家的整局体验转写。语音列出了玩家听到的每句话全文,`, + `> 音效/BGM/震动按发生时间列出。「静默」段 = 玩家什么也听不到。手势是剧本注入的(模拟真人手部动作),`, + `> 非最优操作:包含犹豫、误操作与乱试。语音时长按语速估算(±20%),仅供节奏参考。`, + '', +].join('\n'); + +async function run() { + const audio = new WebAudioEngine('audio/'); + const game = new GameClass(audio, {}); + capture(audio); + await audio.unlock(); + lines.push(`${fmtT()} (玩家点开游戏,轻触屏幕开始)`); + game.start(); + await mock.flush(); + drain(); + + if (sessionMod?.session) { + await sessionMod.session(makeCtx(audio, game, sessionMod.describe), mock); + } else { + // 通用新手策略:等待→单击;没反应就双击→上滑→下滑,各试一次 + const ctx = makeCtx(audio, game, null); + for (let i = 0; i < 30 && mock.now < 10 * 60 * 1000; i++) { + await ctx.waitIdle(); + ctx.status('等待中'); + const before = lines.length; + await ctx.gesture('tap'); + await ctx.waitIdle(); + if (lines.length === before && !voiceBusy(audio)) { + await ctx.gesture('doubletap'); + await ctx.waitIdle(); + if (lines.length === before) await ctx.gesture('up'); + if (lines.length === before) await ctx.gesture('down'); + } + drain(); + } + } + drain(); +} + +await run(); + +fs.mkdirSync(path.dirname(OUT), { recursive: true }); +fs.writeFileSync(OUT, header + lines.join('\n') + '\n', 'utf8'); +realLog(`OK ${OUT} (${lines.length} 行, 虚拟时长 ${(mock.now / 1000).toFixed(0)}s)`); diff --git a/web/harness/voice_text.json b/web/harness/voice_text.json new file mode 100644 index 00000000..325348ec --- /dev/null +++ b/web/harness/voice_text.json @@ -0,0 +1,406 @@ +{ + "storyline": { + "help": "操作说明。单击屏幕:继续剧情。双击:重听刚才的台词。向上滑:听这段说明和当前进度。向下滑:呼出菜单,菜单里可以重新开始。当旁白说“请选择”的时候,向左滑或者向右滑,做出你的决定。选择无法撤销。", + "status1": "当前进度:第一幕,城南地铁站附近。你的目标:活着离开这片废墟,前往北区的广播塔,寻找妹妹林晨的下落。", + "status2": "当前进度:第二幕,酸雨笼罩的街区与断桥。你的目标:渡过江水,抵达广播塔。小心,猎狗的人,就在附近。", + "status3": "当前进度:第三幕,广播塔下。你的目标:把警报发出去,找到林晨。这是最后一段路了。", + "menu": "菜单。向左滑:重新开始整个故事。向右滑,或者单击:回到故事。向上滑:听操作说明。", + "p1": "请选择。向左滑:先检查背包里的收音机。向右滑:先摸黑寻找出口。", + "p2": "请选择。向左滑:钻进旁边的通风管道。向右滑:躺进路边的尸体堆里装死。", + "p3": "请选择。向左滑:循着哭声过去看看。向右滑:不去管它,直接去北区。", + "p4": "请选择。向左滑:带上小满一起走。向右滑:留下食物,独自上路。", + "p5": "请选择。向左滑:走桥下的污水涵洞。向右滑:爬桥上悬着的钢索。", + "p6": "请选择。向左滑:交出坐标,保命要紧。向右滑:拒绝他,想办法周旋。", + "p7": "请选择。向左滑:追上去,警告避难所。向右滑:自己逃命,越远越好。", + "p8": "请选择。向左滑:用公开频道广播,让全城都听见。向右滑:用加密频段,只发给避难所。", + "n00_intro": "大停电后的第三十天,城市陷入彻底的黑暗。没有电,没有网络,只有收音机里偶尔闪过的沙沙声,像垂死者的呼吸。你是林晚,一名前急救员。在这个故事里,你用声音活下去。请记住:单击屏幕,继续剧情;双击,重听上一句;向上滑,听你的状态和帮助;向下滑,呼出菜单。当我说“请选择”的时候,向左滑,或者向右滑,做出你的决定。选择一旦做出,就无法回头。现在,单击屏幕,睁开眼睛。", + "n01_wake": "后脑一阵钝痛,嘴里全是铁锈味。你在废弃的地铁站里醒来,四周黑得像沉在水底。背包还压在身下,手电筒却不知去向。远处滴水的声音,一下,一下,像某种倒计时。", + "n04_exit": "你扶着潮湿的墙,一步一步往外摸。第五十步,脚尖踢到一个硬物——是一支手电,还剩半格电。光柱劈开黑暗的那一瞬,你看见墙上用红漆刷着一行大字:别去北区。", + "n05_signal": "就在这时,背包侧袋里的收音机,沙沙声忽然变得清晰。一个平稳的女声,一遍又一遍地重复着:", + "n06_whistle": "你刚走上街面,黑暗里忽然响起一声口哨。接着是第二声,第三声,从不同的方向,把你围在中间。有人的手电光,扫过你的脸。", + "n08_vent": "你一矮身,钻进了通风管道。铁皮贴着脊背,窄得几乎无法呼吸。身后传来咒骂和铁棍敲击管道口的声音,越来越近,又渐渐远去。十分钟后,你从两条街外的井口爬出来,肺里像塞满了沙子。", + "n09_dead": "你屏住呼吸,把自己埋进路边冰冷的尸体堆里。手电、罐头、半瓶水,被他们一样一样摸走。有人踢了你一脚,你纹丝不动。就在他们离开时,你听见一句不该听见的话——“北区那个陷阱,今晚就收网。”", + "n10_rain": "酸雨开始下了。街面上升起细密的嘶嘶声,像无数条小蛇在游。雨幕那头,隐约传来一阵哭声——细细的,是个孩子。", + "n11_child": "哭声来自一间塌了一半的便利店。一个小男孩抱着膝盖坐在货架底下,身边躺着一个再也不会醒来的女人。他抬起头,脸上全是灰,小声说:“我叫小满。妈妈说,数到一千,她就会醒。我已经数到……数到好多个一千了。”", + "n13_leave": "你把仅剩的一罐罐头放在他身边,转身走进雨里。身后,孩子重新开始数数:一……二……三……你告诉自己,别回头。千万别回头。", + "n14_ignore": "哭声被你甩在身后,越来越远,最后混进雨声里,再也听不见了。你走得很快,快得像在逃跑。快一点,再快一点。你对自己说,只要到了北区,这一切就都值了。", + "n15_bridge": "两个小时后,江水拦住了去路。跨江大桥断成两截,桥身斜插进黑沉沉的江面。要去广播塔,只剩两条路:桥下的污水涵洞,黑得看不见底;或者,桥上悬着的钢索,在风里荡来荡去。", + "n16_culvert": "涵洞里,污水没到胸口,又冷又黏,带着腐烂的甜味。走到一半,水面下有什么东西,擦着你的腿滑了过去。你没有叫出声,只是走,一步,一步,直到看见洞口那点灰白的天光。", + "n16b_culvert_c": "你让小满骑在肩上,自己蹚进没到胸口的污水里。又冷又黏,带着腐烂的甜味。走到一半,水面下有什么东西擦过你的腿,小满吓得一抖,你抬手按住他的膝盖:“数数。”他小声数起来,一,二,三……数到一百七,你们看见了洞口的天光。", + "n17_cable": "钢索比想象中更滑。酸雨把它泡得发黏,你每挪一步,整根钢索就晃一下。江风从断桥的缺口灌进来,像有无数只手在水底下拽你的脚。你不往下看。你只知道,前面就是北岸。", + "n17b_cable_c": "钢索比想象中更滑。小满趴在你背上,一声不吭,两条小胳膊勒得你生疼。走到一半,钢索猛地一沉,你听见身后钢丝崩断的脆响。“闭眼。”你说。然后你用尽全身力气,向前,向前,直到膝盖磕上北岸的石头。", + "n20_convoy": "猎狗的车队朝北区开走了,探照灯在雨幕里划出一道道口子。你蹲在原地,胃里一阵一阵地泛酸。晨晨在北区。而刚才,是你,亲手把狼,引到了她的门口。", + "n22_fight": "你往后退了半步,忽然笑了:“坐标在我脑子里。杀了我,你什么都拿不到。”猎狗愣了半秒。就是这半秒,你抓起一把沙土扬在他脸上,转身就跑。子弹擦着肩膀打进墙里,火辣辣地疼。但你在跑,你在跑——活着的感觉,从来没有这么清楚过。", + "n23_tower": "广播塔就立在头顶,红色的信号灯在雨里一闪一闪,像一颗还在跳动的心脏。塔底的中控台居然还能用。只要爬上去,你就能接入城市广播网,把警报发给北区的每一个人。问题是——用哪个频道。", + "e1_dawn": "加密频道那头沉默了三秒。然后,一个你等了三十天的声音响了起来:“姐?姐!是你吗?”天亮之前,避难所的救援队打开了大门。猎狗的人,在北区的高墙下溃散了。你抱着晨晨,听见广播塔里,重新响起了音乐。后来人们说,这座城市,是从一个女人的声音开始,重新活过来的。——好结局:黎明。感谢你,陪林晚走完了这条路。单击屏幕,可以回到故事开始的地方。", + "e2_price": "你赶在车队前面,撞进了避难所的大门。“关掉广播!关灯!猎狗来了——!”那一夜,北区守住了。探照灯熄灭的时候,晨晨从人群里扑出来抱住你,才发现你胳膊上的血,已经把半边袖子浸透了。坐标是你交出去的,命,是你抢回来的。你赢了,用一条胳膊的代价。——结局:代价。单击屏幕,重新开始。", + "e3_alone": "你逃了。一路向南,没有回头。三天后,收音机里关于北区的广播,停了。又过了七天,你在一个废弃的加油站里,听见最后一个频段,也变成了沙沙声。你活下来了。只是从此以后的每一个夜里,你都会想起那声口哨,和你报出坐标时,自己发抖的声音。——坏结局:孤声。单击屏幕,重新开始。", + "e4_static": "公开频道,把所有人都引来了——幸存者,还有猎狗。塔顶的风很大,你看见山下火把连成的长龙,也看见避难所方向亮起的防御火光。猎狗的刀抵上来的时候,你对着麦克风笑了:“听见了吗,晨晨?姐姐的声音,全城都听见了。”信号中断了。但那晚之后,北区,再没有人投降。——结局:静默。单击屏幕,重新开始。", + "skip_hint": "单击可跳过旁白。", + "n02_linwan": "咳……咳咳……我还活着。晨晨,你在哪儿……你说过,会在北区等我。姐一定,一定找到你。", + "n03_radio": "收音机……还好,没摔坏。等等,这是什么……这段录音,是三天前的……", + "n03_msg": "姐,如果你听到这个,说明你还活着,太好了。听着,跟着广播塔的红色信号灯走,别相信任何自称救援队的人。北区,北区有真正的避难所。我在这儿等你。姐,一定要来。", + "n05_bcast": "北区避难所,仍在接收幸存者。重复,北区避难所,仍在接收幸存者。坐标,三、七点、五。请沿广播塔红色信号灯方向前进。", + "n07_dog": "哟,瞧瞧,有肥羊自己送上门了。别跑啊。这片儿的路,都是我猎狗修的。想过去?行啊,把包留下,把你值钱的玩意儿留下。人嘛……也留下。", + "n12_take": "小满,别怕。数到一千太慢了。跟姐姐走,姐姐带你去找一座会发光的塔。抓紧我的手,别松开。", + "n18_dog": "啧啧啧。涵洞也拦不住你,钢索也拦不住你,命真大啊。正式认识一下——猎狗。北区广播塔底下这片,归我管。把你妹妹的坐标,还有包里剩下的东西,交出来。交出来,我让你死得体面点。", + "n19_betray": "好,好,我说。北区,避难所,坐标是……三、七点、五。拿去,都拿去。求你……放我走。", + "n21_redeem": "再快一点……再快一点!晨晨,等我。这一次,姐说什么,也不会再把你弄丢了!", + "n24_open": "所有人注意!所有人注意!我是林晚!北区避难所正在遭到袭击,重复,正在遭到袭击!能听见的人,拿起你身边能当武器的东西,去北区!救他们——也救救我们!", + "n25_secure": "北区,北区,这里是林晚。频率七点五,老规矩。猎狗带人来了,至少二十个,有车。顶住,我马上到。重复,顶住,我马上到。", + "e1_child": "姐姐,姐姐!天亮了!妈妈说过的,天亮了,就可以不数啦!" + }, + "escape": { + "g0_intro": "黑暗。你在废弃的地下设施里醒来,什么都想不起来。你必须找到出路。", + "g1_move": "先活动一下。朝任意方向滑一下,走一小步。", + "g1_done": "很好,你迈出了第一步。", + "g2_wall": "这个房间不大,四面都是墙。再滑两下,试试碰碰墙。", + "g3_left": "跟着我指的路走。向左滑。", + "g4_down": "对。再向下滑。", + "g5_inspect": "听到水声了吗?单击一下,仔细检查这个房间。", + "g5_key": "你摸到了一把钥匙!", + "g6_doubletap": "钥匙能开锁。双击,是把物品用出去的用法。现在,双击试试。", + "g6_done": "对,就是这样。接下来,靠你自己了。", + "g7_goal": "找到能用这把钥匙打开的东西。需要帮助时,在原地双击。", + "guide_wrong_up": "不是这个方向。向上滑。", + "guide_wrong_down": "不是这个方向。向下滑。", + "guide_wrong_left": "不是这个方向。向左滑。", + "guide_wrong_right": "不是这个方向。向右滑。", + "guide_wrong_gesture": "不是这个操作。照我说的做。", + "guide_blunt_up": "手指贴着屏幕,向上推一下。", + "guide_blunt_down": "手指贴着屏幕,向下推一下。", + "guide_blunt_left": "手指贴着屏幕,向左推一下。", + "guide_blunt_right": "手指贴着屏幕,向右推一下。", + "guide_offpath": "先跟我走。", + "guide_skip": "跳过引导,直接开始自由探索。", + "reopen_prompt": "上滑,重新听一遍引导。单击,直接开始。", + "stuck_ask": "需要帮助吗?", + "stuck_key_1": "铁锈味最重的地方,值得仔细看看。", + "stuck_key_2": "去西南角的储物间,单击检查,找到钥匙。", + "stuck_key_3": "跟我说的方向走,去西南角的储物间。", + "stuck_cabinet_1": "钥匙就在你身上。它能打开某一把锁。", + "stuck_cabinet_2": "去东边的铁柜房,双击,用钥匙打开铁柜。", + "stuck_cabinet_3": "跟我说的方向走,去铁柜所在的房间。", + "stuck_box_1": "保险丝属于电箱。有电流声的地方,就有电箱。", + "stuck_box_2": "去西北角的电箱房,双击,把保险丝装进电箱。", + "stuck_box_3": "跟我说的方向走,去电箱所在的房间。", + "stuck_gate_1": "电已经通了。该去找那扇铁门了。", + "stuck_gate_2": "去东南角的大门,双击,打开它,离开这里。", + "stuck_gate_3": "跟我说的方向走,去大门所在的房间。", + "nav_up": "向上滑。", + "nav_down": "向下滑。", + "nav_left": "向左滑。", + "nav_right": "向右滑。", + "room_storage": "一间储物间。货架上堆满杂物,角落里传来水滴声。", + "room_cabinet": "这个房间里,立着一个铁柜。", + "room_power": "这个房间的墙上,有一只电箱。", + "room_gate": "面前,是一扇沉重的铁门。", + "time_band1": "你逃出来了,用时不到两分钟。了不起!", + "time_band2": "你逃出来了,用时不到五分钟。", + "time_band3": "你逃出来了,用时不到十分钟。", + "time_band4": "你逃出来了,用时超过十分钟。", + "wall": "那边是墙,换个方向。", + "start_room": "你站在设施中央的房间里。滑动移动,单击检查,双击使用物品。", + "found_key": "你蹲下身在储物架的角落里摸索,指尖碰到一个冰凉的金属物件——是一把钥匙!钥匙到手了。", + "inspect_cabinet_locked": "这个房间里立着一个铁柜,柜门上挂着一把锁。也许,有什么钥匙能打开它。", + "unlock_cabinet": "钥匙插进锁孔,缓缓转动。咔哒一声,柜门开了。柜子深处,躺着一枚保险丝。保险丝到手了。", + "inspect_box_dead": "墙上是一只电箱,箱盖敞开着,里面的保险丝座空空如也。没有电,这里的大门永远打不开。", + "box_fixed": "电箱运转正常,电流的嗡鸣声平稳而持续。", + "fix_box": "你把保险丝用力按进卡座。火花一闪,嗡鸣声响起——头顶的线路恢复供电了!", + "inspect_gate": "面前是一扇沉重的铁门。门边的电子锁一片漆黑,没有任何反应。它需要电力。", + "inspect_gate_ready": "电子锁的指示灯亮了,发出微弱的绿光。大门已经通电。双击,打开它,离开这里。", + "escape": "你扳动开关。电机轰鸣,沉重的铁门缓缓升起,刺眼的光线涌了进来。你眯起眼睛,向前迈出了第一步。自由了。你逃出来了。", + "use_fail": "这里没有用得上东西的地方。换个房间试试,或者先单击检查一下周围。", + "inv_empty": "你摸了摸身上,什么也没有。", + "inv_key": "你身上带着一把钥匙。", + "inv_fuse": "你身上带着一枚保险丝。", + "inv_both": "你身上带着一把钥匙和一枚保险丝。", + "replay": "黑暗再次合拢。你回到了中央的房间。这一次,你会更快。", + "again": "单击屏幕,再来一次。下滑,打开菜单。", + "empty_1": "房间里空空荡荡,只有你自己的回声。", + "empty_2": "你伸出手,摸到的只有冰冷粗糙的墙壁。", + "empty_3": "除了远处的水滴声,这里什么都没有。", + "help_ops": "滑动,在房间之间移动。单击,检查房间,或者重听房间的声音。双击,使用物品,或者查看背包。", + "menu_open": "菜单。", + "menu_restart": "重新开始。", + "menu_home": "回大厅。", + "menu_back": "返回游戏。", + "skip_hint": "单击可跳过旁白。" + }, + "simon": { + "t0_welcome": "欢迎来到音序回响。先认识六种声音。", + "t0_goal": "我会演奏一串声音,请你记住顺序,原样复现。", + "t1_up": "向上滑,是这个声音。", + "t2_down": "向下滑,是这个声音。", + "t3_left": "向左滑,是这个声音。", + "t4_right": "向右滑,是这个声音。", + "t5_tap": "单击,是这个声音。", + "t6_double": "双击,是这个声音。", + "t_try": "你试试。", + "t_ok": "对了。", + "t_wrong_up": "不是这个,向上滑试试。", + "t_wrong_down": "不是这个,向下滑试试。", + "t_wrong_left": "不是这个,向左滑试试。", + "t_wrong_right": "不是这个,向右滑试试。", + "t_wrong_tap": "不是这个,单击试试。", + "t_wrong_double": "不是这个,双击试试。", + "t_blunt_up": "手指贴着屏幕,向上推一下。", + "t_blunt_down": "手指贴着屏幕,向下推一下。", + "t_blunt_left": "手指贴着屏幕,向左推一下。", + "t_blunt_right": "手指贴着屏幕,向右推一下。", + "t_blunt_tap": "用指尖,轻轻点一下屏幕。", + "t_blunt_double": "用指尖,快速点两下屏幕。", + "t7_ready": "六种声音都记住了。后面的序列,会越来越长。", + "t7_retry": "答错可以消耗机会重听。双击,可以随时重听。", + "t_skip": "跳过教学,直接开始。", + "round_01": "第一轮,听好了。", + "round_02": "第二轮,听好了。", + "round_03": "第三轮,听好了。", + "round_04": "第四轮,听好了。", + "round_05": "第五轮,听好了。", + "round_06": "第六轮,听好了。", + "round_07": "第七轮,听好了。", + "round_08": "第八轮,听好了。", + "round_09": "第九轮,听好了。", + "round_10": "第十轮,听好了。", + "round_11": "第十一轮,听好了。", + "round_12": "第十二轮,听好了。", + "round_13": "第十三轮,听好了。", + "round_14": "第十四轮,听好了。", + "round_15": "第十五轮,听好了。", + "round_16": "第十六轮,听好了。", + "round_17": "第十七轮,听好了。", + "round_18": "第十八轮,听好了。", + "round_19": "第十九轮,听好了。", + "round_20": "第二十轮,听好了。", + "round_more": "新的一轮,听好了。", + "score_band1": "一轮都没坚持下来。别灰心。", + "score_band2": "你坚持了三轮以内。", + "score_band3": "你坚持了五轮左右。", + "score_band4": "你坚持了将近十轮。", + "score_band5": "你坚持了十轮以上,很厉害。", + "score_band6": "你坚持了十五轮以上,大师级!", + "your_turn": "轮到你了。", + "chances_out": "重听机会用完了,小心。", + "retry_use": "错了。用一次机会,再听一遍。", + "relisten": "再听一遍。", + "replay": "单击屏幕,再来一局。", + "rules_prompt": "上滑,重听规则。下滑,打开菜单。", + "rules": "上行音,向上滑。下行音,向下滑。左边的音,向左滑。右边的音,向右滑。一声轻响,单击。两声轻响,双击。", + "gameover": "游戏结束。", + "correct": "答对了!", + "wrong": "错了。", + "chance_plus": "机会加一。", + "new_record": "新纪录!", + "menu_open": "菜单。", + "menu_restart": "重新开始。", + "menu_home": "回大厅。", + "menu_back": "返回游戏。", + "skip_hint": "单击可跳过旁白。" + }, + "rhythm": { + "welcome": "欢迎来到节拍行者。跟着音乐,我奏一句,你跟一句。", + "welcome_back": "欢迎回来。我奏一句,你跟一句。", + "tut_1": "听,底鼓。在下一小节的同一个位置,单击。", + "tut_2": "这次是左和右。跟着打,左滑,右滑。", + "tut_3": "最后一句,三个音,中间是双击。", + "tut_done": "很好,演出开始。", + "tut_skip": "跳过教学,直接开始。", + "mid_song": "过半了,保持。", + "retry_early": "早了,等鼓点再出手。", + "retry_late": "晚了,跟着鼓点走。", + "retry_gesture": "不是这个手势,再听一遍。", + "retry_listen": "再听一遍,跟着来。", + "retry_skip": "没关系,我们先走下一句。", + "select_hint": "左右滑选曲目,单击开始,下滑回大厅。", + "song1_name": "第一首,启程,九十拍。", + "song2_name": "第二首,追风,一百零五拍。", + "song3_name": "第三首,星爆,一百二十拍。", + "song_locked": "这首还没解锁。上一首拿到 B 级以上就能解锁。", + "unlock_song2": "新曲目解锁,追风!", + "unlock_song3": "新曲目解锁,星爆!", + "grade_s": "S 级!准确率超过九成五,完美演出。", + "grade_a": "A 级!准确率超过八成五,非常出色。", + "grade_b": "B 级,准确率超过七成。不错,还能更好。", + "grade_c": "C 级,准确率不到七成。别灰心,再来一遍。", + "new_best_combo": "新连击纪录!", + "restart": "单击再来一遍,右滑下一首,下滑回大厅。", + "rules": "规则:我奏一句,你在下一小节原样跟打。音要对,拍点也要对。", + "settings_hint": "音色、语速、背景音乐,请回大厅修改。", + "menu_main": "菜单。单击切换选项,双击确认。", + "menu_resume": "继续演奏。", + "menu_lobby": "回大厅。", + "skip_hint": "单击可跳过旁白。" + }, + "space": { + "drill_welcome": "欢迎登上盲航。你只有一双耳朵。", + "drill_rule": "陨石来了,会有声音告诉你方位。", + "drill_left": "听,左边有陨石。向左滑,把它拨开!", + "drill_right": "这次在右边。向右滑!", + "drill_up": "上面有东西,声音又尖又高。向上滑!", + "drill_down": "下面是低沉的轰隆。向下滑!", + "drill_good": "漂亮。", + "drill_retry_left": "那是左边来的,向左滑。", + "drill_retry_right": "那是右边来的,向右滑。", + "drill_retry_up": "声音又高又尖,是上面,向上滑。", + "drill_retry_down": "轰隆声在下面,向下滑。", + "drill_moveon": "没关系,跟着我,我们继续。", + "drill_done": "四个方向你都会了。引擎点火,出发!", + "drill_skip": "跳过演练,直接出发。", + "protect_left": "训练护盾接住了。那颗在左边,听到左边的呼啸,向左滑。", + "protect_right": "训练护盾接住了。那颗在右边,听到右边的呼啸,向右滑。", + "protect_up": "训练护盾接住了。那颗在上面,听到高高的呼啸,向上滑。", + "protect_down": "训练护盾接住了。那颗在下面,听到低沉的轰隆,向下滑。", + "protect_end": "训练护盾关闭。接下来,靠你自己了。", + "feat_boost": "试试单击,引擎会短促加速,直接冲过空隙。", + "feat_boost_done": "感觉到了吗?加速的时候,陨石撞不上你。", + "feat_shield": "双击展开护盾,能挡下一次撞击。", + "feat_shield_done": "护盾展开后会自动充能,好了我会告诉你。", + "shield_ready": "护盾充能完毕。", + "shield_block": "护盾挡下了撞击。", + "hit_left": "左边撞上的。听到左边的呼啸,向左滑。", + "hit_right": "右边撞上的。听到右边的呼啸,向右滑。", + "hit_up": "上面撞上的。听到高高的呼啸,向上滑。", + "hit_down": "下面撞上的。听到低沉的轰隆,向下滑。", + "hit_last": "船体只剩最后一次了,小心!", + "ms_10": "十颗了,稳。", + "ms_25": "二十五颗,老练的飞行员。", + "ms_50": "五十颗,传奇。", + "ms_100": "一百颗!天空属于你。", + "time_1": "不到三十秒,再试一次。", + "time_2": "超过三十秒,有进步。", + "time_3": "超过一分钟,合格的飞行员。", + "time_4": "超过两分钟,王牌飞行员。", + "dodge_1": "只拨开几颗。", + "dodge_2": "拨开了十来颗。", + "dodge_3": "拨开了几十颗。", + "dodge_4": "拨开了一大群,漂亮。", + "new_record": "新纪录!", + "restart_hint": "单击再飞一次,下滑回大厅。", + "second_run_ask": "上滑重新听演练,单击直接出发。", + "menu_main": "菜单。单击切换选项,双击确认。", + "menu_resume": "继续飞行。", + "menu_lobby": "回大厅。", + "menu_help": "重新听教学要点。", + "help_recap": "左边来向左滑,右边来向右滑,上面来向上滑,下面来向下滑。单击加速,双击护盾。", + "settings_hint": "音色、语速、背景音乐,请回大厅修改。", + "paused": "已暂停。", + "skip_hint": "单击可跳过旁白。" + }, + "rpg": { + "intro_1": "你的眼睛看不见了。但你的耳朵,比谁都灵。", + "intro_2": "黑风寨掳走了你唯一的徒弟。追进迷雾林,把他们连根拔起。", + "intro_3": "先记住,怎么用耳朵走路。", + "sys_continue_ask": "检测到你的旅程记录。单击继续,右滑开始新的旅程。", + "sys_new_game": "新的旅程,开始了。", + "sys_saved": "进度已保存。", + "sys_rest": "你在篝火边睡了一觉,状态全满。", + "sys_drink": "溪水清冽,你喝了个饱,伤势尽消。", + "sys_menu": "菜单。左右滑选择,单击确认。", + "sys_menu_resume": "继续旅程。", + "sys_menu_save": "保存并回大厅。", + "sys_menu_help": "重新听帮助。", + "help_explore": "左右滑切换选项,单击确认。双击重新听场景,上滑查看状态,下滑打开菜单。", + "help_battle": "战斗中,左右滑选招式,单击出手。听到敌人的前摇,双击格挡。", + "settings_hint": "音色、语速、背景音乐,请回大厅修改。", + "st_hp_high": "你状态很好。", + "st_hp_mid": "你受了伤。", + "st_hp_low": "你伤势很重,命悬一线。", + "st_gold_poor": "口袋空空。", + "st_gold_some": "有些积蓄。", + "st_gold_rich": "腰包鼓鼓。", + "st_lv_low": "你初出茅庐。", + "st_lv_mid": "你小有名气。", + "st_lv_high": "你已是高手。", + "st_weapon_none": "你赤手空拳。", + "st_weapon_iron": "你手持铁剑。", + "st_weapon_steel": "你手持青钢剑。", + "st_weapon_wind": "你手持听风剑。", + "st_armor_none": "你身无片甲。", + "st_armor_leather": "你身着皮甲。", + "st_armor_iron": "你身着铁鳞甲。", + "desc_village": "雾口村。篝火噼啪作响,村民低声议论着林子里的土匪。", + "desc_village_re": "你回到了雾口村。", + "desc_path": "林间小路。风穿过树叶,脚下的落叶沙沙作响。", + "desc_path_re": "你回到林间小路。", + "desc_fork": "岔路口。风声在左右两边,听起来不太一样。", + "desc_fork_re": "你回到岔路口。", + "desc_chest": "一个枯树洞。洞里似乎藏着什么。", + "desc_chest_re": "你回到枯树洞前。", + "desc_stream": "溪流。水声潺潺,是个歇脚的好地方。", + "desc_stream_re": "你回到溪流边。", + "desc_hunter": "猎人小屋。柴火正旺,还有磨刀的声音。", + "desc_hunter_re": "你回到猎人小屋。", + "desc_deepwood": "密林深处。虫鸣急促,远处有狼嚎,杀气很重。", + "desc_deepwood_re": "你回到密林深处。", + "desc_gate": "黑风寨门前。火把熊熊,人声嘈杂。", + "desc_hall": "聚义厅。火盆熊熊,大厅空旷,回声冰冷。", + "opt_go_path": "前进,去林间小路。", + "opt_go_fork": "前进,去岔路口。", + "opt_go_chest": "往左,看看树洞。", + "opt_go_stream": "往右,去溪流。", + "opt_go_hunter": "前进,去猎人小屋。", + "opt_go_deepwood": "前进,进密林深处。", + "opt_go_gate": "前进,去寨门。", + "opt_back": "返回。", + "opt_shop": "去商店。", + "opt_rest": "休息一晚。", + "opt_status": "查看状态。", + "opt_investigate": "调查四周。", + "opt_open_chest": "打开树洞。", + "opt_drink": "饮水休息。", + "opt_talk_hunter": "和老猎人谈谈。", + "opt_assault": "强攻寨门。", + "opt_sneak": "绕行潜入。", + "opt_leave": "离开。", + "evt_gold15": "你在落叶下摸到十五枚金币。", + "evt_nothing": "这里什么都没有了。", + "evt_chest": "树洞里有两瓶金疮药,你收好了。", + "evt_hunter_gift": "老猎人塞给你一瓶金疮药,还说商店会给你算便宜些。", + "evt_gate_open": "寨门缓缓打开。", + "evt_ch1_end": "寨主倒了,但徒弟不在这里。一张字条,指向南方的腐沼。", + "btl_start_wolf": "野狼拦路!", + "btl_start_bandit": "山贼围上来了!", + "btl_start_spider": "毒蛛从树上垂了下来!", + "btl_start_elite": "寨丁头目挡住了去路!", + "btl_start_boss1": "黑风寨主,就在你面前。", + "cmd_attack": "攻击。", + "cmd_skill": "破空斩。", + "cmd_defend": "防御。", + "cmd_item": "金疮药。", + "btl_nomp": "内劲不足。", + "btl_noitem": "没有金疮药了。", + "btl_flee": "你抽身退出了战斗。", + "btl_noflee": "避无可避!", + "btl_half_bandit": "山贼的攻势缓了下来。", + "btl_enemy_die": "敌人倒下了。", + "btl_win": "战斗胜利。", + "btl_loot_small": "小有收获。", + "btl_loot_mid": "收获不少。", + "btl_loot_big": "大获全胜,收获颇丰。", + "btl_levelup": "你的修为精进了。", + "btl_lose": "你倒下了,黑暗吞没了一切。", + "btl_lose_hint": "记住,听清前摇,双击格挡。", + "tut_b1": "它要扑了,听前摇!", + "tut_b2": "就是现在,双击格挡!", + "tut_b3": "挡住了!轮到你了。左右滑选攻击,单击出剑。", + "tut_b4": "没挡住也没关系,再来一次。", + "tut_b5": "好剑法!接下来,靠你自己了。", + "shop_open": "商店。左右滑看看货,单击购买。", + "shop_price_sword": "铁剑,一百金。", + "shop_price_armor": "皮甲,八十金。", + "shop_price_potion": "金疮药,三十金。", + "shop_owned": "这件你已经有了。", + "shop_poor": "钱不够。", + "shop_buy": "买下了。", + "foe_hp_high": "敌人气焰正盛。", + "foe_hp_mid": "敌人露出疲态。", + "foe_hp_low": "敌人撑不住了。", + "skip_hint": "单击可跳过旁白。", + "tut_battle_1": "第一场战斗来了。别慌,战斗是回合制:你先出手,敌人再反击。", + "tut_battle_2": "左右滑切换招式,攻击、破空斩、防御、金疮药。单击,出手。", + "tut_battle_3": "敌人出手前有一声前摇。听到前摇,马上双击,就能格挡。", + "tut_battle_4": "没把握就防御,伤害减半。金疮药可以回血。", + "tut_battle_5": "记住:听清前摇,双击格挡。开始吧!" + } +} \ No newline at end of file