feat(character): 实现角色状态机与输入路由系统
新增角色状态机框架,包含空闲、移动、跳跃、攻击等状态 添加输入路由组件,统一处理键盘和手柄输入 引入动作库管理角色动作定义,支持PVF脚本配置 重构角色对象,整合运动器、状态机和输入处理 修复Actor子节点排序时的迭代安全问题
This commit is contained in:
142
Game/src/character/CharacterInputRouter.cpp
Normal file
142
Game/src/character/CharacterInputRouter.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
#include "character/CharacterInputRouter.h"
|
||||
#include <SDL2/SDL_gamecontroller.h>
|
||||
#include <cmath>
|
||||
|
||||
namespace frostbite2D {
|
||||
namespace {
|
||||
|
||||
float applyDeadZone(float value, float deadZone) {
|
||||
return std::fabs(value) >= deadZone ? value : 0.0f;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool CharacterInputRouter::OnKeyDown(const KeyEvent& event) {
|
||||
switch (event.getKeyCode()) {
|
||||
case KeyCode::a:
|
||||
case KeyCode::Left:
|
||||
left_ = true;
|
||||
return true;
|
||||
case KeyCode::d:
|
||||
case KeyCode::Right:
|
||||
right_ = true;
|
||||
return true;
|
||||
case KeyCode::w:
|
||||
case KeyCode::Up:
|
||||
up_ = true;
|
||||
return true;
|
||||
case KeyCode::s:
|
||||
case KeyCode::Down:
|
||||
down_ = true;
|
||||
return true;
|
||||
case KeyCode::j:
|
||||
attackPressed_ = true;
|
||||
return true;
|
||||
case KeyCode::k:
|
||||
jumpPressed_ = true;
|
||||
return true;
|
||||
case KeyCode::l:
|
||||
skill1Pressed_ = true;
|
||||
return true;
|
||||
case KeyCode::LShift:
|
||||
dashPressed_ = true;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CharacterInputRouter::OnKeyUp(KeyCode keyCode) {
|
||||
switch (keyCode) {
|
||||
case KeyCode::a:
|
||||
case KeyCode::Left:
|
||||
left_ = false;
|
||||
return true;
|
||||
case KeyCode::d:
|
||||
case KeyCode::Right:
|
||||
right_ = false;
|
||||
return true;
|
||||
case KeyCode::w:
|
||||
case KeyCode::Up:
|
||||
up_ = false;
|
||||
return true;
|
||||
case KeyCode::s:
|
||||
case KeyCode::Down:
|
||||
down_ = false;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CharacterInputRouter::OnJoystickAxis(const JoystickAxisEvent& event) {
|
||||
if (event.getAxis() == SDL_CONTROLLER_AXIS_LEFTX) {
|
||||
leftStickX_ = applyDeadZone(event.getNormalizedValue(), joystickDeadZone_);
|
||||
return true;
|
||||
}
|
||||
if (event.getAxis() == SDL_CONTROLLER_AXIS_LEFTY) {
|
||||
leftStickY_ = applyDeadZone(event.getNormalizedValue(), joystickDeadZone_);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CharacterInputRouter::OnJoystickButtonDown(
|
||||
const JoystickButtonDownEvent& event) {
|
||||
switch (event.getButton()) {
|
||||
case SDL_CONTROLLER_BUTTON_A:
|
||||
jumpPressed_ = true;
|
||||
return true;
|
||||
case SDL_CONTROLLER_BUTTON_X:
|
||||
attackPressed_ = true;
|
||||
return true;
|
||||
case SDL_CONTROLLER_BUTTON_B:
|
||||
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
|
||||
skill1Pressed_ = true;
|
||||
return true;
|
||||
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
|
||||
dashPressed_ = true;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CharacterInputRouter::OnJoystickButtonUp(
|
||||
const JoystickButtonUpEvent& event) {
|
||||
(void)event;
|
||||
return false;
|
||||
}
|
||||
|
||||
void CharacterInputRouter::EmitCommands(CharacterCommandBuffer& commandBuffer) {
|
||||
Vec2 moveAxis(leftStickX_, leftStickY_);
|
||||
if (moveAxis.lengthSquared() < 0.0001f) {
|
||||
moveAxis.x = (right_ ? 1.0f : 0.0f) - (left_ ? 1.0f : 0.0f);
|
||||
moveAxis.y = (down_ ? 1.0f : 0.0f) - (up_ ? 1.0f : 0.0f);
|
||||
}
|
||||
commandBuffer.Submit({CharacterCommandType::Move, moveAxis, 0.0f});
|
||||
|
||||
if (jumpPressed_) {
|
||||
commandBuffer.Submit({CharacterCommandType::JumpPressed, Vec2::Zero(), 0.0f});
|
||||
}
|
||||
if (attackPressed_) {
|
||||
commandBuffer.Submit({CharacterCommandType::AttackPressed, Vec2::Zero(), 0.0f});
|
||||
}
|
||||
if (skill1Pressed_) {
|
||||
commandBuffer.Submit({CharacterCommandType::Skill1Pressed, Vec2::Zero(), 0.0f});
|
||||
}
|
||||
if (dashPressed_) {
|
||||
commandBuffer.Submit({CharacterCommandType::DashPressed, Vec2::Zero(), 0.0f});
|
||||
}
|
||||
|
||||
ClearFrameState();
|
||||
}
|
||||
|
||||
void CharacterInputRouter::ClearFrameState() {
|
||||
jumpPressed_ = false;
|
||||
attackPressed_ = false;
|
||||
skill1Pressed_ = false;
|
||||
dashPressed_ = false;
|
||||
}
|
||||
|
||||
} // namespace frostbite2D
|
||||
Reference in New Issue
Block a user