Extra2D/docs/API_Tutorial/05_Input_Handling.md

190 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 05. 输入处理
Extra2D 提供了统一的输入处理系统,支持手柄、键盘等多种输入设备。
## 输入管理器
通过 `Application::instance().input()` 访问输入管理器:
```cpp
auto& input = Application::instance().input();
```
## 按键检测
### 检测方法
```cpp
// 按键是否按下(持续触发)
if (input.isButtonDown(GamepadButton::A)) {
// 每帧都会触发,只要按键保持按下
}
// 按键是否刚按下(单次触发)
if (input.isButtonPressed(GamepadButton::A)) {
// 只在按下瞬间触发一次
}
// 按键是否刚释放
if (input.isButtonReleased(GamepadButton::A)) {
// 只在释放瞬间触发一次
}
```
### 常用按键
| 按键 | 说明 | Switch 对应 |
|------|------|------------|
| `GamepadButton::A` | A 键 | A 键 |
| `GamepadButton::B` | B 键 | B 键 |
| `GamepadButton::X` | X 键 | X 键 |
| `GamepadButton::Y` | Y 键 | Y 键 |
| `GamepadButton::Start` | 开始键 | + 键 |
| `GamepadButton::Select` | 选择键 | - 键 |
| `GamepadButton::DPadUp` | 方向上 | 方向键上 |
| `GamepadButton::DPadDown` | 方向下 | 方向键下 |
| `GamepadButton::DPadLeft` | 方向左 | 方向键左 |
| `GamepadButton::DPadRight` | 方向右 | 方向键右 |
| `GamepadButton::LeftStick` | 左摇杆按下 | L3 |
| `GamepadButton::RightStick` | 右摇杆按下 | R3 |
| `GamepadButton::LeftShoulder` | 左肩键 | L |
| `GamepadButton::RightShoulder` | 右肩键 | R |
## 摇杆输入
### 获取摇杆值
```cpp
// 获取左摇杆位置(范围 -1.0 到 1.0
Vec2 leftStick = input.getLeftStick();
// 获取右摇杆位置
Vec2 rightStick = input.getRightStick();
// 应用摇杆输入
float speed = 200.0f;
player->setPosition(player->getPosition() + leftStick * speed * dt);
```
### 摇杆死区
```cpp
// 设置摇杆死区(默认 0.15
input.setStickDeadZone(0.2f);
```
## 完整示例
### 菜单导航
参考 `examples/push_box/StartScene.cpp`
```cpp
void StartScene::onUpdate(float dt) {
Scene::onUpdate(dt);
auto& input = Application::instance().input();
// 方向键上下切换选择
if (input.isButtonPressed(GamepadButton::DPadUp)) {
selectedIndex_ = (selectedIndex_ - 1 + menuCount_) % menuCount_;
updateMenuColors();
}
else if (input.isButtonPressed(GamepadButton::DPadDown)) {
selectedIndex_ = (selectedIndex_ + 1) % menuCount_;
updateMenuColors();
}
// A键确认
if (input.isButtonPressed(GamepadButton::A)) {
executeMenuItem();
}
// X键切换音效
if (input.isButtonPressed(GamepadButton::X)) {
g_SoundOpen = !g_SoundOpen;
AudioManager::instance().setEnabled(g_SoundOpen);
updateSoundIcon();
}
}
```
### 玩家移动
```cpp
void Player::update(float dt) {
auto& input = Application::instance().input();
Vec2 moveDir;
// 方向键移动
if (input.isButtonDown(GamepadButton::DPadLeft)) {
moveDir.x -= 1;
}
if (input.isButtonDown(GamepadButton::DPadRight)) {
moveDir.x += 1;
}
if (input.isButtonDown(GamepadButton::DPadUp)) {
moveDir.y -= 1;
}
if (input.isButtonDown(GamepadButton::DPadDown)) {
moveDir.y += 1;
}
// 摇杆移动
Vec2 stick = input.getLeftStick();
if (stick.length() > 0.1f) {
moveDir = stick;
}
// 应用移动
if (moveDir.length() > 0) {
moveDir.normalize();
setPosition(getPosition() + moveDir * speed_ * dt);
}
// 跳跃
if (input.isButtonPressed(GamepadButton::A)) {
jump();
}
}
```
## 输入映射
### 自定义按键映射
```cpp
// 定义动作
enum class Action {
Jump,
Attack,
Pause
};
// 映射按键到动作
std::unordered_map<Action, GamepadButton> actionMap = {
{Action::Jump, GamepadButton::A},
{Action::Attack, GamepadButton::B},
{Action::Pause, GamepadButton::Start}
};
// 检查动作
bool isActionPressed(Action action) {
auto& input = Application::instance().input();
return input.isButtonPressed(actionMap[action]);
}
```
## 最佳实践
1. **使用 isButtonPressed 进行菜单操作** - 避免持续触发
2. **使用 isButtonDown 进行移动控制** - 实现流畅移动
3. **支持多种输入方式** - 同时支持方向键和摇杆
4. **添加输入缓冲** - 提升操作手感
## 下一步
- [06. 碰撞检测](./06_Collision_Detection.md) - 学习碰撞检测系统
- [07. UI 系统](./07_UI_System.md) - 学习 UI 控件使用