#pragma once #include "game/entities/entity.hpp" // Base d'entitats perilloses: al contacte amb el jugador, apliquen dany. // De moment `Player` no té HP exposat; l'andamiatge deixa el hook llest // (`damage_` + `onPlayerContact` publicant un event `"player_hit"`) perquè // la lògica real de vides es cable-je quan s'integri al GameScene. class Hazard : public Entity { public: Hazard() { collides_ = true; } [[nodiscard]] auto getDamage() const -> int { return damage_; } void setDamage(int d) { damage_ = d; } protected: int damage_{1}; }; // Perill estàtic: sempre al mateix tile. Suport opcional de cicle // actiu/inactiu (trampes que oscil·len). Quan `active_=false`, el contacte // no fa dany (però la detecció de col·lisió es manté: pot bloquejar o no // segons la configuració). class StaticHazard : public Hazard { public: StaticHazard() = default; void setCycle(float active_s, float inactive_s) { active_duration_ = active_s; inactive_duration_ = inactive_s; has_cycle_ = (active_s > 0.0F) || (inactive_s > 0.0F); } void update(float delta_time) override { Entity::update(delta_time); if (!has_cycle_) { return; } timer_ += delta_time; const float PERIOD = active_ ? active_duration_ : inactive_duration_; if (timer_ >= PERIOD) { timer_ -= PERIOD; active_ = !active_; } } [[nodiscard]] auto isActive() const -> bool { return active_; } protected: bool has_cycle_{false}; bool active_{true}; float active_duration_{0.0F}; float inactive_duration_{0.0F}; float timer_{0.0F}; }; // Perill dinàmic: es mou. Velocitat expressada en píxels/segon i una // direcció (vec2). Les subclasses decideixen la política de moviment // (IA corridor_wanderer, línia recta, etc.) sobreescribint `step(dt)`. class DynamicHazard : public Hazard { public: DynamicHazard() = default; void setSpeed(float px_per_s) { speed_ = px_per_s; } [[nodiscard]] auto getSpeed() const -> float { return speed_; } void setDirection(float dx, float dy) { dir_x_ = dx; dir_y_ = dy; } [[nodiscard]] auto getDirX() const -> float { return dir_x_; } [[nodiscard]] auto getDirY() const -> float { return dir_y_; } // Política de moviment per frame. La base desplaça el pixel_rect_ // proporcionalment a velocitat i direcció; les subclasses amb IA la // sobreescriuen per triar nova direcció a les interseccions o rebotar. virtual void step(float delta_time) { pixel_rect_.x += dir_x_ * speed_ * delta_time; pixel_rect_.y += dir_y_ * speed_ * delta_time; } void update(float delta_time) override { Entity::update(delta_time); step(delta_time); } protected: float speed_{0.0F}; float dir_x_{0.0F}; float dir_y_{0.0F}; };