From d06617a1b0b8ed6616ed0c53fef92971d14bf3dd Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Mon, 17 Mar 2025 21:37:06 +0100 Subject: [PATCH] =?UTF-8?q?mogut=20el=20contador=20de=20frames=20=20a=20un?= =?UTF-8?q?=20struct=20i=20de=20paso=20el=20shake=5Feffect=20tamb=C3=A9=20?= =?UTF-8?q?l'he=20encapsulat=20millor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/screen.cpp | 129 ++++++-------------------------- source/screen.h | 184 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 151 insertions(+), 162 deletions(-) diff --git a/source/screen.cpp b/source/screen.cpp index 4766a0b..9623676 100644 --- a/source/screen.cpp +++ b/source/screen.cpp @@ -13,6 +13,7 @@ #include "notifier.h" // Para Notifier #include "on_screen_help.h" // Para OnScreenHelp #include "options.h" // Para Options, OptionsVideo, options, Options... +#include "resource.h" // Para Resource // [SINGLETON] Screen *Screen::screen_ = nullptr; @@ -63,6 +64,8 @@ void Screen::start() { SDL_SetRenderTarget(renderer_, game_canvas_); } // Vuelca el contenido del renderizador en pantalla void Screen::render() { + fps_.increment(); + // Renderiza todos los overlays y efectos renderOverlays(); @@ -155,69 +158,17 @@ bool Screen::incWindowZoom() return false; } -// Cambia el tipo de mezcla -void Screen::setBlendMode(SDL_BlendMode blendMode) { SDL_SetRenderDrawBlendMode(renderer_, blendMode); } - // Actualiza la lógica de la clase void Screen::update() { - updateShakeEffect(); - updateFlash(); + fps_.calculate(SDL_GetTicks()); + shake_effect_.update(src_rect_, dst_rect_); + flash_effect_.update(); Notifier::get()->update(); - updateFPS(); OnScreenHelp::get()->update(); Mouse::updateCursorVisibility(); } -// Agita la pantalla -void Screen::shake() -{ - // Si no hay un shake effect activo, se guarda una copia de los valores actuales antes de modificarlos - if (!shake_effect_.enabled) - { - shake_effect_.enabled = true; - shake_effect_.originalPos = src_rect_.x; - shake_effect_.originalWidth = src_rect_.w; - src_rect_.w -= shake_effect_.desp; - dst_rect_.w = src_rect_.w; - } - - // Si ya hay un shake effect en marcha no se pilla el origen, solo se renuevan los contadores - shake_effect_.remaining = shake_effect_.lenght; - shake_effect_.counter = shake_effect_.delay; -} - -// Actualiza la logica para agitar la pantalla -void Screen::updateShakeEffect() -{ - if (shake_effect_.enabled) - { - if (shake_effect_.counter > 0) - { - shake_effect_.counter--; - } - else - { - shake_effect_.counter = shake_effect_.delay; - const auto srcdesp = shake_effect_.remaining % 2 == 0 ? 0 : shake_effect_.desp; - const auto dstdesp = shake_effect_.remaining % 2 == 1 ? 0 : shake_effect_.desp; - src_rect_.x = shake_effect_.originalPos + srcdesp; - dst_rect_.x = shake_effect_.originalPos + dstdesp; - shake_effect_.remaining--; - shake_effect_.enabled = shake_effect_.remaining == -1 ? false : true; - if (!shake_effect_.enabled) - { - src_rect_.x = shake_effect_.originalPos; - src_rect_.w = shake_effect_.originalWidth; - dst_rect_ = src_rect_; - } - } - } -} - -// Pone la pantalla de color -void Screen::flash(Color color, int lenght, int delay) { flash_effect_ = FlashEffect(true, lenght, delay, color); } - // Actualiza y dibuja el efecto de flash en la pantalla void Screen::renderFlash() { @@ -228,19 +179,6 @@ void Screen::renderFlash() } } -// Actualiza el efecto de flash -void Screen::updateFlash() { flash_effect_.update(); } - -// Atenua la pantalla -void Screen::renderAttenuate() -{ - if (attenuate_effect_) - { - SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 64); - SDL_RenderFillRect(renderer_, nullptr); - } -} - // Aplica el efecto de agitar la pantalla void Screen::renderShake() { @@ -268,46 +206,19 @@ void Screen::renderShake() } } -// Activa / desactiva los shaders -void Screen::toggleShaders() -{ - options.video.shaders = !options.video.shaders; -} - -// Activa / desactiva la información de debug -void Screen::toggleDebugInfo() { show_debug_info_ = !show_debug_info_; } - -// Atenua la pantalla -void Screen::attenuate(bool value) { attenuate_effect_ = value; } - -// Calcula los frames por segundo -void Screen::updateFPS() -{ - if (SDL_GetTicks() - fps_ticks_ > 1000) - { - fps_ticks_ = SDL_GetTicks(); - fps_ = fps_counter_; - fps_counter_ = 0; - } -} - // Muestra información por pantalla void Screen::renderInfo() { - if (show_debug_info_) + if (show_debug_info_ && Resource::get()) { + auto text = Resource::get()->getText("smb2"); + // FPS - const std::string fpstext = std::to_string(fps_) + " FPS"; - dbg_print(param.game.width - fpstext.length() * 8, 0, fpstext.c_str(), 255, 255, 0); + const std::string FPS_TEXT = std::to_string(fps_.lastValue) + " FPS"; + text->writeColored(param.game.width - text->lenght(FPS_TEXT), 0, FPS_TEXT, orange_soft_color); // Resolution - dbg_print(0, 0, info_resolution_.c_str(), 255, 255, 0); - - // Contador de service_pressed_counter - if (const int counter = globalInputs::service_pressed_counter; counter > 0) - { - dbg_print(0, 8, std::to_string(counter).c_str(), 255, 0, 255); - } + text->writeColored(0, 0, info_resolution_, orange_soft_color); } } @@ -359,9 +270,6 @@ void Screen::adjustWindowSize() } } -// Ajusta el tamaño lógico del renderizador -void Screen::adjustRenderLogicalSize() { SDL_RenderSetLogicalSize(renderer_, param.game.width, param.game.height); } - // Obtiene el tamaño máximo de zoom posible para la ventana int Screen::getMaxZoom() { @@ -381,9 +289,6 @@ int Screen::getMaxZoom() // Renderiza todos los overlays y efectos void Screen::renderOverlays() { - // Actualiza el contador de FPS - ++fps_counter_; - // Dibuja efectos y elementos sobre el game_canvas_ renderShake(); renderFlash(); @@ -391,4 +296,14 @@ void Screen::renderOverlays() OnScreenHelp::get()->render(); renderInfo(); Notifier::get()->render(); +} + +// Atenua la pantalla +void Screen::renderAttenuate() +{ + if (attenuate_effect_) + { + SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 64); + SDL_RenderFillRect(renderer_, nullptr); + } } \ No newline at end of file diff --git a/source/screen.h b/source/screen.h index 419ca7e..d301cc7 100644 --- a/source/screen.h +++ b/source/screen.h @@ -28,29 +28,34 @@ private: // Constantes static constexpr int WINDOWS_DECORATIONS_ = 35; - // [SINGLETON] Objeto privado - static Screen *screen_; + // Estructuras + struct FPS + { + Uint32 ticks; // Tiempo en milisegundos desde que se comenzó a contar. + int frameCount; // Número acumulado de frames en el intervalo. + int lastValue; // Número de frames calculado en el último segundo. - // Objetos y punteros - SDL_Window *window_; // Ventana de la aplicación - SDL_Renderer *renderer_; // El renderizador de la ventana - SDL_Texture *game_canvas_; // Textura donde se dibuja todo antes de volcarse al renderizador + // Constructor para inicializar la estructura. + FPS() : ticks(0), frameCount(0), lastValue(0) {} - // Variables - SDL_Rect src_rect_; // Coordenadas de donde va a pillar la textura del juego para dibujarla - SDL_Rect dst_rect_; // Coordenadas donde se va a dibujar la textura del juego sobre la pantalla o ventana - bool attenuate_effect_ = false; // Indica si la pantalla ha de estar atenuada - Uint32 fps_ticks_ = 0; // Ticks para contar los frames por segundo - int fps_counter_ = 0; // Contador de frames por segundo - int fps_ = 0; // Frames calculados en el último segundo - std::string info_resolution_; // Texto con la informacion de la pantalla - std::string shader_source_; // Almacena el contenido del archivo GLSL + // Incrementador que se llama en cada frame. + void increment() + { + frameCount++; + } -#ifdef DEBUG - bool show_debug_info_ = false; // Indica si ha de mostrar/ocultar la información de la pantalla -#else - bool show_debug_info_ = false; // Indica si ha de mostrar/ocultar la información de la pantalla -#endif + // Método para calcular y devolver el valor de FPS. + int calculate(Uint32 currentTicks) + { + if (currentTicks - ticks >= 1000) // Si ha pasado un segundo o más. + { + lastValue = frameCount; // Actualizamos el valor del último FPS. + frameCount = 0; // Reiniciamos el contador de frames. + ticks = currentTicks; // Actualizamos el tiempo base. + } + return lastValue; + } + }; struct FlashEffect { @@ -73,42 +78,111 @@ private: struct ShakeEffect { - int desp; // Pixels de desplazamiento para agitar la pantalla en el eje x - int delay; // Retraso entre cada desplazamiento de la pantalla al agitarse - int counter; // Contador para el retraso - int lenght; // Cantidad de desplazamientos a realizar - int remaining; // Cantidad de desplazamientos pendientes a realizar - int originalPos; // Posición inicial de la pantalla para dejarla igual tras el desplazamiento - int originalWidth; // Anchura inicial de la pantalla para dejarla igual tras el desplazamiento - bool enabled; // Indica si el efecto está activo + int desp; // Pixels de desplazamiento para agitar la pantalla en el eje x + int delay; // Retraso entre cada desplazamiento de la pantalla al agitarse + int counter; // Contador para el retraso + int lenght; // Cantidad de desplazamientos a realizar + int remaining; // Cantidad de desplazamientos pendientes a realizar + int original_pos; // Posición inicial de la pantalla para dejarla igual tras el desplazamiento + int original_width; // Anchura inicial de la pantalla para dejarla igual tras el desplazamiento + bool enabled; // Indica si el efecto está activo // Constructor - explicit ShakeEffect(bool en = false, int dp = 2, int dl = 3, int cnt = 0, int len = 8, int rem = 0, int origPos = 0, int origWidth = param.game.width) - : desp(dp), delay(dl), counter(cnt), lenght(len), remaining(rem), originalPos(origPos), originalWidth(origWidth), enabled(en) {} + explicit ShakeEffect(bool en = false, int dp = 2, int dl = 3, int cnt = 0, int len = 8, int rem = 0, int origPos = 0, int origWidth = 800) + : desp(dp), delay(dl), counter(cnt), lenght(len), remaining(rem), original_pos(origPos), original_width(origWidth), enabled(en) {} + + // Método para habilitar el efecto + void enable(SDL_Rect &src_rect, SDL_Rect &dst_rect) + { + if (!enabled) + { + // Configurar el estado inicial si el efecto no está activo + enabled = true; + original_pos = src_rect.x; + original_width = src_rect.w; + + // Acortar los anchos iniciales durante el efecto + src_rect.w -= desp; + dst_rect.w = src_rect.w; + } + + // Renovar contadores y duración del efecto + remaining = lenght; + counter = delay; + } + + // Método para actualizar el efecto de movimiento/agitación + void update(SDL_Rect &src_rect, SDL_Rect &dst_rect) + { + if (enabled) + { + if (counter > 0) + { + counter--; + } + else + { + counter = delay; + + // Calcular desplazamientos según el estado de la agitación + const auto SRC_DESP = (remaining % 2 == 0) ? 0 : desp; + const auto DST_DESP = (remaining % 2 == 1) ? 0 : desp; + + src_rect.x = original_pos + SRC_DESP; + dst_rect.x = original_pos + DST_DESP; + + remaining--; + + if (remaining == -1) + { + // Restaurar posición y dimensiones originales + enabled = false; + src_rect.x = original_pos; + src_rect.w = original_width; + dst_rect.x = original_pos; + dst_rect.w = original_width; + } + } + } + } + + // Método para comprobar si el efecto está activo + bool isEnabled() const + { + return enabled; + } }; - // Variables - Efectos - FlashEffect flash_effect_; // Variable para gestionar el efecto de flash - ShakeEffect shake_effect_; // Variable para gestionar el efecto de agitar la pantalla + // [SINGLETON] Objeto privado + static Screen *screen_; - // Actualiza la logica para agitar la pantalla - void updateShakeEffect(); + // Objetos y punteros + SDL_Window *window_; // Ventana de la aplicación + SDL_Renderer *renderer_; // El renderizador de la ventana + SDL_Texture *game_canvas_; // Textura donde se dibuja todo antes de volcarse al renderizador + + // Variables + SDL_Rect src_rect_; // Coordenadas de donde va a pillar la textura del juego para dibujarla + SDL_Rect dst_rect_; // Coordenadas donde se va a dibujar la textura del juego sobre la pantalla o ventana + FPS fps_; // Variable para gestionar los frames por segundo + std::string info_resolution_; // Texto con la informacion de la pantalla + std::string shader_source_; // Almacena el contenido del archivo GLSL + FlashEffect flash_effect_; // Variable para gestionar el efecto de flash + ShakeEffect shake_effect_; // Variable para gestionar el efecto de agitar la pantalla + bool attenuate_effect_ = false; // Indica si la pantalla ha de estar atenuada + +#ifdef DEBUG + bool show_debug_info_ = false; // Indica si ha de mostrar/ocultar la información de la pantalla +#else + bool show_debug_info_ = false; // Indica si ha de mostrar/ocultar la información de la pantalla +#endif // Dibuja el efecto de flash en la pantalla void renderFlash(); - // Actualiza el efecto de flash - void updateFlash(); - - // Atenua la pantalla - void renderAttenuate(); - // Aplica el efecto de agitar la pantalla void renderShake(); - // Calcula los frames por segundo - void updateFPS(); - // Muestra información por pantalla void renderInfo(); @@ -125,7 +199,7 @@ private: void adjustWindowSize(); // Ajusta el tamaño lógico del renderizador - void adjustRenderLogicalSize(); + void adjustRenderLogicalSize() { SDL_RenderSetLogicalSize(renderer_, param.game.width, param.game.height); } // Obtiene el tamaño máximo de zoom posible para la ventana int getMaxZoom(); @@ -133,6 +207,9 @@ private: // Renderiza todos los overlays y efectos void renderOverlays(); + // Atenua la pantalla + void renderAttenuate(); + // Constructor Screen(SDL_Window *window, SDL_Renderer *renderer); @@ -176,23 +253,17 @@ public: // Aumenta el tamaño de la ventana bool incWindowZoom(); - // Cambia el tipo de mezcla - void setBlendMode(SDL_BlendMode blend_mode); - // Agita la pantalla - void shake(); + void shake() { shake_effect_.enable(src_rect_, dst_rect_); } // Pone la pantalla de color - void flash(Color color, int lenght, int delay = 0); + void flash(Color color, int lenght = 10, int delay = 0) { flash_effect_ = FlashEffect(true, lenght, delay, color); } // Activa / desactiva los shaders - void toggleShaders(); + void toggleShaders() { options.video.shaders = !options.video.shaders; } // Activa / desactiva la información de debug - void toggleDebugInfo(); - - // Atenua la pantalla - void attenuate(bool value); + void toggleDebugInfo() { show_debug_info_ = !show_debug_info_; } // Getters SDL_Renderer *getRenderer() { return renderer_; } @@ -202,4 +273,7 @@ public: // Oculta la ventana void hide() { SDL_HideWindow(window_); } + + // Atenua la pantalla + void attenuate(bool value) { attenuate_effect_ = value; } }; \ No newline at end of file