Files
tianshu-engine/ROADMAP.md
2026-06-07 13:50:05 +08:00

200 lines
7.1 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.

# 交互式电影游戏引擎 — Roadmap
## 技术栈
- **框架**: Vue 3 (Composition API + `<script setup>`)
- **构建**: Vite
- **状态管理**: Pinia
- **可视化编辑器**: Vue Flow
- **存储**: IndexedDB (Dexie.js)
- **语言**: TypeScript
- **视频**: 原生 `<video>` + A/B 双缓冲
## 项目结构
```
moviegame/
├── engine/ # 框架无关的核心引擎(纯 TS
│ ├── core/
│ │ ├── Engine.ts # 主循环,驱动各子系统
│ │ ├── SceneManager.ts # 剧情节点图遍历
│ │ ├── VideoManager.ts # A/B 双缓冲视频播放
│ │ └── StateManager.ts # 全局状态、条件求值
│ ├── systems/
│ │ ├── ChoiceSystem.ts # 选择 UI + 倒计时
│ │ ├── QTESystem.ts # QTE 触发、判定、超时
│ │ └── SaveSystem.ts # IndexedDB 存取
│ └── types.ts # 场景数据类型定义
├── src/ # Vue 应用(播放器端)
│ ├── components/
│ │ ├── GamePlayer.vue # 主播放器(挂载 video 元素)
│ │ ├── ChoicePanel.vue # 选项面板
│ │ ├── QTEOverlay.vue # QTE 遮罩
│ │ ├── SaveLoadMenu.vue # 存档界面
│ │ └── Subtitles.vue # 字幕显示
│ ├── composables/
│ │ ├── useGameEngine.ts # 引擎实例 + 生命周期
│ │ ├── useVideoPlayer.ts # 视频状态响应式封装
│ │ └── useGameState.ts # 状态响应式封装
│ ├── stores/
│ │ └── gameStore.ts # 游戏全局状态Pinia
│ ├── App.vue
│ └── main.ts
├── editor/ # Vue Flow 可视化编辑器(独立入口)
│ ├── components/
│ │ ├── SceneGraph.vue
│ │ ├── NodeEditor.vue
│ │ └── PreviewPanel.vue
│ ├── composables/
│ │ └── useGraphEditor.ts
│ └── App.vue
├── public/
│ ├── videos/ # 视频资源
│ └── scenes/
│ └── demo.json # 示例剧情数据
├── vite.config.ts
├── tsconfig.json
├── package.json
└── index.html
```
## 场景数据格式
```typescript
// engine/types.ts
interface SceneNode {
id: string;
videoUrl: string;
subtitleUrl?: string;
choices?: Choice[];
qte?: QTEDefinition;
nextScene?: string;
onEnter?: Effect[];
}
interface Choice {
text: string;
targetScene: string;
conditions?: Condition[];
effects?: Effect[];
timeLimit?: number; // 限时选择0=不限时
}
interface Condition {
variable: string;
op: '>' | '<' | '>=' | '<=' | '==' | '!=' | 'hasFlag';
value: number | string | boolean;
}
interface Effect {
type: 'set' | 'add' | 'toggleFlag' | 'triggerEvent';
target: string;
value?: number | string | boolean;
}
interface QTEDefinition {
triggerTime: number;
prompt: string;
keys: string[];
timeLimit: number;
successScene: string;
failScene: string;
effects?: {
success: Effect[];
fail: Effect[];
};
}
interface GameData {
scenes: Record<string, SceneNode>;
startScene: string;
variables: Record<string, number>;
}
interface SaveData {
slot: number;
timestamp: number;
currentScene: string;
variables: Record<string, number>;
flags: string[];
history: ChoiceRecord[];
thumbnail?: string;
}
```
## 实现路线
### P0 MVP — 最小可玩原型3-5 天)✅ 已完成 2026-06-07
目标:能播放一段视频 → 弹出选项 → 跳到下一段视频
- [x] 项目脚手架Vite + Vue3 + TypeScript + Pinia
- [x] `engine/core/Engine.ts` — 主循环骨架(加载场景 → 播放 → 等选择 → 切换)
- [x] `engine/core/SceneManager.ts` — 加载 JSON按 ID 查找场景节点
- [x] `engine/core/VideoManager.ts` — 单 video 元素播放,监听 ended 事件
- [x] `engine/core/StateManager.ts` — 变量存取、条件求值、效果执行
- [x] `engine/types.ts` — 类型定义
- [x] `src/components/GamePlayer.vue` — 挂载 video控制播放
- [x] `src/components/ChoicePanel.vue` — 渲染选择按钮,触发引擎切换
- [x] `public/scenes/demo.json` — 编写一段简单剧情7 个场景节点)
- [x] 验证:从 demo.json 加载场景,能走通 开始→选择→分支播放→结束 流程
### P1 核心 — 无缝切换 + 条件分支 + 存档1-2 周)
- [ ] `engine/core/VideoManager.ts` 升级 — A/B 双缓冲预加载候选视频CSS 交叉淡化
- [ ] `engine/core/SceneManager.ts` 升级 — 支持条件分支(根据 variables/flags 过滤选项)
- [ ] `engine/systems/SaveSystem.ts` — Dexie.js IndexedDB 存取,多槽位
- [ ] `engine/systems/ChoiceSystem.ts` — 限时选择倒计时,超时默认选择(第一项或配置的默认项)
- [ ] `src/components/SaveLoadMenu.vue` — 存档/读档 UI
- [ ] `src/stores/gameStore.ts` — Pinia 全局状态管理
- [ ] `src/composables/` — 三个 composable 桥接层
- [ ] 验证:分支剧情走通,存档读档正常,视频切换无明显黑屏
### P2 进阶 — QTE + 字幕 + 多存档槽1 周)
- [ ] `engine/systems/QTESystem.ts` — QTE 触发、键盘监听、超时判定
- [ ] `src/components/QTEOverlay.vue` — QTE 视觉遮罩(按键提示 + 倒计时环)
- [ ] `src/components/Subtitles.vue` — WebVTT 解析 + 字幕渲染
- [ ] 多存档槽位 + 存档缩略图canvas 截图当前视频帧)
- [ ] `engine/core/Engine.ts` — 完整事件总线sceneChange, choiceMade, qteTriggered 等)
- [ ] 验证QTE 正常触发与判定,字幕同步,多存档正常工作
### P3 编辑器 — 可视化剧情编辑2-3 周)
- [ ] 编辑器入口:独立 `editor/index.html` + `editor/main.ts`
- [ ] `editor/components/SceneGraph.vue` — Vue Flow 节点图(节点=场景,边=选择分支)
- [ ] `editor/components/NodeEditor.vue` — 右侧面板编辑选中节点的视频、选项、QTE、条件/效果
- [ ] `editor/components/PreviewPanel.vue` — 嵌入播放器,实时预览当前编辑的剧情线
- [ ] `editor/composables/useGraphEditor.ts` — 图数据与 JSON 双向同步
- [ ] JSON 导出/导入
- [ ] 验证:编辑器能产出合法 JSON引擎能正确加载并运行
## 依赖清单
```json
{
"dependencies": {
"vue": "^3.4",
"pinia": "^2.1",
"@vue-flow/core": "^1.x",
"@vue-flow/background": "^1.x",
"@vue-flow/controls": "^1.x",
"dexie": "^4.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.0",
"typescript": "^5.3",
"vite": "^5.0",
"vue-tsc": "^2.0"
}
}
```
## 关键架构决策记录
1. **引擎与 UI 分离**: `engine/` 下纯 TS 类,不 import Vue。UI 层通过 composables 桥接。
2. **A/B 双缓冲**: 两个 `<video>` 元素轮换,一个播放时另一个预加载候选视频。
3. **JSON 驱动**: 所有剧情数据放在 JSON 中,编辑器本质是 JSON 的可视化读写工具。
4. **IndexedDB 存档**: 比 localStorage 容量大,可存储截屏缩略图。