初始提交:三玩法 Web 原型与设计文档
- 玩法一 数字一笔:规则库、求解器、26 关、竖屏触摸 Web 原型、测试 - 玩法二 连连气球:连消畅玩版核心、Web 原型、Cocos 球槽组件与导出脚本 - 玩法三 六边一笔:规则库、求解器、10 关 + 转墙实验包、Web 原型、测试 - 产品文档、UI 设计规范、各玩法 GDD / HANDOFF - 文档移除全部外部参考作引用;删除玩法二 v0 旧稿
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
# 玩法一 · 数字一笔
|
||||
|
||||
按数字顺序,一笔画走完盘面上每一格。大格只计一步。
|
||||
|
||||
本目录自包含:规格、关卡、规则代码、求解器和 Web 原型。不要依赖 `modes/02` 或 `modes/03`。壳需要的东西通过 `shared/` 的玩法入口对接,见 [`docs/PRODUCT.md`](../../docs/PRODUCT.md)。
|
||||
|
||||
关卡、资源、文案全部原创,不使用第三方题库或素材。
|
||||
|
||||
## 状态
|
||||
|
||||
M1/M2 已达:竖屏触摸 Web 原型可玩,三包 26 关全部经求解器断言唯一解,含 6 关「奇与偶」体验包;存档、补数字 / 指路双提示、音效、振动齐全。68 个单元测试通过。下一步为试玩调校与 M4 迁 Cocos。
|
||||
|
||||
## 目录
|
||||
|
||||
| 路径 | 用途 |
|
||||
|---|---|
|
||||
| [`docs/GDD.md`](docs/GDD.md) | 本玩法规格(权威) |
|
||||
| [`docs/HANDOFF.md`](docs/HANDOFF.md) | 交接文档:实现了什么、怎么实现、与 GDD 的偏差、待办与 Cocos 迁移顺序 |
|
||||
| [`../../docs/design.md`](../../docs/design.md) | UI 设计规范(色彩 / 字阶 / 组件 / 动效)。`web/style.css :root` 与 `src/theme.ts` 由 `tests/theme.test.ts` 校验一致 |
|
||||
| [`levels/pack-1-tutorial.json`](levels/pack-1-tutorial.json) | 第一包 10 关(教学) |
|
||||
| [`levels/pack-2-advanced.json`](levels/pack-2-advanced.json) | 第二包 10 关(进阶,生成器产出 + 人工过目) |
|
||||
| [`levels/pack-3-parity.json`](levels/pack-3-parity.json) | 第三包 6 关(奇与偶,每条奇偶线索都参与唯一性) |
|
||||
| [`src/`](src/) | **纯 TS 规则层,零 DOM / 零 Cocos 依赖**。Web 与 Cocos 共用 |
|
||||
| [`web/`](web/) | 浏览器原型:DOM / Canvas / PointerEvent / localStorage 粘合层 |
|
||||
| [`tools/`](tools/) | 求解器命令行:全关卡校验、关卡设计辅助 |
|
||||
| [`tests/`](tests/) | 规则层单元测试(node:test) |
|
||||
|
||||
`src/` 分层:
|
||||
|
||||
```
|
||||
types.ts 关卡 JSON 结构
|
||||
board.ts Cell / Board:单位网格、四向邻接、共享边
|
||||
clue.ts 数字 / 奇偶线索统一判定与显示文字
|
||||
game.ts 对局状态机:Command → GameEvent(含 rewind 多步回退、reveal 补数字)
|
||||
input.ts 手势语义:按下/移动/松手 + “当前压在哪个格” → Command
|
||||
solver.ts 枚举满足线索的哈密顿路径、唯一解、提示(下一步 / 退回分叉)
|
||||
clue-hint.ts 在尚未解开的数字区间补中间数,不替玩家画路线
|
||||
layout.ts 盘面适配、格矩形、桥矩形、命中测试(带死区)
|
||||
view.ts BoardView:格/桥/数字/冲突/提示/过关动效,只调用 Painter
|
||||
painter.ts 绘制原语接口(圆角矩形、圆、居中文字)
|
||||
theme.ts 配色
|
||||
progress.ts 存档(KeyValueStore 抽象,桶 mode:01-number-stroke)
|
||||
levels.ts 关卡包解析
|
||||
```
|
||||
|
||||
## 运行
|
||||
|
||||
```bash
|
||||
cd modes/01-number-stroke
|
||||
npm install
|
||||
npm run dev # 起本地服务 + 监听改动,终端会打印手机可访问的局域网地址
|
||||
npm run build # 打包到 web/dist/app.js,之后可直接双击 web/index.html
|
||||
npm run build:standalone # 导出项目根目录 releases/数字一笔-试玩版.html
|
||||
npm run check # 类型检查(含 src/ 无 DOM 校验)+ 单元测试 + 全关卡唯一解校验
|
||||
```
|
||||
|
||||
`?dev=1` 解锁全部关卡并暴露 `window.__numberStroke` 调试句柄(自动化手势测试用)。
|
||||
直接体验奇偶:`http://localhost:8000/?dev=1&level=3-1`。`level` 跳关参数仅在开发模式下生效;不清空已有存档。
|
||||
|
||||
**发给朋友测试**:运行 `npm run build:standalone`,发送生成的 [`数字一笔-试玩版.html`](../../releases/数字一笔-试玩版.html) 一个文件即可。脚本、样式、26 关数据与合成音效全部内置,无需安装或启动服务,可离线用浏览器打开。全部 26 关直接可选,无需解锁或添加参数;通关记录仍保存在试玩者的浏览器中。
|
||||
|
||||
关卡工具:
|
||||
|
||||
```bash
|
||||
npm run validate # 每关:连通、恰好 1 条满足线索的哈密顿路径
|
||||
npm run validate -- 1-7 # 只看某关,并打印解
|
||||
npm run design -- 1-7 --minimize # 当前线索里哪些可删
|
||||
npm run design -- 1-7 --suggest 3 --path a,b,c,... # 给作者解找最少线索
|
||||
npm run generate -- --seed 3 --out levels/pack-2-advanced.json # 随机铺盘+作者解+挑线索,批量产关
|
||||
```
|
||||
|
||||
选关页按包分区渲染,跨包线性解锁(2-1 需先过 1-10);`web/main.ts` 顶部的 `packs` 数组登记包文件,加新包时往数组里加 import 即可。
|
||||
|
||||
## 第一包 · 10 关
|
||||
|
||||
每关只加一个旋钮(GDD §7)。线索数已按 §4.6 收到教学所需的最少。
|
||||
|
||||
| 关 | N | 教什么 | 大格 | 线索 |
|
||||
|---|---|---|---|---|
|
||||
| 1-1 | 3 | 滑动,邻格自动出步号 | – | 1 |
|
||||
| 1-2 | 4 | 必须走完所有格 | – | 1, 4 |
|
||||
| 1-3 | 5 | 走错可以退(第一次死路) | – | 1, 3 |
|
||||
| 1-4 | 4 | 大格只算一步 | 2×2 | 1, 3 |
|
||||
| 1-5 | 7 | 中段线索 | – | 1, 4 |
|
||||
| 1-6 | 9 | 空洞:隔洞不相邻,先看终点再起手 | – | 1, 9 |
|
||||
| 1-7 | 12 | 先推再画:三处分叉各需一次推理 | – | 1, 4, 8 |
|
||||
| 1-8 | 11 | 2×2 当枢纽:6 个出口只能选远角 | 2×2 | 1, 8 |
|
||||
| 1-9 | 11 | 横长条:b 紧挨 1 却是第 6 步,只能从长条下边进上边出 | 2×1 | 1, 6 |
|
||||
| 1-10 | 14 | 小考:顶行直走只有 5 步,要借 2×2 垫一步;竖长条收尾 | 2×2 + 1×2 | 1, 6 |
|
||||
|
||||
GDD §7.1 的 12 关教学梯度压缩到 10 关:竖长条与“两个大格”并入 1-10;无线索 `1` 的关按 §7 留在第 13 关之后,本包不含。
|
||||
|
||||
## 第二包 · 10 关(进阶)
|
||||
|
||||
`tools/generate.ts` 自动生成(seed=43)+ 人工过目。面向已经会玩的人,三个设计原则(来自试玩反馈,已写进 GDD §4/§7/§8.2):
|
||||
|
||||
- **难度的主旋钮是相邻线索的步号差**。每关开局固定「线索 1 + 4~7 步内的引导线索」,玩家先有起手方向;难度靠后面的差距拉开(包内最大差从 8 升到 16)。
|
||||
- **大连块高频出现**:每关 2~3 个多单位格,`2×2` 在 7 关出现,`3×3` 在 2-2、2-4 出现。大连块只计 1 步但出口多,是推理的主战场。
|
||||
- **格子可以是俄罗斯方块式异形**(L/I/S/T,随机旋转镜像)。异形格占 2~4 个单位格、仍只计 1 步,凹口让邻接关系更不规则;渲染上拼块连成一整块(单位矩形 + 延展接缝),与 `2×2` 观感一致。
|
||||
|
||||
| 关 | N | 大连块与异形 | 空洞 | 线索 | 步号差 |
|
||||
|---|---|---|---|---|---|
|
||||
| 2-1 | 16 | 异形×2 + 2×2 | – | 1, 7, 14 | 6/7/2 |
|
||||
| 2-2 | 14 | **3×3** + 异形 | – | 1, 4, 12 | 3/8/2 |
|
||||
| 2-3 | 18 | 异形×2 | 1 | 1, 4, 8, 16 | 3/4/8/2 |
|
||||
| 2-4 | 15 | **3×3** | 1 | 1, 6, 15 | 5/9/0 |
|
||||
| 2-5 | 16 | 2×2×2 + 异形 | – | 1, 6, 15 | 5/9/1 |
|
||||
| 2-6 | 18 | 2×2×2 | 1 | 1, 4, 8 | 3/4/10 |
|
||||
| 2-7 | 21 | 2×2 + 条 | – | 1, 7, 17 | 6/10/4 |
|
||||
| 2-8 | 19 | 异形×2 | – | 3, 5, 15, 17 | 2/10/2/2 |
|
||||
| 2-9 | 21 | 2×2 + 条 | – | 1, 7, 20 | 6/13/1 |
|
||||
| 2-10 | 21 | 2×2 + 条 | – | 1, 5, 21 | 4/16/0 |
|
||||
|
||||
2-8 **无线索 1**(全游戏第一关):起点也要自己找。
|
||||
|
||||
每关 JSON 里的 `teach` 字段存了生成参数与作者解(剧透,永不渲染)。想换一批:`npm run generate -- --seed <新种子> --out levels/pack-2-advanced.json`,然后 `npm run check`。
|
||||
|
||||
## 第三包 · 6 关(奇与偶)
|
||||
|
||||
「奇」要求走到该格时的步数为 1、3、5…,「偶」要求 2、4、6…。整块仍只计一步,数字与奇偶条件要同时满足。走过后显示实际步号并保留奇偶标记;走错可撤回,提示也考虑奇偶要求。
|
||||
|
||||
| 关 | 格数 | 内容 |
|
||||
|---|---|---|
|
||||
| 3-1 | 4 | 「偶」入门,借 2×2 调整步数 |
|
||||
| 3-2 | 6 | 「奇」写在 3×3 上,整块只计一步 |
|
||||
| 3-3 | 11 | 用奇数条件决定绕行方向 |
|
||||
| 3-4 | 16 | 异形格上的「偶」+「奇」+数字线索 |
|
||||
| 3-5 | 18 | 双异形、奇偶与中段数字共同推理 |
|
||||
| 3-6 | 18 | 两个 2×2、两个「奇」,仅固定起点 1 |
|
||||
|
||||
3-2 为新盘,其余复用既有关卡的几何并重新设计线索(来源及作者解记在 `teach`)。每关唯一解;逐条删去任意奇偶条件都会出现多解,确保新规则有实际作用。此包先用于体验规则,难度手感仍待真人试玩。
|
||||
|
||||
关卡中写 `"parity": "odd"` / `"parity": "even"`,与同格 `clue` 互斥;可与 `shape` 或 `3×3` 共用。`npm run design -- 3-4 --minimize` 会同时检查数字和奇偶线索。现有随机生成器仍产出数字关,奇偶包采用人工配线索并用求解器筛选。
|
||||
|
||||
## 交互(已实现,对齐 GDD §5)
|
||||
|
||||
- 有线索 `1` 时只能从它起手,点别处 `1` 抖一下
|
||||
- 按住滑到相邻未走格追加;点按或滑到任意已走格,直接撤掉该格之后的路径,不松手就能换方向继续画
|
||||
- 松手保留路径;从末端按下继续;点末端旁的空格仍可追加;不相邻的空格忽略
|
||||
- 快速滑动在两帧之间插值采样,避免漏掉中间格;直接落到历史格时优先回退。触屏死区收至 8%,鼠标维持 14%;只跟踪一个指针
|
||||
- 踩错线索,或第 n 步走到预定数字 n 所在格以外的位置,立即让该格变红并轻晃,连接线保持紫色,不加叉号;本格要求不符时仍显示原数字 / 奇偶要求。原始数字与补出的数字都生效;退回后清除冲突。死路当前格抖动,不弹失败
|
||||
- 补数字:优先当前尚未解开的数字区间,1~9 补 5;每次只给一个确定数字,遵守原来的奇偶规则。重开保留补数,退出重进则恢复原关卡
|
||||
- 指路:无路径指起点;是解的前缀给下一步;已偏离则高亮分叉格并压暗错段,点高亮格即可直接回退
|
||||
- 过关:路径提亮、按步序扫光,约 0.9s 后自动下一关;最后一关回选关
|
||||
|
||||
## 移植到 Cocos Creator
|
||||
|
||||
技术选型就是为这一步做的:
|
||||
|
||||
1. **`src/` 原样拷进 `assets/modes/01-number-stroke/scripts/`。** 它用 `tsconfig.src.json`(`lib: ["ES2020"]`,无 DOM)编译通过;import 全部无后缀,符合 Cocos 模块规范(Cocos 不允许 `import './foo.ts'`)。
|
||||
2. **Painter 换实现。** `web/canvas-painter.ts` 对应一个 `GraphicsPainter`:`fillRoundRect/strokeRoundRect/fillCircle` 用 `Graphics`,`text` 用一组按需复用的 `Label` 节点。`BoardView.draw()` 不用改。Cocos 的 y 轴向上,在 Painter 里翻一次 y 即可。异形格不用新原语:`layout.cellShapeRects()` 把拼块拆成单位矩形 + 接缝矩形,复用同一套 `fillRoundRect`。
|
||||
3. **输入换事件源。** `Node.on(TOUCH_START/MOVE/END)` 把触点转成 Canvas 节点局部坐标 → `layout.hitTest()` → `PointerInput.down/move/up()`。插值采样那几行照搬 `web/main.ts`。
|
||||
4. **存档换 store。** `Progress` 接收 `KeyValueStore`,Cocos 用 `sys.localStorage` 包一层。
|
||||
5. **关卡 JSON 放 `resources/`**,`resources.load` 成 `JsonAsset` 后走同一个 `parsePack/loadPack`。
|
||||
6. **HUD / 选关是 UI 节点。** 对应 `web/index.html` 里那几个元素:顶栏(返回、关号、剩余格)、字幕、底栏(重开、补数字、指路)、选关网格。
|
||||
7. **音效**:`web/audio.ts` 是 WebAudio 合成;Cocos 用 `AudioSource` 播 4 段短音(step / conflict / cleared / reject),接口一致。
|
||||
8. 每帧:`view.update(dt)` 放 `update(dt)`,`view.draw(painter)` 在 `isAnimating` 为真时清空 Graphics 重画。
|
||||
|
||||
不搬进 Cocos 的东西:`web/`、`tools/`、`tests/`(测试可以继续在 Node 跑,它们只依赖 `src/`)。
|
||||
Reference in New Issue
Block a user