Files
coffee_crisis_arcade_edition/source/screen.h

211 lines
10 KiB
C++

#pragma once
#include <SDL3/SDL.h> // Para SDL_FRect, SDL_HideWindow, SDL_Renderer, SDL_ShowWindow, Uint32, SDL_Texture, SDL_Window
#include <memory> // Para shared_ptr
#include <string> // Para basic_string, string
#include "options.h" // Para VideoOptions, video
#include "utils.h" // Para Color
class Notifier;
class ServiceMenu;
class Text;
// Clase Screen: gestiona la ventana, el renderizador y los efectos visuales globales
class Screen {
public:
// --- Métodos de singleton ---
static void init(); // Inicializa el objeto Screen
static void destroy(); // Libera el objeto Screen
static Screen *get(); // Obtiene el puntero al objeto Screen
// --- Métodos principales ---
void update(); // Actualiza la lógica de la clase
void coreUpdate(); // Actualiza los elementos mínimos
void clean(Color color = Color(0x00, 0x00, 0x00)); // Limpia la pantalla
void start(); // Prepara para empezar a dibujar en la textura de juego
void render(); // Vuelca el contenido del renderizador en pantalla
void coreRender(); // Vuelca el contenido del renderizador en pantalla exceptuando ciertas partes
// --- Configuración de ventana y render ---
void setFullscreenMode(); // Establece el modo de pantalla completa
void toggleFullscreen(); // Cambia entre pantalla completa y ventana
void setWindowZoom(int size); // Cambia el tamaño de la ventana
bool decWindowSize(); // Reduce el tamaño de la ventana
bool incWindowSize(); // Aumenta el tamaño de la ventana
void applySettings(); // Aplica los valores de las opciones
void initShaders(); // Inicializa los shaders
// --- Efectos visuales ---
void shake(int desp = 2, int delay = 3, int lenght = 8) { shake_effect_.enable(src_rect_, dst_rect_, desp, delay, lenght); } // Agita la pantalla
void flash(Color color, int lenght = 10, int delay = 0) { flash_effect_ = FlashEffect(true, lenght, delay, color); } // Pone la pantalla de color
void toggleShaders(); // Alterna entre activar y desactivar los shaders
void toggleIntegerScale(); // Alterna entre activar y desactivar el escalado entero
void toggleVSync(); // Alterna entre activar y desactivar el V-Sync
void setVSync(bool enabled); // Establece el estado del V-Sync
void attenuate(bool value) { attenuate_effect_ = value; } // Atenúa la pantalla
// --- Getters ---
SDL_Renderer *getRenderer() { return renderer_; } // Obtiene el renderizador
void show() { SDL_ShowWindow(window_); } // Muestra la ventana
void hide() { SDL_HideWindow(window_); } // Oculta la ventana
void getSingletons(); // Obtiene los punteros a los singletones
bool getVSync() const { return Options::video.v_sync; } // Obtiene el valor de V-Sync
std::shared_ptr<Text> getText() const { return text_; } // Obtiene el puntero al texto de Screen
#ifdef DEBUG
// --- Debug ---
void toggleDebugInfo() { debug_info_.show = !debug_info_.show; }
void setDebugInfoEnabled(bool value) { debug_info_.show = value; }
#endif
private:
// --- Constantes ---
static constexpr int WINDOWS_DECORATIONS_ = 35;
// --- Estructuras internas ---
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.
FPS() : ticks(0), frameCount(0), lastValue(0) {}
void increment() { frameCount++; }
int calculate(Uint32 currentTicks) {
if (currentTicks - ticks >= 1000) {
lastValue = frameCount;
frameCount = 0;
ticks = currentTicks;
}
return lastValue;
}
};
// Efecto de flash en pantalla: pinta la pantalla de un color durante unos frames
struct FlashEffect {
bool enabled; // Indica si el efecto está activo
int lenght; // Duración total del efecto en frames
int delay; // Retraso antes de mostrar el flash
int counter; // Contador de frames restantes
Color color; // Color del flash
explicit FlashEffect(bool enabled = false, int lenght = 0, int delay = 0, Color color = Color(0xFF, 0xFF, 0xFF))
: enabled(enabled), lenght(lenght), delay(delay), counter(lenght), color(color) {}
void update() { (enabled && counter > 0) ? counter-- : enabled = false; }
bool isRendarable() { return enabled && counter < lenght - delay; }
};
// Efecto de sacudida/agitación de pantalla: mueve la imagen para simular un temblor
struct ShakeEffect {
int desp; // Desplazamiento máximo de la sacudida (en píxeles)
int delay; // Frames entre cada movimiento de sacudida
int counter; // Contador de frames para el siguiente movimiento
int lenght; // Duración total del efecto en frames
int remaining; // Frames restantes de sacudida
int original_pos; // Posición original de la imagen (x)
int original_width; // Ancho original de la imagen
bool enabled; // Indica si el efecto está activo
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) {}
// Activa el efecto de sacudida y guarda la posición y tamaño originales
void enable(SDL_FRect &src_rect, SDL_FRect &dst_rect, int new_desp = -1, int new_delay = -1, int new_lenght = -1) {
if (!enabled) {
enabled = true;
original_pos = src_rect.x;
original_width = src_rect.w;
// Usar nuevos valores si se proporcionan, sino mantener los actuales
if (new_desp != -1)
desp = new_desp;
if (new_delay != -1)
delay = new_delay;
if (new_lenght != -1)
lenght = new_lenght;
src_rect.w -= desp;
dst_rect.w = src_rect.w;
}
remaining = lenght;
counter = delay;
}
// Actualiza el estado del efecto de sacudida
void update(SDL_FRect &src_rect, SDL_FRect &dst_rect) {
if (enabled) {
if (counter > 0) {
counter--;
} else {
counter = delay;
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) {
enabled = false;
src_rect.x = original_pos;
src_rect.w = original_width;
dst_rect.x = original_pos;
dst_rect.w = original_width;
}
}
}
}
bool isEnabled() const { return enabled; }
};
#ifdef DEBUG
struct Debug {
std::shared_ptr<Text> text;
bool show = false;
};
#endif
// --- Singleton ---
static Screen *instance_;
// --- 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
ServiceMenu *service_menu_; // Objeto para mostrar el menú de servicio
Notifier *notifier_; // Objeto para mostrar las notificaciones por pantalla
// --- Variables de estado ---
SDL_FRect src_rect_; // Coordenadas de origen para dibujar la textura del juego
SDL_FRect dst_rect_; // Coordenadas destino para dibujar la textura del juego
FPS fps_; // Gestión de frames por segundo
std::string shader_source_; // Almacena el contenido del archivo GLSL
FlashEffect flash_effect_; // Efecto de flash en pantalla
ShakeEffect shake_effect_; // Efecto de agitar la pantalla
bool attenuate_effect_ = false; // Indica si la pantalla ha de estar atenuada
#ifdef DEBUG
Debug debug_info_; // Información de debug
#endif
// --- Texto ---
std::shared_ptr<Text> text_; // Objeto para escribir texto en pantalla
// --- Métodos internos ---
bool initSDLVideo(); // Arranca SDL VIDEO y crea la ventana
void renderFlash(); // Dibuja el efecto de flash en la pantalla
void renderShake(); // Aplica el efecto de agitar la pantalla
void renderInfo(); // Muestra información por pantalla
void renderScreen(); // Selecciona y ejecuta el método de renderizado adecuado
void loadShaders(); // Carga el contenido del archivo GLSL
void adjustWindowSize(); // Calcula el tamaño de la ventana
static void getDisplayInfo(); // Obtiene información sobre la pantalla
void renderOverlays(); // Renderiza todos los overlays y efectos
void renderAttenuate(); // Atenúa la pantalla
void createText(); // Crea el objeto de texto
// --- Constructores y destructor ---
Screen();
~Screen();
};