You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

6.8 KiB

六边形追击游戏设计文档

1. 背景与目标

本设计用于在现有 Pixi 项目中实现一个单局时长较短、可重复游玩的回合制追击玩法:

  • 地图由六边形节点和连线组成;
  • 玩家操控小偷每回合移动一步到相邻格;
  • 小偷行动后官兵逼近一步;
  • 到达出口即胜利,被抓住或无路可走即失败;
  • 地图、出口、初始位置由 seed 驱动随机生成;
  • 必须保证“存在可逃脱可能”,但不能过于简单;
  • 左上角显示成功次数;
  • 胜利后“重新开始”开新局;失败后“重试”重开当前局,“新一局”开新局。

2. 需求边界与约束

2.1 已确认交互决策

  • 小偷移动方式:点击相邻六边形(纯点击)。
  • 官兵策略:支持难度配置(简单 / 普通 / 困难)。
  • 失败判定:同格失败 + 下一步无路可走失败。
  • 地图规模:小图,约 20~30 节点。
  • seed 方式:默认随机 + 支持手动输入。
  • 难度选择时机:开局前选择,本局固定。

2.2 非目标(本期不做)

  • 联网排行、存档系统、道具系统;
  • 多官兵、多出口、迷雾视野;
  • 复杂动画编排与特效系统化封装。

3. 总体架构

新增主玩法场景 src/stages/games/chase/page_chase.ts,从 init 进入。场景内部采用“模型与渲染分离”:

  • GameModel(纯逻辑层)
    • 管理地图、seed、回合、角色位置、胜负状态;
    • 负责生成校验(可逃脱且不简单);
    • 对外暴露纯数据状态与动作接口。
  • GameView(展示与交互层)
    • 渲染六边形节点、连线、角色标记、出口;
    • 管理顶部 HUD、开局面板、结算弹层;
    • 将点击行为转换为 GameModel 动作并刷新画面。

该拆分保证:

  • “重试同局”可通过快照精确恢复;
  • seed 逻辑可单测;
  • UI 调整不影响核心规则。

4. 数据模型

4.1 核心类型

  • NodeId: string
  • GraphNode { id, q, r, neighbors: NodeId[] }
  • GameGraph { nodes: Map<NodeId, GraphNode>, edgeList: [NodeId, NodeId][] }
  • Difficulty = "easy" | "normal" | "hard"
  • GameStatus = "setup" | "playing" | "win" | "lose"
  • RoundSnapshot
    • seed
    • difficulty
    • graph
    • thiefStartNodeId
    • guardStartNodeId
    • exitNodeId
    • thiefNodeId
    • guardNodeId
    • status

4.2 会话状态

  • winCount: number(会话累计,场景生命周期内保留)
  • currentSeed: number
  • currentSnapshot: RoundSnapshot | null(失败后“重试”回放源)

5. 地图生成与 seed 方案

5.1 RNG

实现确定性 RNG(如 mulberry32):

  • 输入:32 位整数 seed;
  • 输出:稳定伪随机序列;
  • 任意同 seed + 同配置,生成结果一致。

5.2 六边形图构造

  1. 使用轴坐标 (q, r) 作为节点坐标;
  2. 依据小图配置随机生成 20~30 个节点;
  3. 先构建连通骨架(类似生成树)确保全图可达;
  4. 再按概率补少量边形成分叉路径,避免过线性。

5.3 出口与初始点放置

  • exit:优先从边缘节点集合选取;
  • thiefStart:到出口最短路距离至少 minEscapeDist = 4
  • guardStart:与小偷初始距离至少 minInitialGap = 3,并避免过近出口。

5.4 可玩性校验(硬约束)

生成后执行验证,不满足则内部重采样(可通过 seed 偏移重试):

  1. 可逃脱性:存在至少一条小偷策略可在有限步内到达出口;
  2. 非过简性:不能出现“几乎无脑 2~3 步必胜”局面;
  3. 推荐目标:首条可行逃生路径长度在 [4, 9] 区间。

若连续重试超过阈值(例如 40 次),放宽“非过简性”下限一档,避免卡死生成。

6. 回合规则与难度

6.1 回合流程(固定顺序)

  1. 玩家点击相邻节点,小偷移动一步;
  2. 立即判胜:若小偷到达出口 => win
  3. 若未胜,官兵移动一步;
  4. 判负:
    • 官兵与小偷同节点 => lose
    • 小偷下一回合无可移动邻格 => lose

6.2 官兵逼近策略

  • easy:60% 走最短路下一格,40% 走“次优候选”随机格;
  • normal:85% 最短路,15% 次优随机;
  • hard:100% 最短路。

“次优候选”定义:不会显著增大小偷距离,且仍保持追击方向。

6.3 非法输入处理

  • 非邻接点击:忽略并提示“只能移动到相邻格”;
  • playing 状态点击地图:忽略。

7. UI 设计

7.1 顶部 HUD

  • 左上:成功次数:X
  • 右上:当前 seed:<seed>

7.2 开局面板

  • 难度单选(简单/普通/困难)
  • seed 输入框(可空)
    • 空:自动随机
    • 非空:按输入值开局
  • 开始游戏 按钮

7.3 对局中视觉

  • 高亮小偷可移动邻格;
  • 小偷、官兵、出口使用不同视觉标识;
  • 状态提示文案(你的回合 / 官兵逼近中 / 已被包围)。

7.4 结算弹层

  • 胜利:文案“成功逃脱!”,按钮 重新开始(新 seed 新局),并 winCount + 1
  • 失败:文案“你被抓住了”或“你已无路可走”,按钮:
    • 重试:按 currentSnapshot 完全恢复当前局;
    • 新一局:生成新 seed 新局。

按钮统一加点击防抖(短时禁用)避免重复触发。

8. 关键流程定义

8.1 新一局流程

  1. 读取 UI 配置(难度、可选手动 seed);
  2. 解析 seed(手动或自动随机);
  3. 生成并验证地图;
  4. 构造 snapshot,并进入 playing
  5. 刷新渲染。

8.2 重试流程(失败后)

  1. 校验 currentSnapshot 存在;
  2. 从快照恢复全部状态(同图同起点同出口同难度同 seed);
  3. 状态置为 playing
  4. 刷新渲染。

9. 测试与验收标准

9.1 单元测试(逻辑层)

  • 同 seed 生成一致性;
  • 不同 seed 生成差异性;
  • 连通性校验;
  • 可逃脱性校验;
  • 非过简性校验;
  • 官兵三档策略概率行为(统计容差);
  • 胜负判定(同格、到出口、无路可走)。

9.2 集成测试(场景层)

  • 点击相邻节点可移动,非相邻无效;
  • 小偷一步后官兵一步;
  • 胜利后“重新开始”进入新地图;
  • 失败后“重试”恢复同局,“新一局”生成新局;
  • 成功次数仅在胜利时增加。

9.3 验收清单

  • 地图节点数稳定在 20~30;
  • 初始小偷与官兵有距离,不贴脸开局;
  • 所有局保证存在可逃脱可能;
  • 但并非“随便走都赢”;
  • seed 可复现;
  • UI 操作路径与文案符合需求。

10. 实施拆分建议

建议按以下顺序进入实现计划:

  1. 先完成 GameModel 与地图生成/校验;
  2. 接入 games/chase 场景基础渲染与点击移动;
  3. 接入难度策略与胜负/结算流程;
  4. 最后完善 HUD、seed 输入、按钮交互与测试。