diff --git a/source/game/scenes/title.cpp b/source/game/scenes/title.cpp index ee09cff..fa9259b 100644 --- a/source/game/scenes/title.cpp +++ b/source/game/scenes/title.cpp @@ -32,6 +32,7 @@ Title::Title() menu_text_(Resource::get()->getText("gauntlet")), first_active_letter_(0), last_active_letter_(0), + cheevos_scroll_velocity_(0.0F), state_time_(0.0F), fade_accumulator_(0.0F), exit_scene_(SceneManager::Scene::GAME), @@ -175,12 +176,6 @@ void Title::handleInput(float delta_time) { break; case State::CHEEVOS_MENU: - if (Input::get()->checkAction(InputAction::RIGHT, Input::ALLOW_REPEAT)) { - moveCheevosList(1, delta_time); - } else if (Input::get()->checkAction(InputAction::LEFT, Input::ALLOW_REPEAT)) { - moveCheevosList(0, delta_time); - } - if (Input::get()->checkAction(InputAction::ACCEPT, Input::DO_NOT_ALLOW_REPEAT) || Input::get()->checkAction(InputAction::CANCEL, Input::DO_NOT_ALLOW_REPEAT)) { resetCheevosScroll(); @@ -358,6 +353,45 @@ void Title::updateMainMenu(float delta_time) { void Title::updateCheevosMenu(float delta_time) { // Actualiza la marquesina (sigue visible en fondo) updateMarquee(delta_time); + + // Determina la velocidad objetivo basada en el input + float target_velocity = 0.0F; + if (Input::get()->checkAction(InputAction::RIGHT, Input::ALLOW_REPEAT)) { + target_velocity = CHEEVOS_SCROLL_MAX_SPEED; // Scroll hacia abajo + } else if (Input::get()->checkAction(InputAction::LEFT, Input::ALLOW_REPEAT)) { + target_velocity = -CHEEVOS_SCROLL_MAX_SPEED; // Scroll hacia arriba + } + + // Interpola suavemente la velocidad actual hacia la velocidad objetivo + if (target_velocity != 0.0F) { + // Acelerando hacia la velocidad objetivo + const float ACCELERATION_STEP = CHEEVOS_SCROLL_ACCELERATION * delta_time; + if (cheevos_scroll_velocity_ < target_velocity) { + cheevos_scroll_velocity_ = std::min(cheevos_scroll_velocity_ + ACCELERATION_STEP, target_velocity); + } else if (cheevos_scroll_velocity_ > target_velocity) { + cheevos_scroll_velocity_ = std::max(cheevos_scroll_velocity_ - ACCELERATION_STEP, target_velocity); + } + } else { + // Desacelerando hacia 0 + const float DECELERATION_STEP = CHEEVOS_SCROLL_DECELERATION * delta_time; + if (cheevos_scroll_velocity_ > 0.0F) { + cheevos_scroll_velocity_ = std::max(cheevos_scroll_velocity_ - DECELERATION_STEP, 0.0F); + } else if (cheevos_scroll_velocity_ < 0.0F) { + cheevos_scroll_velocity_ = std::min(cheevos_scroll_velocity_ + DECELERATION_STEP, 0.0F); + } + } + + // Aplica la velocidad actual al scroll position + if (cheevos_scroll_velocity_ != 0.0F) { + cheevos_surface_view_.y += cheevos_scroll_velocity_ * delta_time; + + // Ajusta los límites + const float BOTTOM = cheevos_surface_->getHeight() - cheevos_surface_view_.h; + cheevos_surface_view_.y = std::clamp(cheevos_surface_view_.y, 0.0F, BOTTOM); + + cheevos_sprite_->setClip(cheevos_surface_view_); + } + // No incrementar state_time_ (no timeout en este estado) } @@ -407,23 +441,6 @@ void Title::run() { } } -// Desplaza la lista de logros -void Title::moveCheevosList(int direction, float delta_time) { - // Calcula el desplazamiento basado en tiempo - const float DISPLACEMENT = CHEEVOS_SCROLL_SPEED * delta_time; - - // Modifica la posición de la ventana de vista - cheevos_surface_view_.y = direction == 0 - ? cheevos_surface_view_.y - DISPLACEMENT - : cheevos_surface_view_.y + DISPLACEMENT; - - // Ajusta los limites - const float BOTTOM = cheevos_surface_->getHeight() - cheevos_surface_view_.h; - cheevos_surface_view_.y = std::clamp(cheevos_surface_view_.y, 0.0F, BOTTOM); - - cheevos_sprite_->setClip(cheevos_surface_view_); -} - // Crea y rellena la textura para mostrar los logros void Title::createCheevosTexture() { // Define la zona central del menu (entre el logo y la marquesina) @@ -482,6 +499,7 @@ void Title::createCheevosTexture() { // Resetea el scroll de la lista de logros void Title::resetCheevosScroll() { cheevos_surface_view_.y = 0; + cheevos_scroll_velocity_ = 0.0F; cheevos_sprite_->setClip(cheevos_surface_view_); } diff --git a/source/game/scenes/title.hpp b/source/game/scenes/title.hpp index dfcf3ab..c1e0e01 100644 --- a/source/game/scenes/title.hpp +++ b/source/game/scenes/title.hpp @@ -46,7 +46,9 @@ class Title { static constexpr float MAIN_MENU_IDLE_TIMEOUT = 20.0F; // Timeout para ir a créditos (antes 2200 frames) static constexpr float KEYBOARD_REMAP_DISPLAY_DELAY = 2.0F; // Tiempo mostrando teclas definidas antes de guardar static constexpr float MARQUEE_SPEED = 100.0F; // Velocidad de marquesina (pixels/segundo) - static constexpr float CHEEVOS_SCROLL_SPEED = 120.0F; // Velocidad de scroll de logros (pixels/segundo) + static constexpr float CHEEVOS_SCROLL_MAX_SPEED = 180.0F; // Velocidad máxima de scroll de logros (pixels/segundo) + static constexpr float CHEEVOS_SCROLL_ACCELERATION = 600.0F; // Aceleración del scroll (pixels/segundo²) + static constexpr float CHEEVOS_SCROLL_DECELERATION = 800.0F; // Desaceleración del scroll (pixels/segundo²) // --- Constantes de marquesina --- static constexpr float MARQUEE_START_X = 256.0F; // Posición inicial (ancho pantalla) @@ -72,6 +74,7 @@ class Title { int first_active_letter_; // Primera letra activa (optimización) int last_active_letter_; // Última letra activa (optimización) SDL_FRect cheevos_surface_view_; // Zona visible de la surface con el listado de logros + float cheevos_scroll_velocity_; // Velocidad actual del scroll de logros (pixels/segundo) State state_; // Estado en el que se encuentra el bucle principal float state_time_; // Tiempo acumulado en el estado actual float fade_accumulator_; // Acumulador para controlar el fade por tiempo @@ -109,7 +112,6 @@ class Title { void renderCheevosMenu(); // Dibuja el menu de logros void renderKeyboardRemap(); // Dibuja la pantalla de redefinir teclado void renderJoystickRemap(); // Dibuja la pantalla de redefinir joystick - void moveCheevosList(int direction, float delta_time); // Desplaza la lista de logros (time-based) void handleKeyboardRemap(const SDL_Event& event); // Maneja la captura de teclas void handleJoystickRemap(const SDL_Event& event); // Maneja la captura de botones del gamepad static auto isKeyValid(SDL_Scancode scancode) -> bool; // Valida si una tecla es permitida