diff --git a/source/director.cpp b/source/director.cpp index a55d398..2ada3de 100644 --- a/source/director.cpp +++ b/source/director.cpp @@ -52,7 +52,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::HI_SCORE_TABLE; + section::name = section::Name::INSTRUCTIONS; #else // NORMAL GAME section::name = section::Name::LOGO; section::attract_mode = section::AttractMode::TITLE_TO_DEMO; diff --git a/source/instructions.cpp b/source/instructions.cpp index 3c9bd51..4b8a3e6 100644 --- a/source/instructions.cpp +++ b/source/instructions.cpp @@ -22,6 +22,10 @@ #include "utils.h" // Para Color, shdw_txt_color, Zone, no_color #include "mouse.h" +#include +#include +#include + // Constructor Instructions::Instructions() : renderer_(Screen::get()->getRenderer()), @@ -46,6 +50,9 @@ Instructions::Instructions() fade_->setMode(FadeMode::IN); fade_->activate(); + // Inicializa las líneas con un retraso progresivo de 50 ms + lines_ = initializeLines(256); + // Rellena la textura de texto fillTexture(); @@ -225,14 +232,36 @@ void Instructions::update() // Actualiza los sprites updateSprites(); + // Establece la ventana del backbuffer + view_.y = std::max(0, param.game.height - counter_ + 100); + + // Verifica si view_.y == 0 y gestiona el temporizador + if (view_.y == 0) + { + if (!start_delay_triggered_) + { + // Activa el temporizador si no ha sido activado + start_delay_triggered_ = true; + start_delay_time_ = SDL_GetTicks(); + } + else if (SDL_GetTicks() - start_delay_time_ >= 4000) + { + // Han pasado tres segundos, mover líneas + all_lines_off_screen_ = moveLines(lines_, 320, 1.0f, 5); + } + } + // Actualiza el mosaico de fondo tiled_bg_->update(); // Actualiza el objeto "fade" fade_->update(); + // Rellena el backbuffer + fillBackbuffer(); + // Comprueba si el contador ha llegado al final - if (counter_ == counter_end_) + if (all_lines_off_screen_) { section::name = section::Name::TITLE; section::options = section::Options::TITLE_1; @@ -243,9 +272,6 @@ void Instructions::update() // Pinta en pantalla void Instructions::render() { - // Rellena el backbuffer - fillBackbuffer(); - // Prepara para empezar a dibujar en la textura de juego Screen::get()->start(); @@ -255,11 +281,11 @@ void Instructions::render() // Dibuja el mosacico de fondo tiled_bg_->render(); - // Establece la ventana del backbuffer - view_.y = std::max(0, param.game.height - counter_ + 100); - // Copia la textura y el backbuffer al renderizador - SDL_RenderCopy(renderer_, backbuffer_, nullptr, &view_); + if (view_.y == 0) + renderLines(renderer_, backbuffer_, lines_); + else + SDL_RenderCopy(renderer_, backbuffer_, nullptr, &view_); fade_->render(); @@ -334,4 +360,61 @@ void Instructions::run() checkEvents(); // Tiene que ir antes del render render(); } +} + +// Método para inicializar las líneas +std::vector Instructions::initializeLines(int height) +{ + std::vector lines; + for (int y = 0; y < height; y++) + { + int direction = (y % 2 == 0) ? -1 : 1; // Pares a la izquierda, impares a la derecha + lines.emplace_back(y, 0.0f, direction); + } + return lines; +} + +// Método para mover las líneas con suavizado +bool Instructions::moveLines(std::vector &lines, int width, float duration, Uint32 startDelay) +{ + Uint32 currentTime = SDL_GetTicks(); + bool allLinesOffScreen = true; + + for (auto &line : lines) + { + // Establecer startTime en el primer cuadro de animación + if (line.startTime == 0) + { + line.startTime = currentTime + line.y * startDelay; + } + + float elapsedTime = (currentTime - line.startTime) / 1000.0f; // Convertir a segundos + if (elapsedTime < 0) + { + allLinesOffScreen = false; // Si aún no se debe mover esta línea, no están todas fuera de pantalla + continue; + } + if (elapsedTime >= duration) + { + continue; // Si la línea ha salido de los límites, no la muevas más + } + + float t = elapsedTime / duration; + float smoothFactor = easeInOutQuint(t); + line.x = line.direction * smoothFactor * width; + allLinesOffScreen = false; // Si alguna línea aún se está moviendo, no están todas fuera de pantalla + } + + return allLinesOffScreen; +} + +// Método para renderizar las líneas +void Instructions::renderLines(SDL_Renderer *renderer, SDL_Texture *texture, const std::vector &lines) +{ + for (const auto &line : lines) + { + SDL_Rect srcRect = {0, line.y, 320, 1}; + SDL_Rect dstRect = {static_cast(line.x), line.y, 320, 1}; + SDL_RenderCopy(renderer, texture, &srcRect, &dstRect); + } } \ No newline at end of file diff --git a/source/instructions.h b/source/instructions.h index 5ca2d5e..f82c116 100644 --- a/source/instructions.h +++ b/source/instructions.h @@ -24,6 +24,19 @@ class TiledBG; // lines 12-12 por la pantalla sobre el mosaico de fondo (gestionado por el correspondiente objeto) */ +// Estructura para almacenar información de línea +struct Line +{ + int y; // Coordenada Y de la línea + float x; // Coordenada X inicial (usamos float para mayor precisión en el suavizado) + int direction; // Dirección de movimiento: -1 para izquierda, 1 para derecha + Uint32 startTime; // Tiempo de inicio del movimiento + + // Constructor de Line + Line(int y, float x, int direction) + : y(y), x(x), direction(direction), startTime(0) {} +}; + // Clase Instructions class Instructions { @@ -40,12 +53,15 @@ private: std::unique_ptr fade_; // Objeto para renderizar fades // Variables - int counter_ = 0; // Contador - int counter_end_ = 700; // Valor final para el contador - Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa - SDL_Rect view_; // Vista del backbuffer que se va amostrar por pantalla - SDL_Point sprite_pos_ = {0, 0}; // Posición del primer sprite - int item_space_ = 2; // Espacio entre los items + int counter_ = 0; // Contador para manejar el progreso en la pantalla de instrucciones + Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa + SDL_Rect view_; // Vista del backbuffer que se va a mostrar por pantalla + SDL_Point sprite_pos_ = {0, 0}; // Posición del primer sprite en la lista + int item_space_ = 2; // Espacio entre los items en pantalla + std::vector lines_; // Vector que contiene las líneas animadas en la pantalla + bool all_lines_off_screen_ = false; // Indica si todas las líneas han salido de la pantalla + Uint32 start_delay_time_ = 0; // Tiempo de inicio del retraso para mover las líneas + bool start_delay_triggered_ = false; // Bandera para determinar si el retraso ha comenzado // Actualiza las variables void update(); @@ -74,6 +90,15 @@ private: // Recarga todas las texturas void reloadTextures(); + // Método para inicializar las líneas + std::vector initializeLines(int height); + + // Método para mover las líneas + bool moveLines(std::vector &lines, int width, float duration, Uint32 startDelay); + + // Método para renderizar las líneas + void renderLines(SDL_Renderer *renderer, SDL_Texture *texture, const std::vector &lines); + public: // Constructor Instructions(); diff --git a/source/utils.cpp b/source/utils.cpp index a1dbfde..01dab0e 100644 --- a/source/utils.cpp +++ b/source/utils.cpp @@ -213,6 +213,12 @@ double easeInOutSine(double t) return -0.5 * (std::cos(M_PI * t) - 1); } +// Función de suavizado +double easeInOut(double t) +{ + return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t; +} + // Comprueba si una vector contiene una cadena bool stringInVector(const std::vector &vec, const std::string &str) { diff --git a/source/utils.h b/source/utils.h index 81961b6..83cccb9 100644 --- a/source/utils.h +++ b/source/utils.h @@ -170,6 +170,7 @@ double easeInOutQuint(double t); double easeInQuad(double t); double easeOutQuad(double t); double easeInOutSine(double t); +double easeInOut(double t); // Comprueba si una vector contiene una cadena bool stringInVector(const std::vector &vec, const std::string &str);