修建系统 PRD
本文是 #001 独立开发者的文档驱动 AI 编程实践 中提到的 PRD 样例。这是我们项目中实际使用过并且正在维护的一篇文档。我并不认为存在适用于一切项目的标准化 PRD 格式,但希望可以给大家一个思路。
本文档导出自内部 Notion 工作区。文中 斜体 标注的名称为其他内部文档的交叉引用,不可公开访问。
概述
管理要塞的建筑规划与建造:
- 玩家在建造模式下放置建筑蓝图,指派船员优先级后,能进行建造的船员自动搬运材料并完成建造
- 支持旋转、拆除和优先级调整。
概念/术语
空间结构
| 术语 | 中文 | 说明 |
|---|---|---|
| Deck | 甲板 | 最外层的整体层级区域,由多个Block组成。游戏世界的Y坐标对应不同的Deck |
| Block | 区块 | 游戏内的最小空间单位,建造与拆除的操作对象。一个Block可以容纳多层(Layer)建筑 |
| Layer | 层 | Block内的垂直分层空间,用于放置不同类别的建筑。同一Block的不同Layer可以各放置一个建筑 |
Layer类型定义
| Layer | 中文 | 说明 |
|---|---|---|
| Floor | 地板层 | 所有建造的基础,其他层必须建立在Floor之上 |
| Facility | 设施层 | 工作台、传送带、引擎、墙壁、床、火炮等 |
| Pipe | 管道层 | 管道系统 |
| Light | 顶灯层 | 照明设备 |
| Room | 房间层 | 房间标记 |
建筑实体
| 术语 | 中文 | 说明 |
|---|---|---|
| Building Entity | 建筑实体 | 玩家放置建筑后,占据空间格子的实体。框架、成品都是建筑实体的不同阶段 |
| Building Preview | 建筑预览 | 鼠标跟随的虚影,绿色(允许放置)或红色(不允许放置),点击确认后变成框架 |
| Building Frame | 建筑框架 | 玩家放置后的建筑实体,显示为半透明轮廓。材料陆续运达,船员积累工作量完成建造 |
| Building Completed | 建筑成品 | 建造完成后的建筑实体,可被使用或拆除。详见 建筑 Building |
| Work Amount | 工作量 | 完成某一建筑从框架到成品建造所需的总工作点数 |
状态
状态定义
| 状态 | 中文 | 说明 |
|---|---|---|
| Idle | 空闲 | 初始状态,建筑实体不存在 |
| Frame | 框架 | 已放置的建筑,等待材料和建造 |
| Completed | 完工 | 成品状态,建造完成 |
| Destroyed | 已摧毁 | 终态:被摧毁 |
| Removed | 已拆除 | 终态:被拆除 |
事件定义
| 事件 | 中文 | 说明 | 触发方 |
|---|---|---|---|
| E1: Designated | 已指定 | 放置建筑框架 | 玩家 |
| E3: MaterialDelivered | 材料送达 | 材料已送达 | 船员 |
| E4: WorkProgressed | 工作推进 | 工作已推进 | 船员 |
| E5: WorkCompleted | 工作完成 | 工作已完成 | 系统 |
| E6: Deconstructed | 已拆除 | 拆除(瞬间) | 玩家 |
| E7: Destroyed | 已摧毁 | 被摧毁 | 系统 |
E2 已删除(原「已取消」状态合并到 E6 拆除)
扩展变量
| 变量 | 中文 | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
| material_progress | 材料进度 | float | 0% | 0%-100%,已送达材料/所需材料 |
| work_progress | 工作进度 | float | 0% | 0%-100%,已完成工作量/总工作量 |
状态转移表
| 源状态 | 事件 | 守卫条件 | 动作 | 任务操作 | 目标状态 |
|---|---|---|---|---|---|
| 空闲 | E1: 已指定 | — | — | 生成 Build Task | 框架 |
| 框架 | E6: 已拆除 | — | 掉落已送达的全部材料 | 销毁关联 Task | 已拆除 |
| 框架 | E3: 材料已送达 | — | 更新 material_progress | — | 框架 |
| 框架 | E4: 工作已推进 | 材料进度 ≥ 100% | 更新 work_progress | — | 框架 |
| 框架 | E5: 工作已完成 | work_progress ≥ 100% | — | — | 完工 |
| 框架 | E7: 已摧毁 | — | — | 销毁关联 Task | 已摧毁 |
| 完工 | E6: 已拆除 | — | 掉落已送达的全部材料 | — | 已拆除 |
| 完工 | E7: 已摧毁 | — | — | — | 已摧毁 |
状态图
stateDiagram-v2
state "空闲" as Idle
state "框架" as Frame
state "完工" as Completed
state "已摧毁" as Destroyed
state "已拆除" as Removed
[*] --> Idle
Idle --> Frame: E1 已指定 / 生成 Build Task
Frame --> Removed: E6 已拆除 / 销毁关联 Task,掉落全部材料
Frame --> Frame: E4 工作已推进 [材料进度 ≥ 100%] / 更新work_progress
Frame --> Frame: E3 材料已送达 / 更新material_progress
Frame --> Completed: E5 工作已完成 [work_progress ≥ 100%]
Frame --> Destroyed: E7 已摧毁 / 销毁关联 Task
Completed --> Removed: E6 已拆除 / 掉落全部材料
Completed --> Destroyed: E7 已摧毁
Destroyed --> [*]
Removed --> [*]
交互
菜单导航(底栏 Tab 切换、分类展开)由全局 UI 框架 管理。本章节只描述建造系统专属的交互模式。
快捷键:
- B键:切换建造tab,展开建筑分类菜单
- C键:切换到拆除tab,进入拆除模式
操作模式状态机
描述建造系统的操作模式状态。此状态机不关心UI框架层面的tab切换或菜单浏览,只关心建造系统是否处于特殊操作模式。右键上下文菜单由 UI 框架 统一管理。
状态定义
| 状态 | 中文 | 说明 |
|---|---|---|
| Normal | 正常 | 建造系统无特殊操作模式。玩家在UI框架层面的行为(按B、浏览菜单、切换tab等)不影响此状态 |
| Previewing | 预览中 | 正在放置建筑蓝图,可调整位置/方向 |
| Deconstructing | 拆除模式 | 批量拆除模式,点击框架或成品触发拆除 |
事件定义
| 事件 | 中文 | 说明 | 触发方 |
|---|---|---|---|
| I1: EnterPreviewing | 进入预览 | 进入预览模式,携带建筑类型参数 | UI框架(当玩家在Building tab菜单中点击具体建筑时调用) |
| I2: EnterDeconstructing | 进入拆除 | 进入拆除模式 | UI框架(当玩家切换到拆除tab时调用) |
| I3: ExitMode | 退出模式 | 退出预览/拆除模式 | 玩家输入(Esc / 右键空白处) |
| I4: MouseMove | 鼠标移动 | 更新预览位置 | 玩家输入(预览模式下移动鼠标) |
| I5: Rotate | 旋转 | 旋转预览方向 | 玩家输入(Q/E/滚轮) |
| I6: LeftClick | 左键点击 | 确认放置 / 执行拆除 | 玩家输入(预览/拆除模式下左键点击) |
| I7: LeftDrag | 左键拖动 | 连续放置建筑 | 玩家输入(预览模式下左键拖动) |
守卫条件依赖
| 变量 | 中文 | 类型 | 来源 |
|---|---|---|---|
| position_valid | 位置合法 | bool | 建造系统 |
| supports_drag | 支持连续放置 | bool | 建造系统 |
状态转移表
| 源状态 | 事件 | 守卫条件 | 目标状态 | 动作 |
|---|---|---|---|---|
| 正常 | I1: 进入预览 | — | 预览中 | — |
| 正常 | I2: 进入拆除 | — | 拆除模式 | — |
| 预览中 | I3: 退出模式 | — | 正常 | — |
| 预览中 | I4: 鼠标移动 | — | 预览中 | 更新预览位置 |
| 预览中 | I5: 旋转 | — | 预览中 | 旋转90° |
| 预览中 | I6: 左键点击 | 位置合法 | 预览中 | 触发 E1 已指定 |
| 预览中 | I6: 左键点击 | !位置合法 | 预览中 | 播放错误提示 |
| 预览中 | I7: 左键拖动 | 支持连续放置 | 预览中 | 触发 E1 已指定 ×N |
| 拆除模式 | I3: 退出模式 | — | 正常 | — |
| 拆除模式 | I6: 左键点击 | 点击框架或成品 | 拆除模式 | 触发 E6 已拆除 |
状态图
stateDiagram-v2
state "正常" as Normal
state "预览模式" as Preview
state "拆除模式" as Decon
[*] --> Normal
Normal --> Preview: I1 进入预览 / UI框架调用
Normal --> Decon: I2 进入拆除 / UI框架调用
Preview --> Normal: I3 退出模式 (Esc / 右键空白处)
Preview --> Preview: I4 鼠标移动
Preview --> Preview: I5 旋转
Preview --> Preview: I6 左键点击 [位置合法] / 触发 E1
Preview --> Preview: I6 左键点击 [!位置合法] / 播放错误提示
Preview --> Preview: I7 左键拖动 [支持连续放置] / 触发 E1 ×N
Decon --> Normal: I3 退出模式 (Esc / 右键空白处)
Decon --> Decon: I6 左键点击框架或成品 / 触发 E6
右键菜单
建造系统定义的右键菜单内容。显示/隐藏统一由 UI 框架 管理。
框架菜单(右键点击建筑框架)
| 按钮 | 操作 | 触发事件 |
|---|---|---|
| 优先级 | 修改建造优先级 | — |
| 拆除 | 拆除该框架 | E6 已拆除 |
成品菜单(右键点击建筑成品)
| 按钮 | 操作 | 触发事件 |
|---|---|---|
| 拆除 | 拆除该建筑 | E6 已拆除 |
反馈
按触发源组织:
- 操作模式反馈(玩家交互)
- 实体状态反馈(持续显示)
- 系统事件反馈(瞬时触发)
操作模式反馈:预览模式
持续反馈(鼠标移动时实时检查)
| 检查条件 | 音效 | Toast | 视觉反馈 | 系统行为 |
|---|---|---|---|---|
| 违反Layer依赖规则(R1) | — | — | 预览显示红色 | — |
| 违反Layer互斥规则(R2) | — | — | 预览显示红色,冲突建筑也显示红色 | — |
瞬时反馈(左键点击时触发)
| 检查条件 | 音效 | Toast | 视觉反馈 | 系统行为 |
|---|---|---|---|---|
| 违反Layer依赖规则(R1) | 错误音效 | “此处无法建造:需要Floor基础” | — | 阻止放置 |
| 违反Layer互斥规则(R2) | 错误音效 | “此处无法建造:空间已占用” | — | 阻止放置 |
| 位置合法 | 放置音效 | — | 预览变为框架,生成框架实体 | 触发 E1 已指定 |
实体状态反馈:框架状态
持续反馈(框架存在期间持续显示)
UI 反馈由框架自己检查条件决定,不依赖 Task 状态。
| 检查条件 | 音效 | Toast | 视觉反馈 | 系统行为 |
|---|---|---|---|---|
| material_progress < 100% | — | — | 框架显示缺失材料图标 | — |
| 地图无可用材料 | — | — | 框架显示黄色警告图标 + “缺少材料” | — |
| 框架位置不可达 | — | — | 框架显示红色警告图标 + “无法到达” | — |
| Task 未分配,无可用 Crew | — | — | 框架显示待分配图标 | — |
系统事件反馈(非玩家触发)
E5: 工作完成(瞬时触发)
| 检查条件 | 音效 | Toast | 视觉反馈 | 系统行为 |
|---|---|---|---|---|
| — | 完成音效 | “[建筑名称] 建造完成” | 建筑生成动画 | 框架转为成品 |
规则
R1: Layer依赖规则
- 必须:所有非Floor层的建筑必须建立在已放置Floor的Block上
- 非Floor层之间在建造时没有依赖关系,可以任意顺序放置
R2: Layer互斥规则
- 禁止:同一Block的同一Layer放置多个建筑
- Room层仅与Room类型建筑互斥,不影响其他Layer
R3: 拆除级联规则
- 必须:拆除Floor时,级联移除该Block内所有其他Layer的建筑(顺序:Light → Pipe → Facility → Floor)
- 拆除非Floor建筑时,仅移除该Layer建筑,不影响其他Layer
船员建造流程
本章节使用 任务系统 Task System 定义的 Task/Action 框架。Task 生命周期、Action 定义、中断响应表等通用内容详见 任务系统 文档,本章节只描述建造系统特定的内容。
Task: Build(建造)
工作类型:修建 Construction
执行流程
flowchart TD
start(("开始")) --> check1{"material_progress < 100%?"}
check1 -->|是| A1["GoTo(材料)"]
A1 --> A2["PickUp"]
A2 --> A3["CarryTo(框架)"]
A3 --> A4["Drop"]
A4 --> E3["E3: MaterialDelivered"]
E3 --> check1
check1 -->|否| check2{"work_progress < 100%?"}
check2 -->|是| B1["GoTo(框架)"]
B1 --> B2["Build"]
B2 --> E4["E4: WorkProgressed"]
E4 --> check2
check2 -->|否| E5["E5: WorkCompleted"]
Action 说明
| Action | 说明 |
|---|---|
| GoTo(材料) | 前往最近的可用材料位置 |
| PickUp | 拾取材料 |
| CarryTo(框架) | 携带材料前往框架位置 |
| Drop | 放下材料 |
| GoTo(框架) | 前往框架相邻位置 |
| Build | 推进建造进度 |
设计原则:
- 不要求同一 Crew 完成整个建造流程
- 进度由框架实体追踪(
material_progress,work_progress),不由 Task 追踪
任务生成与分配
框架与 Task 的关联机制详见 任务系统 Task System「实体与 Task 关联」
Build Task 的重新生成条件:
work_progress < 100%(框架未完工,或者材料未运输到位)。
Task 侧分配条件:
| 条件 | 说明 |
|---|---|
| 材料可用 | 所需材料在地图上存在且可达 |
| 框架可达 | 框架位置存在可通路径 |
Crew 侧分配条件:详见 任务系统 Task System。
计算逻辑
计算项:建造速度
\[\text{实际每 tick 工作贡献} = \text{每 tick 基准工作贡献} \times \text{建造等级} \times 0.3\]建造等级取值范围详见 船员 Crew「技能与熟练度」。
每tick基准工作贡献 = 1
数值配置
修建配置
[Notion 嵌入数据库 — 修建配置表]
材料消耗
| 建筑 | 材料消耗 | 工作量 |
|---|---|---|
| 所有建筑 | 木材 × 100 | 1000 |
验收检查
交互
- B 键打开建造菜单
- C 键进入拆除模式
- Q/E/滚轮旋转预览
- Esc/右键空白处退出模式
- 左键点击放置框架
- 左键拖动连续放置
- 右键框架显示菜单(优先级、拆除)
- 右键成品显示菜单(拆除)
反馈
- 预览违反 R1/R2 时显示红色
- 违反 R2 时冲突建筑也显示红色
- 放置失败播放错误音效 + Toast
- 放置成功播放放置音效
- 框架缺材料时显示缺失材料图标
- 地图无可用材料时显示黄色警告
- 框架不可达时显示红色警告
- 完成时播放音效、Toast、动画
规则
- R1: 非 Floor 建筑必须在 Floor 上
- R2: 同 Block 同 Layer 不能放多个建筑
- R3: 拆除 Floor 时级联拆除其他 Layer
建造流程
- 放置后生成框架和 Build Task
- Crew 正确搬运材料到框架
- 建造速度符合公式(基准×建造等级×0.3)
- 工作量达标后框架转为成品
- 中断后框架重新生成 Task
状态与材料
- 拆除框架:掉落已送达材料,销毁 Task
- 拆除成品:掉落全部材料
- 框架/成品被摧毁:销毁关联 Task
待细化
- 建造过程中,优先级相关的内容