# SortilegeCrazeApp **Repository Path**: BestRivenLG/sortilege-craze-app ## Basic Information - **Project Name**: SortilegeCrazeApp - **Description**: SortilegeCrazeApp - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-11-21 - **Last Updated**: 2025-12-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 魔法杂货铺 (Sortilege Craze) ## 详细需求文档 ### 1. 核心体验 1. 启动应用首先弹出广告/隐私授权弹窗,用户点击“继续”后进入主界面。 2. 主界面进入关卡选择,共 6 章 × 10 关,按星星数量解锁章节。 3. 关卡 HUD 包含:关卡编号、当前星星、倒计时、目标进度、金币、连击能量槽以及道具按钮(LV3/LV6 锁标记)。 4. 玩家通过点击或拖拽彩色球到货位。单个货位为堆栈队列,仅前 3 个球可见,其余带遮挡透明度(100%/70%/40%)。 5. 当同一货位前 3 个球颜色一致,立即触发三消、加分并推进后方球。倒计时内完成目标则胜利,否则失败。 ### 2. 货位与堆栈规则 - `presetQueue`:每个货位在关卡加载前即生成完整序列,游戏过程中不会再随机,确保可复现性。 - 插入模式:`front`(新球进队首)与 `hidden`(预设序列中包含后排球,实际游戏不再调整)。 - 可见槽位固定为 3,超出部分继续存在队列中直至向前推进。 - 章节最低空槽:章1-2 ≥3、章3-4 ≥4、章5-6 ≥5。生成关卡时需满足 `capacity - totalItems ≥ minEmptySlots`。 - `reservedSlots` 支持 `permanent-empty`(全程空)与 `capacity-1`(最多放 capacity-1 个),生成器需保证约束生效。 ### 3. 得分与连击 - 基础分:每组三消 100 分;若为目标颜色额外 +20%。 - 连击:首次消除进入 1 连击并触发 3 秒倒计时;倒计时内再次消除则连击 +1 并刷新倒计时,超时未消除重置为 0。 - 加成:得分 = 基础分 × `min(1.8, 1 + 0.2 × (combo - 1))`。 - 连击能量:达到 5 连击获得 1 点,集满 3 点触发 2 秒时间冻结。 - 附加奖励:剩余时间每 10 秒 +10 分;完美整理(无道具且无失误)+300 分 +20 金币。 ### 4. 失败与补偿 - 失败条件:倒计时结束未完成目标,或所有货位满且无法移动。 - 失败弹窗提供提示,并允许使用金币或观看广告继续(恢复 50% 剩余时间并保留布局)。 ### 5. 道具与系统 | 道具 | 解锁 | 效果 | | --- | --- | --- | | 魔法重排 | LV3 | 打乱当前所有可见球(隐藏序列不变) | | 时间冻结 | LV6 | 暂停倒计时 5 秒 | | 障碍清除 | 章3 起 | 移除指定障碍或🟢球 | #### 内购与背景机制 - 金币来源:关卡奖励、每日挑战、**内购金币包**。内购商品 ID 参考 `com.sortilegecraze.coins_xxx` 配置,使用 StoreKit 2 拉取并完成交易后立即增加金币余额。 - 金币消耗: 1. 背景商店(普通 300、稀有 800、史诗 1500),购买后永久解锁。 2. 其他可扩展用途(如道具补充)。 - 背景更换:玩家在背景商店中选择“使用”按钮 → 立即更新全局背景主题,影响所有界面和关卡;已购背景可随时切换且不再消耗金币。 - 数据持久化:金币余额、已购背景、当前背景、内购收据等由 `GameState`/`GameSession` 管理并存入 UserDefaults。 ### 6. 关卡生成字段 ```jsonc { "levelId": 19, "chapter": 2, "grid": {"rows": 3, "cols": 4}, "slotCount": 12, "capacity": 36, "minEmptySlots": 3, "reservedSlots": [ {"slotId": "R1C4", "type": "capacity-1"}, {"slotId": "R3C1", "type": "permanent-empty"} ], "targets": [ {"color": "🟡", "count": 9}, {"color": "🔵", "count": 6} ], "timeLimit": 540, "powerupsAvailable": {"shuffle": 1, "freeze": 0, "clear": 0}, "specialRules": ["hiddenSlots"], "slots": [ {"slotId": "R1C1", "capacity": 3, "insertMode": "front", "presetQueue": ["🔴", "🟡", "🔵"]}, {"slotId": "R1C2", "capacity": 3, "insertMode": "hidden", "presetQueue": ["🟡", "🟢", "🔵"]} ], "totalItems": 27 } ``` ### 7. 关卡网格与物品表 | 章 | 关 | 网格 (行×列) | 货位数 | 可容纳物品数 | 实际物品数 | 最低空槽 | | --- | --- | --- | --- | --- | --- | --- | | 1 | 1 | 2×2 | 4 | 12 | 12 | 3 | | 1 | 2 | 3×2 | 6 | 18 | 15 | 3 | | 1 | 3 | 3×2 | 6 | 18 | 15 | 3 | | 1 | 4 | 3×3 | 9 | 27 | 18 | 3 | | 1 | 5 | 3×3 | 9 | 27 | 18 | 3 | | 1 | 6 | 3×3 | 9 | 27 | 18 | 3 | | 1 | 7 | 4×2 | 8 | 24 | 21 | 3 | | 1 | 8 | 4×2 | 8 | 24 | 21 | 3 | | 1 | 9 | 4×3 | 12 | 36 | 24 | 3 | | 1 | 10 | 4×3 | 12 | 36 | 24 | 3 | | 2 | 11 | 3×2 | 6 | 18 | 18 | 3 | | 2 | 12 | 3×2 | 6 | 18 | 18 | 3 | | 2 | 13 | 3×3 | 9 | 27 | 21 | 3 | | 2 | 14 | 3×3 | 9 | 27 | 21 | 3 | | 2 | 15 | 3×3 | 9 | 27 | 21 | 3 | | 2 | 16 | 4×2 | 8 | 24 | 24 | 3 | | 2 | 17 | 4×2 | 8 | 24 | 24 | 3 | | 2 | 18 | 4×2 | 8 | 24 | 24 | 3 | | 2 | 19 | 3×4 | 12 | 36 | 27 | 3 | | 2 | 20 | 3×4 | 12 | 36 | 27 | 3 | | 3 | 21 | 3×3 | 9 | 27 | 21 | 4 | | 3 | 22 | 3×3 | 9 | 27 | 21 | 4 | | 3 | 23 | 4×2 | 8 | 24 | 24 | 4 | | 3 | 24 | 4×2 | 8 | 24 | 24 | 4 | | 3 | 25 | 4×2 | 8 | 24 | 24 | 4 | | 3 | 26 | 3×4 | 12 | 36 | 27 | 4 | | 3 | 27 | 3×4 | 12 | 36 | 27 | 4 | | 3 | 28 | 3×4 | 12 | 36 | 27 | 4 | | 3 | 29 | 4×3 | 12 | 36 | 30 | 4 | | 3 | 30 | 4×3 | 12 | 36 | 30 | 4 | | 4 | 31 | 4×2 | 8 | 24 | 24 | 4 | | 4 | 32 | 4×2 | 8 | 24 | 24 | 4 | | 4 | 33 | 3×3 | 9 | 27 | 27 | 4 | | 4 | 34 | 3×3 | 9 | 27 | 27 | 4 | | 4 | 35 | 3×3 | 9 | 27 | 27 | 4 | | 4 | 36 | 4×3 | 12 | 36 | 30 | 4 | | 4 | 37 | 4×3 | 12 | 36 | 30 | 4 | | 4 | 38 | 4×3 | 12 | 36 | 30 | 4 | | 4 | 39 | 3×4 | 12 | 36 | 33 | 4 | | 4 | 40 | 3×4 | 12 | 36 | 33 | 4 | | 5 | 41 | 3×3 | 9 | 27 | 27 | 5 | | 5 | 42 | 3×3 | 9 | 27 | 27 | 5 | | 5 | 43 | 4×3 | 12 | 36 | 30 | 5 | | 5 | 44 | 4×3 | 12 | 36 | 30 | 5 | | 5 | 45 | 4×3 | 12 | 36 | 30 | 5 | | 5 | 46 | 3×4 | 12 | 36 | 33 | 5 | | 5 | 47 | 3×4 | 12 | 36 | 33 | 5 | | 5 | 48 | 3×4 | 12 | 36 | 33 | 5 | | 5 | 49 | 4×3 | 12 | 36 | 36 | 5 | | 5 | 50 | 4×3 | 12 | 36 | 36 | 5 | | 6 | 51 | 4×3 | 12 | 36 | 30 | 5 | | 6 | 52 | 4×3 | 12 | 36 | 30 | 5 | | 6 | 53 | 3×4 | 12 | 36 | 33 | 5 | | 6 | 54 | 3×4 | 12 | 36 | 33 | 5 | | 6 | 55 | 3×4 | 12 | 36 | 33 | 5 | | 6 | 56 | 4×3 | 12 | 36 | 36 | 5 | | 6 | 57 | 4×3 | 12 | 36 | 36 | 5 | | 6 | 58 | 4×3 | 12 | 36 | 36 | 5 | | 6 | 59 | 3×5 | 15 | 45 | 39 | 5 | | 6 | 60 | 3×5 | 15 | 45 | 39 | 5 | > 表格中的“可容纳物品数 = 货位数 × 3”,若某关需要更大后备容量,可在 `slots` 中增加堆栈深度,但仍需满足最低空槽约束。