From 9cd1755266fe748f8b6281f0f914ced04948cdd6 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Sun, 2 Nov 2025 09:48:07 +0100 Subject: [PATCH] =?UTF-8?q?LoadingScreen:=20implementat=20visualment=20la?= =?UTF-8?q?=20c=C3=A0rrega=20de=20headers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/assets.txt | 1 + data/loading/program_jaildoc.gif | Bin 0 -> 175 bytes source/game/scene_manager.hpp | 2 +- source/game/scenes/loading_screen.cpp | 120 +++++++++++++++++--------- source/game/scenes/loading_screen.hpp | 82 ++++++++++-------- 5 files changed, 127 insertions(+), 78 deletions(-) create mode 100644 data/loading/program_jaildoc.gif diff --git a/config/assets.txt b/config/assets.txt index ae060b7..63b532b 100644 --- a/config/assets.txt +++ b/config/assets.txt @@ -374,6 +374,7 @@ BITMAP|${PREFIX}/data/logo/since_1998.gif # =================================================================== BITMAP|${PREFIX}/data/loading/loading_screen_bn.gif BITMAP|${PREFIX}/data/loading/loading_screen_color.gif +BITMAP|${PREFIX}/data/loading/program_jaildoc.gif # =================================================================== # TITLE SCREEN diff --git a/data/loading/program_jaildoc.gif b/data/loading/program_jaildoc.gif new file mode 100644 index 0000000000000000000000000000000000000000..5af6993d5b820d1fe0481e0680e1f6de3ccfba89 GIT binary patch literal 175 zcmZ?wbh9u|Y+&GEXkdT>#sA!Xt|7tBjsdPldIrplKw-t7ESy|GS_h;Aq?m!JxTSyP z>9_og=jcXwZ@#DIu)g8AYTDDz-j%z`-nJ&FvUe1i+%A0m>hb&!R~uy8&rQC3rfrq0 zkVeY8yrT++yVe9w3_8{Mb<441m)2XftowH6$tQ!~itf8zwoZu6_m`~r(7!s}W$D*L Vj~{IpPw{X*@!|)^%m4-kYXCqxNaFwi literal 0 HcmV?d00001 diff --git a/source/game/scene_manager.hpp b/source/game/scene_manager.hpp index 9ee627a..7cf180d 100644 --- a/source/game/scene_manager.hpp +++ b/source/game/scene_manager.hpp @@ -34,7 +34,7 @@ enum class Options { // --- Variables de estado globales --- #ifdef _DEBUG -inline Scene current = Scene::GAME; // Escena actual +inline Scene current = Scene::LOADING_SCREEN; // Escena actual inline Options options = Options::LOGO_TO_LOADING_SCREEN; // Opciones de la escena actual #else inline Scene current = Scene::LOGO; // Escena actual diff --git a/source/game/scenes/loading_screen.cpp b/source/game/scenes/loading_screen.cpp index 174d70d..21b5cef 100644 --- a/source/game/scenes/loading_screen.cpp +++ b/source/game/scenes/loading_screen.cpp @@ -2,6 +2,7 @@ #include +#include // Para std::sin #include // Para rand #include "core/audio/audio.hpp" // Para Audio @@ -21,20 +22,18 @@ LoadingScreen::LoadingScreen() : mono_loading_screen_surface_(Resource::get()->getSurface("loading_screen_bn.gif")), color_loading_screen_surface_(Resource::get()->getSurface("loading_screen_color.gif")), - mono_loading_screen_sprite_(std::make_shared(mono_loading_screen_surface_, 0, 0, mono_loading_screen_surface_->getWidth(), mono_loading_screen_surface_->getHeight())), - color_loading_screen_sprite_(std::make_shared(color_loading_screen_surface_, 0, 0, color_loading_screen_surface_->getWidth(), color_loading_screen_surface_->getHeight())), + mono_loading_screen_sprite_(std::make_unique(mono_loading_screen_surface_, 0, 0, mono_loading_screen_surface_->getWidth(), mono_loading_screen_surface_->getHeight())), + color_loading_screen_sprite_(std::make_unique(color_loading_screen_surface_, 0, 0, color_loading_screen_surface_->getWidth(), color_loading_screen_surface_->getHeight())), + program_sprite_(std::make_unique(Resource::get()->getSurface("program_jaildoc.gif"))), screen_surface_(std::make_shared(Options::game.width, Options::game.height)), - delta_timer_(std::make_unique()), - state_(State::SILENT1), - state_time_(0.0F), - current_border_type_(Border::NONE), - load_rect_{0, 0, 0, 1.0F} { + delta_timer_(std::make_unique()) { // Configura la superficie donde se van a pintar los sprites screen_surface_->clear(static_cast(PaletteColor::WHITE)); // Inicializa variables SceneManager::current = SceneManager::Scene::LOADING_SCREEN; SceneManager::options = SceneManager::Options::NONE; + program_sprite_->setPosition(0.0F, 8.0F); // Inicializa el array de índices de líneas initLineIndexArray(); @@ -85,27 +84,29 @@ void LoadingScreen::transitionToState(State new_state) { switch (new_state) { case State::SILENT1: case State::SILENT2: - current_border_type_ = Border::WHITE; + current_border_type_ = Border::RED; Audio::get()->stopMusic(); break; case State::HEADER1: case State::HEADER2: - current_border_type_ = Border::RED; + current_border_type_ = Border::RED_AND_CYAN; // Reproducir sonido de cargar el header Audio::get()->playMusic("loading_sound1.ogg"); break; - case State::BYTES1: - case State::BYTES2: + case State::DATA1: + printProgramName(); + /* CONTINUA */ + case State::DATA2: case State::LOADING_MONO: - current_border_type_ = Border::YELLOW; + current_border_type_ = Border::YELLOW_AND_BLUE; // Reproducir sonido de carga monocromática Audio::get()->playMusic("loading_sound2.ogg"); break; case State::LOADING_COLOR: - current_border_type_ = Border::YELLOW; + current_border_type_ = Border::YELLOW_AND_BLUE; // Reproducir sonido de carga en color Audio::get()->playMusic("loading_sound3.ogg"); break; @@ -135,12 +136,12 @@ void LoadingScreen::updateState(float delta_time) { case State::HEADER1: if (state_time_ >= HEADER1_DURATION) { - transitionToState(State::BYTES1); + transitionToState(State::DATA1); } break; - case State::BYTES1: - if (state_time_ >= BYTES1_DURATION) { + case State::DATA1: + if (state_time_ >= DATA1_DURATION) { transitionToState(State::SILENT2); } break; @@ -157,8 +158,8 @@ void LoadingScreen::updateState(float delta_time) { } break; - case State::BYTES2: - if (state_time_ >= BYTES2_DURATION) { + case State::DATA2: + if (state_time_ >= DATA2_DURATION) { transitionToState(State::COMPLETE); } break; @@ -226,7 +227,7 @@ void LoadingScreen::updateColorLoad(float delta_time) { // Verificar si ha completado todos los bloques if (CURRENT_BLOCK >= COLOR_TOTAL_BLOCKS) { - transitionToState(State::BYTES2); + transitionToState(State::DATA2); return; } @@ -247,7 +248,7 @@ void LoadingScreen::updateColorLoad(float delta_time) { } // Dibuja el efecto de carga amarillo y azul en el borde -void LoadingScreen::renderYellowBorder() { +void LoadingScreen::renderDataBorder() { // Obtiene la Surface del borde auto border = Screen::get()->getBorderSurface(); @@ -274,22 +275,22 @@ void LoadingScreen::renderYellowBorder() { } // Dibuja el efecto de carga rojo y azul en el borde -void LoadingScreen::renderRedBorder() { +void LoadingScreen::renderHeaderBorder() { // Obtiene la Surface del borde auto border = Screen::get()->getBorderSurface(); - // Pinta el borde de color azul - border->clear(static_cast(PaletteColor::CYAN)); + // Pinta el borde de color azul o rojo + border->clear(carrier_.toggle ? static_cast(PaletteColor::CYAN) : static_cast(PaletteColor::RED)); - // Añade lineas rojas - const auto COLOR = static_cast(PaletteColor::RED); + // Añade lineas rojas o azules + const auto COLOR = carrier_.toggle ? static_cast(PaletteColor::RED) : static_cast(PaletteColor::CYAN); const int WIDTH = Options::game.width + (Options::video.border.width * 2); const int HEIGHT = Options::game.height + (Options::video.border.height * 2); bool draw_enabled = true; - // Primera linea (para que tenga poca variacion) + // Primera linea (con el color y tamaño de la portadora) int row = 0; - const int FIRST_ROW_HEIGHT = (rand() % 4) + 3; + const int FIRST_ROW_HEIGHT = static_cast(carrier_.offset); if (draw_enabled) { for (int i = row; i < row + FIRST_ROW_HEIGHT; ++i) { border->drawLine(0, i, WIDTH, i, COLOR); @@ -298,26 +299,25 @@ void LoadingScreen::renderRedBorder() { row += FIRST_ROW_HEIGHT; draw_enabled = !draw_enabled; - // Resto de lineas + // Resto de lineas (siguen a la portadora) while (row < HEIGHT) { - const int ROW_HEIGHT = (rand() % 3) + 8; if (draw_enabled) { - for (int i = row; i < row + ROW_HEIGHT; ++i) { + for (int i = row; i < row + HEADER_DATAROW_HEIGHT; ++i) { border->drawLine(0, i, WIDTH, i, COLOR); } } - row += ROW_HEIGHT; + row += HEADER_DATAROW_HEIGHT; draw_enabled = !draw_enabled; } } -// Dibuja el borde de color blanco -void LoadingScreen::renderWhiteBorder() { +// Dibuja el borde de color +void LoadingScreen::renderColoredBorder(PaletteColor color) { // Obtiene la Surface del borde auto border = Screen::get()->getBorderSurface(); // Pinta el borde de color azul - border->clear(static_cast(PaletteColor::WHITE)); + border->clear(static_cast(color)); } // Actualiza las variables @@ -332,14 +332,16 @@ void LoadingScreen::update() { // Actualizar la carga según el estado actual switch (state_) { case State::SILENT1: - case State::HEADER1: - case State::BYTES1: + case State::DATA1: case State::SILENT2: - case State::HEADER2: - case State::BYTES2: + case State::DATA2: // Por ahora no hacen nada específico // Tú definirás la lógica de cada estado aquí break; + case State::HEADER1: + case State::HEADER2: + updateCarrier(DELTA_TIME); + break; case State::LOADING_MONO: updateMonoLoad(DELTA_TIME); @@ -397,18 +399,50 @@ void LoadingScreen::renderBorder() { if (Options::video.border.enabled) { // Dibuja el efecto de carga en el borde según el tipo actual switch (current_border_type_) { - case Border::YELLOW: - renderYellowBorder(); + case Border::YELLOW_AND_BLUE: + renderDataBorder(); break; - case Border::RED: - renderRedBorder(); + case Border::RED_AND_CYAN: + renderHeaderBorder(); break; case Border::WHITE: - renderWhiteBorder(); + renderColoredBorder(PaletteColor::WHITE); + break; + case Border::RED: + renderColoredBorder(PaletteColor::RED); + break; + case Border::CYAN: + renderColoredBorder(PaletteColor::CYAN); break; case Border::NONE: // No renderizar borde break; } } +} + +// Escribe el nombre del programa +void LoadingScreen::printProgramName() { + auto previous_renderer = Screen::get()->getRendererSurface(); + Screen::get()->setRendererSurface(screen_surface_); + program_sprite_->render(1, stringToColor("black")); + Screen::get()->setRendererSurface(previous_renderer); +} + +void LoadingScreen::updateCarrier(float delta_time) { + constexpr float CARRIER_BASE_SPEED = -250.0F; + constexpr float CARRIER_HEIGHT = HEADER_DATAROW_HEIGHT; + + // Oscilación compuesta: mezcla de dos frecuencias para evitar patrón predecible + const float modulation = std::sin(carrier_.total_time * 1.2F) * std::sin(carrier_.total_time * 0.35F + 1.0F); + const float speed = CARRIER_BASE_SPEED * (0.5F + 0.5F * modulation); // rango [-200, 0] + + carrier_.offset += speed * delta_time; + + if (carrier_.offset < 0.0F) { + carrier_.offset += CARRIER_HEIGHT; // reinicia al rango [0,HEADER_DATAROW_HEIGHT] + carrier_.toggle = !carrier_.toggle; + } + + carrier_.total_time += delta_time; } \ No newline at end of file diff --git a/source/game/scenes/loading_screen.hpp b/source/game/scenes/loading_screen.hpp index c7548ec..4bbc8f1 100644 --- a/source/game/scenes/loading_screen.hpp +++ b/source/game/scenes/loading_screen.hpp @@ -6,6 +6,7 @@ #include // Para shared_ptr #include "utils/delta_timer.hpp" // Para DeltaTimer +#include "utils/utils.hpp" // Para PaletteColor class SurfaceSprite; // Forward declaration class Surface; // Forward declaration @@ -15,21 +16,23 @@ class LoadingScreen { enum class State { SILENT1, // Pausa inicial antes de empezar HEADER1, // Cabecera - BYTES1, // Datos + DATA1, // Datos SILENT2, // Segunda pausa HEADER2, // Cabecera pantalla LOADING_MONO, // Carga de pantalla monocromática (escaneo de líneas) LOADING_COLOR, // Carga de pantalla en color (bloques) - BYTES2, // Datos + DATA2, // Datos COMPLETE // Carga completa }; // Tipos de borde para la pantalla de carga enum class Border { NONE, - YELLOW, + YELLOW_AND_BLUE, + RED_AND_CYAN, + WHITE, RED, - WHITE + CYAN }; // --- Constructor y Destructor --- @@ -40,52 +43,63 @@ class LoadingScreen { void run(); private: + struct Carrier { + float offset{0.0F}; // Offset para la carga de cabeceras + bool toggle{false}; // Para cambiar el color inicial + float total_time{0.0F}; // Tiempo acumulado para modulación de velocidad + }; + // --- Constantes de tiempo (en segundos) --- static constexpr float SILENT1_DURATION = 1.0F; // Pausa inicial - static constexpr float HEADER1_DURATION = 2.0F; // Cabecera - static constexpr float BYTES1_DURATION = 0.5F; // Datos + static constexpr float HEADER1_DURATION = 4.0F; // Cabecera + static constexpr float DATA1_DURATION = 0.3F; // Datos static constexpr float SILENT2_DURATION = 2.0F; // Segunda pausa static constexpr float HEADER2_DURATION = 2.0F; // Cabecera pantalla static constexpr float LOADING_MONO_DURATION = 16.0F; // Duración total de la carga monocromática static constexpr float LOADING_COLOR_DURATION = 4.0F; // Duración total de la carga en color - static constexpr float BYTES2_DURATION = 2.0F; // Datos + static constexpr float DATA2_DURATION = 2.0F; // Datos // --- Constantes de geometría --- - static constexpr int MONO_TOTAL_LINES = 192; // Total de líneas en carga monocromática - static constexpr int MONO_STEPS_PER_LINE = 5; // Pasos de animación por línea - static constexpr int COLOR_TOTAL_BLOCKS = 768; // Total de bloques en carga color - static constexpr int COLOR_BLOCK_WIDTH = 16; // Ancho del bloque de color - static constexpr int COLOR_BLOCK_HEIGHT = 8; // Alto del bloque de color - static constexpr int COLOR_BLOCKS_PER_ROW = 32; // Bloques por fila (256 / 8) - static constexpr int COLOR_BLOCK_SPACING = 8; // Espaciado entre bloques + static constexpr int MONO_TOTAL_LINES = 192; // Total de líneas en carga monocromática + static constexpr int MONO_STEPS_PER_LINE = 5; // Pasos de animación por línea + static constexpr int COLOR_TOTAL_BLOCKS = 768; // Total de bloques en carga color + static constexpr int COLOR_BLOCK_WIDTH = 16; // Ancho del bloque de color + static constexpr int COLOR_BLOCK_HEIGHT = 8; // Alto del bloque de color + static constexpr int COLOR_BLOCKS_PER_ROW = 32; // Bloques por fila (256 / 8) + static constexpr int COLOR_BLOCK_SPACING = 8; // Espaciado entre bloques + static constexpr int HEADER_DATAROW_HEIGHT = 9.0F; // Alto de las barras del borde de la carga de las cabeceras // --- Objetos y punteros --- std::shared_ptr mono_loading_screen_surface_; // Surface con la pantalla de carga en blanco y negro std::shared_ptr color_loading_screen_surface_; // Surface con la pantalla de carga en color - std::shared_ptr mono_loading_screen_sprite_; // SSprite para manejar la textura loadingScreenTexture1 - std::shared_ptr color_loading_screen_sprite_; // SSprite para manejar la textura loadingScreenTexture2 + std::unique_ptr mono_loading_screen_sprite_; // SurfaceSprite para manejar la textura mono_loading_screen_surface_ + std::unique_ptr color_loading_screen_sprite_; // SurfaceSprite para manejar la textura color_loading_screen_surface_ + std::unique_ptr program_sprite_; // SurfaceSprite para manejar la textura con el noimbre del programa std::shared_ptr screen_surface_; // Surface para dibujar la pantalla de carga + std::unique_ptr delta_timer_; // Timer para delta time // --- Variables de estado --- - std::unique_ptr delta_timer_; // Timer para delta time - State state_; // Estado actual de la secuencia - float state_time_; // Tiempo acumulado en el estado actual - Border current_border_type_; // Tipo de borde actual + State state_{State::SILENT1}; // Estado actual de la secuencia + float state_time_{0.0F}; // Tiempo acumulado en el estado actual + Border current_border_type_{Border::NONE}; // Tipo de borde actual std::array line_index_; // El orden en el que se procesan las 192 líneas de la pantalla de carga - SDL_FRect load_rect_; // Rectángulo para dibujar la pantalla de carga + SDL_FRect load_rect_{0.0F, 0.0F, 0.0F, 1.0F}; // Rectángulo para dibujar la pantalla de carga + Carrier carrier_; // Estructura para los efectos de la carga de cabeceras // --- Funciones --- - void update(); // Actualiza las variables - void render(); // Dibuja en pantalla - static void handleEvents(); // Comprueba el manejador de eventos - static void handleInput(); // Comprueba las entradas - void updateState(float delta_time); // Actualiza el estado actual - void transitionToState(State new_state); // Transiciona a un nuevo estado - void updateMonoLoad(float delta_time); // Gestiona la carga monocromática (time-based) - void updateColorLoad(float delta_time); // Gestiona la carga en color (time-based) - void renderBorder(); // Pinta el borde - static void renderYellowBorder(); // Dibuja el efecto de carga amarillo y azul en el borde - static void renderRedBorder(); // Dibuja el efecto de carga rojo y azul en el borde - static void renderWhiteBorder(); // Dibuja el borde de color blanco - void initLineIndexArray(); // Inicializa el array de índices de líneas + void update(); // Actualiza las variables + void render(); // Dibuja en pantalla + static void handleEvents(); // Comprueba el manejador de eventos + static void handleInput(); // Comprueba las entradas + void updateState(float delta_time); // Actualiza el estado actual + void transitionToState(State new_state); // Transiciona a un nuevo estado + void updateMonoLoad(float delta_time); // Gestiona la carga monocromática (time-based) + void updateColorLoad(float delta_time); // Gestiona la carga en color (time-based) + void renderBorder(); // Pinta el borde + static void renderDataBorder(); // Dibuja el efecto de carga amarillo y azul en el borde + void renderHeaderBorder(); // Dibuja el efecto de carga rojo y azul en el borde + static void renderColoredBorder(PaletteColor color); // Dibuja el borde de color + void initLineIndexArray(); // Inicializa el array de índices de líneas + void printProgramName(); // Escribe el nombre del programa + void updateCarrier(float delta_time); // Actualiza la portadora }; \ No newline at end of file