Skip to content

game.ts — 游戏 Store

文件: web/src/stores/game.ts

职责

  • 3 款游戏进度管理(象形配对、拼图闯关、汉字消消乐)
  • 道具管理(锤子、洗牌、提示)
  • 关卡解锁逻辑(前一关通关即解锁下一关)
  • 游戏配置加载

依赖

无外部 Store 依赖。

数据加载

  • load(): 通过 2 个 API 并行加载:
    • api.get<GameDataMap>("/games/data") — 游戏进度 + 道具数据
    • api.get<GameConfig[]>("/games") — 游戏配置(关卡定义)
  • 加载后自动执行 ensureLevelsInit()ensurePowerUpsInit() 初始化缺失的关卡和道具。
  • 初始化时自动调用。

数据持久化

方法API 端点方式
load()GET /games/data + GET /games读取
save()PUT /games/data全量保存
saveGameResult()POST /games/:gameId/levels/:levelId/result专用端点,payload: { stars, score, completed, completedChars }
saveCharCompleted()内部调用 save()PUT /games/data全量保存
usePowerUp()POST /games/:gameId/power-ups/:type/use专用端点
addPowerUp()POST /games/:gameId/power-ups/:type/add专用端点,payload: { amount }
unlockGame()内部调用 save()PUT /games/data全量保存

saveGameResultusePowerUpaddPowerUp 已改为专用 API 端点。saveCharCompletedunlockGame 仍使用 save() 全量保存。

核心数据结构

typescript
interface GameDataMap {
  pictograph_match: GameProgress   // 象形配对
  stroke_puzzle: GameProgress      // 拼图闯关
  char_match3: GameProgress        // 汉字消消乐
}

interface GameProgress {
  unlocked: boolean                         // 游戏是否解锁
  levels: Record<string, GameLevel>         // 关卡数据(key: "1"-"10")
  powerUps: Record<string, number>          // 道具数量
}

interface GameLevel {
  stars: number               // 星级(0-3)
  highScore: number           // 最高分
  completed: boolean          // 是否通关
  completedChars: string[]    // 已完成的汉字列表
}

默认道具

游戏道具
象形配对hint: 1
拼图闯关hint: 1
汉字消消乐hammer: 3, shuffle: 2, hint: 3

默认解锁状态

游戏默认解锁
象形配对
拼图闯关
汉字消消乐

Reactive State

属性类型说明
gameDataRef<GameDataMap>3 款游戏的完整进度数据
loadingRef<boolean>加载状态

方法

数据加载与保存

方法签名说明
load() => Promise<void>并行加载游戏进度和配置,初始化关卡和道具
save() => void全量保存游戏数据(fire-and-forget)

查询方法

方法签名返回值说明
getGameConfig(gameId: string) => GameConfig | undefined游戏配置获取游戏关卡定义
getGameProgress(gameId: string) => GameProgressSummary进度摘要获取游戏进度摘要(total/completed/totalStars)
getGameProgressRaw(gameId: string) => GameProgressGameProgress获取游戏完整进度对象
getLevelStatus(gameId: string, levelId: string) => GameLevel关卡状态获取关卡详情
isLevelUnlocked(gameId: string, levelId: string) => boolean是否解锁第 1 关需游戏已解锁,后续关卡需前一关通关
isCharCompleted(gameId: string, levelId: string, char: string) => boolean是否完成检查某汉字在当前关卡是否已完成

游戏操作

方法签名返回值说明
saveGameResult(gameId, levelId, options: { stars, score, completed, completedChars? }) => SaveGameResult{ changed, oldStars, newStars }保存游戏结果,自动解锁下一关。changed: "first_clear" / "improved" / "none"
saveCharCompleted(gameId: string, levelId: string|number, char: string) => void记录关卡内完成的汉字,调用 save()
unlockGame(gameId: string) => void解锁游戏,调用 save()

道具操作

方法签名返回值说明
usePowerUp(gameId: string, type: string) => boolean是否成功使用道具(数量 > 0 才成功),调用专用端点
addPowerUp(gameId: string, type: string, amount?: number) => void增加道具(默认 +1),调用专用端点

内部方法

方法签名说明
ensureLevelsInit() => void确保每款游戏 1-10 关都有默认数据
ensurePowerUpsInit() => void确保每款游戏有默认道具数量