#include "core/rendering/fade.h" #include #include // for rand #include // for char_traits, basic_ostream, operator<< #include "game/defaults.hpp" // for GAMECANVAS_HEIGHT, GAMECANVAS_WIDTH // Constructor Fade::Fade(SDL_Renderer *renderer) : renderer_(renderer) { backbuffer_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT); if (backbuffer_ != nullptr) { SDL_SetTextureScaleMode(backbuffer_, SDL_SCALEMODE_NEAREST); } if (backbuffer_ == nullptr) { std::cout << "Error: textTexture could not be created!\nSDL Error: " << SDL_GetError() << '\n'; } } // Destructor Fade::~Fade() { SDL_DestroyTexture(backbuffer_); backbuffer_ = nullptr; } // Inicializa las variables void Fade::init(Uint8 r, Uint8 g, Uint8 b) { fade_type_ = Type::CENTER; enabled_ = false; finished_ = false; counter_ = 0; elapsed_s_ = 0.0F; r_ = r; g_ = g; b_ = b; r_original_ = r; g_original_ = g; b_original_ = b; last_square_ticks_ = 0; squares_drawn_ = 0; fullscreen_done_ = false; } // Pinta una transición en pantalla void Fade::render() { if (enabled_ && !finished_) { switch (fade_type_) { case Type::FULLSCREEN: renderFadeFullscreen(); break; case Type::CENTER: renderFadeCenter(); break; case Type::RANDOM_SQUARE: renderFadeRandomSquare(); break; default: break; } } if (finished_) { SDL_SetRenderDrawColor(renderer_, r_, g_, b_, 255); SDL_RenderClear(renderer_); } } // Helper de render: tipo FULLSCREEN void Fade::renderFadeFullscreen() { if (fullscreen_done_) { return; } const int ALPHA = counter_ * 4; if (ALPHA >= 255) { fullscreen_done_ = true; // Deja todos los buffers del mismo color SDL_SetRenderTarget(renderer_, backbuffer_); SDL_SetRenderDrawColor(renderer_, r_, g_, b_, 255); SDL_RenderClear(renderer_); SDL_SetRenderTarget(renderer_, nullptr); SDL_SetRenderDrawColor(renderer_, r_, g_, b_, 255); SDL_RenderClear(renderer_); finished_ = true; return; } // Dibujamos sobre el renderizador SDL_SetRenderTarget(renderer_, nullptr); // Copia el backbuffer con la imagen que había al renderizador SDL_RenderTexture(renderer_, backbuffer_, nullptr, nullptr); SDL_FRect f_rect1 = {0, 0, (float)GAMECANVAS_WIDTH, (float)GAMECANVAS_HEIGHT}; SDL_SetRenderDrawColor(renderer_, r_, g_, b_, ALPHA); SDL_RenderFillRect(renderer_, &f_rect1); } // Helper de render: tipo CENTER void Fade::renderFadeCenter() { SDL_FRect f_r1 = {0, 0, (float)GAMECANVAS_WIDTH, 0}; SDL_FRect f_r2 = {0, 0, (float)GAMECANVAS_WIDTH, 0}; SDL_SetRenderDrawColor(renderer_, r_, g_, b_, 64); for (int i = 0; i < counter_; i++) { f_r1.h = f_r2.h = (float)(i * 4); f_r2.y = (float)(GAMECANVAS_HEIGHT - (i * 4)); SDL_RenderFillRect(renderer_, &f_r1); SDL_RenderFillRect(renderer_, &f_r2); } if ((counter_ * 4) > GAMECANVAS_HEIGHT) { finished_ = true; } } // Helper de render: tipo RANDOM_SQUARE void Fade::renderFadeRandomSquare() { const Uint32 NOW = SDL_GetTicks(); if (squares_drawn_ < 50 && NOW - last_square_ticks_ >= 100) { last_square_ticks_ = NOW; SDL_FRect f_rs = {0, 0, 32, 32}; // Crea un color al azar const Uint8 R = 255 * (rand() % 2); const Uint8 G = 255 * (rand() % 2); const Uint8 B = 255 * (rand() % 2); SDL_SetRenderDrawColor(renderer_, R, G, B, 64); // Dibujamos sobre el backbuffer SDL_SetRenderTarget(renderer_, backbuffer_); f_rs.x = (float)(rand() % (GAMECANVAS_WIDTH - 32)); f_rs.y = (float)(rand() % (GAMECANVAS_HEIGHT - 32)); SDL_RenderFillRect(renderer_, &f_rs); // Volvemos a usar el renderizador de forma normal SDL_SetRenderTarget(renderer_, nullptr); squares_drawn_++; } // Copiamos el backbuffer al renderizador SDL_RenderTexture(renderer_, backbuffer_, nullptr, nullptr); if (squares_drawn_ >= 50) { finished_ = true; } } // Actualiza las variables internas void Fade::update() { if (enabled_) { counter_++; } } // Time-based. Per a no haver de refactoritzar `render()` tot d'un cop // (encara hi ha codi frame-based que també escriu counter_), aquí derivem // `counter_` a partir de `elapsed_s_` usant la cadència de referència de la // versió antiga (60 Hz). Així el comportament visual del fade és idèntic. // Quan tot el codi sigui time-based, render passarà a usar elapsed_s_ amb // constants en segons i counter_ desapareixerà. void Fade::update(float dt_s) { if (!enabled_) { return; } elapsed_s_ += dt_s; constexpr float FADE_STEPS_PER_S = 60.0F; counter_ = static_cast(elapsed_s_ * FADE_STEPS_PER_S); } // Activa el fade void Fade::activateFade() { enabled_ = true; finished_ = false; counter_ = 0; elapsed_s_ = 0.0F; squares_drawn_ = 0; last_square_ticks_ = 0; fullscreen_done_ = false; r_ = r_original_; g_ = g_original_; b_ = b_original_; } // Comprueba si está activo auto Fade::isEnabled() const -> bool { return enabled_; } // Comprueba si ha terminado la transicion auto Fade::hasEnded() const -> bool { return finished_; } // Establece el tipo de fade void Fade::setFadeType(Type fade_type) { fade_type_ = fade_type; }