Files
tianshu-engine/ROADMAP.md
cocos02 3b4c6d7024 feat: P3 - visual scenario editor with Vue Flow
- editor/: stand-alone Vite multi-page app for visual scenario editing
- editor/components/SceneGraph.vue: Vue Flow graph with scene nodes, branch/default/QTE edges
- editor/components/NodeEditor.vue: right panel editing video/subtitle paths, choices, QTE params
- editor/components/PreviewPanel.vue: embedded video player previewing selected scene
- editor/composables/useGraphEditor.ts: bidirectional graph<->JSON sync
- editor/App.vue: toolbar (new scene, import/export JSON, load demo, start scene selector)
- @vue-flow/core|background|controls: graph visualization dependencies
- vite.config.ts: multi-page build (main + editor)
- ROADMAP: mark P3 as completed
2026-06-07 21:38:08 +08:00

209 lines
8.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 周)✅ 已完成 2026-06-07
- [x] `engine/core/VideoManager.ts` 升级 — A/B 双缓冲预加载候选视频CSS 交叉淡化
- [x] `engine/core/SceneManager.ts` 升级 — 支持条件分支(根据 variables/flags 过滤选项)
- [x] `engine/systems/SaveSystem.ts` — Dexie.js IndexedDB 存取,多槽位
- [x] `engine/systems/ChoiceSystem.ts` — 限时选择倒计时,超时默认选择
- [x] `src/components/SaveLoadMenu.vue` — 存档/读档 UI
- [x] `src/stores/gameStore.ts` — Pinia 全局状态管理(含计时器、存档列表)
- [x] `src/composables/useGameEngine.ts` — 桥接层(双 video、存档、计时器
- [x] `src/components/GamePlayer.vue` — 双 video 元素 + 交叉淡化 CSS
- [x] `src/components/ChoicePanel.vue` — 倒计时进度条 + 计时文字
- [x] `src/App.vue` — 整合 SaveLoadMenu、双 video、计时器
- [x] 验证:条件分支走通,存档读档正常,视频切换交叉淡化
### P2 进阶 — QTE + 字幕 + 多存档槽1 周)✅ 已完成 2026-06-07
- [x] `engine/systems/QTESystem.ts` — QTE 触发、键盘监听(支持多键匹配)、超时判定
- [x] `src/components/QTEOverlay.vue` — SVG 倒计时环 + 按键提示 + 成功/失败动画
- [x] `src/components/Subtitles.vue` — WebVTT 解析 + 字幕同步渲染
- [x] `engine/core/Engine.ts` — 集成 QTEtimeupdate 检测 + 条件跳转 + 效果应用)
- [x] 多存档槽位 + 存档缩略图canvas 截图当前视频帧320x180 JPEG
- [x] `engine/core/VideoManager.ts` — 新增 `getActiveVideoElement()` 供截图
- [x] `engine/systems/SaveSystem.ts` — DB 版本升级 v2支持 thumbnail 字段)
- [x] `src/components/SaveLoadMenu.vue` — 存档缩略图预览
- [x] 完整事件总线sceneChange, choiceRequest, choiceTimer, choiceTimeout, videoEnd, qteTrigger, qteTimer, qteResult, gameEnd
- [x] 验证QTE 正常触发与判定ArrowLeft/ArrowRight/A/D 躲石块),字幕同步,存档缩略图正常
### P3 编辑器 — 可视化剧情编辑2-3 周)✅ 已完成 2026-06-07
- [x] 编辑器入口:独立 `editor/index.html` + `editor/main.ts`Vite 多入口构建)
- [x] `editor/components/SceneGraph.vue` — Vue Flow 节点图(场景节点 + 分支/默认/QTE 连线)
- [x] `editor/components/NodeEditor.vue` — 右侧面板(视频/字幕路径、nextScene、选项增删改、QTE 参数编辑)
- [x] `editor/components/PreviewPanel.vue` — 嵌入播放器实时预览选中场景视频
- [x] `editor/composables/useGraphEditor.ts` — 图数据与 JSON 双向同步
- [x] JSON 导出/导入(文件下载 + 文件选择)
- [x] 工具栏:新建场景、导入 JSON、导出 JSON、加载示例、起始场景选择
- [x] `vite.config.ts` — 多页面构建main + editor
- [x] 验证:编辑器能产出合法 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 容量大,可存储截屏缩略图。