完成攀爬状态-粗略
This commit is contained in:
@@ -65,6 +65,7 @@ add_executable(${TARGET}
|
||||
src/game/component/state/walk_state.cpp
|
||||
src/game/component/state/jump_state.cpp
|
||||
src/game/component/state/fall_state.cpp
|
||||
src/game/component/state/climb_state.cpp
|
||||
src/game/component/state/hurt_state.cpp
|
||||
src/game/component/state/dead_state.cpp
|
||||
src/game/component/ai/patrol_behavior.cpp
|
||||
|
||||
@@ -126,8 +126,8 @@
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":32,
|
||||
"x":114.060606060606,
|
||||
"y":156.598484848485
|
||||
"x":482.643939393939,
|
||||
"y":381.098484848485
|
||||
},
|
||||
{
|
||||
"gid":607,
|
||||
|
||||
@@ -458,6 +458,15 @@
|
||||
"value":true
|
||||
}]
|
||||
},
|
||||
{
|
||||
"id":257,
|
||||
"properties":[
|
||||
{
|
||||
"name":"ladder",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}]
|
||||
},
|
||||
{
|
||||
"id":261,
|
||||
"properties":[
|
||||
|
||||
@@ -44,6 +44,7 @@ public:
|
||||
void addAnimation(std::unique_ptr<engine::render::Animation> animation); ///< @brief 向 animations_ map容器中添加一个动画。
|
||||
void playAnimation(const std::string& name); ///< @brief 播放指定名称的动画。
|
||||
void stopAnimation() { is_playing_ = false; } ///< @brief 停止当前动画播放。
|
||||
void resumeAnimation() {is_playing_ = true; } ///< @brief 恢复当前动画播放。
|
||||
|
||||
// --- Getters and Setters ---
|
||||
std::string getCurrentAnimationName() const;
|
||||
|
||||
@@ -33,6 +33,7 @@ private:
|
||||
bool collided_above_ = false;
|
||||
bool collided_left_ = false;
|
||||
bool collided_right_ = false;
|
||||
bool collided_ladder_ = false;
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -74,17 +75,20 @@ public:
|
||||
collided_above_ = false;
|
||||
collided_left_ = false;
|
||||
collided_right_ = false;
|
||||
collided_ladder_ = false;
|
||||
}
|
||||
|
||||
void setCollidedBelow(bool collided) { collided_below_ = collided; } ///< @brief 设置下方碰撞标志
|
||||
void setCollidedAbove(bool collided) { collided_above_ = collided; } ///< @brief 设置上方碰撞标志
|
||||
void setCollidedLeft(bool collided) { collided_left_ = collided; } ///< @brief 设置左方碰撞标志
|
||||
void setCollidedRight(bool collided) { collided_right_ = collided; } ///< @brief 设置右方碰撞标志
|
||||
void setCollidedLadder(bool collided) { collided_ladder_ = collided; } ///< @brief 设置梯子碰撞标志
|
||||
|
||||
bool hasCollidedBelow() const { return collided_below_; } ///< @brief 检查是否与下方发生碰撞
|
||||
bool hasCollidedAbove() const { return collided_above_; } ///< @brief 检查是否与上方发生碰撞
|
||||
bool hasCollidedLeft() const { return collided_left_; } ///< @brief 检查是否与左方发生碰撞
|
||||
bool hasCollidedRight() const { return collided_right_; } ///< @brief 检查是否与右方发生碰撞
|
||||
bool hasCollidedLadder() const { return collided_ladder_; } ///< @brief 检查是否与梯子发生碰撞
|
||||
|
||||
private:
|
||||
// 核心循环方法
|
||||
|
||||
@@ -32,6 +32,7 @@ enum class TileType {
|
||||
SLOPE_1_2, ///< @brief 斜坡瓦片,高度:左1 右1/2
|
||||
SLOPE_2_0, ///< @brief 斜坡瓦片,高度:左1/2右0
|
||||
HAZARD, ///< @brief 危险瓦片(例如火焰、尖刺等)
|
||||
LADDER, ///< @brief 梯子瓦片
|
||||
// 未来补充其它类型
|
||||
};
|
||||
|
||||
|
||||
@@ -361,6 +361,10 @@ void PhysicsEngine::checkTileTriggers()
|
||||
if (tile_type == engine::component::TileType::HAZARD) {
|
||||
triggers_set.insert(tile_type); // 记录触发事件,set 保证每个瓦片类型只记录一次
|
||||
}
|
||||
// 梯子类型不必记录到事件容器,物理引擎自己处理
|
||||
else if (tile_type == engine::component::TileType::LADDER) {
|
||||
pc->setCollidedLadder(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 遍历触发事件集合,添加到 tile_trigger_events_ 中
|
||||
|
||||
@@ -368,6 +368,10 @@ engine::component::TileType LevelLoader::getTileType(const nlohmann::json &tile_
|
||||
auto is_hazard = property.value("value", false);
|
||||
return is_hazard ? engine::component::TileType::HAZARD : engine::component::TileType::NORMAL;
|
||||
}
|
||||
else if (property.contains("name") && property["name"] == "ladder") {
|
||||
auto is_ladder = property.value("value", false);
|
||||
return is_ladder ? engine::component::TileType::LADDER : engine::component::TileType::NORMAL;
|
||||
}
|
||||
// TODO: 可以在这里添加更多的自定义属性处理逻辑
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ private:
|
||||
// --- 移动相关参数
|
||||
float move_force_ = 200.0f; ///< @brief 水平移动力
|
||||
float max_speed_ = 120.0f; ///< @brief 最大移动速度 (像素/秒)
|
||||
float climb_speed_ = 100.0f; ///< @brief 爬梯子速度 (像素/秒)
|
||||
float friction_factor_ = 0.85f; ///< @brief 摩擦系数 (Idle时缓冲效果,每帧乘以此系数)
|
||||
float jump_vel_ = 350.0f; ///< @brief 跳跃速度 (按下"jump"键给的瞬间向上的速度)
|
||||
|
||||
@@ -70,6 +71,8 @@ public:
|
||||
float getMoveForce() const { return move_force_; } ///< @brief 获取水平移动力
|
||||
void setMaxSpeed(float max_speed) { max_speed_ = max_speed; } ///< @brief 设置最大移动速度
|
||||
float getMaxSpeed() const { return max_speed_; } ///< @brief 获取最大移动速度
|
||||
void setClimbSpeed(float climb_speed) { climb_speed_ = climb_speed; } ///< @brief 设置爬梯子速度
|
||||
float getClimbSpeed() const { return climb_speed_; } ///< @brief 获取爬梯子速度
|
||||
void setFrictionFactor(float friction_factor) { friction_factor_ = friction_factor; } ///< @brief 设置摩擦系数
|
||||
float getFrictionFactor() const { return friction_factor_; } ///< @brief 获取摩擦系数
|
||||
void setJumpVelocity(float jump_vel) { jump_vel_ = jump_vel; } ///< @brief 设置跳跃速度
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
#include "climb_state.h"
|
||||
#include "jump_state.h"
|
||||
#include "idle_state.h"
|
||||
#include "walk_state.h"
|
||||
#include "fall_state.h"
|
||||
#include "../player_component.h"
|
||||
#include "../../../engine/core/context.h"
|
||||
#include "../../../engine/input/input_manager.h"
|
||||
#include "../../../engine/component/physics_component.h"
|
||||
#include "../../../engine/component/sprite_component.h"
|
||||
#include "../../../engine/component/animation_component.h"
|
||||
#include <glm/common.hpp>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
namespace game::component::state {
|
||||
|
||||
void ClimbState::enter() {
|
||||
spdlog::debug("进入攀爬状态");
|
||||
playAnimation("climb");
|
||||
if (auto* physics = player_component_->getPhysicsComponent(); physics) {
|
||||
physics->setUseGravity(false); // 禁用重力
|
||||
}
|
||||
}
|
||||
|
||||
void ClimbState::exit() {
|
||||
spdlog::debug("退出攀爬状态");
|
||||
|
||||
if (auto* physics = player_component_->getPhysicsComponent(); physics) {
|
||||
physics->setUseGravity(true); // 重新启用重力
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<PlayerState> ClimbState::handleInput(engine::core::Context& context) {
|
||||
|
||||
auto input_manager = context.getInputManager();
|
||||
auto physics_component = player_component_->getPhysicsComponent();
|
||||
auto animation_component = player_component_->getAnimationComponent();
|
||||
|
||||
// --- 攀爬状态下,按键则移动,不按键则静止 ---
|
||||
auto is_up = input_manager.isActionDown("move_up");
|
||||
auto is_down = input_manager.isActionDown("move_down");
|
||||
auto is_left = input_manager.isActionDown("move_left");
|
||||
auto is_right = input_manager.isActionDown("move_right");
|
||||
auto speed = player_component_->getClimbSpeed();
|
||||
|
||||
physics_component->velocity_.y = is_up ? -speed : // 三目运算符嵌套,自左向右执行
|
||||
is_down ? speed : 0.0f;
|
||||
physics_component->velocity_.x = is_left ? -speed :
|
||||
is_right ? speed : 0.0f;
|
||||
|
||||
// --- 根据是否有按键决定动画播放情况 ---
|
||||
(is_up || is_down || is_left || is_right)
|
||||
? animation_component->resumeAnimation() // 有按键则恢复动画播放
|
||||
: animation_component->stopAnimation(); // 无按键则停止动画播放
|
||||
|
||||
// 按跳跃键主动离开攀爬状态
|
||||
if (input_manager.isActionPressed("jump")) {
|
||||
return std::make_unique<JumpState>(player_component_);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<PlayerState> ClimbState::update(float, engine::core::Context&) {
|
||||
auto physics_component = player_component_->getPhysicsComponent();
|
||||
// 如果着地,则切换到 IdleState
|
||||
if (physics_component->hasCollidedBelow()) {
|
||||
return std::make_unique<IdleState>(player_component_);
|
||||
}
|
||||
// 如果离开梯子区域,则切换到 FallState(能走到这里 说明非着地状态)
|
||||
if (!physics_component->hasCollidedLadder()) {
|
||||
return std::make_unique<FallState>(player_component_);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
} // namespace game::component::state
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "player_state.h"
|
||||
|
||||
namespace game::component::state {
|
||||
|
||||
class ClimbState final : public PlayerState {
|
||||
friend class game::component::PlayerComponent;
|
||||
public:
|
||||
ClimbState(PlayerComponent* player_component) : PlayerState(player_component) {}
|
||||
~ClimbState() override = default;
|
||||
|
||||
private:
|
||||
void enter() override;
|
||||
void exit() override;
|
||||
std::unique_ptr<PlayerState> handleInput(engine::core::Context&) override;
|
||||
std::unique_ptr<PlayerState> update(float delta_time, engine::core::Context&) override;
|
||||
};
|
||||
|
||||
} // namespace game::component::state
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "fall_state.h"
|
||||
#include "idle_state.h"
|
||||
#include "walk_state.h"
|
||||
#include "climb_state.h"
|
||||
#include "../player_component.h"
|
||||
#include "../../../engine/core/context.h"
|
||||
#include "../../../engine/input/input_manager.h"
|
||||
@@ -24,6 +25,12 @@ std::unique_ptr<PlayerState> FallState::handleInput(engine::core::Context& conte
|
||||
auto physics_component = player_component_->getPhysicsComponent();
|
||||
auto sprite_component = player_component_->getSpriteComponent();
|
||||
|
||||
// 如果按下上下键,且与梯子重合,则切换到 ClimbState
|
||||
if (physics_component->hasCollidedLadder() &&
|
||||
(input_manager.isActionDown("move_up") || input_manager.isActionDown("move_down"))) {
|
||||
return std::make_unique<ClimbState>(player_component_);
|
||||
}
|
||||
|
||||
// 下落状态下可以左右移动
|
||||
if (input_manager.isActionDown("move_left")) {
|
||||
if (physics_component->velocity_.x > 0.0f) physics_component->velocity_.x = 0.0f;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "fall_state.h"
|
||||
#include "jump_state.h"
|
||||
#include "walk_state.h"
|
||||
#include "climb_state.h"
|
||||
#include "../player_component.h"
|
||||
#include "../../../engine/core/context.h"
|
||||
#include "../../../engine/input/input_manager.h"
|
||||
@@ -21,6 +22,13 @@ void IdleState::exit() {
|
||||
std::unique_ptr<PlayerState> IdleState::handleInput(engine::core::Context& context)
|
||||
{
|
||||
auto input_manager = context.getInputManager();
|
||||
auto physics_component = player_component_->getPhysicsComponent();
|
||||
|
||||
// 如果按"move_up"键,且与梯子重合,则切换到 ClimbState
|
||||
if (physics_component->hasCollidedLadder() && input_manager.isActionDown("move_up")) {
|
||||
return std::make_unique<ClimbState>(player_component_);
|
||||
}
|
||||
|
||||
// 如果按下了左右移动键,则切换到 WalkState
|
||||
if (input_manager.isActionDown("move_left") || input_manager.isActionDown("move_right")) {
|
||||
return std::make_unique<WalkState>(player_component_);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "idle_state.h"
|
||||
#include "walk_state.h"
|
||||
#include "fall_state.h"
|
||||
#include "climb_state.h"
|
||||
#include "../player_component.h"
|
||||
#include "../../../engine/core/context.h"
|
||||
#include "../../../engine/input/input_manager.h"
|
||||
@@ -29,6 +30,12 @@ std::unique_ptr<PlayerState> JumpState::handleInput(engine::core::Context& conte
|
||||
auto physics_component = player_component_->getPhysicsComponent();
|
||||
auto sprite_component = player_component_->getSpriteComponent();
|
||||
|
||||
// 如果按下上下键,且与梯子重合,则切换到 ClimbState
|
||||
if (physics_component->hasCollidedLadder() &&
|
||||
(input_manager.isActionDown("move_up") || input_manager.isActionDown("move_down"))) {
|
||||
return std::make_unique<ClimbState>(player_component_);
|
||||
}
|
||||
|
||||
// 跳跃状态下可以左右移动
|
||||
if (input_manager.isActionDown("move_left")) {
|
||||
if (physics_component->velocity_.x > 0.0f) physics_component->velocity_.x = 0.0f;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "jump_state.h"
|
||||
#include "fall_state.h"
|
||||
#include "idle_state.h"
|
||||
#include "climb_state.h"
|
||||
#include "../player_component.h"
|
||||
#include "../../../engine/core/context.h"
|
||||
#include "../../../engine/input/input_manager.h"
|
||||
@@ -27,6 +28,11 @@ std::unique_ptr<PlayerState> WalkState::handleInput(engine::core::Context& conte
|
||||
auto physics_component = player_component_->getPhysicsComponent();
|
||||
auto sprite_component = player_component_->getSpriteComponent();
|
||||
|
||||
// 如果按"move_up"键,且与梯子重合,则切换到 ClimbState
|
||||
if (physics_component->hasCollidedLadder() && input_manager.isActionDown("move_up")) {
|
||||
return std::make_unique<ClimbState>(player_component_);
|
||||
}
|
||||
|
||||
// 如果按下“jump”则切换到 JumpState
|
||||
if (input_manager.isActionPressed("jump")) {
|
||||
return std::make_unique<JumpState>(player_component_);
|
||||
|
||||
Reference in New Issue
Block a user