diff --git a/source/game/ui/console.cpp b/source/game/ui/console.cpp index 63144db..5c1db75 100644 --- a/source/game/ui/console.cpp +++ b/source/game/ui/console.cpp @@ -167,72 +167,79 @@ void Console::redrawText() { } // Actualiza la animación de la consola -void Console::update(float delta_time) { // NOLINT(readability-function-cognitive-complexity) - if (status_ == Status::HIDDEN) { +// Parpadeig del cursor (només quan ACTIVE) +void Console::updateCursorBlink(float delta_time) { + cursor_timer_ += delta_time; + const float THRESHOLD = cursor_visible_ ? CURSOR_ON_TIME : CURSOR_OFF_TIME; + if (cursor_timer_ >= THRESHOLD) { + cursor_timer_ = 0.0F; + cursor_visible_ = !cursor_visible_; + } +} + +// Revelat lletra a lletra de msg_lines_ (només quan ACTIVE) +void Console::updateTypewriter(float delta_time) { + const int TOTAL_CHARS = std::accumulate(msg_lines_.begin(), msg_lines_.end(), 0, [](int acc, const auto& line) { return acc + static_cast(line.size()); }); + if (typewriter_chars_ >= TOTAL_CHARS) { return; } + typewriter_timer_ += delta_time; + while (typewriter_timer_ >= TYPEWRITER_CHAR_DELAY && typewriter_chars_ < TOTAL_CHARS) { + typewriter_timer_ -= TYPEWRITER_CHAR_DELAY; + ++typewriter_chars_; + } +} + +// Animació d'altura quan msg_lines_ canvia (només quan ACTIVE i height_ != target_height_) +void Console::updateResizeAnimation(float delta_time) { + if (anim_progress_ == 0.0F) { + // Iniciar animació de resize + anim_start_ = height_; + anim_end_ = target_height_; + } + anim_progress_ = std::min(anim_progress_ + (delta_time / ANIM_DURATION), 1.0F); + height_ = anim_start_ + ((anim_end_ - anim_start_) * Easing::cubicInOut(anim_progress_)); + if (anim_progress_ >= 1.0F) { + height_ = target_height_; + anim_progress_ = 0.0F; + } + // Reconstruir la Surface al nou tamany (xicoteta: 256×~18-72px) + const float WIDTH = Options::game.width; + surface_ = std::make_shared(WIDTH, height_); + sprite_->setSurface(surface_); +} + +// Animació RISING/VANISHING (basada en temps amb easing) +void Console::updateOpenCloseAnimation(float delta_time) { + anim_progress_ = std::min(anim_progress_ + (delta_time / ANIM_DURATION), 1.0F); + y_ = anim_start_ + ((anim_end_ - anim_start_) * Easing::cubicInOut(anim_progress_)); + + if (anim_progress_ < 1.0F) { return; } + y_ = anim_end_; + anim_progress_ = 0.0F; + if (status_ == Status::RISING) { + status_ = Status::ACTIVE; return; } + status_ = Status::HIDDEN; + // Resetear el missatge una vegada completament oculta + msg_lines_ = {std::string(CONSOLE_NAME) + " " + std::string(CONSOLE_VERSION)}; + target_height_ = calcTargetHeight(static_cast(msg_lines_.size())); +} + +void Console::update(float delta_time) { + if (status_ == Status::HIDDEN) { return; } - // Parpadeo del cursor (solo cuando activa) if (status_ == Status::ACTIVE) { - cursor_timer_ += delta_time; - const float THRESHOLD = cursor_visible_ ? CURSOR_ON_TIME : CURSOR_OFF_TIME; - if (cursor_timer_ >= THRESHOLD) { - cursor_timer_ = 0.0F; - cursor_visible_ = !cursor_visible_; + updateCursorBlink(delta_time); + updateTypewriter(delta_time); + if (height_ != target_height_) { + updateResizeAnimation(delta_time); } } - // Efecto typewriter: revelar letras una a una (solo cuando ACTIVE) - if (status_ == Status::ACTIVE) { - const int TOTAL_CHARS = std::accumulate(msg_lines_.begin(), msg_lines_.end(), 0, [](int acc, const auto& line) { return acc + static_cast(line.size()); }); - if (typewriter_chars_ < TOTAL_CHARS) { - typewriter_timer_ += delta_time; - while (typewriter_timer_ >= TYPEWRITER_CHAR_DELAY && typewriter_chars_ < TOTAL_CHARS) { - typewriter_timer_ -= TYPEWRITER_CHAR_DELAY; - ++typewriter_chars_; - } - } - } - - // Animación de altura (resize cuando msg_lines_ cambia); solo en ACTIVE - if (status_ == Status::ACTIVE && height_ != target_height_) { - if (anim_progress_ == 0.0F) { - // Iniciar animación de resize - anim_start_ = height_; - anim_end_ = target_height_; - } - anim_progress_ = std::min(anim_progress_ + (delta_time / ANIM_DURATION), 1.0F); - height_ = anim_start_ + ((anim_end_ - anim_start_) * Easing::cubicInOut(anim_progress_)); - if (anim_progress_ >= 1.0F) { - height_ = target_height_; - anim_progress_ = 0.0F; - } - // Reconstruir la Surface al nuevo tamaño (pequeña: 256×~18-72px) - const float WIDTH = Options::game.width; - surface_ = std::make_shared(WIDTH, height_); - sprite_->setSurface(surface_); - } - - // Redibujar texto cada frame redrawText(); - // Animación de apertura/cierre (basada en tiempo con easing) if (status_ == Status::RISING || status_ == Status::VANISHING) { - anim_progress_ = std::min(anim_progress_ + (delta_time / ANIM_DURATION), 1.0F); - y_ = anim_start_ + ((anim_end_ - anim_start_) * Easing::cubicInOut(anim_progress_)); - - if (anim_progress_ >= 1.0F) { - y_ = anim_end_; - anim_progress_ = 0.0F; - if (status_ == Status::RISING) { - status_ = Status::ACTIVE; - } else { - status_ = Status::HIDDEN; - // Resetear el mensaje una vez completamente oculta - msg_lines_ = {std::string(CONSOLE_NAME) + " " + std::string(CONSOLE_VERSION)}; - target_height_ = calcTargetHeight(static_cast(msg_lines_.size())); - } - } + updateOpenCloseAnimation(delta_time); } SDL_FRect rect = {.x = 0, .y = y_, .w = Options::game.width, .h = height_}; diff --git a/source/game/ui/console.hpp b/source/game/ui/console.hpp index 92f4948..e0644a7 100644 --- a/source/game/ui/console.hpp +++ b/source/game/ui/console.hpp @@ -79,6 +79,12 @@ class Console { void processCommand(); // Procesa el comando introducido por el usuario [[nodiscard]] auto wrapText(const std::string& text) const -> std::vector; // Word-wrap por ancho en píxeles + // Sub-pasos de update() (extrets per reduir complexitat cognitiva) + void updateCursorBlink(float delta_time); // Parpadeig del cursor + void updateTypewriter(float delta_time); // Revelat lletra a lletra de msg_lines_ + void updateResizeAnimation(float delta_time); // Animació d'altura quan msg_lines_ canvia + void updateOpenCloseAnimation(float delta_time); // Animació RISING/VANISHING + // Objetos de renderizado std::shared_ptr text_; std::shared_ptr surface_;