diff --git a/source/player.cpp b/source/player.cpp index e34453c..cb3fd15 100644 --- a/source/player.cpp +++ b/source/player.cpp @@ -473,8 +473,22 @@ void Player::updateStepCounter(float deltaTime) { // Pinta el jugador en pantalla void Player::render() { if (power_up_ && isPlaying()) { - if (power_up_counter_ > (POWERUP_COUNTER / 4) || power_up_counter_ % 20 > 4) { + // Convertir lógica de parpadeo a deltaTime + float total_powerup_time_ms = static_cast(POWERUP_COUNTER) / 60.0f * 1000.0f; // Total time in ms + float quarter_time_ms = total_powerup_time_ms / 4.0f; // 25% del tiempo total + + if (power_up_time_accumulator_ > quarter_time_ms) { + // En los primeros 75% del tiempo, siempre visible power_sprite_->render(); + } else { + // En el último 25%, parpadea cada 20 frames (333ms aprox) + constexpr float blink_period_ms = 20.0f / 60.0f * 1000.0f; // 20 frames in ms + constexpr float visible_proportion = 4.0f / 20.0f; // 4 frames visible de 20 total + + float cycle_position = fmod(power_up_time_accumulator_, blink_period_ms) / blink_period_ms; + if (cycle_position >= visible_proportion) { + power_sprite_->render(); + } } } @@ -662,23 +676,28 @@ void Player::handleFiringCooldown() { // Fase 2: Manejo de cooldown de disparo (time-based) void Player::handleFiringCooldown(float deltaTime) { - cooling_time_accumulator_ = static_cast(COOLING_DURATION) / 60.0f; + // Convertir frames a tiempo en milisegundos + float halfwayTime = static_cast(recoiling_state_duration_) / 2.0f / 60.0f * 1000.0f; - // Convertir frames a tiempo: 1 frame = 1/60 segundos - float frameTime = 1.0f / 60.0f; - float halfwayTime = static_cast(recoiling_state_duration_) / 2.0f / 60.0f; - // Reducir tiempo acumulado cant_fire_time_accumulator_ -= deltaTime; - + // Transition to recoiling state at halfway point - if (cant_fire_time_accumulator_ <= halfwayTime && cant_fire_time_accumulator_ > halfwayTime - frameTime) { + if (cant_fire_time_accumulator_ <= halfwayTime && !recoiling_transition_done_) { transitionToRecoiling(); + recoiling_transition_done_ = true; } if (cant_fire_time_accumulator_ <= 0) { cant_fire_time_accumulator_ = 0; - recoiling_time_accumulator_ = static_cast(recoiling_state_duration_) / 60.0f; + recoiling_time_accumulator_ = static_cast(recoiling_state_duration_) / 60.0f * 1000.0f; // Convert to milliseconds + + // Solo inicializar cooling si no está ya activo (para permitir disparos consecutivos) + if (cooling_time_accumulator_ <= 0) { + cooling_time_accumulator_ = static_cast(COOLING_DURATION) / 60.0f * 1000.0f; // Convert to milliseconds + } + + recoiling_transition_done_ = false; // Reset flag } } @@ -716,14 +735,14 @@ void Player::handleCoolingState() { // Fase 2: Manejo del estado de enfriamiento (time-based) void Player::handleCoolingState(float deltaTime) { - float coolingCompleteTime = static_cast(COOLING_COMPLETE) / 60.0f; - float coolingDurationTime = static_cast(COOLING_DURATION) / 60.0f; - float frameTime = 1.0f / 60.0f; - + float coolingCompleteTime = static_cast(COOLING_COMPLETE); // 0 + float coolingDurationTime = static_cast(COOLING_DURATION) / 60.0f * 1000.0f; // Convert to milliseconds + if (cooling_time_accumulator_ > coolingCompleteTime) { // Transición a cooling cuando empezamos (equivalente a == COOLING_DURATION) - if (cooling_time_accumulator_ <= coolingDurationTime && cooling_time_accumulator_ > coolingDurationTime - frameTime) { + if (!cooling_transition_done_ && cooling_time_accumulator_ >= coolingDurationTime - 16.67f) { // ~1 frame tolerance in ms transitionToCooling(); + cooling_transition_done_ = true; } cooling_time_accumulator_ -= deltaTime; } @@ -731,6 +750,7 @@ void Player::handleCoolingState(float deltaTime) { if (cooling_time_accumulator_ <= coolingCompleteTime) { cooling_time_accumulator_ = coolingCompleteTime; completeCooling(); + cooling_transition_done_ = false; // Reset flag } } @@ -771,12 +791,12 @@ void Player::completeCooling() { cooling_state_counter_ = -1; } -// Actualiza al jugador a su posicion, animación y controla los contadores +// Actualiza al jugador a su posicion, animación y controla los contadores (frame-based) void Player::update() { move(); setAnimation(); shiftColliders(); - updateCooldown(); + updateFireSystem(16.67f); // Usar nuevo sistema con deltaTime fijo (16.67ms ≈ 1/60s) updatePowerUp(); updateInvulnerable(); updateScoreboard(); @@ -788,9 +808,9 @@ void Player::update() { // Fase 1-4: Método deltaTime completo void Player::update(float deltaTime) { move(deltaTime); // Sistema de movimiento time-based - setAnimation(deltaTime); // Animaciones time-based + setAnimation(deltaTime); // Animaciones time-based shiftColliders(); // Sin cambios (posicional) - updateCooldown(deltaTime); // Fase 2: Sistema de disparo time-based + updateFireSystem(deltaTime); // NUEVO: Sistema de disparo de dos líneas updatePowerUp(deltaTime); // Fase 3: Sistema de power-up time-based updateInvulnerable(deltaTime); // Fase 3: Sistema de invulnerabilidad time-based updateScoreboard(); // Sin cambios (no temporal) @@ -1003,7 +1023,7 @@ void Player::decScoreMultiplier() { void Player::setInvulnerable(bool value) { invulnerable_ = value; invulnerable_counter_ = invulnerable_ ? INVULNERABLE_COUNTER : 0; - invulnerable_time_accumulator_ = invulnerable_ ? static_cast(INVULNERABLE_COUNTER) / 60.0f : 0.0f; // Initialize time accumulator + invulnerable_time_accumulator_ = invulnerable_ ? static_cast(INVULNERABLE_COUNTER) / 60.0f * 1000.0f : 0.0f; // Convert frames to milliseconds } // Monitoriza el estado (frame-based) @@ -1042,16 +1062,16 @@ void Player::updateInvulnerable(float deltaTime) { if (invulnerable_time_accumulator_ > 0) { invulnerable_time_accumulator_ -= deltaTime; - // Frecuencia fija de parpadeo adaptada a deltaTime - constexpr float blink_period = 8.0f / 60.0f; // 8 frames convertidos a segundos + // Frecuencia fija de parpadeo adaptada a deltaTime (en milisegundos) + constexpr float blink_period_ms = 8.0f / 60.0f * 1000.0f; // 8 frames convertidos a ms // Calcula proporción decreciente basada en tiempo restante - float total_invulnerable_time = static_cast(INVULNERABLE_COUNTER) / 60.0f; - float progress = 1.0f - (invulnerable_time_accumulator_ / total_invulnerable_time); + float total_invulnerable_time_ms = static_cast(INVULNERABLE_COUNTER) / 60.0f * 1000.0f; + float progress = 1.0f - (invulnerable_time_accumulator_ / total_invulnerable_time_ms); float white_proportion = 0.5f - progress * 0.2f; // Menos blanco hacia el final // Calcula si debe mostrar textura de invulnerabilidad basado en el ciclo temporal - float cycle_position = fmod(invulnerable_time_accumulator_, blink_period) / blink_period; + float cycle_position = fmod(invulnerable_time_accumulator_, blink_period_ms) / blink_period_ms; bool should_show_invulnerable = cycle_position < white_proportion; size_t target_texture = should_show_invulnerable ? INVULNERABLE_TEXTURE : coffees_; @@ -1072,7 +1092,7 @@ void Player::updateInvulnerable(float deltaTime) { void Player::setPowerUp() { power_up_ = true; power_up_counter_ = POWERUP_COUNTER; - power_up_time_accumulator_ = static_cast(POWERUP_COUNTER) / 60.0f; // Initialize time accumulator + power_up_time_accumulator_ = static_cast(POWERUP_COUNTER) / 60.0f * 1000.0f; // Convert frames to milliseconds } // Actualiza el valor de la variable (frame-based) @@ -1144,7 +1164,7 @@ void Player::updateContinueCounter() { void Player::updateContinueCounter(float deltaTime) { if (playing_state_ == State::CONTINUE) { continue_time_accumulator_ += deltaTime; - constexpr float CONTINUE_INTERVAL = 1.0f; // 1 segundo + constexpr float CONTINUE_INTERVAL = 1000.0f; // 1 segundo en milisegundos if (continue_time_accumulator_ >= CONTINUE_INTERVAL) { continue_time_accumulator_ -= CONTINUE_INTERVAL; decContinueCounter(); @@ -1166,7 +1186,7 @@ void Player::updateEnterNameCounter() { void Player::updateEnterNameCounter(float deltaTime) { if (playing_state_ == State::ENTERING_NAME || playing_state_ == State::ENTERING_NAME_GAME_COMPLETED) { name_entry_time_accumulator_ += deltaTime; - constexpr float NAME_ENTRY_INTERVAL = 1.0f; // 1 segundo + constexpr float NAME_ENTRY_INTERVAL = 1000.0f; // 1 segundo en milisegundos if (name_entry_time_accumulator_ >= NAME_ENTRY_INTERVAL) { name_entry_time_accumulator_ -= NAME_ENTRY_INTERVAL; decNameEntryCounter(); @@ -1268,4 +1288,145 @@ void Player::addScoreToScoreBoard() const { void Player::addCredit() { ++credits_used_; playSound("credit.wav"); +} + +// ======================================== +// IMPLEMENTACIÓN DEL NUEVO SISTEMA DE DOS LÍNEAS +// ======================================== + +// Método principal del nuevo sistema de disparo +void Player::updateFireSystem(float deltaTime) { + updateFunctionalLine(deltaTime); // Línea 1: CanFire + updateVisualLine(deltaTime); // Línea 2: Animaciones +} + +// LÍNEA 1: Sistema Funcional (CanFire) +void Player::updateFunctionalLine(float deltaTime) { + if (fire_cooldown_timer_ > 0) { + fire_cooldown_timer_ -= deltaTime; + can_fire_new_system_ = false; + } else { + fire_cooldown_timer_ = 0; // Evitar valores negativos + can_fire_new_system_ = true; + } +} + +// LÍNEA 2: Sistema Visual (Animaciones) +void Player::updateVisualLine(float deltaTime) { + if (visual_fire_state_ == VisualFireState::NORMAL) { + return; // No hay temporizador activo en estado NORMAL + } + + visual_state_timer_ -= deltaTime; + + switch (visual_fire_state_) { + case VisualFireState::AIMING: + if (visual_state_timer_ <= 0) { + transitionToRecoilingNew(); + } + break; + + case VisualFireState::RECOILING: + if (visual_state_timer_ <= 0) { + transitionToThreatPose(); + } + break; + + case VisualFireState::THREAT_POSE: + if (visual_state_timer_ <= 0) { + transitionToNormalNew(); + } + break; + + case VisualFireState::NORMAL: + // Ya manejado arriba + break; + } +} + +// Inicia un nuevo disparo en ambas líneas +void Player::startFiringNewSystem(int cooldown_frames) { + // LÍNEA 1: Inicia cooldown funcional + fire_cooldown_timer_ = static_cast(cooldown_frames) / 60.0f * 1000.0f; // Convertir frames a ms + can_fire_new_system_ = false; + + // LÍNEA 2: Resetea completamente el estado visual + aiming_duration_ = fire_cooldown_timer_ * AIMING_DURATION_FACTOR; // 50% del cooldown + recoiling_duration_ = aiming_duration_ * RECOILING_DURATION_MULTIPLIER; // 4 veces la duración de aiming + + visual_fire_state_ = VisualFireState::AIMING; + visual_state_timer_ = aiming_duration_; + + updateFiringStateFromVisual(); // Sincroniza firing_state_ para animaciones +} + +// Sincroniza firing_state_ con visual_fire_state_ +void Player::updateFiringStateFromVisual() { + // Mantener la dirección actual del disparo + State base_state = State::FIRING_NONE; + + if (firing_state_ == State::FIRING_LEFT || firing_state_ == State::RECOILING_LEFT || firing_state_ == State::COOLING_LEFT) { + base_state = State::FIRING_LEFT; + } else if (firing_state_ == State::FIRING_RIGHT || firing_state_ == State::RECOILING_RIGHT || firing_state_ == State::COOLING_RIGHT) { + base_state = State::FIRING_RIGHT; + } else if (firing_state_ == State::FIRING_UP || firing_state_ == State::RECOILING_UP || firing_state_ == State::COOLING_UP) { + base_state = State::FIRING_UP; + } + + switch (visual_fire_state_) { + case VisualFireState::NORMAL: + firing_state_ = State::FIRING_NONE; + break; + + case VisualFireState::AIMING: + firing_state_ = base_state; // FIRING_LEFT/RIGHT/UP + break; + + case VisualFireState::RECOILING: + switch (base_state) { + case State::FIRING_LEFT: firing_state_ = State::RECOILING_LEFT; break; + case State::FIRING_RIGHT: firing_state_ = State::RECOILING_RIGHT; break; + case State::FIRING_UP: firing_state_ = State::RECOILING_UP; break; + default: firing_state_ = State::RECOILING_UP; break; + } + break; + + case VisualFireState::THREAT_POSE: + switch (base_state) { + case State::FIRING_LEFT: firing_state_ = State::COOLING_LEFT; break; + case State::FIRING_RIGHT: firing_state_ = State::COOLING_RIGHT; break; + case State::FIRING_UP: firing_state_ = State::COOLING_UP; break; + default: firing_state_ = State::COOLING_UP; break; + } + break; + } +} + +// Transiciones del sistema visual +void Player::transitionToRecoilingNew() { + visual_fire_state_ = VisualFireState::RECOILING; + visual_state_timer_ = recoiling_duration_; + updateFiringStateFromVisual(); +} + +void Player::transitionToThreatPose() { + visual_fire_state_ = VisualFireState::THREAT_POSE; + + // Calcular threat_pose_duration ajustada: + // Duración original (833ms) menos el tiempo extra que ahora dura recoiling + float original_recoiling_duration = fire_cooldown_timer_; // Era 100% del cooldown + float new_recoiling_duration = aiming_duration_ * RECOILING_DURATION_MULTIPLIER; // Ahora es más del cooldown + float extra_recoiling_time = new_recoiling_duration - original_recoiling_duration; + float adjusted_threat_duration = THREAT_POSE_DURATION - extra_recoiling_time; + + // Asegurar que no sea negativo + visual_state_timer_ = std::max(adjusted_threat_duration, MIN_THREAT_POSE_DURATION); + + updateFiringStateFromVisual(); +} + +void Player::transitionToNormalNew() { + visual_fire_state_ = VisualFireState::NORMAL; + visual_state_timer_ = 0; + updateFiringStateFromVisual(); } \ No newline at end of file diff --git a/source/player.h b/source/player.h index e288764..9524454 100644 --- a/source/player.h +++ b/source/player.h @@ -17,7 +17,21 @@ class Texture; -// --- Clase Player --- +// --- Clase Player: jugador principal del juego --- +// +// Esta clase gestiona todos los aspectos de un jugador durante el juego, +// incluyendo movimiento, disparos, animaciones y estados especiales. +// +// Funcionalidades principales: +// • Sistema de disparo de dos líneas: funcional (cooldown) + visual (animaciones) +// • Estados de animación: normal → aiming → recoiling → threat_pose → normal +// • Movimiento time-based: compatibilidad con deltaTime para fluidez variable +// • Power-ups e invulnerabilidad: coffee machine, extra hits, parpadeos +// • Sistema de puntuación: multipliers, high scores, entrada de nombres +// • Estados de juego: playing, rolling, continue, entering_name, etc. +// +// El sistema de disparo utiliza duraciones configurables mediante constantes +// para facilitar el ajuste del gameplay y la sensación de disparo. class Player { public: // --- Constantes --- @@ -150,7 +164,8 @@ class Player { [[nodiscard]] auto isTitleHidden() const -> bool { return playing_state_ == State::TITLE_HIDDEN; } // Getters - [[nodiscard]] auto canFire() const -> bool { return cant_fire_time_accumulator_ <= 0; } + [[nodiscard]] auto canFire() const -> bool { return can_fire_new_system_; } // Usa nuevo sistema + [[nodiscard]] auto canFireOld() const -> bool { return cant_fire_time_accumulator_ <= 0; } // Sistema anterior [[nodiscard]] auto hasExtraHit() const -> bool { return extra_hit_; } [[nodiscard]] auto isCooling() const -> bool { return firing_state_ == State::COOLING_LEFT || firing_state_ == State::COOLING_UP || firing_state_ == State::COOLING_RIGHT; } [[nodiscard]] auto isRecoiling() const -> bool { return firing_state_ == State::RECOILING_LEFT || firing_state_ == State::RECOILING_UP || firing_state_ == State::RECOILING_RIGHT; } @@ -180,10 +195,7 @@ class Player { // Setters inline void setController(int index) { controller_index_ = index; } - void setCantFireCounter(int counter) { - recoiling_state_duration_ = cant_fire_counter_ = counter; - cant_fire_time_accumulator_ = static_cast(counter) / 60.0f * 1000.0f; // Convert frames to milliseconds - } + void startFiringNewSystem(int cooldown_frames); // Método público para iniciar disparo en nuevo sistema void setFiringState(State state) { firing_state_ = state; } void setInvulnerableCounter(int value) { invulnerable_counter_ = value; } void setName(const std::string &name) { name_ = name; } @@ -201,15 +213,27 @@ class Player { [[nodiscard]] auto getUsesKeyboard() const -> bool { return uses_keyboard_; } private: - // --- Constantes --- - static constexpr int POWERUP_COUNTER = 1500; // Duración del estado PowerUp - static constexpr int INVULNERABLE_COUNTER = 200; // Duración del estado invulnerable - static constexpr size_t INVULNERABLE_TEXTURE = 3; // Textura usada durante invulnerabilidad + // --- Constantes de física y movimiento --- static constexpr float BASE_SPEED = 1.5F; // Velocidad base del jugador + + // --- Constantes de power-ups y estados especiales --- + static constexpr int POWERUP_COUNTER = 1500; // Duración del estado PowerUp (frames) + static constexpr int INVULNERABLE_COUNTER = 200; // Duración del estado invulnerable (frames) + 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 + + // --- Constantes de estados 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 = 833.33f; // 50 frames = ~833ms (duración base) + static constexpr float MIN_THREAT_POSE_DURATION = 100.0f; // Duración mínima para threat pose + // --- Objetos y punteros --- std::unique_ptr player_sprite_; // Sprite para dibujar el jugador std::unique_ptr power_sprite_; // Sprite para dibujar el aura del jugador con el poder a tope @@ -253,6 +277,32 @@ class Player { float name_entry_time_accumulator_ = 0.0f; // Acumulador de tiempo para name entry counter (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 + + // 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 + }; + + 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 + + // Variables del sistema obsoleto (mantener para compatibilidad temporal) + bool recoiling_transition_done_ = false; // Flag sistema obsoleto + bool cooling_transition_done_ = false; // Flag sistema obsoleto + int invulnerable_counter_ = INVULNERABLE_COUNTER; // Contador para la invulnerabilidad int score_ = 0; // Puntos del jugador int coffees_ = 0; // Indica cuántos cafés lleva acumulados @@ -289,15 +339,27 @@ class Player { 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 handleFiringCooldown(); // Gestiona el tiempo de espera después de disparar antes de permitir otro disparo (frame-based) - void handleFiringCooldown(float deltaTime); // Gestiona el tiempo de espera después de disparar antes de permitir otro disparo (time-based) - void handleRecoilAndCooling(); // Procesa simultáneamente el retroceso del arma y la transición al estado de enfriamiento si aplica (frame-based) - void handleRecoilAndCooling(float deltaTime); // Procesa simultáneamente el retroceso del arma y la transición al estado de enfriamiento si aplica (time-based) - void handleCoolingState(); // Actualiza la lógica interna mientras el sistema está en estado de enfriamiento (frame-based) - void handleCoolingState(float deltaTime); // Actualiza la lógica interna mientras el sistema está en estado de enfriamiento (time-based) - void transitionToRecoiling(); // Cambia el estado actual al de retroceso después de disparar - void transitionToCooling(); // Cambia el estado actual al de enfriamiento (por ejemplo, tras una ráfaga o sobrecalentamiento) - void completeCooling(); // Finaliza el proceso de enfriamiento y restablece el estado listo para disparar + + // --- 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 + + // --- Métodos del sistema de disparo obsoleto --- + void handleFiringCooldown(); // Gestiona el tiempo de espera después de disparar (frame-based) + void handleFiringCooldown(float deltaTime); // Gestiona el tiempo de espera después de disparar (time-based) + void handleRecoilAndCooling(); // Procesa retroceso y enfriamiento (frame-based) + void handleRecoilAndCooling(float deltaTime); // Procesa retroceso y enfriamiento (time-based) + void handleCoolingState(); // Actualiza estado de enfriamiento (frame-based) + void handleCoolingState(float deltaTime); // Actualiza estado de enfriamiento (time-based) + void transitionToRecoiling(); // Transición a retroceso (sistema obsoleto) + 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 handleRecoverMovement(); // Comprueba si ha acabado la animación diff --git a/source/sections/game.cpp b/source/sections/game.cpp index 5e51d84..fdb7382 100644 --- a/source/sections/game.cpp +++ b/source/sections/game.cpp @@ -1354,7 +1354,7 @@ void Game::handleFireInput(const std::shared_ptr &player, BulletType bul cant_fire_counter = NORMAL_COOLDOWN; } - player->setCantFireCounter(cant_fire_counter); + player->startFiringNewSystem(cant_fire_counter); // Usar nuevo sistema de dos líneas } }