Files
tianshu-engine/FUTURE.md

342 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 远期功能扩展笔记
以下功能在讨论中出现但暂不纳入实施计划,后续需要扩展时参考。
## 云存档(移自 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 AudioWeb 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 / hotspotsBFS 遍历)
- 章节起始场景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">`
### 编辑器拆分
编辑器同理:编辑器 UIVue 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`