342 lines
15 KiB
Markdown
342 lines
15 KiB
Markdown
# 远期功能扩展笔记
|
||
|
||
以下功能在讨论中出现但暂不纳入实施计划,后续需要扩展时参考。
|
||
|
||
## 云存档(移自 P16)
|
||
|
||
- 存档上传/下载 API 接口设计(REST: `PUT /saves/:slot`, `GET /saves`)
|
||
- `engine/systems/SaveSystem.ts` 升级 — save/load 支持 `remote: boolean` 参数
|
||
- 登录态管理(不强制登录,本地存档为主,云存档为可选)
|
||
- 存档同步冲突解决策略(最后写入胜出 / 时间戳比对)
|
||
|
||
## 自适应码率(移自 P16)
|
||
|
||
- `engine/core/VideoManager.ts` — 支持 HLS(`.m3u8`)和 DASH(`.mpd`)流媒体源
|
||
- `SceneNode.videoUrl` 支持多码率:`{ auto: '/videos/hls/scene.m3u8', hd: '/videos/scene_1080p.mp4' }`
|
||
- 网络质量检测(`navigator.connection` API),自动降级
|
||
|
||
## 代码清理
|
||
|
||
- **移除 flag 机制** — `StateManager.flags` / `hasFlag` / `setFlag` / `clearFlag` 全部移除;
|
||
`Condition.op: 'hasFlag'` 和 `Effect.type: 'toggleFlag'` 删除;
|
||
统一用 `variable == 1` / `set: variable, value: 1` 替代;
|
||
SaveSystem 存档移除 `flags` 字段;P8 不再需要 `defaultFlags`
|
||
变量机制完全能覆盖 flag 功能,flag 是早期过度设计
|
||
|
||
## P7 全屏模式 - 扩展
|
||
|
||
- **自动进入全屏** — 点击"开始游戏"时同步 `requestFullscreen()`,利用用户手势
|
||
- **UI 自动隐藏** — 播放中 3 秒无鼠标移动自动隐藏菜单按钮和光标(`pointer-events: none`),鼠标移动恢复
|
||
- **Pointer Lock** — `requestPointerLock()` 锁定鼠标,防移出窗口,配合热区点击和 QTE
|
||
- **移动端适配** — iOS Safari `webkitEnterFullscreen`,Android Chrome 视口适配
|
||
|
||
## P8 章节选择 - 扩展
|
||
|
||
- 章节缩略图懒加载
|
||
- 章节解锁动画
|
||
- 按进度百分比展示章节完成度
|
||
|
||
## P9 跳过/倍速 - 扩展
|
||
|
||
- 智能跳过(仅跳过"对话"部分,保留"动作"部分)
|
||
- 快捷键自定义
|
||
- 2x/4x/8x 多档位
|
||
|
||
## P10b 手柄导航 — 远期(Gamepad API)
|
||
|
||
以下功能在 P10a 键盘导航完成后,作为手柄支持的第二期实现:
|
||
|
||
### 手柄映射
|
||
|
||
| 操作 | 手柄按键 |
|
||
|------|----------|
|
||
| 选项导航 | 左摇杆 / 方向键(↑↓←→) |
|
||
| 确认 | A 键(Xbox)/ × 键(PS) |
|
||
| 取消/菜单 | B 键(Xbox)/ ○ 键(PS) |
|
||
| QTE 按键 | A/B/X/Y 自动映射到 QTE 定义的 keys 顺序 |
|
||
| 跳过 | Start 键 |
|
||
| 倍速 | LB / RB 循环 |
|
||
|
||
### QTE 设备感知
|
||
|
||
- 键盘连接时 QTE 提示显示键盘按键名称(空格、WASD)
|
||
- 手柄连接时 QTE 提示自动切换为手柄按钮图标(A/B/X/Y + 方向图标)
|
||
- `QTESystem` 升级:输入源切换 + 按键提示动态渲染
|
||
|
||
### 视觉反馈
|
||
|
||
- QTE Overlay 的中央圆圈根据设备动态渲染(键盘=方块内字母,手柄=圆形内图标)
|
||
- 手柄连接后自动隐藏鼠标光标,`inputMode = 'gamepad'`
|
||
- 手柄断连后自动恢复键盘模式,不再依赖手柄
|
||
|
||
### 实现要点
|
||
|
||
- [ ] `engine/systems/InputSystem.ts` 升级 — `gamepadconnected`/`gamepaddisconnected` 事件监听
|
||
- [ ] Gamepad API 轮询(rAF 中 `navigator.getGamepads()` 读取摇杆/按键状态)
|
||
- [ ] QTE 手柄映射逻辑:方向键/摇杆 → `keys[]` 中的方向匹配,按钮 → A/B/X/Y
|
||
- [ ] `src/components/QTEOverlay.vue` 升级 — 根据 inputMode 渲染不同图标
|
||
- [ ] 键位映射配置持久化(IndexedDB)
|
||
- [ ] 手柄震动反馈(`GamepadHapticActuator.pulse()`)
|
||
- [ ] 手柄热插拔检测 + 自动切换 inputMode
|
||
|
||
## P11 多语言字幕 - 扩展
|
||
|
||
- 字幕字体/大小/颜色/背景自定义
|
||
- 语音语言独立轨道(语音和字幕可不同语言)
|
||
- 自动检测浏览器语言
|
||
|
||
## P12 场景过渡特效 - 扩展
|
||
|
||
- 可自定义转场(JSON 中定义颜色/时长/曲线)
|
||
- 转场预览(编辑器中实时预览)
|
||
- 条件转场(根据 variables 选择不同转场类型)
|
||
|
||
## P13 重玩驱动 - 扩展
|
||
|
||
- Steam Achievement API 集成
|
||
- 排行榜(最快通关、最少死亡等)
|
||
- 分享结局截图到社交媒体
|
||
|
||
## P14 沉浸感 - 扩展
|
||
|
||
- SFX 空间化(3D Audio,Web Audio PannerNode)
|
||
- 对话轮动画曲线自定义
|
||
- 画面震动强度/频率可配置
|
||
- 动态字幕说话人识别(AI 自动标注)
|
||
|
||
## P15 章节回顾 — 关键节点时间线图(Life is Strange 方案)
|
||
|
||
### 背景
|
||
|
||
当前 P15 的章节回顾是**列表模式**(BFS 遍历可达场景 + visited/unvisited 列表 + 完成度百分比 + 条件提示),已满足核心目标——知道哪些场景到过、漏了什么、怎么解锁。
|
||
|
||
原计划使用 Vue Flow 完整分支图,但经评估后确认:分支数多时(多父同子、回边循环),自动布局的流程图会变成"意大利面",玩家理解成本反高于简单列表。
|
||
|
||
### 业界对比
|
||
|
||
| 方案 | 做法 | 清晰度 | 成本 |
|
||
|------|------|--------|------|
|
||
| **Detroit 手绘图** | 美术逐章手工设计 InfoGraphic | 极高 | 极高 |
|
||
| **Life is Strange 时间线** | 只画 `keyMoment` 标记的关键节点,Dagre 自动排成水平时间线,跳过琐碎小场景 | 高 | 中 |
|
||
| **Telltale 纯统计** | 片尾弹出 "52% 玩家选了救 Doug",不画任何图 | N/A | 极低 |
|
||
| **当前列表版** | BFS 遍历全场景 + visited/unvisited 标记 | 中 | 已实现 |
|
||
|
||
### 实施路线
|
||
|
||
当需要可视化展示时,采用 **Life is Strange 时间线方案**:
|
||
|
||
**数据层:**
|
||
```ts
|
||
// engine/types.ts
|
||
interface SceneNode {
|
||
// ...existing fields
|
||
keyMoment?: boolean // 标记为"关键节点",只有这些节点出现在时间线图中
|
||
}
|
||
```
|
||
|
||
**布局引擎:**
|
||
- 复用编辑器已有的 Dagre 布局(`editor/composables/useLayout.ts`)
|
||
- `rankdir: 'LR'` 从左到右水平排列
|
||
- 只遍历 `keyMoment === true` 的场景,普通场景跳过不渲染
|
||
- 仅展示关键节点之间的 choices / nextScene / QTE 跳转关系
|
||
|
||
**视觉设计:**
|
||
- visited 节点:绿色实心
|
||
- unvisited 节点:灰色虚线边框
|
||
- 回边(循环引用):虚线 + 半透明
|
||
- 条件提示:小锁图标 + 文本(如 `🔒 trust >= 80`)
|
||
- 普通小场景完全不出现,避免线路交织
|
||
|
||
**组件:**
|
||
- `src/components/ChapterTimeline.vue` — 新建,只读 Vue Flow + Dagre 时间线
|
||
- 与 `ChapterRecap.vue` 并列,不同入口或同一个面板的切换 Tab
|
||
|
||
### 优先级
|
||
|
||
低。列表版已满足 P15 核心目标,时间线图是锦上添花的视觉增强。
|
||
|
||
## P15+ 平台分发 - 扩展
|
||
|
||
- PWA 支持(离线播放、安装到桌面)
|
||
- Web Monetization API 付费解锁章节
|
||
- 开发者 API(第三方创作工具接入)
|
||
|
||
## 通用扩展
|
||
|
||
- 性能监控面板(FPS、内存、网络)
|
||
- 自动化测试框架(剧情路径遍历、回归测试)
|
||
- 热更新支持(不刷新页面替换 JSON 和视频)
|
||
- WebSocket 多人同步(观察者模式、投票选分支)
|
||
|
||
# AI化
|
||
在引擎的基础上深入融合AI,由AI去自动化完成引擎的使用。
|
||
|
||
AI的定位:一个对**使用引擎**降本增效的工具。懂业务的人还是主题,AI是辅助人的。
|
||
|
||
一个新技术的出现会帮助人类实现两种效果:突破式效果,帮助人类突破了一种以前从没有的能力,比如飞机帮助人类飞行,飞机之前人类无论如何都不能起飞的;降本增效式效果,改善了人类已有能力的效果,比如汽车帮助人类跑的更快了。
|
||
|
||
AI目前来看还是降本增效式效果,没有AI的帮助,人类也能做到现在AI能做的效果,只是成本高点、速度慢点。
|
||
|
||
|
||
无论一个工具如何强大,只要在懂业务的人的手里才能发挥效果。比如缝纫机的出现,并没有取代真正的衣服制作者,并不会让不懂衣服制作的所有人都能制作衣服,善于使用缝纫机的人还是本身就懂衣服制作的人,即使没有缝纫机,他也知道如何制作衣服,只是缝纫机更快更高质量的帮助他完成了衣服的制作。
|
||
|
||
AI工具也一样,一个不懂电影游戏制作的人,只靠AI是做不出高质量的东西的,只有本身就懂电影游戏制作的人,无论使用啥工具都能做出合格的产品。
|
||
|
||
本引擎就是帮助懂电影游戏制作的人更快更高质量的完成产品,AI是帮助引擎更容易使用,达到降本增效的效果。
|
||
|
||
引擎帮助人降本增效,AI帮助引擎更容易被使用和提升产出效率。
|
||
|
||
## 游戏内流图可视化 — Detroit 式分支图即时查看
|
||
|
||
基于已有 P15 的章节回顾 Vue Flow 节点图,升级为游戏内实时查看。
|
||
玩家在决策点暂停时,可快速预览当前章节的分支结构,已走路高亮,未解锁路径灰色。
|
||
|
||
**核心功能:**
|
||
|
||
- 暂停菜单中新增"查看分支图"按钮,点击后全屏展示当前章节流图
|
||
- 已到达场景节点绿色实心,当前场景节点带呼吸动画
|
||
- 未到达场景灰色虚线边框,提前未知路径用虚线表示
|
||
- 条件分支显示条件提示(如"需要 trust >= 80"),帮助玩家理解未解锁原因
|
||
- 点击已到达的节点可直接跳转到该场景重新开始(需玩家确认)
|
||
|
||
**数据依赖(已有基础):**
|
||
- `visitedSceneIds`(P15 — `goToScene` 自动记录,IndexedDB 持久化)
|
||
- 场景间边关系(从 `SceneManager.getScenes()` 解析 choices / nextScene / qte success/fail / hotspots,BFS 遍历)
|
||
- 章节起始场景(P8 — `ChapterInfo.startScene`)
|
||
- Vue Flow 组件(P3 编辑器已有,只读渲染 + 高亮 + 动画)
|
||
|
||
**关键技术点:**
|
||
- 章节可达场景 BFS 遍历(P15 ChapterRecap 已有实现)
|
||
- 节点 `visited` 高亮样式(P15 已有)
|
||
- 节点跳转回游戏内场景 → 引擎已有 `startChapter → goToScene`,新增 `jumpToScene(sceneId)` 直接跳(不重置变量,作为"分歧点回退")
|
||
|
||
**实现要点:**
|
||
- [ ] `src/components/InGameFlowChart.vue` — 复用 Vue Flow,只读模式 + 呼吸动画 + 节点点击跳转
|
||
- [ ] `src/stores/gameStore.ts` — `showFlowChart` 状态 + 当前章节场景图数据
|
||
- [ ] `src/App.vue` — 暂停菜单/ESC 菜单中增加"查看分支图"入口
|
||
- [ ] `engine/core/Engine.ts` — 支持从流图节点跳转到场景(`jumpToScene(sceneId)`)
|
||
|
||
## 人物关系系统 — 角色好感度可视化
|
||
|
||
对标 Detroit 的角色关系 HUD。游戏变量中角色好感度值(如 trust / friendship)在决策后通过角色头像 +
|
||
关系变化值(+数值显示)+ 迷你进度条动画展示给玩家,增强叙事沉浸感和角色互动的反馈。
|
||
|
||
**核心功能:**
|
||
|
||
- JSON 中定义角色信息:头像 URL、名称标签、关联变量
|
||
- 变量值变化时 → HUD 弹出角色头像 + 变化值(如 `+10 信任`),短暂停留后淡出
|
||
- 暂停或按特定键可查看完整的角色好感度一览(个人资料 + 当前值 + 历史变化趋势)
|
||
|
||
**数据示例:**
|
||
```json
|
||
{
|
||
"characters": [
|
||
{ "id": "stranger", "name": "陌生人", "portrait": "/images/stranger.jpg", "variable": "trust" },
|
||
{ "id": "partner", "name": "伙伴", "portrait": "/images/partner.jpg", "variable": "courage" }
|
||
]
|
||
}
|
||
```
|
||
|
||
**技术架构:**
|
||
- `StateManager.apply` 前快照旧值 → apply 后计算变化 → emit `relationChange` 事件
|
||
- `RelationshipHUD.vue` 监听事件,显示浮动弹出(`+/- N`)+ 头像 → 短暂停留后自动消失
|
||
- 完整角色一览面板通过暂停菜单按钮打开
|
||
|
||
**实现要点:**
|
||
- [ ] `engine/types.ts` — `GameData.characters: CharacterDef[]`
|
||
- [ ] `engine/core/StateManager.ts` — `apply` 前快照 `variables` → apply 后对比 → emit `relationChange`
|
||
- [ ] `src/components/RelationshipHUD.vue` — 底部/侧边角色头像条,值变化时弹出变化箭头动画
|
||
- [ ] `src/stores/gameStore.ts` — `changedCharacters` 列表(前/后变量值对比结果)
|
||
- [ ] `src/App.vue` — 整合 RelationshipHUD
|
||
|
||
## Engine/UI 分离架构 — 制作者定制 UI 能力
|
||
|
||
当前 `moviegame-starter` 分发的是完整构建产物(引擎 + UI 打包在一起),制作者只能改 JSON。
|
||
要给制作者更多 UI 定制能力,需要将引擎和 UI 拆分为独立的可替换层。
|
||
|
||
### 目标架构
|
||
|
||
```
|
||
moviegame-engine (npm 包 / CDN 脚本,闭源)
|
||
└── engine/core/*.ts → dist/engine.mjs
|
||
Engine, VideoManager, StateManager, SceneManager, AudioSystem ...
|
||
|
||
moviegame-ui (npm 包 / 源文件分发,开源)
|
||
└── src/components/*.vue 源码暴露
|
||
GamePlayer, ChoicePanel, Subtitles, QTEOverlay ...
|
||
└── src/composables/useGameEngine.ts 桥接引擎和 UI
|
||
|
||
moviegame-starter (制作者项目)
|
||
├── imports: moviegame-engine + moviegame-ui
|
||
├── public/ ← 视频、音频、JSON
|
||
├── src/App.vue ← 制作者自由修改
|
||
└── theme.css ← 制作者写 CSS
|
||
```
|
||
|
||
### 三层用户定制方案
|
||
|
||
| 技能等级 | 使用方式 | 修改什么 |
|
||
|----------|---------|---------|
|
||
| **零代码**(预计 90% 制作者) | clone starter → 只改 JSON + 换视频 | 不动代码 |
|
||
| **会 CSS**(预计 8% 制作者) | 改 `theme.css` — 颜色、字体、按钮样式 | 一行 `<link>` 引入 |
|
||
| **会 Vue**(预计 2% 制作者) | fork `moviegame-ui` → 改 `.vue` 组件 → `npm install` 自己版本 | 完全重做 UI |
|
||
|
||
### 方案 A: CSS 主题变量(JSON 驱动)
|
||
|
||
在 `my_story.json` 顶层加 `theme` 字段,映射到 CSS 变量。复杂度低,但表达力有限。
|
||
|
||
```json
|
||
{
|
||
"theme": {
|
||
"primaryColor": "#ff6b35",
|
||
"bgColor": "#1a1a2e",
|
||
"fontSize": 16,
|
||
"subtitleColor": "#ffff00"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 方案 B: 自定义 CSS 文件(推荐)
|
||
|
||
`dist/` 中放空 `theme.css`,引擎 `index.html` 中 `<link>` 引入。制作者填 CSS 覆盖默认样式。
|
||
一行代码解决,零侵入引擎,零复杂度。面向 98% 的定制需求。
|
||
|
||
```html
|
||
<!-- index.html -->
|
||
<link rel="stylesheet" href="/theme.css">
|
||
```
|
||
|
||
```css
|
||
/* theme.css — 制作者自由填 */
|
||
.choice-btn { border-radius: 20px; background: linear-gradient(...); }
|
||
.subtitles .sub-text { font-family: 'MyCustomFont', serif; }
|
||
```
|
||
|
||
### 方案 C: 开放 UI 源码(Vue 组件替换)
|
||
|
||
`moviegame-ui` 发布 Vue `.vue` 源码包,制作者 `npm install` 后可直接修改组件。
|
||
适合有前端能力的高级制作者,可完全重做 UI(如把选项列表改成对话轮盘)。
|
||
|
||
### engine 本身体积大小预估
|
||
|
||
若 engine 独立构建为 ESM 库:
|
||
|
||
- 当前 engine 代码共 6 个 TS 文件:`Engine.ts` (417 行)、`StateManager.ts` (102 行)、`VideoManager.ts` (188 行)、`SceneManager.ts` (53 行)、`AudioSystem.ts` (145 行)、`ChoiceSystem.ts` / `QTESystem.ts` / `AchievementSystem.ts` / `SaveSystem.ts`
|
||
- 总计约 1600 行 TS,`tsc` 编译后约 15-20KB minified
|
||
- 不包含 Vue / Pinia / Dexie / Vue Flow — 这些属于 UI 层或按需引入
|
||
- 可作为极轻量 CDN 脚本分发:`<script src="moviegame-engine.min.js">`
|
||
|
||
### 编辑器拆分
|
||
|
||
编辑器同理:编辑器 UI(Vue Flow 节点图)属于 UI 层,数据层(`SceneManager.getScenes()`)属于 engine 层。
|
||
拆分后编辑器也引用同一个 `moviegame-engine` 包。
|
||
|
||
### 实施清单(远期)
|
||
|
||
- [ ] engine 独立 Vite build(`vite build --config vite.engine.config.ts`)→ `dist/engine.mjs`
|
||
- [ ] engine 发布 npm:`moviegame-engine` — `export { Engine, VideoManager, ... }`
|
||
- [ ] UI 层剥离:Vue 组件 + composables 从 engine 项目中抽到独立目录
|
||
- [ ] `moviegame-ui` 发布 npm(源码包,不编译,`.vue` 文件保留)
|
||
- [ ] starter 改造:Vite + Vue + Pinia 脚手架,引入 engine + ui 两个 npm 包
|
||
- [ ] `theme.css` 空白模板 + 注释(CSS 定制方案 B)
|
||
- [ ] 编辑器重新引用 `moviegame-engine` 包 |