---
name: path_input_handler.aicomponent
description: 路径消除玩法的棋盘输入处理器。处理点击命中路径头部的消除逻辑、单指拖拽棋盘、双指缩放，以及新手引导和连击系统的交互触发。
triggers: 需要处理玩家与路径消除棋盘的触摸/鼠标交互时触发。
---

# 棋盘输入处理器（Board Input Handler）

## 说明

`InputHandler` 负责所有棋盘输入事件：

- **点击/点触路径头部**：命中检测 → `attemptMovePath()` → 消除成功或阻挡扣命
- **单指拖拽**：长按+移动时拖拽棋盘（边界约束）
- **双指缩放**：Pinch 手势缩放棋盘（最小/最大缩放限制）
- **鼠标滚轮**：缩放棋盘
- **连击触发**：成功消除路径时通知 `ComboManager`
- **引导系统**：一二关特殊引导逻辑的交互配合

## Scaffold

| 目标路径 | 来源 | 说明 |
|---------|-----|-----|
| `src/game/scenes/GameUI/InputHandler.ts` | `ref/InputHandler.ts` | 完整输入处理器实现 |

## Imports

- `phaser.aicomponent`（硬依赖：Phaser 输入事件 API）
- `grid_board_layout.aicomponent`（硬依赖：棋盘格子坐标计算）
- `path_renderer.aicomponent`（硬依赖：路径绘制触发刷新）

## Skill Definition

```yaml
tools:
  - read_file
  - write_file
inputs:
  - source: src/game/scenes/GameUI/InputHandler.ts
outputs:
  - inputHandler: InputHandler class + InputGameRef interface
```

## 关键接口

```typescript
interface InputGameRef extends Phaser.Scene {
  level: ParsedLevel | null;
  removedPaths: Set<number>;
  blockedPaths: Set<number>;
  animatingPaths: Set<number>;
  isInputLocked: boolean;
  zoom: number; minZoom: number; maxZoom: number;
  // ... 其他场景引用
}

class InputHandler {
  bindEvents(): void;     // 在 Scene.create() 末尾调用
  resetState(): void;     // 关卡重置时调用
}
```

## Recipe

| 决策 | 原因 |
|------|------|
| **InputGameRef 接口解耦** | InputHandler 通过接口而非具体 `Game` 类访问场景状态，避免与 GameScene 的强循环依赖；也便于测试时 mock 场景引用 |
| **输入与游戏状态分离** | InputHandler 负责"什么事件发生"，具体的消除/扣命逻辑委托给接口方法（如 `attemptMovePath`）；不直接写 `removedPaths` |
| **拖拽+缩放+点击三模式** | 试玩广告需支持触屏和鼠标；单指拖动、双指缩放、鼠标滚轮在同一 InputHandler 内统一处理，避免事件冲突 |

## Adapter

- **Role**: `boardInputHandler` — 棋盘触摸/鼠标输入处理器（点击消除 + 拖拽 + 缩放）
- **Provides**: `InputHandler` 类（`bindEvents()`、`resetState()`）、`InputGameRef` 接口
- **Requires**: `phaser.aicomponent`、`grid_board_layout.aicomponent`（格子坐标计算）、`path_renderer.aicomponent`（触发渲染刷新）
- **Consumed by**: `game_scene.aicomponent`（在 `create()` 中 `new InputHandler(this)` 并调用 `bindEvents()`）
- **Integration point**: `src/game/scenes/GameUI/InputHandler.ts` → `Game.ts` 的 `create()` 末尾

## 核心逻辑：attemptMovePath

```
1. 检查路径是否已消除或正在动画中 → 跳过
2. 计算路径 head 在 direction 上到边界的路径
3. 对路径上每个格子检查 isCellOccupiedByAnyPath()
4. 全部空闲 → animatePathOffBoard → removedPaths.add → 连击处理
5. 有阻挡 → animateBlockedPath → loseLife() → 连击重置
```
