完成生命组件与死伤状态

This commit is contained in:
Ziyu
2025-06-16 14:44:47 +08:00
parent a31890fc20
commit 26ed9c34e4
15 changed files with 370 additions and 5 deletions
+84
View File
@@ -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
+59
View File
@@ -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