diff --git a/source/director.cpp b/source/director.cpp index 10933e3..ee779b2 100644 --- a/source/director.cpp +++ b/source/director.cpp @@ -49,7 +49,7 @@ Director::Director(int argc, const char *argv[]) Section::name = Section::Name::GAME; Section::options = Section::Options::GAME_PLAY_1P; #elif DEBUG - Section::name = Section::Name::LOGO; + Section::name = Section::Name::TITLE; Section::options = Section::Options::GAME_PLAY_1P; #else // NORMAL GAME Section::name = Section::Name::LOGO; diff --git a/source/sections/title.cpp b/source/sections/title.cpp index b8b0f2a..925948e 100644 --- a/source/sections/title.cpp +++ b/source/sections/title.cpp @@ -64,16 +64,10 @@ void Title::update() { if (SDL_GetTicks() - ticks_ > param.game.speed) { - // Actualiza el contador de ticks_ ticks_ = SDL_GetTicks(); - - // Actualiza el fade updateFade(); - - // Actualiza el estado updateState(); - - // Actualiza el objeto screen + updateStartPrompt(); Screen::get()->update(); } } @@ -81,20 +75,12 @@ void Title::update() // Dibuja el objeto en pantalla void Title::render() { - // Prepara para empezar a dibujar en la textura de juego Screen::get()->start(); - - // Limpia la pantalla Screen::get()->clean(); - // Dibuja el mosacico de fondo tiled_bg_->render(); - - // Dibuja el logo con el título del juego game_logo_->render(); - constexpr Color shadow = Color(0x14, 0x87, 0xc4); - if (state_ != TitleState::LOGO_ANIMATING) { // Mini logo @@ -104,34 +90,13 @@ void Title::render() mini_logo_sprite_->render(); // Texto con el copyright - text_->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, pos2, TEXT_COPYRIGHT, 1, NO_TEXT_COLOR, 1, shadow); + text_->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, pos2, TEXT_COPYRIGHT, 1, NO_TEXT_COLOR, 1, TITLE_SHADOW_TEXT_COLOR); } - if (state_ == TitleState::LOGO_FINISHED) - { - // 'PRESS TO PLAY' - if (counter_ % 50 > 14 && !define_buttons_->isEnabled()) - { - text_->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, param.title.press_start_position, Lang::getText("[TITLE] PRESS_BUTTON_TO_PLAY"), 1, NO_TEXT_COLOR, 1, shadow); - } - } - - if (state_ == TitleState::START_HAS_BEEN_PRESSED) - { - // 'PRESS TO PLAY' - if (counter_ % 10 > 4 && !define_buttons_->isEnabled()) - { - text_->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, param.title.press_start_position, Lang::getText("[TITLE] PRESS_BUTTON_TO_PLAY"), 1, NO_TEXT_COLOR, 1, shadow); - } - } - - // Define Buttons + renderStartPrompt(); define_buttons_->render(); - - // Fade fade_->render(); - // Vuelca el contenido del renderizador en pantalla Screen::get()->render(); } @@ -366,4 +331,50 @@ void Title::updateState() default: break; } +} + +void Title::updateStartPrompt() +{ + constexpr Uint32 LOGO_BLINK_PERIOD = 833; // milisegundos + constexpr Uint32 LOGO_BLINK_ON_TIME = 583; // 833 - 250 + + constexpr Uint32 START_BLINK_PERIOD = 167; + constexpr Uint32 START_BLINK_ON_TIME = 83; // 167 - 83 + + Uint32 time_ms = SDL_GetTicks(); + bool condition_met = false; + + if (!define_buttons_->isEnabled()) + { + switch (state_) + { + case TitleState::LOGO_FINISHED: + condition_met = (time_ms % LOGO_BLINK_PERIOD) >= (LOGO_BLINK_PERIOD - LOGO_BLINK_ON_TIME); + break; + + case TitleState::START_HAS_BEEN_PRESSED: + condition_met = (time_ms % START_BLINK_PERIOD) >= (START_BLINK_PERIOD - START_BLINK_ON_TIME); + break; + + default: + break; + } + } + + should_render_start_prompt = condition_met; +} + +void Title::renderStartPrompt() +{ + if (should_render_start_prompt) + { + text_->writeDX(TEXT_CENTER | TEXT_SHADOW, + param.game.game_area.center_x, + param.title.press_start_position, + Lang::getText("[TITLE] PRESS_BUTTON_TO_PLAY"), + 1, + NO_TEXT_COLOR, + 1, + TITLE_SHADOW_TEXT_COLOR); + } } \ No newline at end of file diff --git a/source/sections/title.h b/source/sections/title.h index 72cb057..d1baf1c 100644 --- a/source/sections/title.h +++ b/source/sections/title.h @@ -58,6 +58,7 @@ private: Section::Options selection_ = Section::Options::TITLE_TIME_OUT; // Opción elegida en el título int num_controllers_; // Número de mandos conectados TitleState state_; // Estado actual de la sección + bool should_render_start_prompt = false; // Indica si se muestra o no el texto de PRESS START BUTTON TO PLAY // --- Métodos internos --- void update(); // Actualiza las variables del objeto @@ -70,4 +71,6 @@ private: void showControllers(); // Muestra información sobre los controles y los jugadores void updateFade(); // Actualiza el fade void updateState(); // Actualiza el estado + void updateStartPrompt(); + void renderStartPrompt(); }; \ No newline at end of file diff --git a/source/utils.h b/source/utils.h index 776244a..799fc48 100644 --- a/source/utils.h +++ b/source/utils.h @@ -61,38 +61,43 @@ struct Color } // Método estático para crear Color desde string hexadecimal - static Color fromHex(const std::string& hexStr) + static Color fromHex(const std::string &hexStr) { std::string hex = hexStr; - + // Quitar '#' si existe - if (!hex.empty() && hex[0] == '#') { + if (!hex.empty() && hex[0] == '#') + { hex = hex.substr(1); } - + // Verificar longitud válida (6 para RGB o 8 para RGBA) - if (hex.length() != 6 && hex.length() != 8) { + if (hex.length() != 6 && hex.length() != 8) + { throw std::invalid_argument("String hexadecimal debe tener 6 o 8 caracteres"); } - + // Verificar que todos los caracteres sean hexadecimales válidos - for (char c : hex) { - if (!std::isxdigit(c)) { + for (char c : hex) + { + if (!std::isxdigit(c)) + { throw std::invalid_argument("String contiene caracteres no hexadecimales"); } } - + // Convertir cada par de caracteres a valores RGB(A) Uint8 r = static_cast(std::stoi(hex.substr(0, 2), nullptr, 16)); Uint8 g = static_cast(std::stoi(hex.substr(2, 2), nullptr, 16)); Uint8 b = static_cast(std::stoi(hex.substr(4, 2), nullptr, 16)); Uint8 a = 255; // Alpha por defecto - + // Si tiene 8 caracteres, extraer el alpha - if (hex.length() == 8) { + if (hex.length() == 8) + { a = static_cast(std::stoi(hex.substr(6, 2), nullptr, 16)); } - + return Color(r, g, b, a); } }; @@ -106,14 +111,13 @@ struct HSV // Estructura para definir el ciclo de color enum class ColorCycleStyle { - SubtlePulse, // Variación leve en brillo (por defecto) - HueWave, // Variación suave en tono (sin verde) - Vibrant, // Cambios agresivos en tono y brillo - DarkenGlow, // Oscurece hacia el centro y regresa - LightFlash // Ilumina hacia el centro y regresa + SubtlePulse, // Variación leve en brillo (por defecto) + HueWave, // Variación suave en tono (sin verde) + Vibrant, // Cambios agresivos en tono y brillo + DarkenGlow, // Oscurece hacia el centro y regresa + LightFlash // Ilumina hacia el centro y regresa }; - // Posiciones de las notificaciones enum class NotifyPosition { @@ -173,6 +177,7 @@ using ColorCycle = std::array; // Colores constexpr Color NO_TEXT_COLOR = Color(0XFF, 0XFF, 0XFF); constexpr Color SHADOW_TEXT_COLOR = Color(0X43, 0X43, 0X4F); +constexpr Color TITLE_SHADOW_TEXT_COLOR = Color(0x14, 0x87, 0xc4); constexpr Color FLASH_COLOR = Color(0XFF, 0XFF, 0XFF);