diff --git a/source/define_buttons.cpp b/source/define_buttons.cpp index dc949cc..ba1c8b0 100644 --- a/source/define_buttons.cpp +++ b/source/define_buttons.cpp @@ -1,5 +1,7 @@ #include "define_buttons.h" +#include + #include "input.h" // Para Input, InputAction #include "lang.h" // Para getText #include "options.h" // Para OptionsController, Options, options @@ -86,9 +88,6 @@ auto DefineButtons::enable(int index) -> bool { return false; } -// Comprueba si está habilitado -auto DefineButtons::isEnabled() const -> bool { return enabled_; } - // Incrementa el indice de los botones void DefineButtons::incIndexButton() { if (index_button_ < buttons_.size() - 1) { @@ -100,7 +99,6 @@ void DefineButtons::incIndexButton() { // Guarda los cambios en las opciones void DefineButtons::saveBindingsToOptions() { - // Modifica las opciones para colocar los valores asignados auto &controller = Options::controllers.at(index_controller_); controller.name = input_->getControllerName(index_controller_); for (size_t j = 0; j < controller.inputs.size(); ++j) { @@ -110,12 +108,9 @@ void DefineButtons::saveBindingsToOptions() { // Comprueba que un botón no esté ya asignado auto DefineButtons::checkButtonNotInUse(SDL_GamepadButton button) -> bool { - for (const auto &b : buttons_) { - if (b.button == button) { - return false; - } - } - return true; + return std::ranges::all_of(buttons_, [button](const auto &b) { + return b.button != button; + }); } // Limpia la asignación de botones @@ -130,18 +125,10 @@ void DefineButtons::clearButtons() { // Comprueba si ha finalizado void DefineButtons::checkEnd() { - // Comprueba si ha finalizado if (finished_) { - // Asigna los botones definidos al input_ - bindButtons(); - - // Guarda los cambios en las opciones - saveBindingsToOptions(); - - // Reinicia los estados de las pulsaciones de los botones - input_->resetInputStates(); - - // Deshabilita - enabled_ = false; + bindButtons(); // Asigna los botones definidos al input_ + saveBindingsToOptions(); // Guarda los cambios en las opciones + input_->resetInputStates(); // Reinicia los estados de las pulsaciones de los botones + enabled_ = false; // Deshabilita } } \ No newline at end of file diff --git a/source/define_buttons.h b/source/define_buttons.h index 9ebd0f3..e876238 100644 --- a/source/define_buttons.h +++ b/source/define_buttons.h @@ -15,45 +15,45 @@ enum class InputAction : int; // Estructura para definir botones struct DefineButtonsButton { - std::string label; // Texto en pantalla - InputAction input; // Acción asociada - SDL_GamepadButton button; // Botón del mando + std::string label; // Texto en pantalla + InputAction input; // Acción asociada + SDL_GamepadButton button; // Botón del mando - DefineButtonsButton(std::string lbl, InputAction inp, SDL_GamepadButton btn) - : label(std::move(lbl)), input(inp), button(btn) {} + DefineButtonsButton(std::string lbl, InputAction inp, SDL_GamepadButton btn) + : label(std::move(lbl)), input(inp), button(btn) {} }; // Clase DefineButtons class DefineButtons { - public: - DefineButtons(); - ~DefineButtons() = default; + public: + DefineButtons(); + ~DefineButtons() = default; - void render(); // Dibuja el objeto en pantalla - void checkEvents(const SDL_Event &event); // Procesa los eventos - auto enable(int index_controller) -> bool; // Habilita la redefinición de botones - [[nodiscard]] auto isEnabled() const -> bool; // Comprueba si está habilitado + void render(); // Dibuja el objeto en pantalla + void checkEvents(const SDL_Event &event); // Procesa los eventos + auto enable(int index_controller) -> bool; // Habilita la redefinición de botones + [[nodiscard]] auto isEnabled() const -> bool { return enabled_; }; // Comprueba si está habilitado -private: - // Objetos - Input *input_ = nullptr; // Gestión de entrada - std::shared_ptr text_; // Renderizado de texto + private: + // Objetos + Input *input_ = nullptr; // Gestión de entrada + std::shared_ptr text_; // Renderizado de texto - // Variables - bool enabled_ = false; // Indica si está activo - int x_ = 0, y_ = 0; // Coordenadas de texto - std::vector buttons_; // Definiciones de botones - size_t index_controller_ = 0; // Índice del controlador asignado - size_t index_button_ = 0; // Índice del botón en proceso - std::vector controller_names_; // Nombres de los mandos - bool finished_ = false; + // Variables + bool enabled_ = false; // Indica si está activo + int x_ = 0, y_ = 0; // Coordenadas de texto + std::vector buttons_; // Definiciones de botones + size_t index_controller_ = 0; // Índice del controlador asignado + size_t index_button_ = 0; // Índice del botón en proceso + std::vector controller_names_; // Nombres de los mandos + bool finished_ = false; - // Métodos internos - void incIndexButton(); // Incrementa el índice de botones - void doControllerButtonDown(const SDL_GamepadButtonEvent &event); // Procesa pulsaciones - void bindButtons(); // Asigna botones al sistema de entrada - void saveBindingsToOptions(); // Guarda configuraciones - auto checkButtonNotInUse(SDL_GamepadButton button) -> bool; // Verifica uso de botones - void clearButtons(); // Limpia asignaciones actuales - void checkEnd(); // Comprueba si ha finalizado + // Métodos internos + void incIndexButton(); // Incrementa el índice de botones + void doControllerButtonDown(const SDL_GamepadButtonEvent &event); // Procesa pulsaciones + void bindButtons(); // Asigna botones al sistema de entrada + void saveBindingsToOptions(); // Guarda configuraciones + auto checkButtonNotInUse(SDL_GamepadButton button) -> bool; // Verifica uso de botones + void clearButtons(); // Limpia asignaciones actuales + void checkEnd(); // Comprueba si ha finalizado }; diff --git a/source/notifier.cpp b/source/notifier.cpp index 3c0c3b0..c06b573 100644 --- a/source/notifier.cpp +++ b/source/notifier.cpp @@ -15,16 +15,16 @@ #include "texture.h" // Para Texture // Singleton -Notifier *Notifier::instance = nullptr; +Notifier* Notifier::instance = nullptr; // Inicializa la instancia única del singleton -void Notifier::init(const std::string &icon_file, std::shared_ptr text) { Notifier::instance = new Notifier(icon_file, text); } +void Notifier::init(const std::string& icon_file, std::shared_ptr text) { Notifier::instance = new Notifier(icon_file, text); } // Libera la instancia void Notifier::destroy() { delete Notifier::instance; } // Obtiene la instancia -auto Notifier::get() -> Notifier * { return Notifier::instance; } +auto Notifier::get() -> Notifier* { return Notifier::instance; } // Constructor Notifier::Notifier(std::string icon_file, std::shared_ptr text) @@ -46,71 +46,108 @@ void Notifier::render() { // Actualiza el estado de las notificaiones void Notifier::update() { for (int i = 0; i < (int)notifications_.size(); ++i) { - // Si la notificación anterior está "saliendo", no hagas nada - if (i > 0) { - if (notifications_[i - 1].state == NotificationStatus::RISING) { - break; - } + if (!shouldProcessNotification(i)) { + break; } - notifications_[i].counter++; - - // Hace sonar la notificación en el primer frame - if (notifications_[i].counter == 1) { - if (param.notification.sound) { - if (notifications_[i].state == NotificationStatus::RISING) { - // Reproduce el sonido de la notificación - Audio::get()->playSound("notify.wav", Audio::Group::INTERFACE); - } - } - } - - // Comprueba los estados - if (notifications_[i].state == NotificationStatus::RISING) { - const float STEP = ((float)notifications_[i].counter / notifications_[i].travel_dist); - const int ALPHA = 255 * STEP; - - if (param.notification.pos_v == NotifyPosition::TOP) { - notifications_[i].rect.y++; - } else { - notifications_[i].rect.y--; - } - notifications_[i].texture->setAlpha(ALPHA); - - if (notifications_[i].rect.y == notifications_[i].y) { - notifications_[i].state = NotificationStatus::STAY; - notifications_[i].texture->setAlpha(255); - notifications_[i].counter = 0; - } - } - - else if (notifications_[i].state == NotificationStatus::STAY) { - if (notifications_[i].counter == wait_time_) { - notifications_[i].state = NotificationStatus::VANISHING; - notifications_[i].counter = 0; - } - } else if (notifications_[i].state == NotificationStatus::VANISHING) { - const float STEP = (notifications_[i].counter / (float)notifications_[i].travel_dist); - const int ALPHA = 255 * (1 - STEP); - - if (param.notification.pos_v == NotifyPosition::TOP) { - notifications_[i].rect.y--; - } else { - notifications_[i].rect.y++; - } - notifications_[i].texture->setAlpha(ALPHA); - - if (notifications_[i].rect.y == notifications_[i].y - notifications_[i].travel_dist) { - notifications_[i].state = NotificationStatus::FINISHED; - } - } - - notifications_[i].sprite->setPosition(notifications_[i].rect); + processNotification(i); } clearFinishedNotifications(); } +bool Notifier::shouldProcessNotification(int index) const { + // Si la notificación anterior está "saliendo", no hagas nada + if (index > 0 && notifications_[index - 1].state == NotificationStatus::RISING) { + return false; + } + return true; +} + +void Notifier::processNotification(int index) { + auto& notification = notifications_[index]; + notification.counter++; + + playNotificationSoundIfNeeded(notification); + updateNotificationState(index); + notification.sprite->setPosition(notification.rect); +} + +void Notifier::playNotificationSoundIfNeeded(const Notification& notification) { + // Hace sonar la notificación en el primer frame + if (notification.counter == 1 && + param.notification.sound && + notification.state == NotificationStatus::RISING) { + Audio::get()->playSound("notify.wav", Audio::Group::INTERFACE); + } +} + +void Notifier::updateNotificationState(int index) { + auto& notification = notifications_[index]; + + switch (notification.state) { + case NotificationStatus::RISING: + handleRisingState(index); + break; + case NotificationStatus::STAY: + handleStayState(index); + break; + case NotificationStatus::VANISHING: + handleVanishingState(index); + break; + default: + break; + } +} + +void Notifier::handleRisingState(int index) { + auto& notification = notifications_[index]; + + const float step = (float)notification.counter / notification.travel_dist; + const int alpha = 255 * step; + + moveNotificationVertically(notification, param.notification.pos_v == NotifyPosition::TOP ? 1 : -1); + notification.texture->setAlpha(alpha); + + if (notification.rect.y == notification.y) { + transitionToStayState(index); + } +} + +void Notifier::handleStayState(int index) { + auto& notification = notifications_[index]; + + if (notification.counter == wait_time_) { + notification.state = NotificationStatus::VANISHING; + notification.counter = 0; + } +} + +void Notifier::handleVanishingState(int index) { + auto& notification = notifications_[index]; + + const float step = notification.counter / (float)notification.travel_dist; + const int alpha = 255 * (1 - step); + + moveNotificationVertically(notification, param.notification.pos_v == NotifyPosition::TOP ? -1 : 1); + notification.texture->setAlpha(alpha); + + if (notification.rect.y == notification.y - notification.travel_dist) { + notification.state = NotificationStatus::FINISHED; + } +} + +void Notifier::moveNotificationVertically(Notification& notification, int direction) { + notification.rect.y += direction; +} + +void Notifier::transitionToStayState(int index) { + auto& notification = notifications_[index]; + notification.state = NotificationStatus::STAY; + notification.texture->setAlpha(255); + notification.counter = 0; +} + // Elimina las notificaciones finalizadas void Notifier::clearFinishedNotifications() { for (int i = (int)notifications_.size() - 1; i >= 0; --i) { @@ -120,7 +157,7 @@ void Notifier::clearFinishedNotifications() { } } -void Notifier::show(std::vector texts, int icon, const std::string &code) { +void Notifier::show(std::vector texts, int icon, const std::string& code) { // Si no hay texto, acaba if (texts.empty()) { return; @@ -132,12 +169,12 @@ void Notifier::show(std::vector texts, int icon, const std::string } // Elimina las cadenas vacías - texts.erase(std::remove_if(texts.begin(), texts.end(), [](const std::string &s) { return s.empty(); }), + texts.erase(std::remove_if(texts.begin(), texts.end(), [](const std::string& s) { return s.empty(); }), texts.end()); // Encuentra la cadena más larga std::string longest; - for (const auto &text : texts) { + for (const auto& text : texts) { if (text.length() > longest.length()) { longest = text; } @@ -238,7 +275,7 @@ void Notifier::show(std::vector texts, int icon, const std::string // Escribe el texto de la notificación const Color COLOR{255, 255, 255}; int iterator = 0; - for (const auto &text : texts) { + for (const auto& text : texts) { text_->writeColored(PADDING_IN_H + ICON_SPACE, PADDING_IN_V + iterator * (text_->getCharacterSize() + 1), text, COLOR); ++iterator; } @@ -258,7 +295,7 @@ void Notifier::show(std::vector texts, int icon, const std::string // Finaliza y elimnina todas las notificaciones activas void Notifier::clearAllNotifications() { - for (auto ¬ification : notifications_) { + for (auto& notification : notifications_) { notification.state = NotificationStatus::FINISHED; } @@ -268,7 +305,7 @@ void Notifier::clearAllNotifications() { // Obtiene los códigos de las notificaciones auto Notifier::getCodes() -> std::vector { std::vector codes; - for (const auto ¬ification : notifications_) { + for (const auto& notification : notifications_) { codes.emplace_back(notification.code); } return codes; diff --git a/source/notifier.h b/source/notifier.h index e11db59..7531207 100644 --- a/source/notifier.h +++ b/source/notifier.h @@ -14,74 +14,83 @@ class Texture; // --- Clase Notifier: gestiona las notificaciones en pantalla (singleton) --- class Notifier { - public: - // --- Métodos de singleton --- - static void init(const std::string &icon_file, std::shared_ptr text); // Inicializa el singleton - static void destroy(); // Libera el singleton - static auto get() -> Notifier *; // Obtiene la instancia + public: + // --- Métodos de singleton --- + static void init(const std::string &icon_file, std::shared_ptr text); // Inicializa el singleton + static void destroy(); // Libera el singleton + static auto get() -> Notifier *; // Obtiene la instancia - // --- Métodos principales --- - void render(); // Dibuja las notificaciones por pantalla - void update(); // Actualiza el estado de las notificaciones + // --- Métodos principales --- + void render(); // Dibuja las notificaciones por pantalla + void update(); // Actualiza el estado de las notificaciones - // --- Gestión de notificaciones --- - void show(std::vector texts, int icon = -1, const std::string &code = std::string()); // Muestra una notificación de texto por pantalla - [[nodiscard]] auto isActive() const -> bool { return !notifications_.empty(); } // Indica si hay notificaciones activas - auto getCodes() -> std::vector; // Obtiene los códigos de las notificaciones activas - auto checkCode(const std::string &code) -> bool { return stringInVector(getCodes(), code); } // Comprueba si hay alguna notificación con un código concreto + // --- Gestión de notificaciones --- + void show(std::vector texts, int icon = -1, const std::string &code = std::string()); // Muestra una notificación de texto por pantalla + [[nodiscard]] auto isActive() const -> bool { return !notifications_.empty(); } // Indica si hay notificaciones activas + auto getCodes() -> std::vector; // Obtiene los códigos de las notificaciones activas + auto checkCode(const std::string &code) -> bool { return stringInVector(getCodes(), code); } // Comprueba si hay alguna notificación con un código concreto -private: - // --- Singleton --- - static Notifier *instance; + private: + // --- Tipos internos --- + enum class NotificationStatus { + RISING, + STAY, + VANISHING, + FINISHED, + }; - // --- Tipos internos --- - enum class NotificationStatus { - RISING, - STAY, - VANISHING, - FINISHED, - }; + enum class NotificationShape { + ROUNDED, + SQUARED, + }; - enum class NotificationShape { - ROUNDED, - SQUARED, - }; + // --- Estructura Notification --- + struct Notification { + std::shared_ptr texture; // Textura de la notificación + std::shared_ptr sprite; // Sprite asociado + std::vector texts; // Textos a mostrar + int counter{0}; // Contador de tiempo + NotificationStatus state{NotificationStatus::RISING}; // Estado de la notificación + NotificationShape shape{NotificationShape::SQUARED}; // Forma de la notificación + SDL_FRect rect; // Rectángulo de la notificación + int y{0}; // Posición vertical + int travel_dist{0}; // Distancia a recorrer + std::string code; // Código identificador de la notificación - // --- Estructura Notification --- - struct Notification { - std::shared_ptr texture; // Textura de la notificación - std::shared_ptr sprite; // Sprite asociado - std::vector texts; // Textos a mostrar - int counter{0}; // Contador de tiempo - NotificationStatus state{NotificationStatus::RISING}; // Estado de la notificación - NotificationShape shape{NotificationShape::SQUARED}; // Forma de la notificación - SDL_FRect rect; // Rectángulo de la notificación - int y{0}; // Posición vertical - int travel_dist{0}; // Distancia a recorrer - std::string code; // Código identificador de la notificación + // Constructor + explicit Notification() + : texture(nullptr), sprite(nullptr), rect{0, 0, 0, 0} {} + }; - // Constructor - explicit Notification() - : texture(nullptr), sprite(nullptr), rect{0, 0, 0, 0} {} - }; + // --- Objetos y punteros --- + SDL_Renderer *renderer_; // El renderizador de la ventana + std::shared_ptr icon_texture_; // Textura para los iconos de las notificaciones + std::shared_ptr text_; // Objeto para dibujar texto - // --- Objetos y punteros --- - SDL_Renderer *renderer_; // El renderizador de la ventana - std::shared_ptr icon_texture_; // Textura para los iconos de las notificaciones - std::shared_ptr text_; // Objeto para dibujar texto + // --- Variables de estado --- + Color bg_color_; // Color de fondo de las notificaciones + int wait_time_; // Tiempo que se ve la notificación + std::vector notifications_; // Lista de notificaciones activas + bool stack_; // Indica si las notificaciones se apilan + bool has_icons_; // Indica si el notificador tiene textura para iconos - // --- Variables de estado --- - Color bg_color_; // Color de fondo de las notificaciones - int wait_time_; // Tiempo que se ve la notificación - std::vector notifications_; // Lista de notificaciones activas - bool stack_; // Indica si las notificaciones se apilan - bool has_icons_; // Indica si el notificador tiene textura para iconos + // --- Métodos internos --- + void clearFinishedNotifications(); // Elimina las notificaciones cuyo estado es FINISHED + void clearAllNotifications(); // Elimina todas las notificaciones activas, sin importar el estado + bool shouldProcessNotification(int index) const; // Determina si una notificación debe ser procesada (según su estado y posición) + void processNotification(int index); // Procesa una notificación en la posición dada: actualiza su estado y comportamiento visual + void playNotificationSoundIfNeeded(const Notification ¬ification); // Reproduce sonido asociado si es necesario (dependiendo del estado o contenido) + void updateNotificationState(int index); // Actualiza el estado interno de una notificación (ej. de RISING a STAY) + void handleRisingState(int index); // Lógica de animación para el estado RISING (apareciendo) + void handleStayState(int index); // Lógica para mantener una notificación visible en el estado STAY + void handleVanishingState(int index); // Lógica de animación para el estado VANISHING (desapareciendo) + void moveNotificationVertically(Notification ¬ification, int direction); // Mueve verticalmente una notificación en una dirección dada (útil para animación en apilamiento) + void transitionToStayState(int index); // Cambia el estado de una notificación de RISING a STAY cuando ha alcanzado su posición final - // --- Métodos internos --- - void clearFinishedNotifications(); // Elimina las notificaciones finalizadas - void clearAllNotifications(); // Finaliza y elimina todas las notificaciones activas + // --- Constructor y destructor --- + Notifier(std::string icon_file, std::shared_ptr text); // Constructor privado + ~Notifier() = default; // Destructor privado - // --- Constructor y destructor --- - Notifier(std::string icon_file, std::shared_ptr text); // Constructor privado - ~Notifier() = default; // Destructor privado + // --- Singleton --- + static Notifier *instance; }; \ No newline at end of file diff --git a/source/scoreboard.cpp b/source/scoreboard.cpp index b1305d2..aab7653 100644 --- a/source/scoreboard.cpp +++ b/source/scoreboard.cpp @@ -153,148 +153,177 @@ void Scoreboard::fillPanelTextures() { SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0); SDL_RenderClear(renderer_); - switch (panel_[i].mode) { - case ScoreboardMode::SCORE: { - // SCORE - text_scoreboard_->writeDX(TEXT_COLOR | TEXT_CENTER, slot4_1_.x, slot4_1_.y, name_[i], 1, text_color1_); - text_scoreboard_->writeDX(TEXT_COLOR | TEXT_CENTER, slot4_2_.x, slot4_2_.y, updateScoreText(score_[i]), 1, text_color2_); - - // MULT - text_scoreboard_->writeDX(TEXT_COLOR | TEXT_CENTER, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 3"), 1, text_color1_); - text_scoreboard_->writeDX(TEXT_COLOR | TEXT_CENTER, slot4_4_.x, slot4_4_.y, "x" + std::to_string(mult_[i]).substr(0, 3), 1, text_color2_); - break; - } - - case ScoreboardMode::DEMO: { - // DEMO MODE - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y + 4, Lang::getText("[SCOREBOARD] 6"), 1, text_color1_); - - // PRESS START TO PLAY - if (time_counter_ % 10 < 8) { - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y - 2, Lang::getText("[SCOREBOARD] 8"), 1, text_color1_); - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y - 2, Lang::getText("[SCOREBOARD] 9"), 1, text_color1_); - } - break; - } - - case ScoreboardMode::WAITING: { - // GAME OVER - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y + 4, Lang::getText("[SCOREBOARD] 7"), 1, text_color1_); - - // PRESS START TO PLAY - if (time_counter_ % 10 < 8) { - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y - 2, Lang::getText("[SCOREBOARD] 8"), 1, text_color1_); - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y - 2, Lang::getText("[SCOREBOARD] 9"), 1, text_color1_); - } - break; - } - - case ScoreboardMode::GAME_OVER: { - // GAME OVER - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y + 4, Lang::getText("[SCOREBOARD] 7"), 1, text_color1_); - - // PLEASE WAIT - if (time_counter_ % 10 < 8) { - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y - 2, Lang::getText("[SCOREBOARD] 12"), 1, text_color1_); - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y - 2, Lang::getText("[SCOREBOARD] 13"), 1, text_color1_); - } - break; - } - - case ScoreboardMode::STAGE_INFO: { - // STAGE - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y, Lang::getText("[SCOREBOARD] 5") + std::to_string(stage_), 1, text_color1_); - - // POWERMETER - power_meter_sprite_->setSpriteClip(0, 0, 40, 7); - power_meter_sprite_->render(); - power_meter_sprite_->setSpriteClip(40, 0, int(power_ * 40.0F), 7); - power_meter_sprite_->render(); - - // HI-SCORE - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 4"), 1, text_color1_); - const std::string NAME = hi_score_name_.empty() ? "" : hi_score_name_ + " - "; - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y, NAME + updateScoreText(hi_score_), 1, text_color2_); - break; - } - - case ScoreboardMode::CONTINUE: { - // SCORE - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y, name_[i], 1, text_color1_); - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_2_.x, slot4_2_.y, updateScoreText(score_[i]), 1, text_color2_); - - // CONTINUE - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 10"), 1, text_color1_); - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y, std::to_string(continue_counter_[i]), 1, text_color2_); - break; - } - - case ScoreboardMode::ENTER_NAME: { - // SCORE - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y, name_[i], 1, text_color1_); - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_2_.x, slot4_2_.y, updateScoreText(score_[i]), 1, text_color2_); - - // ENTER NAME - { - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 11"), 1, text_color1_); - SDL_FRect rect = {enter_name_pos_.x, enter_name_pos_.y, 5.0F, 7.0F}; - - // Recorre todos los slots de letras del nombre - for (size_t j = 0; j < NAME_SIZE; ++j) { - // Selecciona el color - const Color COLOR = j < selector_pos_[i] ? text_color2_ : text_color1_; - - if (j != selector_pos_[i] || time_counter_ % 3 == 0) { - // Dibuja la linea - if (j >= selector_pos_[i]) { - SDL_SetRenderDrawColor(renderer_, COLOR.r, COLOR.g, COLOR.b, 255); - SDL_RenderLine(renderer_, rect.x, rect.y + rect.h, rect.x + rect.w, rect.y + rect.h); - } - - // Dibuja la letra - if (j < record_name_[i].size()) { - text_scoreboard_->writeColored(rect.x, rect.y, record_name_[i].substr(j, 1), COLOR); - } - } - rect.x += 7; - } - } - break; - } - case ScoreboardMode::SHOW_NAME: { - // SCORE - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y, name_[i], 1, text_color1_); - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_2_.x, slot4_2_.y, updateScoreText(score_[i]), 1, text_color2_); - - // NAME - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 11"), 1, text_color1_); - - /* TEXTO CENTRADO */ - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y, record_name_[i], 1, getColorLikeKnightRider(name_colors_, loop_counter_ / 5)); - - /* TEXTO A LA IZQUIERDA */ - // text_scoreboard_->writeColored(enter_name_pos_.x, enter_name_pos_.y, record_name_[i], getColorLikeKnightRider(name_colors_, loop_counter_ / 5)); - break; - } - case ScoreboardMode::GAME_COMPLETED: { - // GAME OVER - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y + 4, Lang::getText("[SCOREBOARD] 7"), 1, text_color1_); - - // SCORE - if (time_counter_ % 10 < 8) { - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y - 2, Lang::getText("[SCOREBOARD] 14"), 1, text_color1_); - text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y - 2, updateScoreText(score_[i]), 1, text_color2_); - } - } - default: - break; - } + renderPanelContent(i); } // Deja el renderizador apuntando donde estaba SDL_SetRenderTarget(renderer_, temp); } +void Scoreboard::renderPanelContent(size_t panelIndex) { + switch (panel_[panelIndex].mode) { + case ScoreboardMode::SCORE: + renderScoreMode(panelIndex); + break; + case ScoreboardMode::DEMO: + renderDemoMode(); + break; + case ScoreboardMode::WAITING: + renderWaitingMode(); + break; + case ScoreboardMode::GAME_OVER: + renderGameOverMode(); + break; + case ScoreboardMode::STAGE_INFO: + renderStageInfoMode(); + break; + case ScoreboardMode::CONTINUE: + renderContinueMode(panelIndex); + break; + case ScoreboardMode::ENTER_NAME: + renderEnterNameMode(panelIndex); + break; + case ScoreboardMode::SHOW_NAME: + renderShowNameMode(panelIndex); + break; + case ScoreboardMode::GAME_COMPLETED: + renderGameCompletedMode(panelIndex); + break; + default: + break; + } +} + +void Scoreboard::renderScoreMode(size_t panelIndex) { + // SCORE + text_scoreboard_->writeDX(TEXT_COLOR | TEXT_CENTER, slot4_1_.x, slot4_1_.y, name_[panelIndex], 1, text_color1_); + text_scoreboard_->writeDX(TEXT_COLOR | TEXT_CENTER, slot4_2_.x, slot4_2_.y, updateScoreText(score_[panelIndex]), 1, text_color2_); + + // MULT + text_scoreboard_->writeDX(TEXT_COLOR | TEXT_CENTER, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 3"), 1, text_color1_); + text_scoreboard_->writeDX(TEXT_COLOR | TEXT_CENTER, slot4_4_.x, slot4_4_.y, "x" + std::to_string(mult_[panelIndex]).substr(0, 3), 1, text_color2_); +} + +void Scoreboard::renderDemoMode() { + // DEMO MODE + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y + 4, Lang::getText("[SCOREBOARD] 6"), 1, text_color1_); + + // PRESS START TO PLAY + if (time_counter_ % 10 < 8) { + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y - 2, Lang::getText("[SCOREBOARD] 8"), 1, text_color1_); + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y - 2, Lang::getText("[SCOREBOARD] 9"), 1, text_color1_); + } +} + +void Scoreboard::renderWaitingMode() { + // GAME OVER + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y + 4, Lang::getText("[SCOREBOARD] 7"), 1, text_color1_); + + // PRESS START TO PLAY + if (time_counter_ % 10 < 8) { + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y - 2, Lang::getText("[SCOREBOARD] 8"), 1, text_color1_); + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y - 2, Lang::getText("[SCOREBOARD] 9"), 1, text_color1_); + } +} + +void Scoreboard::renderGameOverMode() { + // GAME OVER + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y + 4, Lang::getText("[SCOREBOARD] 7"), 1, text_color1_); + + // PLEASE WAIT + if (time_counter_ % 10 < 8) { + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y - 2, Lang::getText("[SCOREBOARD] 12"), 1, text_color1_); + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y - 2, Lang::getText("[SCOREBOARD] 13"), 1, text_color1_); + } +} + +void Scoreboard::renderStageInfoMode() { + // STAGE + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y, Lang::getText("[SCOREBOARD] 5") + std::to_string(stage_), 1, text_color1_); + + // POWERMETER + power_meter_sprite_->setSpriteClip(0, 0, 40, 7); + power_meter_sprite_->render(); + power_meter_sprite_->setSpriteClip(40, 0, int(power_ * 40.0F), 7); + power_meter_sprite_->render(); + + // HI-SCORE + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 4"), 1, text_color1_); + const std::string NAME = hi_score_name_.empty() ? "" : hi_score_name_ + " - "; + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y, NAME + updateScoreText(hi_score_), 1, text_color2_); +} + +void Scoreboard::renderContinueMode(size_t panelIndex) { + // SCORE + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y, name_[panelIndex], 1, text_color1_); + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_2_.x, slot4_2_.y, updateScoreText(score_[panelIndex]), 1, text_color2_); + + // CONTINUE + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 10"), 1, text_color1_); + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y, std::to_string(continue_counter_[panelIndex]), 1, text_color2_); +} + +void Scoreboard::renderEnterNameMode(size_t panelIndex) { + // SCORE + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y, name_[panelIndex], 1, text_color1_); + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_2_.x, slot4_2_.y, updateScoreText(score_[panelIndex]), 1, text_color2_); + + // ENTER NAME + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 11"), 1, text_color1_); + + renderNameInputField(panelIndex); +} + +void Scoreboard::renderNameInputField(size_t panelIndex) { + SDL_FRect rect = {enter_name_pos_.x, enter_name_pos_.y, 5.0F, 7.0F}; + + // Recorre todos los slots de letras del nombre + for (size_t j = 0; j < NAME_SIZE; ++j) { + // Selecciona el color + const Color COLOR = j < selector_pos_[panelIndex] ? text_color2_ : text_color1_; + + if (j != selector_pos_[panelIndex] || time_counter_ % 3 == 0) { + // Dibuja la linea + if (j >= selector_pos_[panelIndex]) { + SDL_SetRenderDrawColor(renderer_, COLOR.r, COLOR.g, COLOR.b, 255); + SDL_RenderLine(renderer_, rect.x, rect.y + rect.h, rect.x + rect.w, rect.y + rect.h); + } + + // Dibuja la letra + if (j < record_name_[panelIndex].size()) { + text_scoreboard_->writeColored(rect.x, rect.y, record_name_[panelIndex].substr(j, 1), COLOR); + } + } + rect.x += 7; + } +} + +void Scoreboard::renderShowNameMode(size_t panelIndex) { + // SCORE + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y, name_[panelIndex], 1, text_color1_); + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_2_.x, slot4_2_.y, updateScoreText(score_[panelIndex]), 1, text_color2_); + + // NAME + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 11"), 1, text_color1_); + + /* TEXTO CENTRADO */ + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y, record_name_[panelIndex], 1, getColorLikeKnightRider(name_colors_, loop_counter_ / 5)); + + /* TEXTO A LA IZQUIERDA */ + // text_scoreboard_->writeColored(enter_name_pos_.x, enter_name_pos_.y, record_name_[panelIndex], getColorLikeKnightRider(name_colors_, loop_counter_ / 5)); +} + +void Scoreboard::renderGameCompletedMode(size_t panelIndex) { + // GAME OVER + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y + 4, Lang::getText("[SCOREBOARD] 7"), 1, text_color1_); + + // SCORE + if (time_counter_ % 10 < 8) { + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y - 2, Lang::getText("[SCOREBOARD] 14"), 1, text_color1_); + text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y - 2, updateScoreText(score_[panelIndex]), 1, text_color2_); + } +} + // Rellena la textura de fondo void Scoreboard::fillBackgroundTexture() { // Rellena los diferentes paneles del marcador diff --git a/source/scoreboard.h b/source/scoreboard.h index 8ea5ba1..1016edc 100644 --- a/source/scoreboard.h +++ b/source/scoreboard.h @@ -113,6 +113,17 @@ class Scoreboard { void updateTimeCounter(); // Actualiza el contador void renderSeparator(); // Dibuja la línea que separa la zona de juego del marcador void iniNameColors(); // Inicializa el vector de colores para el nombre + void renderPanelContent(size_t panelIndex); + void renderScoreMode(size_t panelIndex); + void renderDemoMode(); + void renderWaitingMode(); + void renderGameOverMode(); + void renderStageInfoMode(); + void renderContinueMode(size_t panelIndex); + void renderEnterNameMode(size_t panelIndex); + void renderNameInputField(size_t panelIndex); + void renderShowNameMode(size_t panelIndex); + void renderGameCompletedMode(size_t panelIndex); // --- Constructor y destructor privados (singleton) --- Scoreboard();