# 任务：多地图 + 难度系统 + 场景化改造

## 目标
1. 主页新增难度选择（低/中/高），点击后带参数跳转游戏
2. 实现3张地图，每5波切换一次（地图1→地图2→地图3）
3. 每张地图有专属背景图、路径形状、装饰物
4. 波次配置根据难度动态调整（怪物数量、速度、Boss频率）

## 素材已就绪
`/public/game-assets/` 目录中已有：
- `map1-bg.png`、`map2-bg.png`、`map3-bg.png` — 三张地图背景
- `deco-coffee.png`、`deco-monitor.png`、`deco-desk.png` — 装饰物

## 文件改动清单

### 1. `game/data/mapConfigs.ts`（新建）
定义3张地图的配置：

```typescript
export type DifficultyLevel = 'easy' | 'normal' | 'hard'

export interface MapConfig {
  id: number
  name: string          // 地图名称
  bgKey: string         // Phaser 加载的背景图 key
  bgPath: string        // 背景图路径
  pathColor: number     // 路径格颜色
  buildColor: number    // 可建格颜色
  waypoints: readonly { x: number; y: number }[]  // 路径折线坐标
  decorations: {        // 装饰物（固定摆放的非路径格）
    key: string
    col: number
    row: number
  }[]
  labels: { col: number; row: number; text: string }[]
  waveCount: number     // 每张地图波次数（固定5）
  // 每波配置（相对于 normal 难度的基础配置）
  waves: WaveConfigEntry[]
}

export interface WaveConfigEntry {
  enemies: {
    type: 'FreshGraduate' | 'OldEmployee' | 'TroubleMaker' | 'BossVP'
    count: number
    interval: number  // ms
  }[]
}

// 难度倍率
export const DIFFICULTY_MULTIPLIER: Record<DifficultyLevel, {
  enemyCount: number   // 数量倍率
  enemySpeed: number   // 速度倍率
  bossHp: number       // Boss HP 倍率
  hcReward: number     // HC 奖励倍率（难度高奖励少）
}> = {
  easy:   { enemyCount: 0.7, enemySpeed: 0.8, bossHp: 0.7, hcReward: 1.2 },
  normal: { enemyCount: 1.0, enemySpeed: 1.0, bossHp: 1.0, hcReward: 1.0 },
  hard:   { enemyCount: 1.4, enemySpeed: 1.3, bossHp: 1.5, hcReward: 0.8 },
}

// 地图1：人力资源部（HR走廊，S型路径）
// 路径：(0,2)→(11,2)→(11,9)→(15,9)
const MAP1: MapConfig = {
  id: 1,
  name: '人力资源部 · 降本增效',
  bgKey: 'map1-bg',
  bgPath: '/game-assets/map1-bg.png',
  pathColor: 0x3d2b1f,
  buildColor: 0x1e3a5f,
  waypoints: [
    { x: 0, y: 2 },
    { x: 11, y: 2 },
    { x: 11, y: 9 },
    { x: 15, y: 9 },
  ],
  decorations: [
    { key: 'deco-coffee', col: 3, row: 0 },
    { key: 'deco-monitor', col: 14, row: 1 },
    { key: 'deco-desk', col: 5, row: 5 },
    { key: 'deco-coffee', col: 9, row: 11 },
    { key: 'deco-monitor', col: 1, row: 7 },
    { key: 'deco-desk', col: 13, row: 4 },
  ],
  labels: [
    { col: 0, row: 0, text: '面试间' },
    { col: 14, row: 10, text: '财务室' },
    { col: 6, row: 5, text: 'HR办公区' },
  ],
  waveCount: 5,
  waves: [
    { enemies: [{ type: 'FreshGraduate', count: 10, interval: 800 }] },
    { enemies: [{ type: 'FreshGraduate', count: 8, interval: 700 }, { type: 'OldEmployee', count: 2, interval: 2000 }] },
    { enemies: [{ type: 'OldEmployee', count: 4, interval: 1800 }, { type: 'TroubleMaker', count: 3, interval: 1500 }] },
    { enemies: [{ type: 'FreshGraduate', count: 12, interval: 600 }, { type: 'TroubleMaker', count: 3, interval: 1200 }] },
    { enemies: [{ type: 'BossVP', count: 1, interval: 0 }, { type: 'OldEmployee', count: 3, interval: 2000 }, { type: 'FreshGraduate', count: 5, interval: 800 }] },
  ],
}

// 地图2：技术研发部（Z型路径，更复杂）
// 路径：(0,1)→(8,1)→(8,5)→(3,5)→(3,10)→(15,10)
const MAP2: MapConfig = {
  id: 2,
  name: '技术研发部 · 996福报',
  bgKey: 'map2-bg',
  bgPath: '/game-assets/map2-bg.png',
  pathColor: 0x1a3a2a,
  buildColor: 0x0f2040,
  waypoints: [
    { x: 0, y: 1 },
    { x: 8, y: 1 },
    { x: 8, y: 5 },
    { x: 3, y: 5 },
    { x: 3, y: 10 },
    { x: 15, y: 10 },
  ],
  decorations: [
    { key: 'deco-monitor', col: 1, row: 3 },
    { key: 'deco-monitor', col: 10, row: 0 },
    { key: 'deco-coffee', col: 6, row: 7 },
    { key: 'deco-desk', col: 11, row: 3 },
    { key: 'deco-monitor', col: 5, row: 8 },
    { key: 'deco-coffee', col: 14, row: 7 },
    { key: 'deco-desk', col: 0, row: 6 },
    { key: 'deco-monitor', col: 13, row: 5 },
  ],
  labels: [
    { col: 0, row: 0, text: '研发中心' },
    { col: 14, row: 11, text: '服务器机房' },
    { col: 5, row: 3, text: '格子间' },
    { col: 10, row: 8, text: 'Bug池' },
  ],
  waveCount: 5,
  waves: [
    { enemies: [{ type: 'FreshGraduate', count: 12, interval: 700 }, { type: 'OldEmployee', count: 2, interval: 2000 }] },
    { enemies: [{ type: 'OldEmployee', count: 5, interval: 1500 }, { type: 'TroubleMaker', count: 3, interval: 1200 }] },
    { enemies: [{ type: 'FreshGraduate', count: 15, interval: 500 }, { type: 'TroubleMaker', count: 4, interval: 1000 }] },
    { enemies: [{ type: 'BossVP', count: 1, interval: 0 }, { type: 'OldEmployee', count: 4, interval: 1500 }] },
    { enemies: [{ type: 'BossVP', count: 1, interval: 0 }, { type: 'FreshGraduate', count: 10, interval: 600 }, { type: 'TroubleMaker', count: 5, interval: 1000 }] },
  ],
}

// 地图3：高管会议室（W型路径，最难）
// 路径：(0,0)→(5,0)→(5,6)→(10,6)→(10,2)→(15,2) 先上后下再上
const MAP3: MapConfig = {
  id: 3,
  name: '高管会议室 · 最后决战',
  bgKey: 'map3-bg',
  bgPath: '/game-assets/map3-bg.png',
  pathColor: 0x3d1f2b,
  buildColor: 0x2d1a40,
  waypoints: [
    { x: 0, y: 0 },
    { x: 5, y: 0 },
    { x: 5, y: 6 },
    { x: 10, y: 6 },
    { x: 10, y: 2 },
    { x: 15, y: 2 },
  ],
  decorations: [
    { key: 'deco-desk', col: 2, row: 2 },
    { key: 'deco-desk', col: 8, row: 0 },
    { key: 'deco-coffee', col: 12, row: 5 },
    { key: 'deco-desk', col: 7, row: 9 },
    { key: 'deco-monitor', col: 2, row: 9 },
    { key: 'deco-coffee', col: 13, row: 9 },
    { key: 'deco-desk', col: 1, row: 4 },
    { key: 'deco-monitor', col: 14, row: 4 },
    { key: 'deco-desk', col: 8, row: 8 },
  ],
  labels: [
    { col: 0, row: 1, text: '董事会' },
    { col: 14, row: 3, text: '董事长室' },
    { col: 7, row: 4, text: '会议室' },
  ],
  waveCount: 5,
  waves: [
    { enemies: [{ type: 'OldEmployee', count: 6, interval: 1500 }, { type: 'TroubleMaker', count: 4, interval: 1000 }] },
    { enemies: [{ type: 'BossVP', count: 1, interval: 0 }, { type: 'FreshGraduate', count: 12, interval: 600 }, { type: 'OldEmployee', count: 3, interval: 1500 }] },
    { enemies: [{ type: 'BossVP', count: 1, interval: 0 }, { type: 'TroubleMaker', count: 6, interval: 800 }, { type: 'OldEmployee', count: 4, interval: 1500 }] },
    { enemies: [{ type: 'BossVP', count: 2, interval: 5000 }, { type: 'OldEmployee', count: 5, interval: 1200 }, { type: 'FreshGraduate', count: 8, interval: 600 }] },
    { enemies: [{ type: 'BossVP', count: 2, interval: 3000 }, { type: 'TroubleMaker', count: 8, interval: 600 }, { type: 'OldEmployee', count: 6, interval: 1000 }] },
  ],
}

export const ALL_MAPS: MapConfig[] = [MAP1, MAP2, MAP3]
```

### 2. `game/constants.ts`（修改）
- 移除硬编码的 `PATH_WAYPOINTS` 和 `MAP_LABELS`（改为从 mapConfigs 动态读取）
- 保留其他常量不变
- 新增 `WAVES_PER_MAP = 5`

### 3. `game/GameManager.ts`（修改）
新增字段：
```typescript
public difficulty: DifficultyLevel = 'normal'
public currentMapIndex: number = 0   // 0=地图1, 1=地图2, 2=地图3
public totalWaveCleared: number = 0  // 总计已清理波次
```
`reset()` 时保留 difficulty，重置其他字段。
新增方法：`setDifficulty(d: DifficultyLevel)`

### 4. `game/mapRenderer.ts`（修改）
- `buildPathTiles` 和 `PATH_TILES` 改为接受参数（不再使用全局常量）
- `drawAllTiles` 接受 `pathTiles` 参数
- 新增 `renderMapBackground(scene, bgKey)` — 绘制地图背景图（铺满地图区域）
- 新增 `renderDecorations(scene, decorations, pathTiles)` — 在非路径格随机摆放装饰物
- `getCellSize()` 不变

### 5. `game/enemies/WaveManager.ts`（重构）
接受动态波次配置，而非硬编码 WAVE_CONFIG：
```typescript
constructor(
  scene,
  waveConfigs: WaveConfigEntry[],   // 从外部传入，支持多地图
  difficultyMultiplier,             // 难度倍率
  callbacks: { onWaveComplete, onAllWavesComplete, onDestroyRandomTower }
)
```
难度影响：
- `enemyCount *= multiplier.enemyCount`（向上取整）
- 怪物创建时将速度和HP通过参数传入子类
- Boss HP 乘以 `multiplier.bossHp`

### 6. `game/enemies/EnemyBase.ts`（修改）
构造函数新增 `speedMultiplier = 1.0` 和 `hpMultiplier = 1.0` 参数（可选，默认1），子类创建时传入。

### 7. `game/GameScene.ts`（重构）
支持多地图流程：
```typescript
private currentMapIndex = 0
private mapConfigs = ALL_MAPS

// create() 时加载当前地图
// 5波清空后：showMapClearModal → 延迟2s → loadNextMap()
// loadNextMap()：销毁当前地图装饰物，重新 renderMapBackground/renderDecorations，重置 waveManager
```

新增方法：
- `loadMap(mapConfig: MapConfig)` — 初始化地图背景、路径、装饰物、重置 WaveManager
- `onMapCleared()` — 5波清场后显示过关弹窗，然后切换下一张地图
- 地图切换时：重新计算 PATH_TILES（传给 tileGraphics 重绘）、清除装饰物、加载新背景

### 8. `game/ui/MapTransitionModal.ts`（新建）
地图切换过渡弹窗（Phaser DOM或Canvas Text）：
```
过关！人力资源部已清场
KPI: 87% | 获得奖励: +100 HC
[下一关：技术研发部 996福报]  (3秒自动关闭)
```
3秒后自动关闭并触发下一张地图加载。

### 9. `app/page.tsx`（修改）— 主页加难度选择
在「开始游戏」按钮前增加难度选择器（三个按钮：简单/普通/困难）：

```tsx
// 选择难度后存入 localStorage，游戏页面读取
localStorage.setItem('game-difficulty', selectedDifficulty)
```

难度卡片设计：
- 简单：绿色 — "带薪摸鱼，准点下班"
- 普通：蓝色 — "常规打工，偶有加班"  
- 困难：红色 — "地狱模式，007全开"

### 10. `app/game/page.tsx`（修改）
`useEffect` 初始化时从 localStorage 读取难度，通过 `window.__gameDifficulty` 传给场景。

## 注意事项
- 每张地图preload对应背景图（key不同），场景重用时用 `this.textures.exists(key)` 检查避免重复加载
- PATH_TILES 不再是模块级常量，改为每次渲染时动态计算后传参
- `mapRenderer.ts` 导出的 `PATH_TILES` 保持向后兼容（先用地图1的配置初始化），GameScene 内部用局部变量覆盖
- 地图背景图用 `scene.add.image(x, y, key).setDisplaySize(mapW, mapH).setDepth(-1).setOrigin(0,0)` 铺在地图区域（HUD 下方）
- 装饰物图片 `setDisplaySize(cellW*0.7, cellH*0.7)`，`setDepth(1)`，`setAlpha(0.6)`，不影响塔的放置逻辑（只是视觉装饰）
- 地图切换时必须 destroy 掉所有装饰物 Phaser 对象，避免内存泄漏

## 验收标准
1. 主页有三个难度按钮，选中高亮，点击「开始游戏」带难度跳转
2. 游戏开始后可见地图背景图（不是纯色格子）
3. 装饰物（咖啡杯、电脑、桌子）散布在非路径格子上
4. 第5波清场后弹出过关弹窗，3秒后自动切换到下一张地图
5. 地图2路径形状与地图1不同（Z型 vs S型）
6. 困难模式下怪物数量明显增多，Boss更频繁出现
7. 三张地图全部通关后显示最终胜利界面

## 相关文件
- 需求文档：`.docs/prd-tower-defense-game.md`
- 设计系统：`design-system/大厂保卫战/MASTER.md`
- 开发规范：`@rules/dev-best-practices.md`（**必须先阅读**）
- 原子提交：`@rules/atomic-commit.md`

完成后按原子提交规范提交，禁止 `git add .`。
