diff --git a/source/director.cpp b/source/director.cpp index 79f7560..a4a282c 100644 --- a/source/director.cpp +++ b/source/director.cpp @@ -44,7 +44,7 @@ Director::Director(int argc, std::span argv) { Section::name = Section::Name::GAME; Section::options = Section::Options::GAME_PLAY_1P; #elif _DEBUG - Section::name = Section::Name::GAME; + Section::name = Section::Name::HI_SCORE_TABLE; Section::options = Section::Options::GAME_PLAY_1P; #else // NORMAL GAME Section::name = Section::Name::LOGO; diff --git a/source/fade.cpp b/source/fade.cpp index c49452c..0b6bdf3 100644 --- a/source/fade.cpp +++ b/source/fade.cpp @@ -1,13 +1,13 @@ #include "fade.hpp" -#include // Para SDL_SetRenderTarget, SDL_FRect, SDL_GetRenderTarget, SDL_RenderFillRect, SDL_SetRenderDrawBlendMode, SDL_SetRenderDrawColor, Uint8, SDL_GetRenderDrawBlendMode, SDL_BLENDMODE_NONE, SDL_BlendMode, SDL_CreateTexture, SDL_DestroyTexture, SDL_RenderClear, SDL_RenderTexture, SDL_SetTextureAlphaMod, SDL_SetTextureBlendMode, SDL_BLENDMODE_BLEND, SDL_PixelFormat, SDL_TextureAccess +#include -#include // Para min, max -#include // Para rand, size_t +#include +#include -#include "color.hpp" // Para Color -#include "param.hpp" // Para Param, param, ParamGame, ParamFade -#include "screen.hpp" // Para Screen +#include "color.hpp" +#include "param.hpp" +#include "screen.hpp" // Constructor Fade::Fade() @@ -29,7 +29,6 @@ Fade::~Fade() { void Fade::init() { type_ = Type::CENTER; mode_ = Mode::OUT; - counter_ = 0; r_ = 0; g_ = 0; b_ = 0; @@ -38,19 +37,21 @@ void Fade::init() { post_start_time_ = 0; pre_duration_ = 0; pre_start_time_ = 0; + fading_duration_ = param.fade.random_squares_duration_ms; // Duración por defecto para FADING + fading_start_time_ = 0; num_squares_width_ = param.fade.num_squares_width; num_squares_height_ = param.fade.num_squares_height; - random_squares_duration_ = param.fade.random_squares_duration_ms; // Usar como duración en ms - square_transition_duration_ = random_squares_duration_ / 4; // 25% del tiempo total para la transición individual - random_squares_start_time_ = 0; + square_transition_duration_ = fading_duration_ / 4; // 25% del tiempo total para la transición individual } // Resetea algunas variables para volver a hacer el fade sin perder ciertos parametros void Fade::reset() { state_ = State::NOT_ENABLED; - counter_ = 0; post_start_time_ = 0; pre_start_time_ = 0; + fading_start_time_ = 0; + value_ = 0; + // La duración del fade se mantiene, se puede cambiar con setDuration() } // Pinta una transición en pantalla @@ -66,7 +67,7 @@ void Fade::render() { } // Actualiza las variables internas -void Fade::update() { +void Fade::update(float delta_time) { switch (state_) { case State::PRE: updatePreState(); @@ -82,21 +83,12 @@ void Fade::update() { } } -// Compatibilidad delta-time (ignora el parámetro ya que usa SDL_GetTicks) -void Fade::update(float delta_time) { - update(); // Llama al método original -} - void Fade::updatePreState() { - // Sistema basado en tiempo únicamente Uint32 elapsed_time = SDL_GetTicks() - pre_start_time_; if (elapsed_time >= static_cast(pre_duration_)) { state_ = State::FADING; - // CRÍTICO: Reinicializar tiempo de inicio para tipos que usan random_squares_start_time_ - if (type_ == Type::RANDOM_SQUARE2 || type_ == Type::DIAGONAL) { - random_squares_start_time_ = SDL_GetTicks(); - } + fading_start_time_ = SDL_GetTicks(); // Inicia el temporizador del fade AQUI } } @@ -123,7 +115,6 @@ void Fade::updateFadingState() { default: break; } - counter_++; } void Fade::changeToPostState() { @@ -132,39 +123,61 @@ void Fade::changeToPostState() { } void Fade::updatePostState() { - // Sistema basado en tiempo únicamente Uint32 elapsed_time = SDL_GetTicks() - post_start_time_; if (elapsed_time >= static_cast(post_duration_)) { state_ = State::FINISHED; } - // Mantener el alpha final correcto para cada tipo de fade + // Mantener el estado final del fade Uint8 post_alpha = a_; if (type_ == Type::RANDOM_SQUARE2 || type_ == Type::DIAGONAL) { post_alpha = (mode_ == Mode::OUT) ? 255 : 0; + } else { + post_alpha = (mode_ == Mode::OUT) ? 255 : 0; } cleanBackbuffer(r_, g_, b_, post_alpha); } void Fade::updateFullscreenFade() { - // Modifica la transparencia - a_ = mode_ == Mode::OUT ? std::min(counter_ * 4, 255) : 255 - std::min(counter_ * 4, 255); + Uint32 elapsed_time = SDL_GetTicks() - fading_start_time_; + float progress = std::min(static_cast(elapsed_time) / fading_duration_, 1.0F); + + // Modifica la transparencia basada en el progreso + Uint8 current_alpha = static_cast(progress * 255.0f); + a_ = (mode_ == Mode::OUT) ? current_alpha : 255 - current_alpha; SDL_SetTextureAlphaMod(backbuffer_, a_); + value_ = static_cast(progress * 100); + // Comprueba si ha terminado - if (counter_ >= 255 / 4) { + if (elapsed_time >= static_cast(fading_duration_)) { changeToPostState(); } } void Fade::updateCenterFade() { + Uint32 elapsed_time = SDL_GetTicks() - fading_start_time_; + float progress = std::min(static_cast(elapsed_time) / fading_duration_, 1.0F); + + // Calcula la altura de las barras + float rect_height = progress * (param.game.height / 2.0f); + + if (mode_ == Mode::IN) { + rect_height = (param.game.height / 2.0f) - rect_height; + } + + rect1_.h = rect_height; + rect2_.h = rect_height; + rect2_.y = param.game.height - rect_height; + drawCenterFadeRectangles(); + value_ = static_cast(progress * 100); // Comprueba si ha terminado - if ((counter_ * 4) > param.game.height) { - a_ = 255; + if (elapsed_time >= static_cast(fading_duration_)) { + a_ = (mode_ == Mode::OUT) ? 255 : 0; changeToPostState(); } } @@ -172,154 +185,97 @@ void Fade::updateCenterFade() { void Fade::drawCenterFadeRectangles() { auto* temp = SDL_GetRenderTarget(renderer_); SDL_SetRenderTarget(renderer_, backbuffer_); - SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_); + cleanBackbuffer(r_, g_, b_, 0); // Limpiar para modo IN + SDL_SetRenderDrawColor(renderer_, r_, g_, b_, 255); - for (int i = 0; i < counter_; i++) { - rect1_.h = rect2_.h = i * 4; - rect2_.y = param.game.height - (i * 4); - - SDL_RenderFillRect(renderer_, &rect1_); - SDL_RenderFillRect(renderer_, &rect2_); - - value_ = calculateValue(0, counter_, i); - } + SDL_RenderFillRect(renderer_, &rect1_); + SDL_RenderFillRect(renderer_, &rect2_); SDL_SetRenderTarget(renderer_, temp); } void Fade::updateRandomSquareFade() { - Uint32 elapsed_time = SDL_GetTicks() - random_squares_start_time_; - float progress = static_cast(elapsed_time) / random_squares_duration_; + Uint32 elapsed_time = SDL_GetTicks() - fading_start_time_; + float progress = std::min(static_cast(elapsed_time) / fading_duration_, 1.0F); // Calcula cuántos cuadrados deberían estar activos int total_squares = num_squares_width_ * num_squares_height_; int active_squares = static_cast(progress * total_squares); - active_squares = std::min(active_squares, total_squares); - // Dibuja los cuadrados activos drawRandomSquares(active_squares); - value_ = calculateValue(0, total_squares, active_squares); + value_ = static_cast(progress * 100); // Comprueba si ha terminado - if (elapsed_time >= static_cast(random_squares_duration_)) { + if (elapsed_time >= static_cast(fading_duration_)) { changeToPostState(); } } void Fade::updateRandomSquare2Fade() { - Uint32 elapsed_time = SDL_GetTicks() - random_squares_start_time_; - + Uint32 elapsed_time = SDL_GetTicks() - fading_start_time_; int total_squares = num_squares_width_ * num_squares_height_; - // Calcula el tiempo de activación: total - tiempo que necesitan los últimos cuadrados - int activation_time = random_squares_duration_ - square_transition_duration_; - activation_time = std::max(activation_time, square_transition_duration_); // Mínimo igual a la duración de transición + int activation_time = fading_duration_ - square_transition_duration_; + activation_time = std::max(activation_time, square_transition_duration_); - // Lógica diferente según el modo int squares_to_activate = 0; - if (mode_ == Mode::OUT) { - // OUT: Activa cuadrados gradualmente if (elapsed_time < static_cast(activation_time)) { float activation_progress = static_cast(elapsed_time) / activation_time; squares_to_activate = static_cast(activation_progress * total_squares); } else { - squares_to_activate = total_squares; // Activar todos + squares_to_activate = total_squares; } - - // Activa nuevos cuadrados y guarda su tiempo de activación - for (int i = 0; i < squares_to_activate && i < total_squares; ++i) { - if (square_age_[i] == -1) { - square_age_[i] = elapsed_time; // Guarda el tiempo de activación - } + for (int i = 0; i < squares_to_activate; ++i) { + if (square_age_[i] == -1) square_age_[i] = elapsed_time; } } else { - // IN: Todos los cuadrados empiezan activos desde el inicio squares_to_activate = total_squares; - - // Activa cuadrados gradualmente con tiempo de inicio escalonado float activation_progress = static_cast(elapsed_time) / activation_time; - int squares_starting_transition = static_cast(activation_progress * total_squares); - - // Asegurar que al menos 1 cuadrado se active desde el primer frame - squares_starting_transition = std::max(squares_starting_transition, 1); - squares_starting_transition = std::min(squares_starting_transition, total_squares); - + int squares_starting_transition = std::min(total_squares, std::max(1, static_cast(activation_progress * total_squares))); for (int i = 0; i < squares_starting_transition; ++i) { - if (square_age_[i] == -1) { - square_age_[i] = elapsed_time; // Empieza la transición a transparente - } + if (square_age_[i] == -1) square_age_[i] = elapsed_time; } } drawRandomSquares2(); - value_ = calculateValue(0, total_squares, squares_to_activate); - // Comprueba si ha terminado - todos los cuadrados han completado su transición - bool all_completed = (squares_to_activate >= total_squares); - if (all_completed) { - // Verificar que todos han completado su transición individual - for (int i = 0; i < total_squares; ++i) { - if (square_age_[i] >= 0) { // Cuadrado activado - Uint32 square_elapsed = elapsed_time - square_age_[i]; - if (square_elapsed < static_cast(square_transition_duration_)) { - all_completed = false; - break; - } - } - } - - if (all_completed) { - // Pintar textura final: OUT opaca, IN transparente - Uint8 final_alpha = (mode_ == Mode::OUT) ? 255 : 0; - cleanBackbuffer(r_, g_, b_, final_alpha); - changeToPostState(); - } + if (elapsed_time >= static_cast(fading_duration_)) { + Uint8 final_alpha = (mode_ == Mode::OUT) ? 255 : 0; + cleanBackbuffer(r_, g_, b_, final_alpha); + changeToPostState(); } } void Fade::updateDiagonalFade() { - Uint32 elapsed_time = SDL_GetTicks() - random_squares_start_time_; + Uint32 elapsed_time = SDL_GetTicks() - fading_start_time_; - int total_squares = num_squares_width_ * num_squares_height_; - - // Calcula el tiempo de activación: total - tiempo que necesitan los últimos cuadrados - int activation_time = random_squares_duration_ - square_transition_duration_; + int activation_time = fading_duration_ - square_transition_duration_; activation_time = std::max(activation_time, square_transition_duration_); - // Calcula cuántas diagonales deberían estar activas - int max_diagonal = num_squares_width_ + num_squares_height_ - 1; // Número total de diagonales + int max_diagonal = num_squares_width_ + num_squares_height_ - 1; int active_diagonals = 0; - if (mode_ == Mode::OUT) { - // OUT: Activa diagonales gradualmente desde esquina superior izquierda if (elapsed_time < static_cast(activation_time)) { float activation_progress = static_cast(elapsed_time) / activation_time; active_diagonals = static_cast(activation_progress * max_diagonal); } else { - active_diagonals = max_diagonal; // Activar todas + active_diagonals = max_diagonal; } - - // Activa cuadrados por diagonales for (int diagonal = 0; diagonal < active_diagonals; ++diagonal) { activateDiagonal(diagonal, elapsed_time); } } else { - // IN: Todas las diagonales empiezan activas, van desapareciendo active_diagonals = max_diagonal; - - // Activa diagonales gradualmente para transición if (elapsed_time < static_cast(activation_time)) { float activation_progress = static_cast(elapsed_time) / activation_time; int diagonals_starting_transition = static_cast(activation_progress * max_diagonal); - for (int diagonal = 0; diagonal < diagonals_starting_transition; ++diagonal) { activateDiagonal(diagonal, elapsed_time); } } else { - // Activar transición en todas las diagonales restantes for (int diagonal = 0; diagonal < max_diagonal; ++diagonal) { activateDiagonal(diagonal, elapsed_time); } @@ -327,51 +283,22 @@ void Fade::updateDiagonalFade() { } drawDiagonal(); + value_ = calculateValue(0, max_diagonal, active_diagonals); - value_ = calculateValue(0, total_squares, active_diagonals * (total_squares / max_diagonal)); - - // Comprueba si ha terminado - todas las diagonales activadas y último cuadrado completó transición - bool all_completed = (active_diagonals >= max_diagonal); - if (all_completed) { - // Verificar que todos han completado su transición individual - for (int i = 0; i < total_squares; ++i) { - if (square_age_[i] >= 0) { // Cuadrado activado - Uint32 square_elapsed = elapsed_time - square_age_[i]; - if (square_elapsed < static_cast(square_transition_duration_)) { - all_completed = false; - break; - } - } - } - - if (all_completed) { - // Pintar textura final: OUT opaca, IN transparente - Uint8 final_alpha = (mode_ == Mode::OUT) ? 255 : 0; - cleanBackbuffer(r_, g_, b_, final_alpha); - changeToPostState(); - } + if (elapsed_time >= static_cast(fading_duration_)) { + Uint8 final_alpha = (mode_ == Mode::OUT) ? 255 : 0; + cleanBackbuffer(r_, g_, b_, final_alpha); + changeToPostState(); } } void Fade::activateDiagonal(int diagonal_index, Uint32 current_time) { - // Para cada diagonal, activamos los cuadrados que pertenecen a esa diagonal - // Diagonal 0: (0,0) - // Diagonal 1: (1,0), (0,1) - // Diagonal 2: (2,0), (1,1), (0,2) - // etc. - for (int x = 0; x < num_squares_width_; ++x) { int y = diagonal_index - x; - - // Verificar que y está dentro de los límites if (y >= 0 && y < num_squares_height_) { - // Convertir coordenadas (x,y) a índice en el vector int index = (y * num_squares_width_) + x; - - if (index >= 0 && index < static_cast(square_age_.size())) { - if (square_age_[index] == -1) { - square_age_[index] = current_time; // Guarda el tiempo de activación - } + if (index >= 0 && index < static_cast(square_age_.size()) && square_age_[index] == -1) { + square_age_[index] = current_time; } } } @@ -380,40 +307,22 @@ void Fade::activateDiagonal(int diagonal_index, Uint32 current_time) { void Fade::drawDiagonal() { auto* temp = SDL_GetRenderTarget(renderer_); SDL_SetRenderTarget(renderer_, backbuffer_); - - // CRÍTICO: Limpiar la textura antes de dibujar SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0); SDL_RenderClear(renderer_); - SDL_BlendMode blend_mode; SDL_GetRenderDrawBlendMode(renderer_, &blend_mode); - SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND); // Usar BLEND para alpha + SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND); - Uint32 current_time = SDL_GetTicks() - random_squares_start_time_; - - // Lógica unificada: sobre textura transparente, pintar cuadrados según su estado + Uint32 current_time = SDL_GetTicks() - fading_start_time_; for (size_t i = 0; i < square_.size(); ++i) { Uint8 current_alpha = 0; - if (square_age_[i] == -1) { - // Cuadrado no activado - if (mode_ == Mode::OUT) { - current_alpha = 0; // OUT: transparente si no activado - } else { - current_alpha = a_; // IN: opaco si no activado - } + current_alpha = (mode_ == Mode::OUT) ? 0 : a_; } else { - // Cuadrado activado - calculamos progreso Uint32 square_elapsed = current_time - square_age_[i]; float progress = std::min(static_cast(square_elapsed) / square_transition_duration_, 1.0F); - - if (mode_ == Mode::OUT) { - current_alpha = static_cast(progress * a_); // 0 → 255 - } else { - current_alpha = static_cast((1.0F - progress) * a_); // 255 → 0 - } + current_alpha = (mode_ == Mode::OUT) ? static_cast(progress * a_) : static_cast((1.0F - progress) * a_); } - if (current_alpha > 0) { SDL_SetRenderDrawColor(renderer_, r_, g_, b_, current_alpha); SDL_RenderFillRect(renderer_, &square_[i]); @@ -427,7 +336,8 @@ void Fade::drawDiagonal() { void Fade::drawRandomSquares(int active_count) { auto* temp = SDL_GetRenderTarget(renderer_); SDL_SetRenderTarget(renderer_, backbuffer_); - + + // El fondo se prepara en activate() SDL_BlendMode blend_mode; SDL_GetRenderDrawBlendMode(renderer_, &blend_mode); SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_NONE); @@ -445,40 +355,22 @@ void Fade::drawRandomSquares(int active_count) { void Fade::drawRandomSquares2() { auto* temp = SDL_GetRenderTarget(renderer_); SDL_SetRenderTarget(renderer_, backbuffer_); - - // CRÍTICO: Limpiar la textura antes de dibujar SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0); SDL_RenderClear(renderer_); - SDL_BlendMode blend_mode; SDL_GetRenderDrawBlendMode(renderer_, &blend_mode); - SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND); // Usar BLEND para alpha + SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND); - Uint32 current_time = SDL_GetTicks() - random_squares_start_time_; - - // Lógica unificada: sobre textura transparente, pintar cuadrados según su estado + Uint32 current_time = SDL_GetTicks() - fading_start_time_; for (size_t i = 0; i < square_.size(); ++i) { Uint8 current_alpha = 0; - if (square_age_[i] == -1) { - // Cuadrado no activado - if (mode_ == Mode::OUT) { - current_alpha = 0; // OUT: transparente si no activado - } else { - current_alpha = a_; // IN: opaco si no activado - } + current_alpha = (mode_ == Mode::OUT) ? 0 : a_; } else { - // Cuadrado activado - calculamos progreso Uint32 square_elapsed = current_time - square_age_[i]; float progress = std::min(static_cast(square_elapsed) / square_transition_duration_, 1.0F); - - if (mode_ == Mode::OUT) { - current_alpha = static_cast(progress * a_); // 0 → 255 - } else { - current_alpha = static_cast((1.0F - progress) * a_); // 255 → 0 - } + current_alpha = (mode_ == Mode::OUT) ? static_cast(progress * a_) : static_cast((1.0F - progress) * a_); } - if (current_alpha > 0) { SDL_SetRenderDrawColor(renderer_, r_, g_, b_, current_alpha); SDL_RenderFillRect(renderer_, &square_[i]); @@ -490,11 +382,24 @@ void Fade::drawRandomSquares2() { } void Fade::updateVenetianFade() { - if (square_.back().h < param.fade.venetian_size) { - drawVenetianBlinds(); - updateVenetianRectangles(); - calculateVenetianProgress(); - } else { + Uint32 elapsed_time = SDL_GetTicks() - fading_start_time_; + float progress = std::min(static_cast(elapsed_time) / fading_duration_, 1.0F); + + // Calcula la altura de las persianas + float rect_height = progress * param.fade.venetian_size; + if (mode_ == Mode::IN) { + rect_height = param.fade.venetian_size - rect_height; + } + + for (auto& rect : square_) { + rect.h = rect_height; + } + + drawVenetianBlinds(); + value_ = static_cast(progress * 100); + + // Comprueba si ha terminado + if (elapsed_time >= static_cast(fading_duration_)) { changeToPostState(); } } @@ -503,10 +408,17 @@ void Fade::drawVenetianBlinds() { auto* temp = SDL_GetRenderTarget(renderer_); SDL_SetRenderTarget(renderer_, backbuffer_); + // Limpia la textura con el color base (transparente para OUT, opaco para IN) + Uint8 initial_alpha = (mode_ == Mode::OUT) ? 0 : 255; + cleanBackbuffer(r_, g_, b_, initial_alpha); + SDL_BlendMode blend_mode; SDL_GetRenderDrawBlendMode(renderer_, &blend_mode); SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_NONE); - SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_); + + // Dibuja las persianas con el color opuesto al fondo + Uint8 draw_alpha = (mode_ == Mode::OUT) ? 255 : 0; + SDL_SetRenderDrawColor(renderer_, r_, g_, b_, draw_alpha); for (const auto& rect : square_) { SDL_RenderFillRect(renderer_, &rect); @@ -516,172 +428,86 @@ void Fade::drawVenetianBlinds() { SDL_SetRenderTarget(renderer_, temp); } -void Fade::updateVenetianRectangles() { - const auto H = counter_ / 2; - for (size_t i = 0; i < square_.size(); ++i) { - square_.at(i).h = i == 0 ? H : std::max(static_cast(square_.at(i - 1).h) - 2, 0); - } -} - -void Fade::calculateVenetianProgress() { - int completed = 0; - for (const auto& square : square_) { - if (square.h >= param.fade.venetian_size) { - ++completed; - } - } - value_ = calculateValue(0, square_.size() - 1, completed); -} - // Activa el fade void Fade::activate() { - // Si ya está habilitado, no hay que volverlo a activar if (state_ != State::NOT_ENABLED) { return; } - state_ = State::PRE; - counter_ = 0; pre_start_time_ = SDL_GetTicks(); + value_ = 0; + // Preparación inicial de cada tipo switch (type_) { - case Type::FULLSCREEN: { - // Pinta el backbuffer_ de color sólido - cleanBackbuffer(r_, g_, b_, 255); + case Type::FULLSCREEN: + cleanBackbuffer(r_, g_, b_, (mode_ == Mode::OUT) ? 0 : 255); + SDL_SetTextureAlphaMod(backbuffer_, (mode_ == Mode::OUT) ? 255 : 0); break; - } - case Type::CENTER: { + case Type::CENTER: rect1_ = {.x = 0, .y = 0, .w = param.game.width, .h = 0}; - rect2_ = {.x = 0, .y = 0, .w = param.game.width, .h = 0}; - a_ = 64; + rect2_ = {.x = 0, .y = param.game.height, .w = param.game.width, .h = 0}; + a_ = 255; break; - } case Type::RANDOM_SQUARE: { rect1_ = {.x = 0, .y = 0, .w = static_cast(param.game.width / num_squares_width_), .h = static_cast(param.game.height / num_squares_height_)}; square_.clear(); - - // Añade los cuadrados al vector for (int i = 0; i < num_squares_width_ * num_squares_height_; ++i) { rect1_.x = (i % num_squares_width_) * rect1_.w; rect1_.y = (i / num_squares_width_) * rect1_.h; square_.push_back(rect1_); } - - // Desordena el vector de cuadrados - auto num = num_squares_width_ * num_squares_height_; + auto num = square_.size(); while (num > 1) { auto num_arreu = rand() % num; - SDL_FRect temp = square_[num_arreu]; - square_[num_arreu] = square_[num - 1]; - square_[num - 1] = temp; - num--; + std::swap(square_[num_arreu], square_[--num]); } - - // Limpia la textura - a_ = mode_ == Mode::OUT ? 0 : 255; - cleanBackbuffer(r_, g_, b_, a_); - - // Deja el color listo para usar - a_ = mode_ == Mode::OUT ? 255 : 0; - - // Inicializa el tiempo de inicio - random_squares_start_time_ = SDL_GetTicks(); - - break; - } - - case Type::RANDOM_SQUARE2: { - rect1_ = {.x = 0, .y = 0, .w = static_cast(param.game.width / num_squares_width_), .h = static_cast(param.game.height / num_squares_height_)}; - square_.clear(); - square_age_.clear(); - - // Añade los cuadrados al vector - for (int i = 0; i < num_squares_width_ * num_squares_height_; ++i) { - rect1_.x = (i % num_squares_width_) * rect1_.w; - rect1_.y = (i / num_squares_width_) * rect1_.h; - square_.push_back(rect1_); - square_age_.push_back(-1); // -1 indica cuadrado no activado aún - } - - // Desordena el vector de cuadrados y edades - auto num = num_squares_width_ * num_squares_height_; - while (num > 1) { - auto num_arreu = rand() % num; - SDL_FRect temp_rect = square_[num_arreu]; - int temp_age = square_age_[num_arreu]; - square_[num_arreu] = square_[num - 1]; - square_age_[num_arreu] = square_age_[num - 1]; - square_[num - 1] = temp_rect; - square_age_[num - 1] = temp_age; - num--; - } - - // Textura inicial: OUT transparente, IN opaca - Uint8 initial_alpha = (mode_ == Mode::OUT) ? 0 : 255; - cleanBackbuffer(r_, g_, b_, initial_alpha); - - // Deja el color listo para usar (alpha target para los cuadrados) - a_ = 255; // Siempre usar 255 como alpha target - - // Inicializa el tiempo de inicio y recalcula la duración de transición - random_squares_start_time_ = SDL_GetTicks(); - square_transition_duration_ = std::max(random_squares_duration_ / 4, 100); // Mínimo 100ms - + a_ = (mode_ == Mode::OUT) ? 255 : 0; + cleanBackbuffer(r_, g_, b_, (mode_ == Mode::OUT) ? 0 : 255); break; } + case Type::RANDOM_SQUARE2: case Type::DIAGONAL: { rect1_ = {.x = 0, .y = 0, .w = static_cast(param.game.width / num_squares_width_), .h = static_cast(param.game.height / num_squares_height_)}; square_.clear(); - square_age_.clear(); - - // Añade los cuadrados al vector en orden (sin desordenar) + square_age_.assign(num_squares_width_ * num_squares_height_, -1); for (int i = 0; i < num_squares_width_ * num_squares_height_; ++i) { rect1_.x = (i % num_squares_width_) * rect1_.w; rect1_.y = (i / num_squares_width_) * rect1_.h; square_.push_back(rect1_); - square_age_.push_back(-1); // -1 indica cuadrado no activado aún } - // Textura inicial: OUT transparente, IN opaca + if (type_ == Type::RANDOM_SQUARE2) { + auto num = square_.size(); + while (num > 1) { + auto num_arreu = rand() % num; + std::swap(square_[num_arreu], square_[--num]); + // No es necesario desordenar square_age_ ya que todos son -1 + } + } Uint8 initial_alpha = (mode_ == Mode::OUT) ? 0 : 255; cleanBackbuffer(r_, g_, b_, initial_alpha); - - // Deja el color listo para usar (alpha target para los cuadrados) - a_ = 255; // Siempre usar 255 como alpha target - - // Inicializa el tiempo de inicio y recalcula la duración de transición - random_squares_start_time_ = SDL_GetTicks(); - square_transition_duration_ = std::max(random_squares_duration_ / 4, 100); // Mínimo 100ms - + a_ = 255; + square_transition_duration_ = std::max(fading_duration_ / 4, 100); break; } case Type::VENETIAN: { - // Limpia la textura - a_ = mode_ == Mode::OUT ? 0 : 255; - cleanBackbuffer(r_, g_, b_, a_); - - // Deja el color listo para usar - a_ = mode_ == Mode::OUT ? 255 : 0; - - // Añade los cuadrados al vector square_.clear(); - rect1_ = {.x = 0, .y = 0, .w = param.game.width, .h = 0}; + rect1_ = {.x = 0, .y = 0, .w = param.game.width, .h = (mode_ == Mode::OUT) ? 0.0f : static_cast(param.fade.venetian_size)}; const int MAX = param.game.height / param.fade.venetian_size; - for (int i = 0; i < MAX; ++i) { rect1_.y = i * param.fade.venetian_size; square_.push_back(rect1_); } - break; } } } + // Establece el color del fade void Fade::setColor(Uint8 r, Uint8 g, Uint8 b) { r_ = r; @@ -698,27 +524,16 @@ void Fade::setColor(Color color) { // Limpia el backbuffer void Fade::cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a) { - // Dibujamos sobre el backbuffer_ auto* temp = SDL_GetRenderTarget(renderer_); SDL_SetRenderTarget(renderer_, backbuffer_); - - // Pintamos la textura con el color del fade SDL_SetRenderDrawColor(renderer_, r, g, b, a); SDL_RenderClear(renderer_); - - // Vuelve a dejar el renderizador como estaba SDL_SetRenderTarget(renderer_, temp); } // Calcula el valor del estado del fade auto Fade::calculateValue(int min, int max, int current) -> int { - if (current < min) { - return 0; - } - - if (current > max) { - return 100; - } - + if (current <= min) return 0; + if (current >= max) return 100; return static_cast(100.0 * (current - min) / (max - min)); } \ No newline at end of file diff --git a/source/fade.hpp b/source/fade.hpp index 03cd652..7f97daa 100644 --- a/source/fade.hpp +++ b/source/fade.hpp @@ -1,6 +1,6 @@ #pragma once -#include // Para Uint8, SDL_FRect, SDL_Renderer, SDL_Texture, Uint16 +#include // Para Uint8, SDL_FRect, SDL_Renderer, SDL_Texture, Uint32 #include // Para vector @@ -37,17 +37,17 @@ class Fade { ~Fade(); // --- Métodos principales --- - void reset(); // Resetea variables para reutilizar el fade - void render(); // Dibuja la transición en pantalla - void update(); // Actualiza el estado interno (ya usa tiempo real) - void update(float delta_time); // Compatibilidad delta-time (ignora el parámetro) - void activate(); // Activa el fade + void reset(); // Resetea variables para reutilizar el fade + void render(); // Dibuja la transición en pantalla + void update(float delta_time = 0.0F); // Actualiza el estado interno + void activate(); // Activa el fade // --- Configuración --- void setColor(Uint8 r, Uint8 g, Uint8 b); // Establece el color RGB del fade void setColor(Color color); // Establece el color del fade void setType(Type type) { type_ = type; } // Establece el tipo de fade void setMode(Mode mode) { mode_ = mode; } // Establece el modo de fade + void setDuration(int milliseconds) { fading_duration_ = milliseconds; } // Duración del estado FADING en milisegundos void setPostDuration(int milliseconds) { post_duration_ = milliseconds; } // Duración posterior al fade en milisegundos void setPreDuration(int milliseconds) { pre_duration_ = milliseconds; } // Duración previa al fade en milisegundos @@ -63,18 +63,17 @@ class Fade { // --- Variables de estado --- std::vector square_; // Vector de cuadrados - std::vector square_age_; // Edad de cada cuadrado (para RANDOM_SQUARE2) + std::vector square_age_; // Edad de cada cuadrado (para RANDOM_SQUARE2 y DIAGONAL) SDL_FRect rect1_, rect2_; // Rectángulos para efectos Type type_; // Tipo de fade Mode mode_; // Modo de fade State state_ = State::NOT_ENABLED; // Estado actual - Uint16 counter_; // Contador interno Uint8 r_, g_, b_, a_; // Color del fade (RGBA) int num_squares_width_; // Cuadrados en horizontal int num_squares_height_; // Cuadrados en vertical - Uint32 random_squares_start_time_; // Tiempo de inicio del fade de cuadrados - int random_squares_duration_; // Duración total en milisegundos int square_transition_duration_; // Duración de transición de cada cuadrado en ms + int fading_duration_; // Duración del estado FADING en milisegundos + Uint32 fading_start_time_ = 0; // Tiempo de inicio del estado FADING int post_duration_ = 0; // Duración posterior en milisegundos Uint32 post_start_time_ = 0; // Tiempo de inicio del estado POST int pre_duration_ = 0; // Duración previa en milisegundos @@ -95,18 +94,16 @@ class Fade { void changeToPostState(); // Cambia al estado POST e inicializa el tiempo // --- Efectos de fundido (fade) --- - void updateFullscreenFade(); // Actualiza el fundido de pantalla completa - void updateCenterFade(); // Actualiza el fundido desde el centro - void updateRandomSquareFade(); // Actualiza el fundido con cuadrados aleatorios - void updateRandomSquare2Fade(); // Actualiza el fundido con cuadrados aleatorios (variante 2) - void updateDiagonalFade(); // Actualiza el fundido diagonal - void updateVenetianFade(); // Actualiza el fundido tipo persiana veneciana - void updateVenetianRectangles(); // Actualiza los rectángulos del efecto veneciano - void calculateVenetianProgress(); // Calcula el progreso del efecto veneciano + void updateFullscreenFade(); // Actualiza el fundido de pantalla completa + void updateCenterFade(); // Actualiza el fundido desde el centro + void updateRandomSquareFade(); // Actualiza el fundido con cuadrados aleatorios + void updateRandomSquare2Fade(); // Actualiza el fundido con cuadrados aleatorios (variante 2) + void updateDiagonalFade(); // Actualiza el fundido diagonal + void updateVenetianFade(); // Actualiza el fundido tipo persiana veneciana // --- Dibujo de efectos visuales --- void drawCenterFadeRectangles(); // Dibuja los rectángulos del fundido central - void drawRandomSquares(int active_count = -1); // Dibuja los cuadrados aleatorios del fundido + void drawRandomSquares(int active_count); // Dibuja los cuadrados aleatorios del fundido void drawRandomSquares2(); // Dibuja los cuadrados con transición de color (RANDOM_SQUARE2) void drawDiagonal(); // Dibuja los cuadrados con patrón diagonal void activateDiagonal(int diagonal_index, Uint32 current_time); // Activa una diagonal específica