完成生命组件与死伤状态
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
#include "health_component.h"
|
||||
#include "../../engine/object/game_object.h"
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <glm/common.hpp>
|
||||
|
||||
namespace engine::component {
|
||||
|
||||
HealthComponent::HealthComponent(int max_health, float invincibility_duration)
|
||||
: max_health_(glm::max(1, max_health)), // 确保最大生命值至少为 1
|
||||
current_health_(max_health_), // 初始化当前生命值为最大生命值
|
||||
invincibility_duration_(invincibility_duration)
|
||||
{}
|
||||
|
||||
void HealthComponent::update(float delta_time, engine::core::Context&) {
|
||||
// 更新无敌状态计时器
|
||||
if (is_invincible_) {
|
||||
invincibility_timer_ -= delta_time;
|
||||
if (invincibility_timer_ <= 0.0f) {
|
||||
is_invincible_ = false;
|
||||
invincibility_timer_ = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool HealthComponent::takeDamage(int damage_amount) {
|
||||
if (damage_amount <= 0 || !isAlive()) {
|
||||
return false; // 不造成伤害或已经死亡
|
||||
}
|
||||
|
||||
if (is_invincible_) {
|
||||
spdlog::debug("游戏对象 '{}' 处于无敌状态,免疫了 {} 点伤害。", owner_ ? owner_->getName() : "Unknown", damage_amount);
|
||||
return false; // 无敌状态,不受伤
|
||||
}
|
||||
// --- 确实造成伤害了 ---
|
||||
current_health_ -= damage_amount;
|
||||
current_health_ = glm::max(0, current_health_); // 防止生命值变为负数
|
||||
// 如果受伤但没死,并且设置了无敌时间,则触发无敌
|
||||
if (isAlive() && invincibility_duration_ > 0.0f) {
|
||||
setInvincible(invincibility_duration_);
|
||||
}
|
||||
spdlog::debug("游戏对象 '{}' 受到了 {} 点伤害,当前生命值: {}/{}。",
|
||||
owner_ ? owner_->getName() : "Unknown", damage_amount, current_health_, max_health_);
|
||||
return true; // 造成伤害,返回true
|
||||
}
|
||||
|
||||
void HealthComponent::heal(int heal_amount) {
|
||||
if (heal_amount <= 0 || !isAlive()) {
|
||||
return; // 不治疗或已经死亡
|
||||
}
|
||||
|
||||
current_health_ += heal_amount;
|
||||
current_health_ = std::min(max_health_, current_health_); // 防止超过最大生命值
|
||||
spdlog::debug("游戏对象 '{}' 治疗了 {} 点,当前生命值: {}/{}。",
|
||||
owner_ ? owner_->getName() : "Unknown", heal_amount, current_health_, max_health_);
|
||||
}
|
||||
|
||||
void HealthComponent::setInvincible(float duration)
|
||||
{
|
||||
if (duration > 0.0f)
|
||||
{
|
||||
is_invincible_ = true;
|
||||
invincibility_timer_ = duration;
|
||||
spdlog::debug("游戏对象 '{}' 进入无敌状态,持续 {} 秒。", owner_ ? owner_->getName() : "Unknown", duration);
|
||||
} else {
|
||||
// 如果持续时间为 0 或负数,则立即取消无敌
|
||||
is_invincible_ = false;
|
||||
invincibility_timer_ = 0.0f;
|
||||
spdlog::debug("游戏对象 '{}' 的无敌状态被手动移除。", owner_ ? owner_->getName() : "Unknown");
|
||||
}
|
||||
}
|
||||
|
||||
void HealthComponent::setMaxHealth(int max_health)
|
||||
{
|
||||
max_health_ = glm::max(1, max_health); // 确保最大生命值至少为 1
|
||||
current_health_ = glm::min(current_health_, max_health_); // 确保当前生命值不超过最大生命值
|
||||
}
|
||||
|
||||
void HealthComponent::setCurrentHealth(int current_health)
|
||||
{
|
||||
// 确保当前生命值在 0 到最大生命值之间
|
||||
current_health_ = glm::max(0, glm::min(current_health, max_health_));
|
||||
}
|
||||
|
||||
} // namespace engine::component
|
||||
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
#include "../../engine/component/component.h"
|
||||
|
||||
namespace engine::component {
|
||||
|
||||
/**
|
||||
* @brief 管理 GameObject 的生命值,处理伤害、治疗,并提供无敌帧功能。
|
||||
*/
|
||||
class HealthComponent final : public engine::component::Component {
|
||||
friend class engine::object::GameObject;
|
||||
private:
|
||||
int max_health_ = 1; ///< @brief 最大生命值
|
||||
int current_health_ = 1; ///< @brief 当前生命值
|
||||
bool is_invincible_ = false; ///< @brief 是否处于无敌状态
|
||||
float invincibility_duration_ = 2.0f; ///< @brief 受伤后无敌的总时长(秒)
|
||||
float invincibility_timer_ = 0.0f; ///< @brief 无敌时间计时器(秒)
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 构造函数
|
||||
* @param max_health 最大生命值,默认为 1
|
||||
* @param invincibility_duration 无敌状态持续时间,默认为 2.0 秒
|
||||
*/
|
||||
explicit HealthComponent(int max_health = 1, float invincibility_duration = 2.0f);
|
||||
~HealthComponent() override = default;
|
||||
|
||||
// 禁止拷贝和移动
|
||||
HealthComponent(const HealthComponent&) = delete;
|
||||
HealthComponent& operator=(const HealthComponent&) = delete;
|
||||
HealthComponent(HealthComponent&&) = delete;
|
||||
HealthComponent& operator=(HealthComponent&&) = delete;
|
||||
|
||||
/**
|
||||
* @brief 对 GameObject 施加伤害。
|
||||
* 如果当前处于无敌状态,则伤害无效。
|
||||
* 如果成功造成伤害且设置了无敌时长,则会触发无敌帧。
|
||||
* @param damage_amount 造成的伤害量(应为正数)。
|
||||
* @return bool 如果成功造成伤害,则返回 true,否则返回 false。
|
||||
*/
|
||||
bool takeDamage(int damage_amount);
|
||||
void heal(int heal_amount); ///< @brief 治疗 GameObject,增加当前生命值(不超过最大生命值)。
|
||||
|
||||
// --- Getters and Setters ---
|
||||
bool isAlive() const { return current_health_ > 0; } ///< @brief 检查 GameObject 是否存活(当前生命值大于 0)。
|
||||
bool isInvincible() const { return is_invincible_; } ///< @brief 检查 GameObject 是否处于无敌状态。
|
||||
int getCurrentHealth() const { return current_health_; } ///< @brief 获取当前生命值。
|
||||
int getMaxHealth() const { return max_health_; } ///< @brief 获取最大生命值。
|
||||
|
||||
void setCurrentHealth(int current_health); ///< @brief 设置当前生命值 (确保不超过最大生命值)。
|
||||
void setMaxHealth(int max_health); ///< @brief 设置最大生命值 (确保不小于 1)。
|
||||
void setInvincible(float duration); ///< @brief 设置 GameObject 进入无敌状态,持续时间为 duration 秒。
|
||||
void setInvincibilityDuration(float duration) { invincibility_duration_ = duration; } ///< @brief 设置无敌状态持续时间。
|
||||
|
||||
protected:
|
||||
// 核心循环函数
|
||||
void update(float, engine::core::Context&) override;
|
||||
};
|
||||
|
||||
} // namespace engine::component
|
||||
Reference in New Issue
Block a user