diff --git a/source/bullet.cpp b/source/bullet.cpp index d327a27..262f9f6 100644 --- a/source/bullet.cpp +++ b/source/bullet.cpp @@ -4,28 +4,29 @@ #include // Para char_traits, basic_string, operator+, string #include "param.h" // Para Param, ParamGame, param +#include "player.h" // Para Player::Id #include "resource.h" // Para Resource // Constructor -Bullet::Bullet(float x, float y, BulletType bullet_type, bool powered, Player::Id owner) +Bullet::Bullet(float x, float y, Type type, Color color, int owner) : sprite_(std::make_unique(Resource::get()->getTexture("bullet.png"), Resource::get()->getAnimation("bullet.ani"))), - bullet_type_(bullet_type), + type_(type), owner_(owner), pos_x_(x), pos_y_(y) { - vel_x_ = calculateVelocity(bullet_type_); - sprite_->setCurrentAnimation(buildAnimationString(bullet_type_, powered)); + vel_x_ = calculateVelocity(type_); + sprite_->setCurrentAnimation(buildAnimationString(type_, color)); collider_.r = WIDTH / 2; shiftColliders(); } // Calcula la velocidad horizontal de la bala basada en su tipo -auto Bullet::calculateVelocity(BulletType bullet_type) -> float { - switch (bullet_type) { - case BulletType::LEFT: +auto Bullet::calculateVelocity(Type type) -> float { + switch (type) { + case Type::LEFT: return VEL_X_LEFT; - case BulletType::RIGHT: + case Type::RIGHT: return VEL_X_RIGHT; default: return VEL_X_CENTER; @@ -33,17 +34,17 @@ auto Bullet::calculateVelocity(BulletType bullet_type) -> float { } // Construye el string de animación basado en el tipo de bala y si está potenciada -auto Bullet::buildAnimationString(BulletType bullet_type, bool powered) -> std::string { - std::string animation_string = powered ? "powered_" : "normal_"; +auto Bullet::buildAnimationString(Type type, Color color) -> std::string { + std::string animation_string = color == Color::GREEN ? "powered_" : "normal_"; - switch (bullet_type) { - case BulletType::UP: + switch (type) { + case Type::UP: animation_string += "up"; break; - case BulletType::LEFT: + case Type::LEFT: animation_string += "left"; break; - case BulletType::RIGHT: + case Type::RIGHT: animation_string += "right"; break; default: @@ -53,49 +54,48 @@ auto Bullet::buildAnimationString(BulletType bullet_type, bool powered) -> std:: return animation_string; } -// Implementación de render (llama al render del sprite_) +// Implementación de render void Bullet::render() { - if (bullet_type_ != BulletType::NONE) { + if (type_ != Type::NONE) { sprite_->render(); } } -// Actualiza el estado del objeto (time-based) -auto Bullet::update(float deltaTime) -> BulletMoveStatus { +// Actualiza el estado del objeto +auto Bullet::update(float deltaTime) -> MoveStatus { sprite_->update(deltaTime); return move(deltaTime); } -// Implementación del movimiento usando BulletMoveStatus (time-based) -auto Bullet::move(float deltaTime) -> BulletMoveStatus { - // DeltaTime puro: velocidad (pixels/segundo) * tiempo (segundos) +// Implementación del movimiento usando MoveStatus +auto Bullet::move(float deltaTime) -> MoveStatus { pos_x_ += vel_x_ * deltaTime; if (pos_x_ < param.game.play_area.rect.x - WIDTH || pos_x_ > param.game.play_area.rect.w) { disable(); - return BulletMoveStatus::OUT; + return MoveStatus::OUT; } pos_y_ += VEL_Y * deltaTime; if (pos_y_ < param.game.play_area.rect.y - HEIGHT) { disable(); - return BulletMoveStatus::OUT; + return MoveStatus::OUT; } shiftSprite(); shiftColliders(); - return BulletMoveStatus::OK; + return MoveStatus::OK; } auto Bullet::isEnabled() const -> bool { - return bullet_type_ != BulletType::NONE; + return type_ != Type::NONE; } void Bullet::disable() { - bullet_type_ = BulletType::NONE; + type_ = Type::NONE; } -auto Bullet::getOwner() const -> Player::Id { +auto Bullet::getOwner() const -> int { return owner_; } diff --git a/source/bullet.h b/source/bullet.h index a16b52a..b7e19c1 100644 --- a/source/bullet.h +++ b/source/bullet.h @@ -6,22 +6,8 @@ #include // Para string #include "animated_sprite.h" // Para AnimatedSprite -#include "player.h" // Para Player #include "utils.h" // Para Circle -// --- Enums --- -enum class BulletType : Uint8 { - UP, // Bala hacia arriba - LEFT, // Bala hacia la izquierda - RIGHT, // Bala hacia la derecha - NONE // Sin bala -}; - -enum class BulletMoveStatus : Uint8 { - OK = 0, // Movimiento normal - OUT = 1 // Fuera de los límites -}; - // --- Clase Bullet: representa una bala del jugador --- class Bullet { public: @@ -29,19 +15,37 @@ class Bullet { static constexpr float WIDTH = 12.0F; // Anchura de la bala static constexpr float HEIGHT = 12.0F; // Altura de la bala + // --- Enums --- + enum class Type : Uint8 { + UP, // Bala hacia arriba + LEFT, // Bala hacia la izquierda + RIGHT, // Bala hacia la derecha + NONE // Sin bala + }; + + enum class MoveStatus : Uint8 { + OK = 0, // Movimiento normal + OUT = 1 // Fuera de los límites + }; + + enum class Color : Uint8 { + YELLOW, + GREEN + }; + // --- Constructor y destructor --- - Bullet(float x, float y, BulletType bullet_type, bool powered, Player::Id owner); // Constructor principal - ~Bullet() = default; // Destructor + Bullet(float x, float y, Type type, Color color, int owner); // Constructor principal + ~Bullet() = default; // Destructor // --- Métodos principales --- - void render(); // Dibuja la bala en pantalla - auto update(float deltaTime) -> BulletMoveStatus; // Actualiza el estado del objeto (time-based) - void disable(); // Desactiva la bala + void render(); // Dibuja la bala en pantalla + auto update(float deltaTime) -> MoveStatus; // Actualiza el estado del objeto (time-based) + void disable(); // Desactiva la bala // --- Getters --- - [[nodiscard]] auto isEnabled() const -> bool; // Comprueba si está activa - [[nodiscard]] auto getOwner() const -> Player::Id; // Devuelve el identificador del dueño - auto getCollider() -> Circle &; // Devuelve el círculo de colisión + [[nodiscard]] auto isEnabled() const -> bool; // Comprueba si está activa + [[nodiscard]] auto getOwner() const -> int; // Devuelve el identificador del dueño + auto getCollider() -> Circle&; // Devuelve el círculo de colisión private: // --- Constantes --- @@ -54,17 +58,17 @@ class Bullet { std::unique_ptr sprite_; // Sprite con los gráficos // --- Variables de estado --- - Circle collider_; // Círculo de colisión - BulletType bullet_type_; // Tipo de bala - Player::Id owner_; // Identificador del dueño - float pos_x_; // Posición en el eje X - float pos_y_; // Posición en el eje Y - float vel_x_; // Velocidad en el eje X + Circle collider_; // Círculo de colisión + Type type_; // Tipo de bala + int owner_; // Identificador del jugador + float pos_x_; // Posición en el eje X + float pos_y_; // Posición en el eje Y + float vel_x_; // Velocidad en el eje X // --- Métodos internos --- - void shiftColliders(); // Ajusta el círculo de colisión - void shiftSprite(); // Ajusta el sprite - auto move(float deltaTime) -> BulletMoveStatus; // Mueve la bala y devuelve su estado (time-based) - static auto calculateVelocity(BulletType bullet_type) -> float; // Calcula la velocidad horizontal de la bala - static auto buildAnimationString(BulletType bullet_type, bool powered) -> std::string; // Construye el string de animación + void shiftColliders(); // Ajusta el círculo de colisión + void shiftSprite(); // Ajusta el sprite + auto move(float deltaTime) -> MoveStatus; // Mueve la bala y devuelve su estado (time-based) + static auto calculateVelocity(Type type) -> float; // Calcula la velocidad horizontal de la bala + static auto buildAnimationString(Type type, Color color) -> std::string; // Construye el string de animación }; diff --git a/source/player.cpp b/source/player.cpp index a060490..63d04d7 100644 --- a/source/player.cpp +++ b/source/player.cpp @@ -22,7 +22,7 @@ #endif // Constructor -Player::Player(const Config &config) +Player::Player(const Config& config) : player_sprite_(std::make_unique(config.texture.at(0), config.animations.at(0))), power_sprite_(std::make_unique(config.texture.at(4), config.animations.at(1))), enter_name_(std::make_unique()), @@ -396,24 +396,8 @@ void Player::updateStepCounter(float deltaTime) { // Pinta el jugador en pantalla void Player::render() { - if (power_up_ && isPlaying()) { - // Convertir lógica de parpadeo a deltaTime en segundos - const float TOTAL_POWERUP_TIME_S = static_cast(POWERUP_COUNTER) / 60.0f; // Total time in seconds - const float QUARTER_TIME_S = TOTAL_POWERUP_TIME_S / 4.0f; // 25% del tiempo total - - if (power_up_time_accumulator_ > QUARTER_TIME_S) { - // En los primeros 75% del tiempo, siempre visible - power_sprite_->render(); - } else { - // En el último 25%, parpadea cada 20 frames (≈0.333s) - constexpr float BLINK_PERIOD_S = 20.0f / 60.0f; // 20 frames in seconds - constexpr float VISIBLE_PROPORTION = 4.0f / 20.0f; // 4 frames visible de 20 total - - float cycle_position = fmod(power_up_time_accumulator_, BLINK_PERIOD_S) / BLINK_PERIOD_S; - if (cycle_position >= VISIBLE_PROPORTION) { - power_sprite_->render(); - } - } + if (power_sprite_visible_ && isPlaying()) { + power_sprite_->render(); } if (isRenderable()) { @@ -774,6 +758,9 @@ void Player::setPowerUp() { power_up_ = true; power_up_counter_ = POWERUP_COUNTER; power_up_time_accumulator_ = static_cast(POWERUP_COUNTER) / 60.0f; // Convert frames to seconds + power_sprite_visible_ = true; // Inicialmente visible cuando se activa el power-up + in_power_up_ending_phase_ = false; // Empezar en fase normal + bullet_color_toggle_ = false; // Resetear toggle } // Actualiza el valor de la variable (time-based) @@ -784,7 +771,36 @@ void Player::updatePowerUp(float deltaTime) { power_up_ = power_up_time_accumulator_ > 0; if (!power_up_) { power_up_time_accumulator_ = 0; + power_sprite_visible_ = false; + in_power_up_ending_phase_ = false; + bullet_color_toggle_ = false; + bullet_color_ = Bullet::Color::YELLOW; + } else { + // Calcular visibilidad del power sprite + const float TOTAL_POWERUP_TIME_S = static_cast(POWERUP_COUNTER) / 60.0f; + const float QUARTER_TIME_S = TOTAL_POWERUP_TIME_S / 4.0f; + + if (power_up_time_accumulator_ > QUARTER_TIME_S) { + // En los primeros 75% del tiempo, siempre visible + power_sprite_visible_ = true; + in_power_up_ending_phase_ = false; + bullet_color_ = Bullet::Color::GREEN; + } else { + // En el último 25%, parpadea cada 20 frames (≈0.333s) + constexpr float BLINK_PERIOD_S = 20.0f / 60.0f; + constexpr float VISIBLE_PROPORTION = 4.0f / 20.0f; + + float cycle_position = fmod(power_up_time_accumulator_, BLINK_PERIOD_S) / BLINK_PERIOD_S; + power_sprite_visible_ = cycle_position >= VISIBLE_PROPORTION; + in_power_up_ending_phase_ = true; // Activar modo alternancia de colores de balas + bullet_color_ = power_sprite_visible_ ? Bullet::Color::GREEN : Bullet::Color::YELLOW; + } } + } else { + power_sprite_visible_ = false; + in_power_up_ending_phase_ = false; + bullet_color_toggle_ = false; + bullet_color_ = Bullet::Color::YELLOW; } } } @@ -816,7 +832,7 @@ void Player::shiftColliders() { } // Pone las texturas del jugador -void Player::setPlayerTextures(const std::vector> &texture) { +void Player::setPlayerTextures(const std::vector>& texture) { player_sprite_->setTexture(texture[0]); power_sprite_->setTexture(texture[1]); } @@ -905,12 +921,12 @@ void Player::shiftSprite() { } // Hace sonar un sonido -void Player::playSound(const std::string &name) const { +void Player::playSound(const std::string& name) const { if (demo_) { return; } - static auto *audio_ = Audio::get(); + static auto* audio_ = Audio::get(); audio_->playSound(name); } @@ -919,6 +935,17 @@ auto Player::isRenderable() const -> bool { return !isTitleHidden(); }; +// Devuelve el color para la próxima bala (alterna si está en modo toggle) +auto Player::getNextBulletColor() -> Bullet::Color { + if (in_power_up_ending_phase_) { + // En fase final: alternar entre verde y amarillo + bullet_color_toggle_ = !bullet_color_toggle_; + return bullet_color_toggle_ ? Bullet::Color::GREEN : Bullet::Color::YELLOW; + } + // Modo normal: sin power-up = amarillo, con power-up = verde + return bullet_color_; +} + // Añade una puntuación a la tabla de records void Player::addScoreToScoreBoard() const { if (hi_score_table_ == nullptr) { diff --git a/source/player.h b/source/player.h index 542db2d..da61f57 100644 --- a/source/player.h +++ b/source/player.h @@ -8,6 +8,7 @@ #include // Para vector #include "animated_sprite.h" // Para AnimatedSprite +#include "bullet.h" // Para Bullet #include "enter_name.h" // Para EnterName #include "input.h" // Para Input #include "manage_hiscore_table.h" // Para Table @@ -95,22 +96,22 @@ class Player { float x; // Posición X inicial int y; // Posición Y inicial bool demo; // Modo demo - SDL_FRect *play_area; // Área de juego (puntero para mantener referencia) + SDL_FRect* play_area; // Área de juego (puntero para mantener referencia) std::vector> texture; // Texturas del jugador std::vector> animations; // Animaciones del jugador - Table *hi_score_table; // Tabla de puntuaciones (puntero para referencia) - int *glowing_entry; // Entrada brillante (puntero para mantener referencia) - IStageInfo *stage_info; // Gestor de pantallas (puntero) + Table* hi_score_table; // Tabla de puntuaciones (puntero para referencia) + int* glowing_entry; // Entrada brillante (puntero para mantener referencia) + IStageInfo* stage_info; // Gestor de pantallas (puntero) }; // --- Constructor y destructor --- - Player(const Config &config); + Player(const Config& config); ~Player() = default; // --- Inicialización y ciclo de vida --- - void init(); // Inicializa el jugador - void update(float deltaTime); // Actualiza estado, animación y contadores (time-based) - void render(); // Dibuja el jugador en pantalla + void init(); // Inicializa el jugador + void update(float deltaTime); // Actualiza estado, animación y contadores (time-based) + void render(); // Dibuja el jugador en pantalla // --- Entrada y control --- void setInput(Input::Action action); // Procesa entrada general @@ -118,11 +119,11 @@ class Player { void setInputEnteringName(Input::Action action); // Procesa entrada al introducir nombre // --- Movimiento y animación --- - void move(float deltaTime); // Mueve el jugador (time-based) - void setAnimation(float deltaTime); // Establece la animación según el estado (time-based) + void move(float deltaTime); // Mueve el jugador (time-based) + void setAnimation(float deltaTime); // Establece la animación según el estado (time-based) // --- Texturas y animaciones --- - void setPlayerTextures(const std::vector> &texture); // Cambia las texturas del jugador + void setPlayerTextures(const std::vector>& texture); // Cambia las texturas del jugador // --- Estados y contadores --- @@ -132,13 +133,13 @@ class Player { void decScoreMultiplier(); // Decrementa el multiplicador // --- Estados de juego --- - void setPlayingState(State state); // Cambia el estado de juego - void setInvulnerable(bool value); // Establece el valor del estado de invulnerabilidad - void setPowerUp(); // Activa el modo PowerUp - void updatePowerUp(float deltaTime); // Actualiza el valor de PowerUp (time-based) - void giveExtraHit(); // Concede un toque extra al jugador - void removeExtraHit(); // Quita el toque extra al jugador - void decContinueCounter(); // Decrementa el contador de continuar + void setPlayingState(State state); // Cambia el estado de juego + void setInvulnerable(bool value); // Establece el valor del estado de invulnerabilidad + void setPowerUp(); // Activa el modo PowerUp + void updatePowerUp(float deltaTime); // Actualiza el valor de PowerUp (time-based) + void giveExtraHit(); // Concede un toque extra al jugador + void removeExtraHit(); // Quita el toque extra al jugador + void decContinueCounter(); // Decrementa el contador de continuar // --- Getters y comprobaciones de estado --- [[nodiscard]] auto getRecordNamePos() const -> int; // Obtiene la posición que se está editando del nombre del jugador para la tabla de mejores puntuaciones @@ -165,7 +166,7 @@ class Player { [[nodiscard]] auto qualifiesForHighScore() const -> bool { return qualifies_for_high_score_; } [[nodiscard]] auto isInvulnerable() const -> bool { return invulnerable_; } [[nodiscard]] auto isPowerUp() const -> bool { return power_up_; } - auto getCollider() -> Circle & { return collider_; } + auto getCollider() -> Circle& { return collider_; } [[nodiscard]] auto getScoreMultiplier() const -> float { return score_multiplier_; } [[nodiscard]] auto getCoffees() const -> int { return coffees_; } [[nodiscard]] auto getContinueCounter() const -> int { return continue_counter_; } @@ -182,16 +183,19 @@ class Player { [[nodiscard]] auto getScoreBoardPanel() const -> Scoreboard::Id { return scoreboard_panel_; } [[nodiscard]] static auto getWidth() -> int { return WIDTH; } [[nodiscard]] auto getPlayingState() const -> State { return playing_state_; } - [[nodiscard]] auto getName() const -> const std::string & { return name_; } + [[nodiscard]] auto getName() const -> const std::string& { return name_; } [[nodiscard]] auto get1CC() const -> bool { return game_completed_ && credits_used_ <= 1; } [[nodiscard]] auto getEnterNamePositionOverflow() const -> bool { return enter_name_ ? enter_name_->getPositionOverflow() : false; } + [[nodiscard]] auto getBulletColor() const -> Bullet::Color { return bullet_color_; } + [[nodiscard]] auto isInBulletColorToggleMode() const -> bool { return in_power_up_ending_phase_; } + auto getNextBulletColor() -> Bullet::Color; // Devuelve el color para la próxima bala (alterna si está en modo toggle) // Setters inline void setController(int index) { controller_index_ = index; } - void startFiringSystem(int cooldown_frames); // Método público para iniciar disparo + void startFiringSystem(int cooldown_frames); // Método público para iniciar disparo void setFiringState(State state) { firing_state_ = state; } void setInvulnerableCounter(int value) { invulnerable_counter_ = value; } - void setName(const std::string &name) { name_ = name; } + void setName(const std::string& name) { name_ = name; } void setPowerUpCounter(int value) { power_up_counter_ = value; } void setScore(int score) { score_ = score; } void setScoreBoardPanel(Scoreboard::Id panel) { scoreboard_panel_ = panel; } @@ -207,7 +211,7 @@ class Player { private: // --- Constantes de física y movimiento --- - static constexpr float BASE_SPEED = 90.0f; // Velocidad base del jugador (pixels/segundo) + static constexpr float BASE_SPEED = 90.0f; // Velocidad base del jugador (pixels/segundo) // --- Constantes de power-ups y estados especiales --- static constexpr int POWERUP_COUNTER = 1500; // Duración del estado PowerUp (frames) @@ -215,16 +219,16 @@ class Player { static constexpr size_t INVULNERABLE_TEXTURE = 3; // Textura usada durante invulnerabilidad // --- Constantes del sistema de disparo (obsoletas - usar nuevo sistema) --- - static constexpr int COOLING_DURATION = 50; // Duración del enfriamiento tras disparar - static constexpr int COOLING_COMPLETE = 0; // Valor que indica enfriamiento completado + static constexpr int COOLING_DURATION = 50; // Duración del enfriamiento tras disparar + static constexpr int COOLING_COMPLETE = 0; // Valor que indica enfriamiento completado // --- Constantes de estados de espera --- - static constexpr int WAITING_COUNTER = 1000; // Tiempo de espera en estado de espera + static constexpr int WAITING_COUNTER = 1000; // Tiempo de espera en estado de espera // --- Constantes del nuevo sistema de disparo de dos líneas --- - static constexpr float AIMING_DURATION_FACTOR = 0.5f; // 50% del cooldown funcional - static constexpr float RECOILING_DURATION_MULTIPLIER = 4.0f; // 4 veces la duración de aiming - static constexpr float THREAT_POSE_DURATION = 50.0f / 60.0f; // 50 frames = ~0.833s (duración base) + static constexpr float AIMING_DURATION_FACTOR = 0.5f; // 50% del cooldown funcional + static constexpr float RECOILING_DURATION_MULTIPLIER = 4.0f; // 4 veces la duración de aiming + static constexpr float THREAT_POSE_DURATION = 50.0f / 60.0f; // 50 frames = ~0.833s (duración base) static constexpr float MIN_THREAT_POSE_DURATION = 6.0f / 60.0f; // 6 frames = ~0.1s (duración mínima) // --- Objetos y punteros --- @@ -232,9 +236,9 @@ class Player { std::unique_ptr power_sprite_; // Sprite para dibujar el aura del jugador con el poder a tope std::unique_ptr enter_name_; // Clase utilizada para introducir el nombre std::shared_ptr gamepad_ = nullptr; // Dispositivo asociado - Table *hi_score_table_ = nullptr; // Tabla de máximas puntuaciones - int *glowing_entry_ = nullptr; // Entrada de la tabla de puntuaciones para hacerla brillar - IStageInfo *stage_info_; // Informacion de la pantalla actual + Table* hi_score_table_ = nullptr; // Tabla de máximas puntuaciones + int* glowing_entry_ = nullptr; // Entrada de la tabla de puntuaciones para hacerla brillar + IStageInfo* stage_info_; // Informacion de la pantalla actual // --- Variables de estado --- SDL_FRect play_area_; // Rectángulo con la zona de juego @@ -246,43 +250,43 @@ class Player { State walking_state_ = State::WALKING_STOP; // Estado del jugador al moverse State firing_state_ = State::FIRING_NONE; // Estado del jugador al disparar State playing_state_ = State::WAITING; // Estado del jugador en el juego + Bullet::Color bullet_color_ = Bullet::Color::YELLOW; // Color de la bala del jugador - float pos_x_ = 0.0F; // Posición en el eje X - float default_pos_x_; // Posición inicial para el jugador - float vel_x_ = 0.0F; // Cantidad de píxeles a desplazarse en el eje X - float score_multiplier_ = 1.0F; // Multiplicador de puntos - int pos_y_ = 0; // Posición en el eje Y - int default_pos_y_; // Posición inicial para el jugador - int vel_y_ = 0; // Cantidad de píxeles a desplazarse en el eje Y - float invulnerable_time_accumulator_ = 0.0f; // Acumulador de tiempo para invulnerabilidad (time-based) - float power_up_time_accumulator_ = 0.0f; // Acumulador de tiempo para power-up (time-based) - float continue_time_accumulator_ = 0.0f; // Acumulador de tiempo para continue counter (time-based) - float name_entry_time_accumulator_ = 0.0f; // Acumulador de tiempo para name entry counter (time-based) - float showing_name_time_accumulator_ = 0.0f; // Acumulador de tiempo para showing name (time-based) - float waiting_time_accumulator_ = 0.0f; // Acumulador de tiempo para waiting movement (time-based) - float step_time_accumulator_ = 0.0f; // Acumulador de tiempo para step counter (time-based) + float pos_x_ = 0.0F; // Posición en el eje X + float default_pos_x_; // Posición inicial para el jugador + float vel_x_ = 0.0F; // Cantidad de píxeles a desplazarse en el eje X + float score_multiplier_ = 1.0F; // Multiplicador de puntos + int pos_y_ = 0; // Posición en el eje Y + int default_pos_y_; // Posición inicial para el jugador + int vel_y_ = 0; // Cantidad de píxeles a desplazarse en el eje Y + float invulnerable_time_accumulator_ = 0.0f; // Acumulador de tiempo para invulnerabilidad (time-based) + float power_up_time_accumulator_ = 0.0f; // Acumulador de tiempo para power-up (time-based) + float continue_time_accumulator_ = 0.0f; // Acumulador de tiempo para continue counter (time-based) + float name_entry_time_accumulator_ = 0.0f; // Acumulador de tiempo para name entry counter (time-based) + float showing_name_time_accumulator_ = 0.0f; // Acumulador de tiempo para showing name (time-based) + float waiting_time_accumulator_ = 0.0f; // Acumulador de tiempo para waiting movement (time-based) + float step_time_accumulator_ = 0.0f; // Acumulador de tiempo para step counter (time-based) // ======================================== // NUEVO SISTEMA DE DISPARO DE DOS LÍNEAS // ======================================== // LÍNEA 1: SISTEMA FUNCIONAL (CanFire) - float fire_cooldown_timer_ = 0.0f; // Tiempo restante hasta poder disparar otra vez - bool can_fire_new_system_ = true; // true si puede disparar ahora mismo + float fire_cooldown_timer_ = 0.0f; // Tiempo restante hasta poder disparar otra vez + bool can_fire_new_system_ = true; // true si puede disparar ahora mismo // LÍNEA 2: SISTEMA VISUAL (Animaciones) enum class VisualFireState { - NORMAL, // Brazo en posición neutral - AIMING, // Brazo alzado (disparando) - RECOILING, // Brazo en retroceso - THREAT_POSE // Posición amenazante + NORMAL, // Brazo en posición neutral + AIMING, // Brazo alzado (disparando) + RECOILING, // Brazo en retroceso + THREAT_POSE // Posición amenazante }; VisualFireState visual_fire_state_ = VisualFireState::NORMAL; - float visual_state_timer_ = 0.0f; // Tiempo en el estado visual actual - float aiming_duration_ = 0.0f; // Duración del estado AIMING - float recoiling_duration_ = 0.0f; // Duración del estado RECOILING - + float visual_state_timer_ = 0.0f; // Tiempo en el estado visual actual + float aiming_duration_ = 0.0f; // Duración del estado AIMING + float recoiling_duration_ = 0.0f; // Duración del estado RECOILING int invulnerable_counter_ = INVULNERABLE_COUNTER; // Contador para la invulnerabilidad int score_ = 0; // Puntos del jugador @@ -300,33 +304,36 @@ class Player { bool invulnerable_ = true; // Indica si el jugador es invulnerable bool extra_hit_ = false; // Indica si el jugador tiene un toque extra bool power_up_ = false; // Indica si el jugador tiene activo el modo PowerUp + bool power_sprite_visible_ = false; // Indica si el sprite de power-up debe ser visible + bool in_power_up_ending_phase_ = false; // Indica si está en la fase final del power-up (alternando colores) + bool bullet_color_toggle_ = false; // Para alternar entre verde y amarillo en fase final bool demo_ = false; // Para que el jugador sepa si está en el modo demostración bool game_completed_ = false; // Indica si ha completado el juego bool uses_keyboard_ = false; // Indica si usa el teclado como dispositivo de control // --- Métodos internos --- - void shiftColliders(); // Actualiza el círculo de colisión a la posición del jugador - void shiftSprite(); // Recoloca el sprite - void updateInvulnerable(float deltaTime); // Monitoriza el estado de invulnerabilidad (time-based) - void updateContinueCounter(float deltaTime); // Actualiza el contador de continue (time-based) - void updateEnterNameCounter(float deltaTime); // Actualiza el contador de entrar nombre (time-based) - void updateShowingName(float deltaTime); // Actualiza el estado SHOWING_NAME (time-based) - void decNameEntryCounter(); // Decrementa el contador de entrar nombre - void updateScoreboard(); // Actualiza el panel del marcador - void setScoreboardMode(Scoreboard::Mode mode) const; // Cambia el modo del marcador - void playSound(const std::string &name) const; // Hace sonar un sonido - [[nodiscard]] auto isRenderable() const -> bool; // Indica si se puede dibujar el objeto - void addScoreToScoreBoard() const; // Añade una puntuación a la tabla de records + void shiftColliders(); // Actualiza el círculo de colisión a la posición del jugador + void shiftSprite(); // Recoloca el sprite + void updateInvulnerable(float deltaTime); // Monitoriza el estado de invulnerabilidad (time-based) + void updateContinueCounter(float deltaTime); // Actualiza el contador de continue (time-based) + void updateEnterNameCounter(float deltaTime); // Actualiza el contador de entrar nombre (time-based) + void updateShowingName(float deltaTime); // Actualiza el estado SHOWING_NAME (time-based) + void decNameEntryCounter(); // Decrementa el contador de entrar nombre + void updateScoreboard(); // Actualiza el panel del marcador + void setScoreboardMode(Scoreboard::Mode mode) const; // Cambia el modo del marcador + void playSound(const std::string& name) const; // Hace sonar un sonido + [[nodiscard]] auto isRenderable() const -> bool; // Indica si se puede dibujar el objeto + void addScoreToScoreBoard() const; // Añade una puntuación a la tabla de records // --- Métodos del sistema de disparo de dos líneas --- - void updateFireSystem(float deltaTime); // Método principal del nuevo sistema de disparo - void updateFunctionalLine(float deltaTime); // Actualiza la línea funcional (CanFire) - void updateVisualLine(float deltaTime); // Actualiza la línea visual (Animaciones) - void startFiring(int cooldown_frames); // Inicia un nuevo disparo en ambas líneas - void updateFiringStateFromVisual(); // Sincroniza firing_state_ con visual_fire_state_ - void transitionToRecoilingNew(); // Transición AIMING → RECOILING - void transitionToThreatPose(); // Transición RECOILING → THREAT_POSE - void transitionToNormalNew(); // Transición THREAT_POSE → NORMAL + void updateFireSystem(float deltaTime); // Método principal del nuevo sistema de disparo + void updateFunctionalLine(float deltaTime); // Actualiza la línea funcional (CanFire) + void updateVisualLine(float deltaTime); // Actualiza la línea visual (Animaciones) + void startFiring(int cooldown_frames); // Inicia un nuevo disparo en ambas líneas + void updateFiringStateFromVisual(); // Sincroniza firing_state_ con visual_fire_state_ + void transitionToRecoilingNew(); // Transición AIMING → RECOILING + void transitionToThreatPose(); // Transición RECOILING → THREAT_POSE + void transitionToNormalNew(); // Transición THREAT_POSE → NORMAL // --- Métodos del sistema de disparo obsoleto --- void handleFiringCooldown(); // Gestiona el tiempo de espera después de disparar (frame-based) @@ -339,7 +346,7 @@ class Player { void transitionToCooling(); // Transición a enfriamiento (sistema obsoleto) void completeCooling(); // Finaliza enfriamiento (sistema obsoleto) void handlePlayingMovement(); // Gestiona el movimiento del personaje u objeto durante el estado de juego activo (frame-based) - void handlePlayingMovement(float deltaTime); // Gestiona el movimiento del personaje u objeto durante el estado de juego activo (time-based) + void handlePlayingMovement(float deltaTime); // Gestiona el movimiento del personaje u objeto durante el estado de juego activo (time-based) void handleRecoverMovement(); // Comprueba si ha acabado la animación void handleRollingMovement(); // Actualiza la lógica de movimiento de "rodar" (posiblemente tras impacto o acción especial) void handleRollingBoundaryCollision(); // Detecta y maneja colisiones del objeto rodante con los límites de la pantalla @@ -348,19 +355,19 @@ class Player { void handleRollingBounce(); // Aplica una lógica de rebote al colisionar con superficies durante el rodamiento void handleTitleAnimation(float deltaTime); // Ejecuta la animación del título en pantalla (ej. entrada, parpadeo o desplazamiento) void handleContinueTimeOut(); // Gestiona el tiempo de espera en la pantalla de "Continuar" y decide si pasar a otro estado - void handleLeavingScreen(float deltaTime); // Lógica para salir de la pantalla actual (transición visual o cambio de escena) - void handleEnteringScreen(float deltaTime); // Lógica para entrar en una nueva pantalla, posiblemente con animación o retraso - void handlePlayer1Entering(float deltaTime); // Controla la animación o posición de entrada del Jugador 1 en pantalla - void handlePlayer2Entering(float deltaTime); // Controla la animación o posición de entrada del Jugador 2 en pantalla + void handleLeavingScreen(float deltaTime); // Lógica para salir de la pantalla actual (transición visual o cambio de escena) + void handleEnteringScreen(float deltaTime); // Lógica para entrar en una nueva pantalla, posiblemente con animación o retraso + void handlePlayer1Entering(float deltaTime); // Controla la animación o posición de entrada del Jugador 1 en pantalla + void handlePlayer2Entering(float deltaTime); // Controla la animación o posición de entrada del Jugador 2 en pantalla void handleCreditsMovement(); // Movimiento general en la pantalla de créditos (frame-based) - void handleCreditsMovement(float deltaTime); // Movimiento general en la pantalla de créditos (time-based) + void handleCreditsMovement(float deltaTime); // Movimiento general en la pantalla de créditos (time-based) void handleCreditsRightMovement(); // Lógica específica para mover los créditos hacia la derecha void handleCreditsLeftMovement(); // Lógica específica para mover los créditos hacia la izquierda void handleWaitingMovement(); // Controla la animación del jugador saludando (frame-based) - void handleWaitingMovement(float deltaTime); // Controla la animación del jugador saludando (time-based) + void handleWaitingMovement(float deltaTime); // Controla la animación del jugador saludando (time-based) void updateWalkingStateForCredits(); // Actualiza el estado de caminata de algún personaje u elemento animado en los créditos void setInputBasedOnPlayerId(); // Asocia las entradas de control en función del identificador del jugador (teclas, mando, etc.) void updateStepCounter(); // Incrementa o ajusta el contador de pasos (frame-based) - void updateStepCounter(float deltaTime); // Incrementa o ajusta el contador de pasos (time-based) + void updateStepCounter(float deltaTime); // Incrementa o ajusta el contador de pasos (time-based) [[nodiscard]] auto computeAnimation() const -> std::pair; // Calcula la animacion de moverse y disparar del jugador }; \ No newline at end of file diff --git a/source/sections/game.cpp b/source/sections/game.cpp index e8617f6..bc6ac40 100644 --- a/source/sections/game.cpp +++ b/source/sections/game.cpp @@ -15,7 +15,7 @@ #include "background.h" // Para Background #include "balloon.h" // Para Balloon #include "balloon_manager.h" // Para BalloonManager -#include "bullet.h" // Para Bullet, BulletType, BulletMoveStatus +#include "bullet.h" // Para Bullet, Bullet::Type, BulletMoveStatus #include "color.h" // Para Color, Colors::FLASH #include "difficulty.h" // Para Code #include "fade.h" // Para Fade, FadeType, FadeMode @@ -564,7 +564,7 @@ auto Game::checkBulletBalloonCollision(const std::shared_ptr &bullet) -> // Procesa el impacto en un globo void Game::processBalloonHit(const std::shared_ptr &bullet, const std::shared_ptr &balloon) { - auto player = getPlayer(bullet->getOwner()); + auto player = getPlayer(static_cast(bullet->getOwner())); handleItemDrop(balloon, player); handleBalloonDestruction(balloon, player); @@ -602,8 +602,8 @@ void Game::handleBalloonDestruction(std::shared_ptr balloon, const std: // Mueve las balas activas void Game::updateBullets(float deltaTime) { for (auto &bullet : bullets_) { - if (bullet->update(deltaTime) == BulletMoveStatus::OUT) { - getPlayer(bullet->getOwner())->decScoreMultiplier(); + if (bullet->update(deltaTime) == Bullet::MoveStatus::OUT) { + getPlayer(static_cast(bullet->getOwner()))->decScoreMultiplier(); } } } @@ -616,8 +616,8 @@ void Game::renderBullets() { } // Crea un objeto bala -void Game::createBullet(int x, int y, BulletType kind, bool powered_up, Player::Id owner) { - bullets_.emplace_back(std::make_shared(x, y, kind, powered_up, owner)); +void Game::createBullet(int x, int y, Bullet::Type type, Bullet::Color color, int owner) { + bullets_.emplace_back(std::make_shared(x, y, type, color, owner)); } // Vacia el vector de balas @@ -1305,30 +1305,30 @@ void Game::demoHandlePlayerInput(const std::shared_ptr &player, int inde } if (demo_data.fire == 1) { - handleFireInput(player, BulletType::UP); + handleFireInput(player, Bullet::Type::UP); } else if (demo_data.fire_left == 1) { - handleFireInput(player, BulletType::LEFT); + handleFireInput(player, Bullet::Type::LEFT); } else if (demo_data.fire_right == 1) { - handleFireInput(player, BulletType::RIGHT); + handleFireInput(player, Bullet::Type::RIGHT); } } // Maneja el disparo de un jugador, incluyendo la creación de balas y la gestión del tiempo de espera entre disparos. -void Game::handleFireInput(const std::shared_ptr &player, BulletType bullet_type) { +void Game::handleFireInput(const std::shared_ptr &player, Bullet::Type type) { if (player->canFire()) { SDL_Point bullet = {0, 0}; - switch (bullet_type) { - case BulletType::UP: + switch (type) { + case Bullet::Type::UP: player->setInput(Input::Action::FIRE_CENTER); bullet.x = 2 + player->getPosX() + (Player::WIDTH - Bullet::WIDTH) / 2; bullet.y = player->getPosY() - (Bullet::HEIGHT / 2); break; - case BulletType::LEFT: + case Bullet::Type::LEFT: player->setInput(Input::Action::FIRE_LEFT); bullet.x = player->getPosX() - (Bullet::WIDTH / 2); bullet.y = player->getPosY(); break; - case BulletType::RIGHT: + case Bullet::Type::RIGHT: player->setInput(Input::Action::FIRE_RIGHT); bullet.x = player->getPosX() + Player::WIDTH - (Bullet::WIDTH / 2); bullet.y = player->getPosY(); @@ -1336,7 +1336,7 @@ void Game::handleFireInput(const std::shared_ptr &player, BulletType bul default: break; } - createBullet(bullet.x, bullet.y, bullet_type, player->isPowerUp(), player->getId()); + createBullet(bullet.x, bullet.y, type, player->getNextBulletColor(), static_cast(player->getId())); playSound("bullet.wav"); // Establece un tiempo de espera para el próximo disparo. @@ -1402,7 +1402,7 @@ void Game::handleFireInputs(const std::shared_ptr &player, bool autofire } if (input_->checkAction(Input::Action::FIRE_CENTER, autofire, player->getUsesKeyboard(), player->getGamepad())) { - handleFireInput(player, BulletType::UP); + handleFireInput(player, Bullet::Type::UP); #ifdef RECORDING demo_.keys.fire = 1; #endif @@ -1410,7 +1410,7 @@ void Game::handleFireInputs(const std::shared_ptr &player, bool autofire } if (input_->checkAction(Input::Action::FIRE_LEFT, autofire, player->getUsesKeyboard(), player->getGamepad())) { - handleFireInput(player, BulletType::LEFT); + handleFireInput(player, Bullet::Type::LEFT); #ifdef RECORDING demo_.keys.fire_left = 1; #endif @@ -1418,7 +1418,7 @@ void Game::handleFireInputs(const std::shared_ptr &player, bool autofire } if (input_->checkAction(Input::Action::FIRE_RIGHT, autofire, player->getUsesKeyboard(), player->getGamepad())) { - handleFireInput(player, BulletType::RIGHT); + handleFireInput(player, Bullet::Type::RIGHT); #ifdef RECORDING demo_.keys.fire_right = 1; #endif diff --git a/source/sections/game.h b/source/sections/game.h index c8e765c..4d60331 100644 --- a/source/sections/game.h +++ b/source/sections/game.h @@ -6,6 +6,7 @@ #include // Para string #include // Para vector +#include "bullet.h" // Para Bullet #include "hit.h" // Para Hit #include "item.h" // Para Item, ItemType #include "manage_hiscore_table.h" // Para HiScoreEntry @@ -27,7 +28,6 @@ class Scoreboard; class Screen; class Tabe; class Texture; -enum class BulletType : Uint8; namespace Difficulty { enum class Code; @@ -77,7 +77,7 @@ class Game { static constexpr float HELP_COUNTER_S = 16.667f; // Contador de ayuda (1000 frames a 60fps → segundos) static constexpr float GAME_COMPLETED_START_FADE_S = 8.333f; // Inicio del fade al completar (500 frames → segundos) static constexpr float GAME_COMPLETED_END_S = 11.667f; // Fin del juego completado (700 frames → segundos) - static constexpr float GAME_OVER_DURATION_S = 7.0f; // Duración game over (350 frames → segundos) + static constexpr float GAME_OVER_DURATION_S = 7.0f; // Duración game over (350 frames → segundos) static constexpr float TIME_STOPPED_DURATION_S = 6.0f; // Duración del tiempo detenido (360 frames → segundos) static constexpr float DEMO_FADE_PRE_DURATION_S = 0.5f; // Pre-duración del fade en modo demo static constexpr int ITEM_POINTS_1_DISK_ODDS = 10; @@ -112,12 +112,12 @@ class Game { }; // --- Objetos y punteros --- - SDL_Renderer *renderer_; // El renderizador de la ventana - Screen *screen_; // Objeto encargado de dibujar en pantalla - Input *input_; // Manejador de entrada - Scoreboard *scoreboard_; // Objeto para dibujar el marcador + SDL_Renderer* renderer_; // El renderizador de la ventana + Screen* screen_; // Objeto encargado de dibujar en pantalla + Input* input_; // Manejador de entrada + Scoreboard* scoreboard_; // Objeto para dibujar el marcador - SDL_Texture *canvas_; // Textura para dibujar la zona de juego + SDL_Texture* canvas_; // Textura para dibujar la zona de juego std::vector> players_; // Vector con los jugadores std::vector> bullets_; // Vector con las balas @@ -203,39 +203,39 @@ class Game { auto allPlayersAreNotPlaying() -> bool; // Verifica si ningún jugador está activo // --- Colisiones de jugadores --- - void handlePlayerCollision(std::shared_ptr &player, std::shared_ptr &balloon); // Procesa colisión de jugador con globo - auto checkPlayerBalloonCollision(std::shared_ptr &player) -> std::shared_ptr; // Detecta colisión jugador-globo - void checkPlayerItemCollision(std::shared_ptr &player); // Detecta colisión jugador-ítem + void handlePlayerCollision(std::shared_ptr& player, std::shared_ptr& balloon); // Procesa colisión de jugador con globo + auto checkPlayerBalloonCollision(std::shared_ptr& player) -> std::shared_ptr; // Detecta colisión jugador-globo + void checkPlayerItemCollision(std::shared_ptr& player); // Detecta colisión jugador-ítem // --- Sistema de entrada (input) --- void checkInput(); // Gestiona toda la entrada durante el juego void checkPauseInput(); // Verifica solicitudes de pausa de controladores // --- Entrada de jugadores normales --- - void handlePlayersInput(); // Gestiona entrada de todos los jugadores - void handleNormalPlayerInput(const std::shared_ptr &player); // Procesa entrada de un jugador específico - void handleFireInput(const std::shared_ptr &player, BulletType bullet_type); // Gestiona disparo de jugador - void handleFireInputs(const std::shared_ptr &player, bool autofire); // Procesa disparos automáticos - void handlePlayerContinueInput(const std::shared_ptr &player); // Permite continuar al jugador - void handlePlayerWaitingInput(const std::shared_ptr &player); // Permite (re)entrar al jugador - void handleNameInput(const std::shared_ptr &player); // Gestiona entrada de nombre del jugador + void handlePlayersInput(); // Gestiona entrada de todos los jugadores + void handleNormalPlayerInput(const std::shared_ptr& player); // Procesa entrada de un jugador específico + void handleFireInput(const std::shared_ptr& player, Bullet::Type type); // Gestiona disparo de jugador + void handleFireInputs(const std::shared_ptr& player, bool autofire); // Procesa disparos automáticos + void handlePlayerContinueInput(const std::shared_ptr& player); // Permite continuar al jugador + void handlePlayerWaitingInput(const std::shared_ptr& player); // Permite (re)entrar al jugador + void handleNameInput(const std::shared_ptr& player); // Gestiona entrada de nombre del jugador // --- Entrada en modo demo --- void demoHandleInput(); // Gestiona entrada durante el modo demostración void demoHandlePassInput(); // Permite saltar la demostración - void demoHandlePlayerInput(const std::shared_ptr &player, int index); // Procesa entrada de jugador en demo + void demoHandlePlayerInput(const std::shared_ptr& player, int index); // Procesa entrada de jugador en demo // --- Sistema de balas y proyectiles --- - void updateBullets(float deltaTime); // Actualiza posición y estado de todas las balas (time-based) - void renderBullets(); // Renderiza todas las balas activas - void createBullet(int x, int y, BulletType kind, bool powered_up, Player::Id owner); // Crea una nueva bala - void checkBulletCollision(); // Verifica colisiones de todas las balas - void freeBullets(); // Libera memoria del vector de balas + void updateBullets(float deltaTime); // Actualiza posición y estado de todas las balas (time-based) + void renderBullets(); // Renderiza todas las balas activas + void createBullet(int x, int y, Bullet::Type kind, Bullet::Color color, int owner); // Crea una nueva bala + void checkBulletCollision(); // Verifica colisiones de todas las balas + void freeBullets(); // Libera memoria del vector de balas // --- Colisiones específicas de balas --- - auto checkBulletTabeCollision(const std::shared_ptr &bullet) -> bool; // Detecta colisión bala-Tabe - auto checkBulletBalloonCollision(const std::shared_ptr &bullet) -> bool; // Detecta colisión bala-globo - void processBalloonHit(const std::shared_ptr &bullet, const std::shared_ptr &balloon); // Procesa impacto en globo + auto checkBulletTabeCollision(const std::shared_ptr& bullet) -> bool; // Detecta colisión bala-Tabe + auto checkBulletBalloonCollision(const std::shared_ptr& bullet) -> bool; // Detecta colisión bala-globo + void processBalloonHit(const std::shared_ptr& bullet, const std::shared_ptr& balloon); // Procesa impacto en globo // --- Sistema de ítems y power-ups --- void updateItems(float deltaTime); // Actualiza posición y estado de todos los ítems @@ -254,7 +254,7 @@ class Game { void throwCoffee(int x, int y); // Crea efecto de café arrojado al ser golpeado // --- Gestión de caída de ítems --- - void handleItemDrop(const std::shared_ptr &balloon, const std::shared_ptr &player); // Gestiona caída de ítem desde globo + void handleItemDrop(const std::shared_ptr& balloon, const std::shared_ptr& player); // Gestiona caída de ítem desde globo // --- Sprites inteligentes (smartsprites) --- void updateSmartSprites(float deltaTime); // Actualiza todos los sprites con lógica propia (time-based) @@ -268,11 +268,11 @@ class Game { void initPaths(); // Inicializa rutas predefinidas para animaciones // --- Creación de sprites especiales --- - void createItemText(int x, const std::shared_ptr &texture); // Crea texto animado para ítems - void createMessage(const std::vector &paths, const std::shared_ptr &texture); // Crea mensaje con animación por ruta + void createItemText(int x, const std::shared_ptr& texture); // Crea texto animado para ítems + void createMessage(const std::vector& paths, const std::shared_ptr& texture); // Crea mensaje con animación por ruta // --- Sistema de globos y enemigos --- - void handleBalloonDestruction(std::shared_ptr balloon, const std::shared_ptr &player); // Procesa destrucción de globo + void handleBalloonDestruction(std::shared_ptr balloon, const std::shared_ptr& player); // Procesa destrucción de globo void handleTabeHitEffects(); // Gestiona efectos al golpear a Tabe void checkAndUpdateBalloonSpeed(); // Ajusta velocidad de globos según progreso @@ -301,14 +301,14 @@ class Game { void updateHelper(); // Actualiza variables auxiliares de renderizado // --- Sistema de audio --- - static void playMusic(const std::string &music_file, int loop = -1); // Reproduce la música de fondo + static void playMusic(const std::string& music_file, int loop = -1); // Reproduce la música de fondo void stopMusic() const; // Detiene la reproducción de música static void pauseMusic(); // Pausa la música static void resumeMusic(); // Retoma la música que eestaba pausada - void playSound(const std::string &name) const; // Reproduce un efecto de sonido específico + void playSound(const std::string& name) const; // Reproduce un efecto de sonido específico - void sendPlayerToTheBack(const std::shared_ptr &player); // Mueve el jugador para pintarlo al fondo de la lista de jugadores - void sendPlayerToTheFront(const std::shared_ptr &player); // Mueve el jugador para pintarlo el primero de la lista de jugadores + void sendPlayerToTheBack(const std::shared_ptr& player); // Mueve el jugador para pintarlo al fondo de la lista de jugadores + void sendPlayerToTheFront(const std::shared_ptr& player); // Mueve el jugador para pintarlo el primero de la lista de jugadores void onPauseStateChanged(bool is_paused); // SISTEMA DE GRABACIÓN (CONDICIONAL) @@ -318,6 +318,6 @@ class Game { // --- Depuración (solo en modo DEBUG) --- #ifdef _DEBUG - void handleDebugEvents(const SDL_Event &event); // Comprueba los eventos en el modo DEBUG + void handleDebugEvents(const SDL_Event& event); // Comprueba los eventos en el modo DEBUG #endif }; \ No newline at end of file