Rework story engine flow and reorganize project docs
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
2026-04-06 23:19:00 +08:00
parent d678929064
commit ddcb5d5c8c
241 changed files with 19805 additions and 2478 deletions

View File

@@ -0,0 +1,277 @@
# Codex Past Work Experience Summary
日期:`2026-03-23`
## 1. 工作范围概览
这几轮工作主要集中在 4 个方向:
1. 编辑器体系整理
2. NPC 视觉编辑与素材接入
3. 玩家角色与怪物动画资源纠偏
4. 选项行为编辑器与预览链路升级
这些改动不是孤立的 UI 修补,而是横跨了:
- 资源定义层
- 编辑器字段层
- 运行时预览层
- 游戏真实播放逻辑层
## 2. 已完成的核心工作
### 2.1 编辑器入口与页签整理
- 保留 `/preset-editor``/npc-editor``/function-editor`
- 新增 `/behavior-editor` 作为“选项行为”编辑页别名
- 将原先单独的 `NPC 视觉` 标签并回 `NPC` 编辑页
-`Function` 页签改名为 `选项行为`
结论:
- 路由层要尽量兼容旧入口,避免历史链接失效
- 页签命名要贴近创作者语言,而不是内部实现命名
### 2.2 NPC 视觉模块并入 NPC 编辑
完成内容:
- 将 [NpcVisualEditor](/E:/Repos/Genarrative/src/components/NpcVisualEditor.tsx) 嵌入 [PresetEditor](/E:/Repos/Genarrative/src/components/PresetEditor.tsx) 的 NPC 编辑页
- 让 NPC 文本字段与视觉字段围绕同一个当前选中 NPC 联动
- 保留视觉覆盖保存与全局布局保存能力
经验:
- NPC 文本编辑和 NPC 视觉编辑不应分裂成两个互不关联的工作流
- “当前选中的 NPC” 必须是两个模块共享的单一数据源
### 2.3 Medieval NPC 素材定义重建
完成内容:
- 在 [medievalNpcVisuals.ts](/E:/Repos/Genarrative/src/data/medievalNpcVisuals.ts) 中重建了 Medieval NPC 的资产定义
- 补齐了 cloth / leather / metal / melee / magic / ranged 六大类真实素材
- 为素材增加了:
- 语义化名称
- 图块尺寸
- 列数
- 帧数
- 姿态选项
- 让编辑器不再直接使用文件名、序号名作为展示项
经验:
- 编辑器下拉项如果来自手写数组,迟早会和真实素材目录脱节
- 素材定义最好具备“资产元数据”,而不是只有路径字符串
- 一旦资产存在大图块,就不能再默认所有图块都是 `32x32`
### 2.4 NPC 动画器支持大图块武器
完成内容:
- 在 [MedievalNpcAnimator.tsx](/E:/Repos/Genarrative/src/components/MedievalNpcAnimator.tsx) 中为 `AtlasSprite` 增加:
- `tileWidth`
- `tileHeight`
- 对齐偏移支持
效果:
- 长柄武器
- 巨剑
- 64x32 远程武器
- 64x64 投石索类武器
都能正确显示,不再被按 `32x32` 裁坏。
经验:
- 视觉编辑器一旦涉及装备 atlas就必须把“资源尺寸”从数据层带到渲染层
### 2.5 玩家角色动画映射纠偏
完成内容:
- 在 [characterPresets.ts](/E:/Repos/Genarrative/src/data/characterPresets.ts) 中重新核对 5 个玩家角色的 Hero 动画目录
- 修正了错误帧数、错误前缀、遗漏动作
- 补齐了真实存在但之前未接入的动作:
- `acquire`
- `climb`
- `dash`
- `die`
- `double jump`
- `hurt`
- `jump`
- `jump attack`
- `wall slide`
- 给角色动画配置增加了 `file` 字段,支持单文件动画
相关文件:
- [types.ts](/E:/Repos/Genarrative/src/types.ts)
- [CharacterAnimator.tsx](/E:/Repos/Genarrative/src/components/CharacterAnimator.tsx)
- [characterCombat.ts](/E:/Repos/Genarrative/src/data/characterCombat.ts)
经验:
- 只要编辑器允许用户切“预览动作”,就不能让未映射动作静默 fallback 到 `idle`
- 正确做法是:
1. 先补齐真实动作映射
2. 再让预览下拉只显示当前角色实际可用动作
### 2.6 怪物动画空白帧修复
完成内容:
- 在 [monsterPresets.ts](/E:/Repos/Genarrative/src/data/monsterPresets.ts) 中把怪物动画从“连续帧猜测”改成“按图集行起点取帧”
- 补上缺失的 `die` 配置
- 清除了所有落进空白格的动画段
经验:
- 像素怪物图集不一定按一个连续区段排完整套动作
- 如果动作配置只写 `start + frames`,但没结合图集行结构,就非常容易踩进空白帧
### 2.7 选项行为编辑器重构
完成内容:
- 将原 “Function 编辑器” 改造成 “选项行为编辑器”
- 页面文案和入口统一为“选项行为”
- 移除“基础场景 / 结果场景”双窗格预览
- 保留并强化:
- 行为列表
- 覆盖保存
- 快速模板套用
经验:
- 创作者并不关心 “function” 这个技术词,更关心“这个选项会发生什么”
- 同类编辑器如果只给字段表单而没有模板起稿能力,复用效率会很低
### 2.8 选项行为预览升级到实机回放
完成内容:
- 在 [StateFunctionEditor.tsx](/E:/Repos/Genarrative/src/components/StateFunctionEditor.tsx) 中新增 `BehaviorExecutionPreview`
- 预览不再是静态推测,而是:
1. 构造本地 `GameState`
2. 调用真实 `resolveFunctionOption`
3. 再调用 [useCombatFlow.ts](/E:/Repos/Genarrative/src/hooks/useCombatFlow.ts) 的
- `buildResolvedChoiceState`
- `playResolvedChoice`
- 从而直接复用游戏真实逻辑
覆盖能力包括:
- 战斗行为
- 恢复行为
- 脱离行为
- 探索前探
- 切场行为
经验:
- 编辑器预览只要和运行时逻辑写成两套,就一定会越来越不一致
- 预览层最稳的做法是“调用真实业务逻辑”,而不是“模拟真实业务逻辑”
## 3. 关键踩坑记录
### 3.1 图标组件名覆盖原生 `Map`
问题:
- `lucide-react``Map` 图标直接命名为 `Map`
- 在 NPC 页签里 `new Map()` 实际调用到了图标组件
- 导致页签内容直接渲染为空
经验:
- 图标组件命名尽量使用 `MapIcon``UserIcon` 这类后缀
- 避免覆盖 JS/TS 原生对象名
### 3.2 预览 effect 依赖不稳定导致回放反复重启
问题:
- `BehaviorExecutionPreview` 里使用了 `useCombatFlow()`
- 但 effect 依赖了返回对象本身
- 每次 `gameState` 更新effect 都会被视为变更
- 导致预览回放速度异常、重复重启、动画像加速
经验:
- 只要预览组件内部要“异步播放状态变化”,就要高度警惕 effect 依赖环
- 解决方式是:
-`ref` 保存稳定方法引用
- 让 effect 只依赖真正的输入配置,不依赖内部播放状态
### 3.3 实时面板与回放阶段不同步
问题:
- `LIVE PLAYER` 用的是实时 `gameState`
- `BATTLE SNAPSHOT` 用的是预计算首回合快照
- 两者不是同一时间点的数据
- 导致面板看起来“都对,但互相对不上”
经验:
- 预览面板要么都显示“实时状态”
- 要么都显示“同一个阶段的快照”
- 混用实时值和预测值会让创作者误判
## 4. 这类项目里沉淀下来的方法论
### 4.1 先校验资源,再改编辑器
顺序建议:
1. 先扫真实目录
2. 再建资产定义
3. 再修编辑器字段
4. 最后修预览
### 4.2 预览必须尽量复用游戏真实链路
优先级:
1. 复用真实函数
2. 复用真实状态结构
3. 复用真实渲染组件
4. 最后才是补充编辑器专用的辅助信息
### 4.3 编辑器要区分“可编辑字段”和“会生效字段”
经验:
- 不是所有字段都应该在所有行为类型下开放
- 如果某类行为最终不会直接读取某个字段,就应该禁用或弱化它
- 否则创作者会错误地以为改动无效是 bug
### 4.4 模板比空白表单更重要
经验:
- 当系统里已经有多种成熟行为时,最快的创作路径不是“从零填写”
- 而是:
- 选一个最像的
- 套结构
- 微调文案和数值
## 5. 推荐的后续方向
如果继续打磨这套编辑器,建议下一步做:
1. 为选项行为预览增加“时间轴 / 阶段日志”
2. 为选项行为编辑器增加“新建行为向导”
3. 把更多系统状态引入预览上下文
- 同伴
- NPC 状态
- 背包
- 当前场景实体池
4. 把“可编辑字段”和“只读推导字段”视觉上再分开
## 6. 一句话总结
过去这几轮最重要的经验不是“写了多少编辑器 UI”而是
**编辑器一旦想可靠,就不能只编辑静态数据,必须逐步接管真实资源定义、真实运行时状态和真实播放逻辑。**