完成土狼时间与无敌闪烁

This commit is contained in:
Ziyu
2025-06-16 14:44:47 +08:00
parent 2e0edb950c
commit c4afa83817
6 changed files with 75 additions and 7 deletions
+30
View File
@@ -81,6 +81,11 @@ void PlayerComponent::setState(std::unique_ptr<state::PlayerState> new_state) {
}
bool PlayerComponent::is_on_ground() const
{
return coyote_timer_ <= coyote_time_ || physics_component_->hasCollidedBelow();
}
void PlayerComponent::handleInput(engine::core::Context& context) {
if (!current_state_) return;
@@ -93,6 +98,31 @@ void PlayerComponent::handleInput(engine::core::Context& context) {
void PlayerComponent::update(float delta_time, engine::core::Context& context) {
if (!current_state_) return;
// 一旦离地,开始计时 Coyote Timer
if (!physics_component_->hasCollidedBelow()) {
coyote_timer_ += delta_time;
} else { // 如果碰撞到地面,重置 Coyote Timer
coyote_timer_ = 0.0f;
}
// 如果处于无敌状态,则进行闪烁
if (health_component_->isInvincible()) {
flash_timer_ += delta_time; // 闪烁计时器增加
if (flash_timer_ >= 2 * flash_interval_) {
flash_timer_ -= 2 * flash_interval_; // 闪烁计时器在 0~2倍闪烁间隔 中循环
}
// 一半时间可见,一半时间不可见。
if (flash_timer_ < flash_interval_) {
sprite_component_->setHidden(true);
} else {
sprite_component_->setHidden(false);
}
}
// 非无敌状态时确保精灵可见
else if (sprite_component_->isHidden()) {
sprite_component_->setHidden(false);
}
auto next_state = current_state_->update(delta_time, context);
if (next_state) {
setState(std::move(next_state));
+9
View File
@@ -46,6 +46,14 @@ private:
// --- 属性相关参数 ---
float stunned_duration_ = 0.4f; ///< @brief 玩家被击中后的硬直时间(单位:秒)
// 土狼时间(Coyote Time): 允许玩家在离地后短暂时间内仍然可以跳跃
static constexpr float coyote_time_ = 0.1f; ///< @brief Coyote Time (单位:秒)
float coyote_timer_ = 0.0f; ///< @brief Coyote Time 计时器
// 无敌闪烁时间
static constexpr float flash_interval_ = 0.1f; ///< @brief 闪烁间隔时间(单位:秒)
float flash_timer_ = 0.0f; ///< @brief 闪烁计时器,用于无敌状态下的闪烁效果
public:
PlayerComponent() = default;
~PlayerComponent() override = default;
@@ -81,6 +89,7 @@ public:
float getStunnedDuration() const { return stunned_duration_; } ///< @brief 获取硬直时间
void setState(std::unique_ptr<state::PlayerState> new_state); ///< @brief 切换玩家状态
bool is_on_ground() const; ///< @brief 检查玩家是否在地面上(考虑了Coyote Time)
private:
// 核心循环函数
+2 -2
View File
@@ -56,8 +56,8 @@ std::unique_ptr<PlayerState> IdleState::update(float, engine::core::Context&)
auto friction_factor = player_component_->getFrictionFactor();
physics_component->velocity_.x *= friction_factor;
// 如果下方没有碰撞,则切换到 FallState
if (!physics_component->hasCollidedBelow()) {
// 如果离地,则切换到 FallState
if (!player_component_->is_on_ground()) {
return std::make_unique<FallState>(player_component_);
}
return nullptr;
+2 -2
View File
@@ -67,8 +67,8 @@ std::unique_ptr<PlayerState> WalkState::update(float, engine::core::Context&)
auto max_speed = player_component_->getMaxSpeed();
physics_component->velocity_.x = glm::clamp(physics_component->velocity_.x, -max_speed, max_speed);
// 如果下方没有碰撞,则切换到 FallState
if (!physics_component->hasCollidedBelow()) {
// 如果离地,则切换到 FallState
if (!player_component_->is_on_ground()) {
return std::make_unique<FallState>(player_component_);
}