fix: 修复 Codex review 的 5 项问题 + 3 项 open questions
01-charter: 去金币矛盾、JSON→JS module、更新下一步
02-game-design: 道具状态机重设计(仅操作槽位)、去金币改道具奖励、
MVP 跳过洲选择页直入城市、物件数统一为3倍数、新增存档模型
03-content-pipeline: 猫猫路径统一 cat_{city_id}.png、
新增难度生成器系统设计(overlap graph/seed/solver/死局检测)、
新增元素配比规则(5 类目各 ≥2)、piecesPerElement 约束强化
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -100,7 +100,7 @@
|
|||||||
| 图鉴系统 | 1 套基础城市护照/图鉴系统 | 城市解锁进度、猫猫收集、护照盖章 |
|
| 图鉴系统 | 1 套基础城市护照/图鉴系统 | 城市解锁进度、猫猫收集、护照盖章 |
|
||||||
| 每日挑战 | 1 套每日挑战 | 每日 1 关限时挑战,提供日常活跃目标 |
|
| 每日挑战 | 1 套每日挑战 | 每日 1 关限时挑战,提供日常活跃目标 |
|
||||||
| 分享系统 | 1 套基础分享明信片 | 城市通关/猫猫收集成果分享卡片 |
|
| 分享系统 | 1 套基础分享明信片 | 城市通关/猫猫收集成果分享卡片 |
|
||||||
| 激励视频广告 | 复活、重排、道具、奖励翻倍 | 核心变现手段 |
|
| 激励视频广告 | 复活、重排、道具、额外道具奖励 | 核心变现手段 |
|
||||||
| 插屏广告 | 局后展示 | 严格控频(每 3 局最多 1 次,单日上限 5 次) |
|
| 插屏广告 | 局后展示 | 严格控频(每 3 局最多 1 次,单日上限 5 次) |
|
||||||
|
|
||||||
### 8.2 不进入 MVP
|
### 8.2 不进入 MVP
|
||||||
@@ -120,7 +120,7 @@
|
|||||||
|
|
||||||
| 壁垒 | 说明 |
|
| 壁垒 | 说明 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| 城市内容系统 | 城市元素、标签、图鉴、封面、猫猫资产统一配置化(JSON 驱动),新增城市只需配置 + 资源,不改代码 |
|
| 城市内容系统 | 城市元素、标签、图鉴、封面、猫猫资产统一配置化(JS module 配置化驱动),新增城市只需配置 + 资源,不改代码 |
|
||||||
| 可控难度生成器 | 控制遮挡层级、解法数、失败率、难度曲线;支持按城市/关卡精调,保证通关率在目标区间 |
|
| 可控难度生成器 | 控制遮挡层级、解法数、失败率、难度曲线;支持按城市/关卡精调,保证通关率在目标区间 |
|
||||||
| 资源分包策略 | 按洲/城市内容包加载,首包只含核心代码 + 首城资源;后续城市按需下载,保证首包 < 4 MB |
|
| 资源分包策略 | 按洲/城市内容包加载,首包只含核心代码 + 首城资源;后续城市按需下载,保证首包 < 4 MB |
|
||||||
| 纯 Canvas 2D 手写框架 | 不用引擎(Cocos/Laya),首包预算约 2.5 MB;自研轻量渲染/事件/动画/资源管理模块 |
|
| 纯 Canvas 2D 手写框架 | 不用引擎(Cocos/Laya),首包预算约 2.5 MB;自研轻量渲染/事件/动画/资源管理模块 |
|
||||||
@@ -138,7 +138,7 @@
|
|||||||
|
|
||||||
| 变现方式 | 触发场景 | 预估收入占比 | 阶段 |
|
| 变现方式 | 触发场景 | 预估收入占比 | 阶段 |
|
||||||
|---------|---------|-------------|------|
|
|---------|---------|-------------|------|
|
||||||
| 激励视频 | 复活(通关失败时)、重排(牌面无解时)、获取道具、额外奖励翻倍 | 55-65% | MVP 起 |
|
| 激励视频 | 复活(通关失败时)、重排(牌面无解时)、获取道具、额外道具奖励 | 55-65% | MVP 起 |
|
||||||
| 插屏广告 | 局后结算页、城市解锁节点 | 15-20% | MVP 起 |
|
| 插屏广告 | 局后结算页、城市解锁节点 | 15-20% | MVP 起 |
|
||||||
| 去广告月卡 | 12-18 元/月,免除所有强制广告 | 10-15% | V1.1+ |
|
| 去广告月卡 | 12-18 元/月,免除所有强制广告 | 10-15% | V1.1+ |
|
||||||
| 猫猫装扮 | 猫猫皮肤/配饰付费解锁 | 3-5% | V1.1+ |
|
| 猫猫装扮 | 猫猫皮肤/配饰付费解锁 | 3-5% | V1.1+ |
|
||||||
@@ -188,7 +188,7 @@
|
|||||||
|
|
||||||
| 产出物 | 文件 | 内容要点 |
|
| 产出物 | 文件 | 内容要点 |
|
||||||
|--------|------|---------|
|
|--------|------|---------|
|
||||||
| 核心玩法与系统设计 | `02-game-design.md` | 堆叠三消规则、槽位机制、道具设计、地图结构、图鉴系统、每日挑战规则 |
|
| 道具状态机设计 | `02-game-design.md` 补充 | 道具类型、触发条件、状态流转、与激励视频的关联 |
|
||||||
| 内容生产流水线 | `03-content-pipeline.md` | 城市数据结构(JSON schema)、素材规范(尺寸/格式/命名)、AI 生成 prompt 模板、人工修正 checklist |
|
| 存档模型 | `02-game-design.md` 补充 | playerState schema:城市解锁进度、图鉴收集、道具库存、每日挑战记录 |
|
||||||
| MVP 城市清单 | 同上或独立文档 | 6 城市元素清单(每城 12-15 个)、猫猫设计参数、封面/图鉴配置 |
|
| 难度生成器系统设计 | 独立文档或 `02-game-design.md` 补充 | 遮挡层级算法、解法数控制、失败率目标、按城市/关卡精调参数 |
|
||||||
| 核心玩法原型 | 代码原型 | 关卡生成规则草案、难度参数定义、核心交互 demo |
|
| 锁定 5 项待决策 | `01-project-charter.md` §12 | 消除机制、首页层级、首批城市、美术风格、素材生产方式 |
|
||||||
|
|||||||
@@ -22,11 +22,45 @@
|
|||||||
|
|
||||||
### 1.3 道具系统(MVP)
|
### 1.3 道具系统(MVP)
|
||||||
|
|
||||||
|
道具只操作暂存槽,不操作场景物件,避免恢复堆叠遮挡的复杂度。
|
||||||
|
|
||||||
| 道具 | 效果 | 免费额度 | 额外使用 |
|
| 道具 | 效果 | 免费额度 | 额外使用 |
|
||||||
|------|------|---------|---------|
|
|------|------|---------|---------|
|
||||||
| 重排 Shuffle | 重新打乱场景中剩余物件的堆叠顺序 | 每局 1 次 | 激励视频 |
|
| 撤回 Undo | 将暂存槽最后放入的 1 个物件移回场景顶层(不恢复原位,放到顶层空闲位置) | 每局 3 次 | 激励视频 |
|
||||||
| 撤回 Undo | 撤回最后拾取的 3 个物件放回场景原位 | 每局 1 次 | 激励视频 |
|
| 移出 Remove | 将暂存槽中 3 个物件移到旁路寄存区(1 格),下次有任意消除发生时自动回归暂存槽 | 每局 1 次 | 激励视频 |
|
||||||
| 移出 Remove | 从暂存槽移出 3 个不同物件放到临时区(下次消除后回归暂存槽) | 每局 1 次 | 激励视频 |
|
| 洗牌 Shuffle | 重新随机排列场景中所有剩余物件的位置和层级 | 每局 1 次 | 激励视频 |
|
||||||
|
|
||||||
|
**道具状态转移表:**
|
||||||
|
|
||||||
|
```
|
||||||
|
暂存槽状态:[A][B][C][D][E][F][G] (7 格)
|
||||||
|
旁路寄存区:[X][Y][Z] (3 格,仅 Remove 道具使用)
|
||||||
|
|
||||||
|
── Undo ──
|
||||||
|
前置:暂存槽非空
|
||||||
|
操作:取暂存槽末位 1 个物件 → 放回场景顶层可见位置
|
||||||
|
后置:暂存槽空出 1 格
|
||||||
|
特殊:如果暂存槽为空则道具不可用(置灰)
|
||||||
|
|
||||||
|
── Remove ──
|
||||||
|
前置:暂存槽已用 ≥ 3 格 且 旁路寄存区为空
|
||||||
|
操作:取暂存槽中 3 个不同类型的物件 → 移入旁路寄存区
|
||||||
|
后置:暂存槽空出 3 格
|
||||||
|
回归条件:场景中发生任意一次三消 → 旁路寄存区物件自动回归暂存槽
|
||||||
|
回归溢出:如果回归时暂存槽已满 7 格 → 先回归再判定失败(即回归物件 + 当前槽位 > 7 则游戏失败)
|
||||||
|
限制:旁路寄存区非空时不可再次使用 Remove
|
||||||
|
|
||||||
|
── Shuffle ──
|
||||||
|
前置:场景中剩余物件 > 0
|
||||||
|
操作:所有场景物件重新随机分配位置和层级
|
||||||
|
后置:物件总数和种类不变,堆叠关系重新生成
|
||||||
|
特殊:Shuffle 后需保证至少 30% 物件可点击(同关卡生成约束)
|
||||||
|
```
|
||||||
|
|
||||||
|
**道具交互约束:**
|
||||||
|
- Undo 和 Remove 互斥使用:旁路寄存区非空时 Undo 不可用(避免回归顺序混乱)
|
||||||
|
- Shuffle 与其他道具无冲突
|
||||||
|
- 复活(激励视频):清空暂存槽 + 清空旁路寄存区,场景状态不变,继续游戏
|
||||||
|
|
||||||
### 1.4 操作交互
|
### 1.4 操作交互
|
||||||
|
|
||||||
@@ -44,16 +78,19 @@
|
|||||||
### 2.1 导航层级(MVP 简化为二级)
|
### 2.1 导航层级(MVP 简化为二级)
|
||||||
|
|
||||||
```
|
```
|
||||||
主页面:洲选择(3x3 棋盘)
|
MVP 首版:直接进入亚洲城市页(跳过洲选择页)
|
||||||
└── 洲内页面:城市选择(3x3 棋盘)
|
城市选择(3x3 棋盘) → 城市关卡(单局游戏)
|
||||||
└── 城市关卡(单局游戏)
|
|
||||||
|
V1.1 扩展第二个洲后:
|
||||||
|
洲选择(3x3 棋盘) → 城市选择(3x3 棋盘) → 城市关卡
|
||||||
```
|
```
|
||||||
|
|
||||||
|
预留洲选择页的代码入口但 MVP 不显示。
|
||||||
|
|
||||||
### 2.2 主页面设计
|
### 2.2 主页面设计
|
||||||
|
|
||||||
- 3x3 棋盘布局,每格代表一个洲
|
- MVP 直接显示亚洲城市 3x3 棋盘,顶部标题"亚洲"
|
||||||
- MVP 只开放 1 个洲(亚洲),其余锁定显示"即将开放"
|
- V1.1 扩展第二个洲后再开启洲选择页
|
||||||
- 洲封面:标志性元素 + 解锁进度(如"3/9 城市已解锁")
|
|
||||||
|
|
||||||
### 2.3 洲内页面设计
|
### 2.3 洲内页面设计
|
||||||
|
|
||||||
@@ -68,7 +105,7 @@
|
|||||||
每个城市包含 **6 个基础关卡**,全部通关才算"通关该城市"。
|
每个城市包含 **6 个基础关卡**,全部通关才算"通关该城市"。
|
||||||
|
|
||||||
- 每关使用该城市 12-15 个特色元素中的 8-12 个
|
- 每关使用该城市 12-15 个特色元素中的 8-12 个
|
||||||
- 难度递增:关 1 用 6 种元素各 3 个,关 6 用 10 种元素各 3-4 个 + 更深堆叠
|
- 难度递增:关 1 用 6 种元素各 3 个,关 6 用 10 种元素,各 3 或 6 个(混合配置) + 更深堆叠
|
||||||
- 通关后获得该城市的猫猫收集卡
|
- 通关后获得该城市的猫猫收集卡
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -128,7 +165,7 @@
|
|||||||
|------|------|
|
|------|------|
|
||||||
| 内容 | 每天 1 个随机城市的特殊关卡 |
|
| 内容 | 每天 1 个随机城市的特殊关卡 |
|
||||||
| 难度 | 比普通关卡略高(更多物件种类、更深堆叠) |
|
| 难度 | 比普通关卡略高(更多物件种类、更深堆叠) |
|
||||||
| 奖励 | 金币(用于未来 IAP 系统)+ 特殊明信片 |
|
| 奖励 | 道具补给(Undo ×2)+ 特殊明信片 |
|
||||||
| 生成方式 | 程序化生成(基于难度参数随机组合) |
|
| 生成方式 | 程序化生成(基于难度参数随机组合) |
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -151,9 +188,9 @@
|
|||||||
|
|
||||||
| 触发点 | 分享内容 | 奖励 |
|
| 触发点 | 分享内容 | 奖励 |
|
||||||
|--------|---------|------|
|
|--------|---------|------|
|
||||||
| 通关城市 | 城市猫猫卡片 + "我解锁了XX猫!" | 金币 |
|
| 通关城市 | 城市猫猫卡片 + "我解锁了XX猫!" | 道具补给(Undo ×1) |
|
||||||
| 护照盖章 | 护照截图 + 收集进度 | 道具 |
|
| 护照盖章 | 护照截图 + 收集进度 | 道具补给(Shuffle ×1) |
|
||||||
| 每日挑战通关 | 挑战结果卡片 | 金币 |
|
| 每日挑战通关 | 挑战结果卡片 | 道具补给(Undo ×2) |
|
||||||
| 图鉴里程碑 | "已收集X只猫猫" | 特殊明信片 |
|
| 图鉴里程碑 | "已收集X只猫猫" | 特殊明信片 |
|
||||||
|
|
||||||
分享卡片设计:猫猫形象 + 城市背景色 + 进度信息 + 小程序入口按钮。
|
分享卡片设计:猫猫形象 + 城市背景色 + 进度信息 + 小程序入口按钮。
|
||||||
@@ -191,3 +228,80 @@
|
|||||||
| 城市 2-3 | 平滑上升 | 物件种类增加,层级不变 |
|
| 城市 2-3 | 平滑上升 | 物件种类增加,层级不变 |
|
||||||
| 城市 4-5 | 进阶挑战 | 引入更高层级 + 更多种类 |
|
| 城市 4-5 | 进阶挑战 | 引入更高层级 + 更多种类 |
|
||||||
| 城市 6 | 挑战级 | 最大物件数 + 最深堆叠 |
|
| 城市 6 | 挑战级 | 最大物件数 + 最深堆叠 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 玩家存档模型
|
||||||
|
|
||||||
|
所有玩家数据持久化到 `wx.Storage`,key 为 `player_state`。
|
||||||
|
|
||||||
|
### 9.1 存档 Schema
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const playerState = {
|
||||||
|
// 版本控制(存档迁移用)
|
||||||
|
saveVersion: 1,
|
||||||
|
|
||||||
|
// 城市进度
|
||||||
|
unlockedCities: ['beijing'], // 已解锁城市 id 列表
|
||||||
|
levelProgress: {
|
||||||
|
// city_id: { levelId: { stars: 0-3, completed: bool, bestMoves: number } }
|
||||||
|
beijing: {
|
||||||
|
1: { stars: 3, completed: true },
|
||||||
|
2: { stars: 2, completed: true },
|
||||||
|
// ...
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// 收集
|
||||||
|
collectedCats: ['beijing'], // 已收集猫猫的城市 id
|
||||||
|
passportStamps: ['beijing'], // 已盖章城市 id
|
||||||
|
|
||||||
|
// 道具库存
|
||||||
|
inventory: {
|
||||||
|
undo: 3, // 撤回次数
|
||||||
|
remove: 1, // 移出次数
|
||||||
|
shuffle: 1, // 洗牌次数
|
||||||
|
},
|
||||||
|
|
||||||
|
// 每日挑战
|
||||||
|
dailyChallenge: {
|
||||||
|
date: '2026-03-28', // 上次挑战日期(YYYY-MM-DD)
|
||||||
|
completed: false,
|
||||||
|
cityId: 'tokyo', // 今日挑战城市
|
||||||
|
seed: 12345, // 关卡生成种子
|
||||||
|
},
|
||||||
|
|
||||||
|
// 广告冷却
|
||||||
|
adCooldowns: {
|
||||||
|
interstitialCount: 0, // 今日插屏已展示次数
|
||||||
|
lastInterstitialTime: 0, // 上次插屏时间戳
|
||||||
|
lastRewardDate: '2026-03-28', // 上次激励视频日期
|
||||||
|
},
|
||||||
|
|
||||||
|
// 设置
|
||||||
|
settings: {
|
||||||
|
soundEnabled: true,
|
||||||
|
musicEnabled: true,
|
||||||
|
vibrationEnabled: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
// 统计
|
||||||
|
stats: {
|
||||||
|
totalGamesPlayed: 0,
|
||||||
|
totalGamesWon: 0,
|
||||||
|
totalShareCount: 0,
|
||||||
|
firstPlayDate: '2026-03-28',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 9.2 存档读写规则
|
||||||
|
|
||||||
|
| 规则 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| 读取时机 | 游戏启动时读取一次,缓存在内存 |
|
||||||
|
| 写入时机 | 关卡通关/失败、道具使用、城市解锁、设置变更时写入 |
|
||||||
|
| 写入方式 | `wx.setStorageSync('player_state', state)` 同步写入 |
|
||||||
|
| 版本迁移 | 读取时检查 `saveVersion`,低于当前版本则执行迁移函数 |
|
||||||
|
| 数据上限 | wx.Storage 上限 10MB,预估存档 < 50KB |
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ module.exports = {
|
|||||||
continent: 'asia',
|
continent: 'asia',
|
||||||
// 地图封面
|
// 地图封面
|
||||||
cover: {
|
cover: {
|
||||||
catImage: 'images/cats/beijing.png', // 猫猫头像
|
catImage: 'images/cats/cat_beijing.png', // 猫猫头像
|
||||||
bgColor: '#CC2936', // 城市主色调
|
bgColor: '#CC2936', // 城市主色调
|
||||||
},
|
},
|
||||||
// 城市文化信息
|
// 城市文化信息
|
||||||
@@ -57,7 +57,7 @@ module.exports = {
|
|||||||
| `elements[].name` | string | Y | 元素中文名 |
|
| `elements[].name` | string | Y | 元素中文名 |
|
||||||
| `elements[].category` | string | Y | 分类:`food` / `culture` / `landmark` / `nature` / `item` |
|
| `elements[].category` | string | Y | 分类:`food` / `culture` / `landmark` / `nature` / `item` |
|
||||||
| `elements[].image` | string | Y | 图片路径(相对于资源根目录) |
|
| `elements[].image` | string | Y | 图片路径(相对于资源根目录) |
|
||||||
| `levels[].piecesPerElement` | number\|number[] | Y | 3 的倍数;数组时长度须等于 `elementCount` |
|
| `levels[].piecesPerElement` | number\|number[] | Y | 3 的倍数;数组时长度须等于 `elementCount`,每个值必须是 3 的倍数 |
|
||||||
|
|
||||||
### 1.2 洲索引配置
|
### 1.2 洲索引配置
|
||||||
|
|
||||||
@@ -167,31 +167,111 @@ module.exports = {
|
|||||||
|
|
||||||
**难度递进规律:** 关 1-2 低密度入门 -> 关 3-4 中密度爬坡 -> 关 5-6 高密度挑战。关 6 允许 `piecesPerElement` 为数组,制造不均匀分布的额外难度。
|
**难度递进规律:** 关 1-2 低密度入门 -> 关 3-4 中密度爬坡 -> 关 5-6 高密度挑战。关 6 允许 `piecesPerElement` 为数组,制造不均匀分布的额外难度。
|
||||||
|
|
||||||
### 4.2 关卡布局生成
|
### 4.2 布局生成器系统设计
|
||||||
|
|
||||||
不手工摆放物件位置,用程序化生成器:
|
#### 核心概念
|
||||||
|
|
||||||
- **输入:** 难度参数 + 城市元素列表
|
**Overlap Graph(遮挡图)**:
|
||||||
- **输出:** 每个物件的 `{ elementId, x, y, layer, rotation }`
|
- 每个物件是一个节点,如果物件 A 遮挡物件 B,则有一条有向边 A → B
|
||||||
- **生成约束:**
|
- 物件可点击的条件:入度为 0(没有任何物件遮挡它)
|
||||||
- 每层物件不超过总数的 40%
|
- 遮挡判定:两个物件的包围盒重叠面积 > 阈值(物件面积的 20%)且 A.layer > B.layer
|
||||||
- 最底层至少有 30% 的物件初始可点击
|
|
||||||
- 保证可解性(从目标状态反向推导)
|
|
||||||
|
|
||||||
### 4.3 难度验证
|
**Dead-end(死局)定义**:
|
||||||
|
- 所有可点击物件放入暂存槽后无法触发任何三消,且暂存槽已满 7 格
|
||||||
|
- 等价条件:当前可点击物件集合中,没有任何 3 个同类物件
|
||||||
|
|
||||||
用脚本模拟 1000 次随机合理操作,验证通关率:
|
#### 生成算法(反向法)
|
||||||
|
|
||||||
| 关卡 | 目标通关率 |
|
```
|
||||||
|------|-----------|
|
输入:difficulty = { elementCount, piecesPerElement, layers, density }
|
||||||
| 关 1 | > 95% |
|
输出:pieces[] = [{ elementId, x, y, layer }]
|
||||||
| 关 2 | > 90% |
|
|
||||||
| 关 3 | > 80% |
|
|
||||||
| 关 4 | > 70% |
|
|
||||||
| 关 5 | > 60% |
|
|
||||||
| 关 6 | 50-60% |
|
|
||||||
|
|
||||||
失败率过高时降低 `density` 或 `layers`。
|
步骤:
|
||||||
|
1. 创建物件池:按 elementCount × piecesPerElement 生成全部物件
|
||||||
|
2. 定义画布区域:根据 layers 划分 Z 层,每层定义可用网格
|
||||||
|
3. 正向放置:
|
||||||
|
a. 从最底层(layer=0)开始,逐层往上放置物件
|
||||||
|
b. 每层放置数量 = 总数 × layerDistribution[layer]
|
||||||
|
- density='low': [0.4, 0.3, 0.2, 0.1]
|
||||||
|
- density='medium': [0.3, 0.3, 0.25, 0.15]
|
||||||
|
- density='high': [0.25, 0.25, 0.25, 0.25]
|
||||||
|
c. 在层内随机放置,确保相邻物件有 overlap(按 density 控制重叠率)
|
||||||
|
4. 构建 overlap graph
|
||||||
|
5. 可点击性校验:初始可点击物件占比 ≥ 30%(入度为 0 的节点数 / 总节点数)
|
||||||
|
6. 可解性验证(见 4.3)
|
||||||
|
7. 不通过则重新生成(最多重试 50 次)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Seed(种子)
|
||||||
|
|
||||||
|
- 每个关卡实例由 `seed: number` 唯一确定
|
||||||
|
- 正式关卡:`seed = hash(cityId + levelId + attemptCount)`
|
||||||
|
- 每日挑战:`seed = hash(dateString + 'daily')`
|
||||||
|
- 同一 seed 保证生成完全相同的布局(可复现、可分享、可验证)
|
||||||
|
|
||||||
|
#### 可点击判定规则
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
function isClickable(piece, allPieces) {
|
||||||
|
// 同层或更高层的物件中,是否有包围盒重叠超过阈值的
|
||||||
|
for (const other of allPieces) {
|
||||||
|
if (other === piece || other.removed) continue
|
||||||
|
if (other.layer <= piece.layer) continue
|
||||||
|
if (overlapArea(piece, other) > piece.area * 0.2) {
|
||||||
|
return false // 被遮挡
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.3 Solver / 可解性验证
|
||||||
|
|
||||||
|
#### Solver 算法(贪心模拟)
|
||||||
|
|
||||||
|
```
|
||||||
|
输入:pieces[](布局), maxSimulations=1000
|
||||||
|
输出:{ solvable: bool, avgMoves: number, passRate: number }
|
||||||
|
|
||||||
|
每次模拟:
|
||||||
|
1. 初始化暂存槽 slot[7],旁路寄存区 bypass[3]
|
||||||
|
2. 循环直到场景清空或暂存槽满:
|
||||||
|
a. 获取所有可点击物件(overlap graph 入度=0)
|
||||||
|
b. 优先策略:
|
||||||
|
- 优先选择能在暂存槽中凑成三消的物件
|
||||||
|
- 其次选择暂存槽中已有 1-2 个同类的物件
|
||||||
|
- 最后随机选择
|
||||||
|
c. 放入暂存槽,触发三消判定
|
||||||
|
d. 如果暂存槽满且无法消除 → 失败
|
||||||
|
3. 场景清空 → 成功
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 验证标准
|
||||||
|
|
||||||
|
| 关卡 | 目标通关率 | 不达标处理 |
|
||||||
|
|------|-----------|-----------|
|
||||||
|
| 关 1 | > 95% | 降低 layers 或 density |
|
||||||
|
| 关 2 | > 90% | 同上 |
|
||||||
|
| 关 3 | > 80% | 减少 elementCount |
|
||||||
|
| 关 4 | > 70% | 调整 layerDistribution |
|
||||||
|
| 关 5 | > 60% | 同上 |
|
||||||
|
| 关 6 | 50-60% | 在此区间即合格 |
|
||||||
|
|
||||||
|
#### 死局检测
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
function isDeadEnd(slot, clickablePieces) {
|
||||||
|
if (slot.length < 7) return false // 槽未满,还能操作
|
||||||
|
// 检查可点击物件中是否有能和槽中物件凑成三消的
|
||||||
|
for (const piece of clickablePieces) {
|
||||||
|
const sameInSlot = slot.filter(s => s.elementId === piece.elementId).length
|
||||||
|
if (sameInSlot >= 2) return false // 放入后可凑三消
|
||||||
|
}
|
||||||
|
return true // 真死局
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
注意:死局 ≠ 游戏失败。玩家可以使用 Undo/Remove/Shuffle 道具脱困。只有道具用尽且死局时才判定失败。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -203,7 +283,7 @@ module.exports = {
|
|||||||
主包(<= 4MB):
|
主包(<= 4MB):
|
||||||
├── game.js + js/(核心框架、渲染引擎、游戏逻辑) ~150KB
|
├── game.js + js/(核心框架、渲染引擎、游戏逻辑) ~150KB
|
||||||
├── images/ui/(通用 UI 元素、按钮、图标) ~300KB
|
├── images/ui/(通用 UI 元素、按钮、图标) ~300KB
|
||||||
├── images/cats/beijing.png(首个城市猫猫头像) ~50KB
|
├── images/cats/cat_beijing.png(首个城市猫猫头像) ~50KB
|
||||||
├── audio/(通用音效,6-8 个) ~300KB
|
├── audio/(通用音效,6-8 个) ~300KB
|
||||||
├── cities/beijing.js(首个城市数据配置) ~5KB
|
├── cities/beijing.js(首个城市数据配置) ~5KB
|
||||||
└── images/elements/beijing/(首个城市元素图标) ~200KB
|
└── images/elements/beijing/(首个城市元素图标) ~200KB
|
||||||
@@ -214,7 +294,7 @@ module.exports = {
|
|||||||
└── sub-asia/
|
└── sub-asia/
|
||||||
├── cities/tokyo.js + bangkok.js + ...
|
├── cities/tokyo.js + bangkok.js + ...
|
||||||
├── images/elements/tokyo/ + bangkok/ + ...
|
├── images/elements/tokyo/ + bangkok/ + ...
|
||||||
└── images/cats/tokyo.png + bangkok.png + ...
|
└── images/cats/cat_tokyo.png + cat_bangkok.png + ...
|
||||||
```
|
```
|
||||||
|
|
||||||
### 5.2 首包预算分配
|
### 5.2 首包预算分配
|
||||||
@@ -237,7 +317,21 @@ module.exports = {
|
|||||||
|
|
||||||
## 6. MVP 城市清单与素材计划
|
## 6. MVP 城市清单与素材计划
|
||||||
|
|
||||||
### 6.1 首批 6 城市
|
### 6.1 元素选取配比规则
|
||||||
|
|
||||||
|
每个城市的 12-15 个特色元素必须覆盖以下 5 个类目,每类至少 2 个:
|
||||||
|
|
||||||
|
| 类目 | category 值 | 最少数量 | 示例 |
|
||||||
|
|------|------------|---------|------|
|
||||||
|
| 地标建筑 | landmark | 2 | 天安门、鸟巢 |
|
||||||
|
| 美食饮品 | food | 3 | 糖葫芦、烤鸭、豆汁 |
|
||||||
|
| 文化符号 | culture | 2 | 京剧脸谱、兔儿爷 |
|
||||||
|
| 交通器物 | item | 2 | 铜锣、毛笔 |
|
||||||
|
| 动植物/自然 | nature | 2 | — |
|
||||||
|
|
||||||
|
剩余 1-4 个名额自由分配。此规则确保每个城市的元素视觉多样性和辨识度。
|
||||||
|
|
||||||
|
### 6.2 首批 6 城市
|
||||||
|
|
||||||
| 城市 | 元素主题方向 | 猫猫特色 |
|
| 城市 | 元素主题方向 | 猫猫特色 |
|
||||||
|------|------------|---------|
|
|------|------------|---------|
|
||||||
@@ -248,7 +342,7 @@ module.exports = {
|
|||||||
| 新加坡 | 鱼尾狮、辣椒螃蟹、榴莲建筑、叻沙、金沙酒店、兰花、肉骨茶、冰激凌三明治、组屋、咖椰吐司 | 花猫 + 小狮子鬃毛 |
|
| 新加坡 | 鱼尾狮、辣椒螃蟹、榴莲建筑、叻沙、金沙酒店、兰花、肉骨茶、冰激凌三明治、组屋、咖椰吐司 | 花猫 + 小狮子鬃毛 |
|
||||||
| 伊斯坦布尔 | 土耳其红茶、蓝色清真寺、热气球、烤肉串、郁金香、恶魔之眼、土耳其冰淇淋、地毯、石榴、旋转舞裙 | 安哥拉猫 + 恶魔之眼项圈 |
|
| 伊斯坦布尔 | 土耳其红茶、蓝色清真寺、热气球、烤肉串、郁金香、恶魔之眼、土耳其冰淇淋、地毯、石榴、旋转舞裙 | 安哥拉猫 + 恶魔之眼项圈 |
|
||||||
|
|
||||||
### 6.2 生产时间估算(单城市)
|
### 6.3 生产时间估算(单城市)
|
||||||
|
|
||||||
| 步骤 | 耗时 | 说明 |
|
| 步骤 | 耗时 | 说明 |
|
||||||
|------|------|------|
|
|------|------|------|
|
||||||
|
|||||||
Reference in New Issue
Block a user