clang-format

This commit is contained in:
2026-03-21 23:19:15 +01:00
parent 55b58ded70
commit 366c00fd22
68 changed files with 5585 additions and 5603 deletions

View File

@@ -1,6 +1,7 @@
BasedOnStyle: Google BasedOnStyle: Google
IndentWidth: 4 IndentWidth: 4
IndentAccessModifiers: true NamespaceIndentation: All
IndentAccessModifiers: false
ColumnLimit: 0 # Sin límite de longitud de línea ColumnLimit: 0 # Sin límite de longitud de línea
BreakBeforeBraces: Attach # Llaves en la misma línea BreakBeforeBraces: Attach # Llaves en la misma línea
AllowShortIfStatementsOnASingleLine: true AllowShortIfStatementsOnASingleLine: true

View File

@@ -18,9 +18,9 @@
namespace GlobalInputs { namespace GlobalInputs {
// Funciones internas // Funciones internas
namespace { namespace {
void handleQuit() { void handleQuit() {
// En la escena GAME el comportamiento es siempre el mismo (con o sin modo kiosko) // En la escena GAME el comportamiento es siempre el mismo (con o sin modo kiosko)
if (SceneManager::current == SceneManager::Scene::GAME) { if (SceneManager::current == SceneManager::Scene::GAME) {
const std::string CODE = "PRESS AGAIN TO RETURN TO MENU"; const std::string CODE = "PRESS AGAIN TO RETURN TO MENU";
@@ -49,9 +49,9 @@ void handleQuit() {
} else { } else {
Notifier::get()->show({CODE}, Notifier::Style::DEFAULT, -1, true, CODE); Notifier::get()->show({CODE}, Notifier::Style::DEFAULT, -1, true, CODE);
} }
} }
void handleSkipSection() { void handleSkipSection() {
switch (SceneManager::current) { switch (SceneManager::current) {
case SceneManager::Scene::LOGO: case SceneManager::Scene::LOGO:
case SceneManager::Scene::LOADING_SCREEN: case SceneManager::Scene::LOADING_SCREEN:
@@ -67,68 +67,68 @@ void handleSkipSection() {
default: default:
break; break;
} }
} }
void handleToggleBorder() { void handleToggleBorder() {
Screen::get()->toggleBorder(); Screen::get()->toggleBorder();
Notifier::get()->show({"BORDER " + std::string(Options::video.border.enabled ? "ENABLED" : "DISABLED")}); Notifier::get()->show({"BORDER " + std::string(Options::video.border.enabled ? "ENABLED" : "DISABLED")});
} }
void handleToggleVideoMode() { void handleToggleVideoMode() {
Screen::get()->toggleVideoMode(); Screen::get()->toggleVideoMode();
Notifier::get()->show({"FULLSCREEN " + std::string(static_cast<int>(Options::video.fullscreen) == 0 ? "DISABLED" : "ENABLED")}); Notifier::get()->show({"FULLSCREEN " + std::string(static_cast<int>(Options::video.fullscreen) == 0 ? "DISABLED" : "ENABLED")});
} }
void handleDecWindowZoom() { void handleDecWindowZoom() {
if (Screen::get()->decWindowZoom()) { if (Screen::get()->decWindowZoom()) {
Notifier::get()->show({"WINDOW ZOOM x" + std::to_string(Options::window.zoom)}); Notifier::get()->show({"WINDOW ZOOM x" + std::to_string(Options::window.zoom)});
} }
} }
void handleIncWindowZoom() { void handleIncWindowZoom() {
if (Screen::get()->incWindowZoom()) { if (Screen::get()->incWindowZoom()) {
Notifier::get()->show({"WINDOW ZOOM x" + std::to_string(Options::window.zoom)}); Notifier::get()->show({"WINDOW ZOOM x" + std::to_string(Options::window.zoom)});
} }
} }
void handleTogglePostFX() { void handleTogglePostFX() {
Screen::get()->togglePostFX(); Screen::get()->togglePostFX();
Notifier::get()->show({"POSTFX " + std::string(Options::video.postfx ? "ENABLED" : "DISABLED")}); Notifier::get()->show({"POSTFX " + std::string(Options::video.postfx ? "ENABLED" : "DISABLED")});
} }
void handleNextPostFXPreset() { void handleNextPostFXPreset() {
if (!Options::postfx_presets.empty()) { if (!Options::postfx_presets.empty()) {
Options::current_postfx_preset = (Options::current_postfx_preset + 1) % static_cast<int>(Options::postfx_presets.size()); Options::current_postfx_preset = (Options::current_postfx_preset + 1) % static_cast<int>(Options::postfx_presets.size());
Screen::get()->reloadPostFX(); Screen::get()->reloadPostFX();
Notifier::get()->show({"POSTFX " + Options::postfx_presets[static_cast<size_t>(Options::current_postfx_preset)].name}); Notifier::get()->show({"POSTFX " + Options::postfx_presets[static_cast<size_t>(Options::current_postfx_preset)].name});
} }
} }
void handleNextPalette() { void handleNextPalette() {
Screen::get()->nextPalette(); Screen::get()->nextPalette();
Notifier::get()->show({"PALETTE " + Options::video.palette}); Notifier::get()->show({"PALETTE " + Options::video.palette});
} }
void handlePreviousPalette() { void handlePreviousPalette() {
Screen::get()->previousPalette(); Screen::get()->previousPalette();
Notifier::get()->show({"PALETTE " + Options::video.palette}); Notifier::get()->show({"PALETTE " + Options::video.palette});
} }
void handleToggleIntegerScale() { void handleToggleIntegerScale() {
Screen::get()->toggleIntegerScale(); Screen::get()->toggleIntegerScale();
Screen::get()->setVideoMode(Options::video.fullscreen); Screen::get()->setVideoMode(Options::video.fullscreen);
Notifier::get()->show({"INTEGER SCALE " + std::string(Options::video.integer_scale ? "ENABLED" : "DISABLED")}); Notifier::get()->show({"INTEGER SCALE " + std::string(Options::video.integer_scale ? "ENABLED" : "DISABLED")});
} }
void handleToggleVSync() { void handleToggleVSync() {
Screen::get()->toggleVSync(); Screen::get()->toggleVSync();
Notifier::get()->show({"V-SYNC " + std::string(Options::video.vertical_sync ? "ENABLED" : "DISABLED")}); Notifier::get()->show({"V-SYNC " + std::string(Options::video.vertical_sync ? "ENABLED" : "DISABLED")});
} }
#ifdef _DEBUG #ifdef _DEBUG
void handleShowDebugInfo() { void handleShowDebugInfo() {
Screen::get()->toggleDebugInfo(); Screen::get()->toggleDebugInfo();
} }
/* /*
void handleToggleDebug() { void handleToggleDebug() {
@@ -138,8 +138,8 @@ void handleToggleDebug() {
*/ */
#endif #endif
// Detecta qué acción global ha sido presionada (si alguna) // Detecta qué acción global ha sido presionada (si alguna)
auto getPressedAction() -> InputAction { auto getPressedAction() -> InputAction {
if (Input::get()->checkAction(InputAction::EXIT, Input::DO_NOT_ALLOW_REPEAT)) { if (Input::get()->checkAction(InputAction::EXIT, Input::DO_NOT_ALLOW_REPEAT)) {
return InputAction::EXIT; return InputAction::EXIT;
} }
@@ -185,14 +185,14 @@ auto getPressedAction() -> InputAction {
return InputAction::SHOW_DEBUG_INFO; return InputAction::SHOW_DEBUG_INFO;
} }
return InputAction::NONE; return InputAction::NONE;
} }
} // namespace } // namespace
// Funciones públicas // Funciones públicas
// Comprueba los inputs que se pueden introducir en cualquier sección del juego // Comprueba los inputs que se pueden introducir en cualquier sección del juego
void handle() { void handle() {
// Salida de administrador en modo kiosko (Ctrl+Shift+Alt+Q) // Salida de administrador en modo kiosko (Ctrl+Shift+Alt+Q)
if (Options::kiosk.enabled) { if (Options::kiosk.enabled) {
SDL_Keymod mod = SDL_GetModState(); SDL_Keymod mod = SDL_GetModState();
@@ -271,5 +271,5 @@ void handle() {
// No se presionó ninguna acción global // No se presionó ninguna acción global
break; break;
} }
} }
} // namespace GlobalInputs } // namespace GlobalInputs

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
namespace GlobalInputs { namespace GlobalInputs {
// Comprueba los inputs que se pueden introducir en cualquier sección del juego // Comprueba los inputs que se pueden introducir en cualquier sección del juego
void handle(); void handle();
} // namespace GlobalInputs } // namespace GlobalInputs

View File

@@ -1,11 +1,11 @@
#include "core/input/mouse.hpp" #include "core/input/mouse.hpp"
namespace Mouse { namespace Mouse {
Uint32 cursor_hide_time = 3000; // Tiempo en milisegundos para ocultar el cursor Uint32 cursor_hide_time = 3000; // Tiempo en milisegundos para ocultar el cursor
Uint32 last_mouse_move_time = 0; // Última vez que el ratón se movió Uint32 last_mouse_move_time = 0; // Última vez que el ratón se movió
bool cursor_visible = true; // Estado del cursor bool cursor_visible = true; // Estado del cursor
void handleEvent(const SDL_Event& event) { void handleEvent(const SDL_Event& event) {
if (event.type == SDL_EVENT_MOUSE_MOTION) { if (event.type == SDL_EVENT_MOUSE_MOTION) {
last_mouse_move_time = SDL_GetTicks(); last_mouse_move_time = SDL_GetTicks();
if (!cursor_visible) { if (!cursor_visible) {
@@ -13,13 +13,13 @@ void handleEvent(const SDL_Event& event) {
cursor_visible = true; cursor_visible = true;
} }
} }
} }
void updateCursorVisibility() { void updateCursorVisibility() {
Uint32 current_time = SDL_GetTicks(); Uint32 current_time = SDL_GetTicks();
if (cursor_visible && (current_time - last_mouse_move_time > cursor_hide_time)) { if (cursor_visible && (current_time - last_mouse_move_time > cursor_hide_time)) {
SDL_HideCursor(); SDL_HideCursor();
cursor_visible = false; cursor_visible = false;
} }
} }
} // namespace Mouse } // namespace Mouse

View File

@@ -3,10 +3,10 @@
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
namespace Mouse { namespace Mouse {
extern Uint32 cursor_hide_time; // Tiempo en milisegundos para ocultar el cursor extern Uint32 cursor_hide_time; // Tiempo en milisegundos para ocultar el cursor
extern Uint32 last_mouse_move_time; // Última vez que el ratón se movió extern Uint32 last_mouse_move_time; // Última vez que el ratón se movió
extern bool cursor_visible; // Estado del cursor extern bool cursor_visible; // Estado del cursor
void handleEvent(const SDL_Event& event); void handleEvent(const SDL_Event& event);
void updateCursorVisibility(); void updateCursorVisibility();
} // namespace Mouse } // namespace Mouse

View File

@@ -7,15 +7,15 @@
namespace GIF { namespace GIF {
// Función inline para reemplazar el macro READ. // Función inline para reemplazar el macro READ.
// Actualiza el puntero 'buffer' tras copiar 'size' bytes a 'dst'. // Actualiza el puntero 'buffer' tras copiar 'size' bytes a 'dst'.
inline void readBytes(const uint8_t*& buffer, void* dst, size_t size) { inline void readBytes(const uint8_t*& buffer, void* dst, size_t size) {
std::memcpy(dst, buffer, size); std::memcpy(dst, buffer, size);
buffer += size; buffer += size;
} }
// Inicializa el diccionario LZW con los valores iniciales // Inicializa el diccionario LZW con los valores iniciales
inline void initializeDictionary(std::vector<DictionaryEntry>& dictionary, int code_length, int& dictionary_ind) { inline void initializeDictionary(std::vector<DictionaryEntry>& dictionary, int code_length, int& dictionary_ind) {
int size = 1 << code_length; int size = 1 << code_length;
dictionary.resize(1 << (code_length + 1)); dictionary.resize(1 << (code_length + 1));
for (dictionary_ind = 0; dictionary_ind < size; dictionary_ind++) { for (dictionary_ind = 0; dictionary_ind < size; dictionary_ind++) {
@@ -24,10 +24,10 @@ inline void initializeDictionary(std::vector<DictionaryEntry>& dictionary, int c
dictionary[dictionary_ind].len = 1; dictionary[dictionary_ind].len = 1;
} }
dictionary_ind += 2; // Reservamos espacio para clear y stop codes dictionary_ind += 2; // Reservamos espacio para clear y stop codes
} }
// Lee los próximos bits del stream de entrada para formar un código // Lee los próximos bits del stream de entrada para formar un código
inline auto readNextCode(const uint8_t*& input, int& input_length, unsigned int& mask, int code_length) -> int { inline auto readNextCode(const uint8_t*& input, int& input_length, unsigned int& mask, int code_length) -> int {
int code = 0; int code = 0;
for (int i = 0; i < (code_length + 1); i++) { for (int i = 0; i < (code_length + 1); i++) {
if (input_length <= 0) { if (input_length <= 0) {
@@ -43,19 +43,19 @@ inline auto readNextCode(const uint8_t*& input, int& input_length, unsigned int&
code |= (bit << i); code |= (bit << i);
} }
return code; return code;
} }
// Encuentra el primer byte de una cadena del diccionario // Encuentra el primer byte de una cadena del diccionario
inline auto findFirstByte(const std::vector<DictionaryEntry>& dictionary, int code) -> uint8_t { inline auto findFirstByte(const std::vector<DictionaryEntry>& dictionary, int code) -> uint8_t {
int ptr = code; int ptr = code;
while (dictionary[ptr].prev != -1) { while (dictionary[ptr].prev != -1) {
ptr = dictionary[ptr].prev; ptr = dictionary[ptr].prev;
} }
return dictionary[ptr].byte; return dictionary[ptr].byte;
} }
// Agrega una nueva entrada al diccionario // Agrega una nueva entrada al diccionario
inline void addDictionaryEntry(std::vector<DictionaryEntry>& dictionary, int& dictionary_ind, int& code_length, int prev, int code) { inline void addDictionaryEntry(std::vector<DictionaryEntry>& dictionary, int& dictionary_ind, int& code_length, int prev, int code) {
uint8_t first_byte; uint8_t first_byte;
if (code == dictionary_ind) { if (code == dictionary_ind) {
first_byte = findFirstByte(dictionary, prev); first_byte = findFirstByte(dictionary, prev);
@@ -72,10 +72,10 @@ inline void addDictionaryEntry(std::vector<DictionaryEntry>& dictionary, int& di
code_length++; code_length++;
dictionary.resize(1 << (code_length + 1)); dictionary.resize(1 << (code_length + 1));
} }
} }
// Escribe la cadena decodificada al buffer de salida // Escribe la cadena decodificada al buffer de salida
inline auto writeDecodedString(const std::vector<DictionaryEntry>& dictionary, int code, uint8_t*& out) -> int { inline auto writeDecodedString(const std::vector<DictionaryEntry>& dictionary, int code, uint8_t*& out) -> int {
int cur_code = code; int cur_code = code;
int match_len = dictionary[cur_code].len; int match_len = dictionary[cur_code].len;
while (cur_code != -1) { while (cur_code != -1) {
@@ -88,9 +88,9 @@ inline auto writeDecodedString(const std::vector<DictionaryEntry>& dictionary, i
} }
out += match_len; out += match_len;
return match_len; return match_len;
} }
void Gif::decompress(int code_length, const uint8_t* input, int input_length, uint8_t* out) { void Gif::decompress(int code_length, const uint8_t* input, int input_length, uint8_t* out) {
// Verifica que el code_length tenga un rango razonable. // Verifica que el code_length tenga un rango razonable.
if (code_length < 2 || code_length > 12) { if (code_length < 2 || code_length > 12) {
throw std::runtime_error("Invalid LZW code length"); throw std::runtime_error("Invalid LZW code length");
@@ -144,9 +144,9 @@ void Gif::decompress(int code_length, const uint8_t* input, int input_length, ui
writeDecodedString(dictionary, code, out); writeDecodedString(dictionary, code, out);
} }
} }
auto Gif::readSubBlocks(const uint8_t*& buffer) -> std::vector<uint8_t> { auto Gif::readSubBlocks(const uint8_t*& buffer) -> std::vector<uint8_t> {
std::vector<uint8_t> data; std::vector<uint8_t> data;
uint8_t block_size = *buffer; uint8_t block_size = *buffer;
buffer++; buffer++;
@@ -157,9 +157,9 @@ auto Gif::readSubBlocks(const uint8_t*& buffer) -> std::vector<uint8_t> {
buffer++; buffer++;
} }
return data; return data;
} }
auto Gif::processImageDescriptor(const uint8_t*& buffer, const std::vector<RGB>& gct, int resolution_bits) -> std::vector<uint8_t> { auto Gif::processImageDescriptor(const uint8_t*& buffer, const std::vector<RGB>& gct, int resolution_bits) -> std::vector<uint8_t> {
ImageDescriptor image_descriptor; ImageDescriptor image_descriptor;
// Lee 9 bytes para el image descriptor. // Lee 9 bytes para el image descriptor.
readBytes(buffer, &image_descriptor, sizeof(ImageDescriptor)); readBytes(buffer, &image_descriptor, sizeof(ImageDescriptor));
@@ -173,9 +173,9 @@ auto Gif::processImageDescriptor(const uint8_t*& buffer, const std::vector<RGB>&
decompress(lzw_code_size, compressed_data.data(), static_cast<int>(compressed_data.size()), uncompressed_data.data()); decompress(lzw_code_size, compressed_data.data(), static_cast<int>(compressed_data.size()), uncompressed_data.data());
return uncompressed_data; return uncompressed_data;
} }
auto Gif::loadPalette(const uint8_t* buffer) -> std::vector<uint32_t> { auto Gif::loadPalette(const uint8_t* buffer) -> std::vector<uint32_t> {
uint8_t header[6]; uint8_t header[6];
std::memcpy(header, buffer, 6); std::memcpy(header, buffer, 6);
buffer += 6; buffer += 6;
@@ -197,9 +197,9 @@ auto Gif::loadPalette(const uint8_t* buffer) -> std::vector<uint32_t> {
} }
} }
return global_color_table; return global_color_table;
} }
auto Gif::processGifStream(const uint8_t* buffer, uint16_t& w, uint16_t& h) -> std::vector<uint8_t> { auto Gif::processGifStream(const uint8_t* buffer, uint16_t& w, uint16_t& h) -> std::vector<uint8_t> {
// Leer la cabecera de 6 bytes ("GIF87a" o "GIF89a") // Leer la cabecera de 6 bytes ("GIF87a" o "GIF89a")
uint8_t header[6]; uint8_t header[6];
std::memcpy(header, buffer, 6); std::memcpy(header, buffer, 6);
@@ -286,10 +286,10 @@ auto Gif::processGifStream(const uint8_t* buffer, uint16_t& w, uint16_t& h) -> s
} }
return std::vector<uint8_t>{}; return std::vector<uint8_t>{};
} }
auto Gif::loadGif(const uint8_t* buffer, uint16_t& w, uint16_t& h) -> std::vector<uint8_t> { auto Gif::loadGif(const uint8_t* buffer, uint16_t& w, uint16_t& h) -> std::vector<uint8_t> {
return processGifStream(buffer, w, h); return processGifStream(buffer, w, h);
} }
} // namespace GIF } // namespace GIF

View File

@@ -5,66 +5,66 @@
namespace GIF { namespace GIF {
// Constantes definidas con constexpr, en lugar de macros // Constantes definidas con constexpr, en lugar de macros
constexpr uint8_t EXTENSION_INTRODUCER = 0x21; constexpr uint8_t EXTENSION_INTRODUCER = 0x21;
constexpr uint8_t IMAGE_DESCRIPTOR = 0x2C; constexpr uint8_t IMAGE_DESCRIPTOR = 0x2C;
constexpr uint8_t TRAILER = 0x3B; constexpr uint8_t TRAILER = 0x3B;
constexpr uint8_t GRAPHIC_CONTROL = 0xF9; constexpr uint8_t GRAPHIC_CONTROL = 0xF9;
constexpr uint8_t APPLICATION_EXTENSION = 0xFF; constexpr uint8_t APPLICATION_EXTENSION = 0xFF;
constexpr uint8_t COMMENT_EXTENSION = 0xFE; constexpr uint8_t COMMENT_EXTENSION = 0xFE;
constexpr uint8_t PLAINTEXT_EXTENSION = 0x01; constexpr uint8_t PLAINTEXT_EXTENSION = 0x01;
#pragma pack(push, 1) #pragma pack(push, 1)
struct ScreenDescriptor { struct ScreenDescriptor {
uint16_t width; uint16_t width;
uint16_t height; uint16_t height;
uint8_t fields; uint8_t fields;
uint8_t background_color_index; uint8_t background_color_index;
uint8_t pixel_aspect_ratio; uint8_t pixel_aspect_ratio;
}; };
struct RGB { struct RGB {
uint8_t r, g, b; uint8_t r, g, b;
}; };
struct ImageDescriptor { struct ImageDescriptor {
uint16_t image_left_position; uint16_t image_left_position;
uint16_t image_top_position; uint16_t image_top_position;
uint16_t image_width; uint16_t image_width;
uint16_t image_height; uint16_t image_height;
uint8_t fields; uint8_t fields;
}; };
#pragma pack(pop) #pragma pack(pop)
struct DictionaryEntry { struct DictionaryEntry {
uint8_t byte; uint8_t byte;
int prev; int prev;
int len; int len;
}; };
struct Extension { struct Extension {
uint8_t extension_code; uint8_t extension_code;
uint8_t block_size; uint8_t block_size;
}; };
struct GraphicControlExtension { struct GraphicControlExtension {
uint8_t fields; uint8_t fields;
uint16_t delay_time; uint16_t delay_time;
uint8_t transparent_color_index; uint8_t transparent_color_index;
}; };
struct ApplicationExtension { struct ApplicationExtension {
uint8_t application_id[8]; uint8_t application_id[8];
uint8_t version[3]; uint8_t version[3];
}; };
struct PlaintextExtension { struct PlaintextExtension {
uint16_t left, top, width, height; uint16_t left, top, width, height;
uint8_t cell_width, cell_height; uint8_t cell_width, cell_height;
uint8_t foreground_color, background_color; uint8_t foreground_color, background_color;
}; };
class Gif { class Gif {
public: public:
// Descompone (uncompress) el bloque comprimido usando LZW. // Descompone (uncompress) el bloque comprimido usando LZW.
// Este método puede lanzar std::runtime_error en caso de error. // Este método puede lanzar std::runtime_error en caso de error.
@@ -87,6 +87,6 @@ class Gif {
// Procesa el stream completo del GIF y devuelve los datos sin comprimir. // Procesa el stream completo del GIF y devuelve los datos sin comprimir.
static auto processGifStream(const uint8_t* buffer, uint16_t& w, uint16_t& h) -> std::vector<uint8_t>; static auto processGifStream(const uint8_t* buffer, uint16_t& w, uint16_t& h) -> std::vector<uint8_t>;
}; };
} // namespace GIF } // namespace GIF

View File

@@ -12,7 +12,7 @@
class Surface; class Surface;
class Text; class Text;
namespace Rendering { namespace Rendering {
class ShaderBackend; class ShaderBackend;
} }
class Screen { class Screen {

View File

@@ -162,17 +162,17 @@ fragment float4 postfx_fs(PostVOut in [[stage_in]],
namespace Rendering { namespace Rendering {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Destructor // Destructor
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
SDL3GPUShader::~SDL3GPUShader() { SDL3GPUShader::~SDL3GPUShader() {
destroy(); destroy();
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// init // init
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
auto SDL3GPUShader::init(SDL_Window* window, auto SDL3GPUShader::init(SDL_Window* window,
SDL_Texture* texture, SDL_Texture* texture,
const std::string& /*vertex_source*/, const std::string& /*vertex_source*/,
const std::string& /*fragment_source*/) -> bool { const std::string& /*fragment_source*/) -> bool {
@@ -281,12 +281,12 @@ auto SDL3GPUShader::init(SDL_Window* window,
is_initialized_ = true; is_initialized_ = true;
SDL_Log("SDL3GPUShader: initialized OK (%dx%d)", tex_width_, tex_height_); SDL_Log("SDL3GPUShader: initialized OK (%dx%d)", tex_width_, tex_height_);
return true; return true;
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// createPipeline // createPipeline
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
auto SDL3GPUShader::createPipeline() -> bool { auto SDL3GPUShader::createPipeline() -> bool {
const SDL_GPUTextureFormat SWAPCHAIN_FMT = SDL_GetGPUSwapchainTextureFormat(device_, window_); const SDL_GPUTextureFormat SWAPCHAIN_FMT = SDL_GetGPUSwapchainTextureFormat(device_, window_);
#ifdef __APPLE__ #ifdef __APPLE__
@@ -332,12 +332,12 @@ auto SDL3GPUShader::createPipeline() -> bool {
return false; return false;
} }
return true; return true;
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// uploadPixels — copies ARGB8888 CPU pixels into the GPU transfer buffer // uploadPixels — copies ARGB8888 CPU pixels into the GPU transfer buffer
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
void SDL3GPUShader::uploadPixels(const Uint32* pixels, int width, int height) { void SDL3GPUShader::uploadPixels(const Uint32* pixels, int width, int height) {
if (!is_initialized_ || (upload_buffer_ == nullptr)) { return; } if (!is_initialized_ || (upload_buffer_ == nullptr)) { return; }
void* mapped = SDL_MapGPUTransferBuffer(device_, upload_buffer_, false); void* mapped = SDL_MapGPUTransferBuffer(device_, upload_buffer_, false);
@@ -347,12 +347,12 @@ void SDL3GPUShader::uploadPixels(const Uint32* pixels, int width, int height) {
} }
std::memcpy(mapped, pixels, static_cast<size_t>(width * height * 4)); std::memcpy(mapped, pixels, static_cast<size_t>(width * height * 4));
SDL_UnmapGPUTransferBuffer(device_, upload_buffer_); SDL_UnmapGPUTransferBuffer(device_, upload_buffer_);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// render — upload scene texture + PostFX pass → swapchain // render — upload scene texture + PostFX pass → swapchain
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
void SDL3GPUShader::render() { void SDL3GPUShader::render() {
if (!is_initialized_) { return; } if (!is_initialized_) { return; }
SDL_GPUCommandBuffer* cmd = SDL_AcquireGPUCommandBuffer(device_); SDL_GPUCommandBuffer* cmd = SDL_AcquireGPUCommandBuffer(device_);
@@ -439,12 +439,12 @@ void SDL3GPUShader::render() {
} }
SDL_SubmitGPUCommandBuffer(cmd); SDL_SubmitGPUCommandBuffer(cmd);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// cleanup — libera pipeline/texturas/buffer pero mantiene device + swapchain // cleanup — libera pipeline/texturas/buffer pero mantiene device + swapchain
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
void SDL3GPUShader::cleanup() { void SDL3GPUShader::cleanup() {
is_initialized_ = false; is_initialized_ = false;
if (device_ != nullptr) { if (device_ != nullptr) {
@@ -468,12 +468,12 @@ void SDL3GPUShader::cleanup() {
} }
// device_ y el claim de la ventana se mantienen vivos // device_ y el claim de la ventana se mantienen vivos
} }
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// destroy — limpieza completa incluyendo device y swapchain (solo al cerrar) // destroy — limpieza completa incluyendo device y swapchain (solo al cerrar)
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
void SDL3GPUShader::destroy() { void SDL3GPUShader::destroy() {
cleanup(); cleanup();
if (device_ != nullptr) { if (device_ != nullptr) {
@@ -484,12 +484,12 @@ void SDL3GPUShader::destroy() {
device_ = nullptr; device_ = nullptr;
} }
window_ = nullptr; window_ = nullptr;
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Shader creation helpers // Shader creation helpers
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
auto SDL3GPUShader::createShaderMSL(SDL_GPUDevice* device, auto SDL3GPUShader::createShaderMSL(SDL_GPUDevice* device,
const char* msl_source, const char* msl_source,
const char* entrypoint, const char* entrypoint,
SDL_GPUShaderStage stage, SDL_GPUShaderStage stage,
@@ -508,9 +508,9 @@ auto SDL3GPUShader::createShaderMSL(SDL_GPUDevice* device,
SDL_Log("SDL3GPUShader: MSL shader '%s' failed: %s", entrypoint, SDL_GetError()); SDL_Log("SDL3GPUShader: MSL shader '%s' failed: %s", entrypoint, SDL_GetError());
} }
return shader; return shader;
} }
auto SDL3GPUShader::createShaderSPIRV(SDL_GPUDevice* device, auto SDL3GPUShader::createShaderSPIRV(SDL_GPUDevice* device,
const uint8_t* spv_code, const uint8_t* spv_code,
size_t spv_size, size_t spv_size,
const char* entrypoint, const char* entrypoint,
@@ -530,9 +530,9 @@ auto SDL3GPUShader::createShaderSPIRV(SDL_GPUDevice* device,
SDL_Log("SDL3GPUShader: SPIRV shader '%s' failed: %s", entrypoint, SDL_GetError()); SDL_Log("SDL3GPUShader: SPIRV shader '%s' failed: %s", entrypoint, SDL_GetError());
} }
return shader; return shader;
} }
void SDL3GPUShader::setPostFXParams(const PostFXParams& p) { void SDL3GPUShader::setPostFXParams(const PostFXParams& p) {
uniforms_.vignette_strength = p.vignette; uniforms_.vignette_strength = p.vignette;
uniforms_.scanline_strength = p.scanlines; uniforms_.scanline_strength = p.scanlines;
uniforms_.chroma_strength = p.chroma; uniforms_.chroma_strength = p.chroma;
@@ -540,17 +540,17 @@ void SDL3GPUShader::setPostFXParams(const PostFXParams& p) {
uniforms_.gamma_strength = p.gamma; uniforms_.gamma_strength = p.gamma;
uniforms_.curvature = p.curvature; uniforms_.curvature = p.curvature;
uniforms_.bleeding = p.bleeding; uniforms_.bleeding = p.bleeding;
} }
void SDL3GPUShader::setVSync(bool vsync) { void SDL3GPUShader::setVSync(bool vsync) {
vsync_ = vsync; vsync_ = vsync;
if (device_ != nullptr && window_ != nullptr) { if (device_ != nullptr && window_ != nullptr) {
SDL_SetGPUSwapchainParameters(device_, window_, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, vsync_ ? SDL_GPU_PRESENTMODE_VSYNC : SDL_GPU_PRESENTMODE_IMMEDIATE); SDL_SetGPUSwapchainParameters(device_, window_, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, vsync_ ? SDL_GPU_PRESENTMODE_VSYNC : SDL_GPU_PRESENTMODE_IMMEDIATE);
} }
} }
void SDL3GPUShader::setScaleMode(bool integer_scale) { void SDL3GPUShader::setScaleMode(bool integer_scale) {
integer_scale_ = integer_scale; integer_scale_ = integer_scale;
} }
} // namespace Rendering } // namespace Rendering

View File

@@ -21,14 +21,14 @@ struct PostFXUniforms {
namespace Rendering { namespace Rendering {
/** /**
* @brief Backend de shaders usando SDL3 GPU API (Metal en macOS, Vulkan/SPIR-V en Win/Linux) * @brief Backend de shaders usando SDL3 GPU API (Metal en macOS, Vulkan/SPIR-V en Win/Linux)
* *
* Reemplaza el backend OpenGL para que los shaders PostFX funcionen en macOS. * Reemplaza el backend OpenGL para que los shaders PostFX funcionen en macOS.
* Pipeline: Surface pixels (CPU) → SDL_GPUTransferBuffer → SDL_GPUTexture (scene) * Pipeline: Surface pixels (CPU) → SDL_GPUTransferBuffer → SDL_GPUTexture (scene)
* → PostFX render pass → swapchain → present * → PostFX render pass → swapchain → present
*/ */
class SDL3GPUShader : public ShaderBackend { class SDL3GPUShader : public ShaderBackend {
public: public:
SDL3GPUShader() = default; SDL3GPUShader() = default;
~SDL3GPUShader() override; ~SDL3GPUShader() override;
@@ -88,6 +88,6 @@ class SDL3GPUShader : public ShaderBackend {
bool is_initialized_ = false; bool is_initialized_ = false;
bool vsync_ = true; bool vsync_ = true;
bool integer_scale_ = false; bool integer_scale_ = false;
}; };
} // namespace Rendering } // namespace Rendering

View File

@@ -6,11 +6,11 @@
namespace Rendering { namespace Rendering {
/** /**
* @brief Parámetros de intensidad de los efectos PostFX * @brief Parámetros de intensidad de los efectos PostFX
* Definido a nivel de namespace para facilitar el uso desde subclases y screen.cpp * Definido a nivel de namespace para facilitar el uso desde subclases y screen.cpp
*/ */
struct PostFXParams { struct PostFXParams {
float vignette = 0.0F; // Intensidad de la viñeta float vignette = 0.0F; // Intensidad de la viñeta
float scanlines = 0.0F; // Intensidad de las scanlines float scanlines = 0.0F; // Intensidad de las scanlines
float chroma = 0.0F; // Aberración cromática float chroma = 0.0F; // Aberración cromática
@@ -18,15 +18,15 @@ struct PostFXParams {
float gamma = 0.0F; // Corrección gamma (blend 0=off, 1=full) float gamma = 0.0F; // Corrección gamma (blend 0=off, 1=full)
float curvature = 0.0F; // Curvatura barrel CRT float curvature = 0.0F; // Curvatura barrel CRT
float bleeding = 0.0F; // Sangrado de color NTSC float bleeding = 0.0F; // Sangrado de color NTSC
}; };
/** /**
* @brief Interfaz abstracta para backends de renderizado con shaders * @brief Interfaz abstracta para backends de renderizado con shaders
* *
* Esta interfaz define el contrato que todos los backends de shaders * Esta interfaz define el contrato que todos los backends de shaders
* deben cumplir (OpenGL, Metal, Vulkan, etc.) * deben cumplir (OpenGL, Metal, Vulkan, etc.)
*/ */
class ShaderBackend { class ShaderBackend {
public: public:
virtual ~ShaderBackend() = default; virtual ~ShaderBackend() = default;
@@ -87,6 +87,6 @@ class ShaderBackend {
* @return true si usa aceleración (OpenGL/Metal/Vulkan) * @return true si usa aceleración (OpenGL/Metal/Vulkan)
*/ */
[[nodiscard]] virtual auto isHardwareAccelerated() const -> bool = 0; [[nodiscard]] virtual auto isHardwareAccelerated() const -> bool = 0;
}; };
} // namespace Rendering } // namespace Rendering

View File

@@ -24,26 +24,26 @@ struct JA_Sound_t; // lines 18-18
namespace Resource { namespace Resource {
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado // [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
Cache* Cache::cache = nullptr; Cache* Cache::cache = nullptr;
// [SINGLETON] Crearemos el objeto cache con esta función estática // [SINGLETON] Crearemos el objeto cache con esta función estática
void Cache::init() { Cache::cache = new Cache(); } void Cache::init() { Cache::cache = new Cache(); }
// [SINGLETON] Destruiremos el objeto cache con esta función estática // [SINGLETON] Destruiremos el objeto cache con esta función estática
void Cache::destroy() { delete Cache::cache; } void Cache::destroy() { delete Cache::cache; }
// [SINGLETON] Con este método obtenemos el objeto cache y podemos trabajar con él // [SINGLETON] Con este método obtenemos el objeto cache y podemos trabajar con él
auto Cache::get() -> Cache* { return Cache::cache; } auto Cache::get() -> Cache* { return Cache::cache; }
// Constructor // Constructor
Cache::Cache() Cache::Cache()
: loading_text_(Screen::get()->getText()) { : loading_text_(Screen::get()->getText()) {
load(); load();
} }
// Vacia todos los vectores de recursos // Vacia todos los vectores de recursos
void Cache::clear() { void Cache::clear() {
clearSounds(); clearSounds();
clearMusics(); clearMusics();
surfaces_.clear(); surfaces_.clear();
@@ -51,10 +51,10 @@ void Cache::clear() {
text_files_.clear(); text_files_.clear();
texts_.clear(); texts_.clear();
animations_.clear(); animations_.clear();
} }
// Carga todos los recursos // Carga todos los recursos
void Cache::load() { void Cache::load() {
calculateTotal(); calculateTotal();
Screen::get()->setBorderColor(static_cast<Uint8>(PaletteColor::BLACK)); Screen::get()->setBorderColor(static_cast<Uint8>(PaletteColor::BLACK));
std::cout << "\n** LOADING RESOURCES" << '\n'; std::cout << "\n** LOADING RESOURCES" << '\n';
@@ -67,16 +67,16 @@ void Cache::load() {
loadRooms(); loadRooms();
createText(); createText();
std::cout << "\n** RESOURCES LOADED" << '\n'; std::cout << "\n** RESOURCES LOADED" << '\n';
} }
// Recarga todos los recursos // Recarga todos los recursos
void Cache::reload() { void Cache::reload() {
clear(); clear();
load(); load();
} }
// Obtiene el sonido a partir de un nombre // Obtiene el sonido a partir de un nombre
auto Cache::getSound(const std::string& name) -> JA_Sound_t* { auto Cache::getSound(const std::string& name) -> JA_Sound_t* {
auto it = std::ranges::find_if(sounds_, [&name](const auto& s) { return s.name == name; }); auto it = std::ranges::find_if(sounds_, [&name](const auto& s) { return s.name == name; });
if (it != sounds_.end()) { if (it != sounds_.end()) {
@@ -85,10 +85,10 @@ auto Cache::getSound(const std::string& name) -> JA_Sound_t* {
std::cerr << "Error: Sonido no encontrado " << name << '\n'; std::cerr << "Error: Sonido no encontrado " << name << '\n';
throw std::runtime_error("Sonido no encontrado: " + name); throw std::runtime_error("Sonido no encontrado: " + name);
} }
// Obtiene la música a partir de un nombre // Obtiene la música a partir de un nombre
auto Cache::getMusic(const std::string& name) -> JA_Music_t* { auto Cache::getMusic(const std::string& name) -> JA_Music_t* {
auto it = std::ranges::find_if(musics_, [&name](const auto& m) { return m.name == name; }); auto it = std::ranges::find_if(musics_, [&name](const auto& m) { return m.name == name; });
if (it != musics_.end()) { if (it != musics_.end()) {
@@ -97,10 +97,10 @@ auto Cache::getMusic(const std::string& name) -> JA_Music_t* {
std::cerr << "Error: Música no encontrada " << name << '\n'; std::cerr << "Error: Música no encontrada " << name << '\n';
throw std::runtime_error("Música no encontrada: " + name); throw std::runtime_error("Música no encontrada: " + name);
} }
// Obtiene la surface a partir de un nombre // Obtiene la surface a partir de un nombre
auto Cache::getSurface(const std::string& name) -> std::shared_ptr<Surface> { auto Cache::getSurface(const std::string& name) -> std::shared_ptr<Surface> {
auto it = std::ranges::find_if(surfaces_, [&name](const auto& t) { return t.name == name; }); auto it = std::ranges::find_if(surfaces_, [&name](const auto& t) { return t.name == name; });
if (it != surfaces_.end()) { if (it != surfaces_.end()) {
@@ -109,10 +109,10 @@ auto Cache::getSurface(const std::string& name) -> std::shared_ptr<Surface> {
std::cerr << "Error: Imagen no encontrada " << name << '\n'; std::cerr << "Error: Imagen no encontrada " << name << '\n';
throw std::runtime_error("Imagen no encontrada: " + name); throw std::runtime_error("Imagen no encontrada: " + name);
} }
// Obtiene la paleta a partir de un nombre // Obtiene la paleta a partir de un nombre
auto Cache::getPalette(const std::string& name) -> Palette { auto Cache::getPalette(const std::string& name) -> Palette {
auto it = std::ranges::find_if(palettes_, [&name](const auto& t) { return t.name == name; }); auto it = std::ranges::find_if(palettes_, [&name](const auto& t) { return t.name == name; });
if (it != palettes_.end()) { if (it != palettes_.end()) {
@@ -121,10 +121,10 @@ auto Cache::getPalette(const std::string& name) -> Palette {
std::cerr << "Error: Paleta no encontrada " << name << '\n'; std::cerr << "Error: Paleta no encontrada " << name << '\n';
throw std::runtime_error("Paleta no encontrada: " + name); throw std::runtime_error("Paleta no encontrada: " + name);
} }
// Obtiene el fichero de texto a partir de un nombre // Obtiene el fichero de texto a partir de un nombre
auto Cache::getTextFile(const std::string& name) -> std::shared_ptr<Text::File> { auto Cache::getTextFile(const std::string& name) -> std::shared_ptr<Text::File> {
auto it = std::ranges::find_if(text_files_, [&name](const auto& t) { return t.name == name; }); auto it = std::ranges::find_if(text_files_, [&name](const auto& t) { return t.name == name; });
if (it != text_files_.end()) { if (it != text_files_.end()) {
@@ -133,10 +133,10 @@ auto Cache::getTextFile(const std::string& name) -> std::shared_ptr<Text::File>
std::cerr << "Error: TextFile no encontrado " << name << '\n'; std::cerr << "Error: TextFile no encontrado " << name << '\n';
throw std::runtime_error("TextFile no encontrado: " + name); throw std::runtime_error("TextFile no encontrado: " + name);
} }
// Obtiene el objeto de texto a partir de un nombre // Obtiene el objeto de texto a partir de un nombre
auto Cache::getText(const std::string& name) -> std::shared_ptr<Text> { auto Cache::getText(const std::string& name) -> std::shared_ptr<Text> {
auto it = std::ranges::find_if(texts_, [&name](const auto& t) { return t.name == name; }); auto it = std::ranges::find_if(texts_, [&name](const auto& t) { return t.name == name; });
if (it != texts_.end()) { if (it != texts_.end()) {
@@ -145,10 +145,10 @@ auto Cache::getText(const std::string& name) -> std::shared_ptr<Text> {
std::cerr << "Error: Text no encontrado " << name << '\n'; std::cerr << "Error: Text no encontrado " << name << '\n';
throw std::runtime_error("Texto no encontrado: " + name); throw std::runtime_error("Texto no encontrado: " + name);
} }
// Obtiene los datos de animación parseados a partir de un nombre // Obtiene los datos de animación parseados a partir de un nombre
auto Cache::getAnimationData(const std::string& name) -> const AnimationResource& { auto Cache::getAnimationData(const std::string& name) -> const AnimationResource& {
auto it = std::ranges::find_if(animations_, [&name](const auto& a) { return a.name == name; }); auto it = std::ranges::find_if(animations_, [&name](const auto& a) { return a.name == name; });
if (it != animations_.end()) { if (it != animations_.end()) {
@@ -157,10 +157,10 @@ auto Cache::getAnimationData(const std::string& name) -> const AnimationResource
std::cerr << "Error: Animación no encontrada " << name << '\n'; std::cerr << "Error: Animación no encontrada " << name << '\n';
throw std::runtime_error("Animación no encontrada: " + name); throw std::runtime_error("Animación no encontrada: " + name);
} }
// Obtiene la habitación a partir de un nombre // Obtiene la habitación a partir de un nombre
auto Cache::getRoom(const std::string& name) -> std::shared_ptr<Room::Data> { auto Cache::getRoom(const std::string& name) -> std::shared_ptr<Room::Data> {
auto it = std::ranges::find_if(rooms_, [&name](const auto& r) { return r.name == name; }); auto it = std::ranges::find_if(rooms_, [&name](const auto& r) { return r.name == name; });
if (it != rooms_.end()) { if (it != rooms_.end()) {
@@ -169,24 +169,24 @@ auto Cache::getRoom(const std::string& name) -> std::shared_ptr<Room::Data> {
std::cerr << "Error: Habitación no encontrada " << name << '\n'; std::cerr << "Error: Habitación no encontrada " << name << '\n';
throw std::runtime_error("Habitación no encontrada: " + name); throw std::runtime_error("Habitación no encontrada: " + name);
} }
// Obtiene todas las habitaciones // Obtiene todas las habitaciones
auto Cache::getRooms() -> std::vector<RoomResource>& { auto Cache::getRooms() -> std::vector<RoomResource>& {
return rooms_; return rooms_;
} }
// Helper para lanzar errores de carga con formato consistente // Helper para lanzar errores de carga con formato consistente
[[noreturn]] void Cache::throwLoadError(const std::string& asset_type, const std::string& file_path, const std::exception& e) { [[noreturn]] void Cache::throwLoadError(const std::string& asset_type, const std::string& file_path, const std::exception& e) {
std::cerr << "\n[ ERROR ] Failed to load " << asset_type << ": " << getFileName(file_path) << '\n'; std::cerr << "\n[ ERROR ] Failed to load " << asset_type << ": " << getFileName(file_path) << '\n';
std::cerr << "[ ERROR ] Path: " << file_path << '\n'; std::cerr << "[ ERROR ] Path: " << file_path << '\n';
std::cerr << "[ ERROR ] Reason: " << e.what() << '\n'; std::cerr << "[ ERROR ] Reason: " << e.what() << '\n';
std::cerr << "[ ERROR ] Check config/assets.yaml configuration\n"; std::cerr << "[ ERROR ] Check config/assets.yaml configuration\n";
throw; throw;
} }
// Carga los sonidos // Carga los sonidos
void Cache::loadSounds() { void Cache::loadSounds() {
std::cout << "\n>> SOUND FILES" << '\n'; std::cout << "\n>> SOUND FILES" << '\n';
auto list = List::get()->getListByType(List::Type::SOUND); auto list = List::get()->getListByType(List::Type::SOUND);
sounds_.clear(); sounds_.clear();
@@ -218,10 +218,10 @@ void Cache::loadSounds() {
throwLoadError("SOUND", l, e); throwLoadError("SOUND", l, e);
} }
} }
} }
// Carga las musicas // Carga las musicas
void Cache::loadMusics() { void Cache::loadMusics() {
std::cout << "\n>> MUSIC FILES" << '\n'; std::cout << "\n>> MUSIC FILES" << '\n';
auto list = List::get()->getListByType(List::Type::MUSIC); auto list = List::get()->getListByType(List::Type::MUSIC);
musics_.clear(); musics_.clear();
@@ -253,10 +253,10 @@ void Cache::loadMusics() {
throwLoadError("MUSIC", l, e); throwLoadError("MUSIC", l, e);
} }
} }
} }
// Carga las texturas // Carga las texturas
void Cache::loadSurfaces() { void Cache::loadSurfaces() {
std::cout << "\n>> SURFACES" << '\n'; std::cout << "\n>> SURFACES" << '\n';
auto list = List::get()->getListByType(List::Type::BITMAP); auto list = List::get()->getListByType(List::Type::BITMAP);
surfaces_.clear(); surfaces_.clear();
@@ -280,10 +280,10 @@ void Cache::loadSurfaces() {
getSurface("ending4.gif")->setTransparentColor(); getSurface("ending4.gif")->setTransparentColor();
getSurface("ending5.gif")->setTransparentColor(); getSurface("ending5.gif")->setTransparentColor();
getSurface("standard.gif")->setTransparentColor(16); getSurface("standard.gif")->setTransparentColor(16);
} }
// Carga las paletas // Carga las paletas
void Cache::loadPalettes() { void Cache::loadPalettes() {
std::cout << "\n>> PALETTES" << '\n'; std::cout << "\n>> PALETTES" << '\n';
auto list = List::get()->getListByType(List::Type::PALETTE); auto list = List::get()->getListByType(List::Type::PALETTE);
palettes_.clear(); palettes_.clear();
@@ -297,10 +297,10 @@ void Cache::loadPalettes() {
throwLoadError("PALETTE", l, e); throwLoadError("PALETTE", l, e);
} }
} }
} }
// Carga los ficheros de texto // Carga los ficheros de texto
void Cache::loadTextFiles() { void Cache::loadTextFiles() {
std::cout << "\n>> TEXT FILES" << '\n'; std::cout << "\n>> TEXT FILES" << '\n';
auto list = List::get()->getListByType(List::Type::FONT); auto list = List::get()->getListByType(List::Type::FONT);
text_files_.clear(); text_files_.clear();
@@ -314,10 +314,10 @@ void Cache::loadTextFiles() {
throwLoadError("FONT", l, e); throwLoadError("FONT", l, e);
} }
} }
} }
// Carga las animaciones // Carga las animaciones
void Cache::loadAnimations() { void Cache::loadAnimations() {
std::cout << "\n>> ANIMATIONS" << '\n'; std::cout << "\n>> ANIMATIONS" << '\n';
auto list = List::get()->getListByType(List::Type::ANIMATION); auto list = List::get()->getListByType(List::Type::ANIMATION);
animations_.clear(); animations_.clear();
@@ -340,10 +340,10 @@ void Cache::loadAnimations() {
throwLoadError("ANIMATION", l, e); throwLoadError("ANIMATION", l, e);
} }
} }
} }
// Carga las habitaciones desde archivos YAML // Carga las habitaciones desde archivos YAML
void Cache::loadRooms() { void Cache::loadRooms() {
std::cout << "\n>> ROOMS" << '\n'; std::cout << "\n>> ROOMS" << '\n';
auto list = List::get()->getListByType(List::Type::ROOM); auto list = List::get()->getListByType(List::Type::ROOM);
rooms_.clear(); rooms_.clear();
@@ -358,9 +358,9 @@ void Cache::loadRooms() {
throwLoadError("ROOM", l, e); throwLoadError("ROOM", l, e);
} }
} }
} }
void Cache::createText() { void Cache::createText() {
struct ResourceInfo { struct ResourceInfo {
std::string key; // Identificador del recurso std::string key; // Identificador del recurso
std::string texture_file; // Nombre del archivo de textura std::string texture_file; // Nombre del archivo de textura
@@ -380,10 +380,10 @@ void Cache::createText() {
texts_.emplace_back(TextResource{.name = res_info.key, .text = std::make_shared<Text>(getSurface(res_info.texture_file), getTextFile(res_info.text_file))}); texts_.emplace_back(TextResource{.name = res_info.key, .text = std::make_shared<Text>(getSurface(res_info.texture_file), getTextFile(res_info.text_file))});
printWithDots("Text : ", res_info.key, "[ DONE ]"); printWithDots("Text : ", res_info.key, "[ DONE ]");
} }
} }
// Vacía el vector de sonidos // Vacía el vector de sonidos
void Cache::clearSounds() { void Cache::clearSounds() {
// Itera sobre el vector y libera los recursos asociados a cada JA_Sound_t // Itera sobre el vector y libera los recursos asociados a cada JA_Sound_t
for (auto& sound : sounds_) { for (auto& sound : sounds_) {
if (sound.sound != nullptr) { if (sound.sound != nullptr) {
@@ -392,10 +392,10 @@ void Cache::clearSounds() {
} }
} }
sounds_.clear(); // Limpia el vector después de liberar todos los recursos sounds_.clear(); // Limpia el vector después de liberar todos los recursos
} }
// Vacía el vector de musicas // Vacía el vector de musicas
void Cache::clearMusics() { void Cache::clearMusics() {
// Itera sobre el vector y libera los recursos asociados a cada JA_Music_t // Itera sobre el vector y libera los recursos asociados a cada JA_Music_t
for (auto& music : musics_) { for (auto& music : musics_) {
if (music.music != nullptr) { if (music.music != nullptr) {
@@ -404,10 +404,10 @@ void Cache::clearMusics() {
} }
} }
musics_.clear(); // Limpia el vector después de liberar todos los recursos musics_.clear(); // Limpia el vector después de liberar todos los recursos
} }
// Calcula el numero de recursos para cargar // Calcula el numero de recursos para cargar
void Cache::calculateTotal() { void Cache::calculateTotal() {
std::vector<List::Type> asset_types = { std::vector<List::Type> asset_types = {
List::Type::SOUND, List::Type::SOUND,
List::Type::MUSIC, List::Type::MUSIC,
@@ -424,10 +424,10 @@ void Cache::calculateTotal() {
} }
count_ = ResourceCount{.total = total, .loaded = 0}; count_ = ResourceCount{.total = total, .loaded = 0};
} }
// Muestra el progreso de carga // Muestra el progreso de carga
void Cache::renderProgress() { void Cache::renderProgress() {
constexpr float X_PADDING = 60.0F; constexpr float X_PADDING = 60.0F;
constexpr float Y_PADDING = 10.0F; constexpr float Y_PADDING = 10.0F;
constexpr float BAR_HEIGHT = 5.0F; constexpr float BAR_HEIGHT = 5.0F;
@@ -470,10 +470,10 @@ void Cache::renderProgress() {
surface->fillRect(&rect_full, BAR_COLOR); surface->fillRect(&rect_full, BAR_COLOR);
Screen::get()->render(); Screen::get()->render();
} }
// Comprueba los eventos de la pantalla de carga // Comprueba los eventos de la pantalla de carga
void Cache::checkEvents() { void Cache::checkEvents() {
SDL_Event event; SDL_Event event;
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
switch (event.type) { switch (event.type) {
@@ -487,15 +487,15 @@ void Cache::checkEvents() {
break; break;
} }
} }
} }
// Actualiza el progreso de carga // Actualiza el progreso de carga
void Cache::updateLoadingProgress(int steps) { void Cache::updateLoadingProgress(int steps) {
count_.add(1); count_.add(1);
if (count_.loaded % steps == 0 || count_.loaded == count_.total) { if (count_.loaded % steps == 0 || count_.loaded == count_.total) {
renderProgress(); renderProgress();
} }
checkEvents(); checkEvents();
} }
} // namespace Resource } // namespace Resource

View File

@@ -9,7 +9,7 @@
namespace Resource { namespace Resource {
class Cache { class Cache {
public: public:
static void init(); // Inicialización singleton static void init(); // Inicialización singleton
static void destroy(); // Destrucción singleton static void destroy(); // Destrucción singleton
@@ -88,6 +88,6 @@ class Cache {
ResourceCount count_{}; // Contador de recursos ResourceCount count_{}; // Contador de recursos
std::shared_ptr<Text> loading_text_; // Texto para la pantalla de carga std::shared_ptr<Text> loading_text_; // Texto para la pantalla de carga
}; };
} // namespace Resource } // namespace Resource

View File

@@ -12,10 +12,10 @@
namespace Resource::Helper { namespace Resource::Helper {
static bool resource_system_initialized = false; static bool resource_system_initialized = false;
// Initialize the resource system // Initialize the resource system
auto initializeResourceSystem(const std::string& pack_file, bool enable_fallback) auto initializeResourceSystem(const std::string& pack_file, bool enable_fallback)
-> bool { -> bool {
if (resource_system_initialized) { if (resource_system_initialized) {
std::cout << "ResourceHelper: Already initialized\n"; std::cout << "ResourceHelper: Already initialized\n";
@@ -35,19 +35,19 @@ auto initializeResourceSystem(const std::string& pack_file, bool enable_fallback
} }
return success; return success;
} }
// Shutdown the resource system // Shutdown the resource system
void shutdownResourceSystem() { void shutdownResourceSystem() {
if (resource_system_initialized) { if (resource_system_initialized) {
Loader::get().shutdown(); Loader::get().shutdown();
resource_system_initialized = false; resource_system_initialized = false;
std::cout << "ResourceHelper: Shutdown complete\n"; std::cout << "ResourceHelper: Shutdown complete\n";
} }
} }
// Load a file // Load a file
auto loadFile(const std::string& filepath) -> std::vector<uint8_t> { auto loadFile(const std::string& filepath) -> std::vector<uint8_t> {
if (!resource_system_initialized) { if (!resource_system_initialized) {
std::cerr << "ResourceHelper: System not initialized, loading from filesystem\n"; std::cerr << "ResourceHelper: System not initialized, loading from filesystem\n";
// Fallback to direct filesystem access // Fallback to direct filesystem access
@@ -80,10 +80,10 @@ auto loadFile(const std::string& filepath) -> std::vector<uint8_t> {
// Load from filesystem // Load from filesystem
return Loader::get().loadResource(filepath); return Loader::get().loadResource(filepath);
} }
// Check if a file exists // Check if a file exists
auto fileExists(const std::string& filepath) -> bool { auto fileExists(const std::string& filepath) -> bool {
if (!resource_system_initialized) { if (!resource_system_initialized) {
return std::filesystem::exists(filepath); return std::filesystem::exists(filepath);
} }
@@ -98,10 +98,10 @@ auto fileExists(const std::string& filepath) -> bool {
// Check filesystem // Check filesystem
return std::filesystem::exists(filepath); return std::filesystem::exists(filepath);
} }
// Convert asset path to pack path // Convert asset path to pack path
auto getPackPath(const std::string& asset_path) -> std::string { auto getPackPath(const std::string& asset_path) -> std::string {
std::string path = asset_path; std::string path = asset_path;
// Convert backslashes to forward slashes // Convert backslashes to forward slashes
@@ -142,10 +142,10 @@ auto getPackPath(const std::string& asset_path) -> std::string {
} }
return path; return path;
} }
// Check if file should use resource pack // Check if file should use resource pack
auto shouldUseResourcePack(const std::string& filepath) -> bool { auto shouldUseResourcePack(const std::string& filepath) -> bool {
std::string path = filepath; std::string path = filepath;
std::ranges::replace(path, '\\', '/'); std::ranges::replace(path, '\\', '/');
@@ -169,14 +169,14 @@ auto shouldUseResourcePack(const std::string& filepath) -> bool {
} }
return false; return false;
} }
// Check if pack is loaded // Check if pack is loaded
auto isPackLoaded() -> bool { auto isPackLoaded() -> bool {
if (!resource_system_initialized) { if (!resource_system_initialized) {
return false; return false;
} }
return Loader::get().isPackLoaded(); return Loader::get().isPackLoaded();
} }
} // namespace Resource::Helper } // namespace Resource::Helper

View File

@@ -9,30 +9,30 @@
namespace Resource::Helper { namespace Resource::Helper {
// Initialize the resource system // Initialize the resource system
// pack_file: Path to resources.pack // pack_file: Path to resources.pack
// enable_fallback: Allow loading from filesystem if pack not available // enable_fallback: Allow loading from filesystem if pack not available
auto initializeResourceSystem(const std::string& pack_file = "resources.pack", auto initializeResourceSystem(const std::string& pack_file = "resources.pack",
bool enable_fallback = true) -> bool; bool enable_fallback = true) -> bool;
// Shutdown the resource system // Shutdown the resource system
void shutdownResourceSystem(); void shutdownResourceSystem();
// Load a file (tries pack first, then filesystem if fallback enabled) // Load a file (tries pack first, then filesystem if fallback enabled)
auto loadFile(const std::string& filepath) -> std::vector<uint8_t>; auto loadFile(const std::string& filepath) -> std::vector<uint8_t>;
// Check if a file exists // Check if a file exists
auto fileExists(const std::string& filepath) -> bool; auto fileExists(const std::string& filepath) -> bool;
// Convert an asset path to a pack path // Convert an asset path to a pack path
// Example: "data/music/title.ogg" -> "music/title.ogg" // Example: "data/music/title.ogg" -> "music/title.ogg"
auto getPackPath(const std::string& asset_path) -> std::string; auto getPackPath(const std::string& asset_path) -> std::string;
// Check if a file should use the resource pack // Check if a file should use the resource pack
// Returns false for config/ files (always from filesystem) // Returns false for config/ files (always from filesystem)
auto shouldUseResourcePack(const std::string& filepath) -> bool; auto shouldUseResourcePack(const std::string& filepath) -> bool;
// Check if pack is loaded // Check if pack is loaded
auto isPackLoaded() -> bool; auto isPackLoaded() -> bool;
} // namespace Resource::Helper } // namespace Resource::Helper

View File

@@ -16,23 +16,23 @@
namespace Resource { namespace Resource {
// Singleton // Singleton
List* List::instance = nullptr; List* List::instance = nullptr;
void List::init(const std::string& executable_path) { void List::init(const std::string& executable_path) {
List::instance = new List(executable_path); List::instance = new List(executable_path);
} }
void List::destroy() { void List::destroy() {
delete List::instance; delete List::instance;
} }
auto List::get() -> List* { auto List::get() -> List* {
return List::instance; return List::instance;
} }
// Añade un elemento al mapa (función auxiliar) // Añade un elemento al mapa (función auxiliar)
void List::addToMap(const std::string& file_path, Type type, bool required, bool absolute) { void List::addToMap(const std::string& file_path, Type type, bool required, bool absolute) {
std::string full_path = absolute ? file_path : executable_path_ + file_path; std::string full_path = absolute ? file_path : executable_path_ + file_path;
std::string filename = getFileName(full_path); std::string filename = getFileName(full_path);
@@ -44,15 +44,15 @@ void List::addToMap(const std::string& file_path, Type type, bool required, bool
} }
file_list_.emplace(filename, Item{std::move(full_path), type, required}); file_list_.emplace(filename, Item{std::move(full_path), type, required});
} }
// Añade un elemento a la lista // Añade un elemento a la lista
void List::add(const std::string& file_path, Type type, bool required, bool absolute) { void List::add(const std::string& file_path, Type type, bool required, bool absolute) {
addToMap(file_path, type, required, absolute); addToMap(file_path, type, required, absolute);
} }
// Carga recursos desde un archivo de configuración con soporte para variables // Carga recursos desde un archivo de configuración con soporte para variables
void List::loadFromFile(const std::string& config_file_path, const std::string& prefix, const std::string& system_folder) { void List::loadFromFile(const std::string& config_file_path, const std::string& prefix, const std::string& system_folder) {
std::ifstream file(config_file_path); std::ifstream file(config_file_path);
if (!file.is_open()) { if (!file.is_open()) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
@@ -68,10 +68,10 @@ void List::loadFromFile(const std::string& config_file_path, const std::string&
// Parse using loadFromString // Parse using loadFromString
loadFromString(buffer.str(), prefix, system_folder); loadFromString(buffer.str(), prefix, system_folder);
} }
// Carga recursos desde un string de configuración (para release con pack) // Carga recursos desde un string de configuración (para release con pack)
void List::loadFromString(const std::string& config_content, const std::string& prefix, const std::string& system_folder) { void List::loadFromString(const std::string& config_content, const std::string& prefix, const std::string& system_folder) {
try { try {
// Parsear YAML // Parsear YAML
auto yaml = fkyaml::node::deserialize(config_content); auto yaml = fkyaml::node::deserialize(config_content);
@@ -153,10 +153,10 @@ void List::loadFromString(const std::string& config_content, const std::string&
"Error loading assets: %s", "Error loading assets: %s",
e.what()); e.what());
} }
} }
// Devuelve la ruta completa a un fichero (búsqueda O(1)) // Devuelve la ruta completa a un fichero (búsqueda O(1))
auto List::get(const std::string& filename) const -> std::string { auto List::get(const std::string& filename) const -> std::string {
auto it = file_list_.find(filename); auto it = file_list_.find(filename);
if (it != file_list_.end()) { if (it != file_list_.end()) {
return it->second.file; return it->second.file;
@@ -164,10 +164,10 @@ auto List::get(const std::string& filename) const -> std::string {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: file %s not found", filename.c_str()); SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: file %s not found", filename.c_str());
return ""; return "";
} }
// Carga datos del archivo // Carga datos del archivo
auto List::loadData(const std::string& filename) const -> std::vector<uint8_t> { auto List::loadData(const std::string& filename) const -> std::vector<uint8_t> {
auto it = file_list_.find(filename); auto it = file_list_.find(filename);
if (it != file_list_.end()) { if (it != file_list_.end()) {
std::ifstream file(it->second.file, std::ios::binary); std::ifstream file(it->second.file, std::ios::binary);
@@ -193,15 +193,15 @@ auto List::loadData(const std::string& filename) const -> std::vector<uint8_t> {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: file %s not found for data loading", filename.c_str()); SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: file %s not found for data loading", filename.c_str());
return {}; return {};
} }
// Verifica si un recurso existe // Verifica si un recurso existe
auto List::exists(const std::string& filename) const -> bool { auto List::exists(const std::string& filename) const -> bool {
return file_list_.find(filename) != file_list_.end(); return file_list_.find(filename) != file_list_.end();
} }
// Parsea string a Type // Parsea string a Type
auto List::parseAssetType(const std::string& type_str) -> Type { auto List::parseAssetType(const std::string& type_str) -> Type {
if (type_str == "DATA") { if (type_str == "DATA") {
return Type::DATA; return Type::DATA;
} }
@@ -232,10 +232,10 @@ auto List::parseAssetType(const std::string& type_str) -> Type {
} }
throw std::runtime_error("Unknown asset type: " + type_str); throw std::runtime_error("Unknown asset type: " + type_str);
} }
// Devuelve el nombre del tipo de recurso // Devuelve el nombre del tipo de recurso
auto List::getTypeName(Type type) -> std::string { auto List::getTypeName(Type type) -> std::string {
switch (type) { switch (type) {
case Type::DATA: case Type::DATA:
return "DATA"; return "DATA";
@@ -256,10 +256,10 @@ auto List::getTypeName(Type type) -> std::string {
default: default:
return "ERROR"; return "ERROR";
} }
} }
// Devuelve la lista de recursos de un tipo // Devuelve la lista de recursos de un tipo
auto List::getListByType(Type type) const -> std::vector<std::string> { auto List::getListByType(Type type) const -> std::vector<std::string> {
std::vector<std::string> list; std::vector<std::string> list;
for (const auto& [filename, item] : file_list_) { for (const auto& [filename, item] : file_list_) {
@@ -272,10 +272,10 @@ auto List::getListByType(Type type) const -> std::vector<std::string> {
std::ranges::sort(list); std::ranges::sort(list);
return list; return list;
} }
// Reemplaza variables en las rutas // Reemplaza variables en las rutas
auto List::replaceVariables(const std::string& path, const std::string& prefix, const std::string& system_folder) -> std::string { auto List::replaceVariables(const std::string& path, const std::string& prefix, const std::string& system_folder) -> std::string {
std::string result = path; std::string result = path;
// Reemplazar ${PREFIX} // Reemplazar ${PREFIX}
@@ -293,10 +293,10 @@ auto List::replaceVariables(const std::string& path, const std::string& prefix,
} }
return result; return result;
} }
// Parsea las opciones de una línea de configuración // Parsea las opciones de una línea de configuración
auto List::parseOptions(const std::string& options, bool& required, bool& absolute) -> void { auto List::parseOptions(const std::string& options, bool& required, bool& absolute) -> void {
if (options.empty()) { if (options.empty()) {
return; return;
} }
@@ -315,6 +315,6 @@ auto List::parseOptions(const std::string& options, bool& required, bool& absolu
absolute = true; absolute = true;
} }
} }
} }
} // namespace Resource } // namespace Resource

View File

@@ -8,8 +8,8 @@
namespace Resource { namespace Resource {
// --- Clase List: gestor optimizado de recursos (singleton) --- // --- Clase List: gestor optimizado de recursos (singleton) ---
class List { class List {
public: public:
// --- Enums --- // --- Enums ---
enum class Type : int { enum class Type : int {
@@ -71,6 +71,6 @@ class List {
// --- Instancia singleton --- // --- Instancia singleton ---
static List* instance; // Instancia única de List static List* instance; // Instancia única de List
}; };
} // namespace Resource } // namespace Resource

View File

@@ -9,14 +9,14 @@
namespace Resource { namespace Resource {
// Get singleton instance // Get singleton instance
auto Loader::get() -> Loader& { auto Loader::get() -> Loader& {
static Loader instance_; static Loader instance_;
return instance_; return instance_;
} }
// Initialize with a pack file // Initialize with a pack file
auto Loader::initialize(const std::string& pack_file, bool enable_fallback) auto Loader::initialize(const std::string& pack_file, bool enable_fallback)
-> bool { -> bool {
if (initialized_) { if (initialized_) {
std::cout << "Loader: Already initialized\n"; std::cout << "Loader: Already initialized\n";
@@ -50,10 +50,10 @@ auto Loader::initialize(const std::string& pack_file, bool enable_fallback)
std::cout << "Loader: Using filesystem fallback\n"; std::cout << "Loader: Using filesystem fallback\n";
initialized_ = true; initialized_ = true;
return true; return true;
} }
// Load a resource // Load a resource
auto Loader::loadResource(const std::string& filename) -> std::vector<uint8_t> { auto Loader::loadResource(const std::string& filename) -> std::vector<uint8_t> {
if (!initialized_) { if (!initialized_) {
std::cerr << "Loader: Not initialized\n"; std::cerr << "Loader: Not initialized\n";
return {}; return {};
@@ -78,10 +78,10 @@ auto Loader::loadResource(const std::string& filename) -> std::vector<uint8_t> {
std::cerr << "Loader: Resource not found: " << filename << '\n'; std::cerr << "Loader: Resource not found: " << filename << '\n';
return {}; return {};
} }
// Check if a resource exists // Check if a resource exists
auto Loader::resourceExists(const std::string& filename) -> bool { auto Loader::resourceExists(const std::string& filename) -> bool {
if (!initialized_) { if (!initialized_) {
return false; return false;
} }
@@ -99,30 +99,30 @@ auto Loader::resourceExists(const std::string& filename) -> bool {
} }
return false; return false;
} }
// Check if pack is loaded // Check if pack is loaded
auto Loader::isPackLoaded() const -> bool { auto Loader::isPackLoaded() const -> bool {
return resource_pack_ && resource_pack_->isLoaded(); return resource_pack_ && resource_pack_->isLoaded();
} }
// Get pack statistics // Get pack statistics
auto Loader::getPackResourceCount() const -> size_t { auto Loader::getPackResourceCount() const -> size_t {
if (resource_pack_ && resource_pack_->isLoaded()) { if (resource_pack_ && resource_pack_->isLoaded()) {
return resource_pack_->getResourceCount(); return resource_pack_->getResourceCount();
} }
return 0; return 0;
} }
// Cleanup // Cleanup
void Loader::shutdown() { void Loader::shutdown() {
resource_pack_.reset(); resource_pack_.reset();
initialized_ = false; initialized_ = false;
std::cout << "Loader: Shutdown complete\n"; std::cout << "Loader: Shutdown complete\n";
} }
// Load from filesystem // Load from filesystem
auto Loader::loadFromFilesystem(const std::string& filepath) auto Loader::loadFromFilesystem(const std::string& filepath)
-> std::vector<uint8_t> { -> std::vector<uint8_t> {
std::ifstream file(filepath, std::ios::binary | std::ios::ate); std::ifstream file(filepath, std::ios::binary | std::ios::ate);
if (!file) { if (!file) {
@@ -139,15 +139,15 @@ auto Loader::loadFromFilesystem(const std::string& filepath)
} }
return data; return data;
} }
// Check if file exists on filesystem // Check if file exists on filesystem
auto Loader::fileExistsOnFilesystem(const std::string& filepath) -> bool { auto Loader::fileExistsOnFilesystem(const std::string& filepath) -> bool {
return std::filesystem::exists(filepath); return std::filesystem::exists(filepath);
} }
// Validate pack integrity // Validate pack integrity
auto Loader::validatePack() const -> bool { auto Loader::validatePack() const -> bool {
if (!initialized_ || !resource_pack_ || !resource_pack_->isLoaded()) { if (!initialized_ || !resource_pack_ || !resource_pack_->isLoaded()) {
std::cerr << "Loader: Cannot validate - pack not loaded\n"; std::cerr << "Loader: Cannot validate - pack not loaded\n";
return false; return false;
@@ -165,10 +165,10 @@ auto Loader::validatePack() const -> bool {
<< '\n'; << '\n';
std::cout << "Loader: Pack validation successful\n"; std::cout << "Loader: Pack validation successful\n";
return true; return true;
} }
// Load assets.yaml from pack // Load assets.yaml from pack
auto Loader::loadAssetsConfig() const -> std::string { auto Loader::loadAssetsConfig() const -> std::string {
if (!initialized_ || !resource_pack_ || !resource_pack_->isLoaded()) { if (!initialized_ || !resource_pack_ || !resource_pack_->isLoaded()) {
std::cerr << "Loader: Cannot load assets config - pack not loaded\n"; std::cerr << "Loader: Cannot load assets config - pack not loaded\n";
return ""; return "";
@@ -194,6 +194,6 @@ auto Loader::loadAssetsConfig() const -> std::string {
<< " bytes)\n"; << " bytes)\n";
return config_content; return config_content;
} }
} // namespace Resource } // namespace Resource

View File

@@ -11,8 +11,8 @@
namespace Resource { namespace Resource {
// Singleton class for loading resources from pack or filesystem // Singleton class for loading resources from pack or filesystem
class Loader { class Loader {
public: public:
static auto get() -> Loader&; // Singleton instance access static auto get() -> Loader&; // Singleton instance access
@@ -43,6 +43,6 @@ class Loader {
std::unique_ptr<Pack> resource_pack_; // Member variables std::unique_ptr<Pack> resource_pack_; // Member variables
bool fallback_to_files_{true}; bool fallback_to_files_{true};
bool initialized_{false}; bool initialized_{false};
}; };
} // namespace Resource } // namespace Resource

View File

@@ -12,32 +12,32 @@
namespace Resource { namespace Resource {
// Calculate CRC32 checksum for data verification // Calculate CRC32 checksum for data verification
auto Pack::calculateChecksum(const std::vector<uint8_t>& data) -> uint32_t { auto Pack::calculateChecksum(const std::vector<uint8_t>& data) -> uint32_t {
uint32_t checksum = 0x12345678; uint32_t checksum = 0x12345678;
for (unsigned char byte : data) { for (unsigned char byte : data) {
checksum = ((checksum << 5) + checksum) + byte; checksum = ((checksum << 5) + checksum) + byte;
} }
return checksum; return checksum;
} }
// XOR encryption (symmetric - same function for encrypt/decrypt) // XOR encryption (symmetric - same function for encrypt/decrypt)
void Pack::encryptData(std::vector<uint8_t>& data, const std::string& key) { void Pack::encryptData(std::vector<uint8_t>& data, const std::string& key) {
if (key.empty()) { if (key.empty()) {
return; return;
} }
for (size_t i = 0; i < data.size(); ++i) { for (size_t i = 0; i < data.size(); ++i) {
data[i] ^= key[i % key.length()]; data[i] ^= key[i % key.length()];
} }
} }
void Pack::decryptData(std::vector<uint8_t>& data, const std::string& key) { void Pack::decryptData(std::vector<uint8_t>& data, const std::string& key) {
// XOR is symmetric // XOR is symmetric
encryptData(data, key); encryptData(data, key);
} }
// Read entire file into memory // Read entire file into memory
auto Pack::readFile(const std::string& filepath) -> std::vector<uint8_t> { auto Pack::readFile(const std::string& filepath) -> std::vector<uint8_t> {
std::ifstream file(filepath, std::ios::binary | std::ios::ate); std::ifstream file(filepath, std::ios::binary | std::ios::ate);
if (!file) { if (!file) {
std::cerr << "ResourcePack: Failed to open file: " << filepath << '\n'; std::cerr << "ResourcePack: Failed to open file: " << filepath << '\n';
@@ -54,10 +54,10 @@ auto Pack::readFile(const std::string& filepath) -> std::vector<uint8_t> {
} }
return data; return data;
} }
// Add a single file to the pack // Add a single file to the pack
auto Pack::addFile(const std::string& filepath, const std::string& pack_name) auto Pack::addFile(const std::string& filepath, const std::string& pack_name)
-> bool { -> bool {
auto file_data = readFile(filepath); auto file_data = readFile(filepath);
if (file_data.empty()) { if (file_data.empty()) {
@@ -77,10 +77,10 @@ auto Pack::addFile(const std::string& filepath, const std::string& pack_name)
std::cout << "Added: " << pack_name << " (" << file_data.size() << " bytes)\n"; std::cout << "Added: " << pack_name << " (" << file_data.size() << " bytes)\n";
return true; return true;
} }
// Add all files from a directory recursively // Add all files from a directory recursively
auto Pack::addDirectory(const std::string& dir_path, auto Pack::addDirectory(const std::string& dir_path,
const std::string& base_path) -> bool { const std::string& base_path) -> bool {
namespace fs = std::filesystem; namespace fs = std::filesystem;
@@ -114,10 +114,10 @@ auto Pack::addDirectory(const std::string& dir_path,
} }
return true; return true;
} }
// Save the pack to a file // Save the pack to a file
auto Pack::savePack(const std::string& pack_file) -> bool { auto Pack::savePack(const std::string& pack_file) -> bool {
std::ofstream file(pack_file, std::ios::binary); std::ofstream file(pack_file, std::ios::binary);
if (!file) { if (!file) {
std::cerr << "ResourcePack: Failed to create pack file: " << pack_file << '\n'; std::cerr << "ResourcePack: Failed to create pack file: " << pack_file << '\n';
@@ -159,10 +159,10 @@ auto Pack::savePack(const std::string& pack_file) -> bool {
std::cout << "Total size: " << data_size << " bytes\n"; std::cout << "Total size: " << data_size << " bytes\n";
return true; return true;
} }
// Load a pack from a file // Load a pack from a file
auto Pack::loadPack(const std::string& pack_file) -> bool { auto Pack::loadPack(const std::string& pack_file) -> bool {
std::ifstream file(pack_file, std::ios::binary); std::ifstream file(pack_file, std::ios::binary);
if (!file) { if (!file) {
std::cerr << "ResourcePack: Failed to open pack file: " << pack_file << '\n'; std::cerr << "ResourcePack: Failed to open pack file: " << pack_file << '\n';
@@ -226,10 +226,10 @@ auto Pack::loadPack(const std::string& pack_file) -> bool {
std::cout << "Data size: " << data_size << " bytes\n"; std::cout << "Data size: " << data_size << " bytes\n";
return true; return true;
} }
// Get a resource by name // Get a resource by name
auto Pack::getResource(const std::string& filename) -> std::vector<uint8_t> { auto Pack::getResource(const std::string& filename) -> std::vector<uint8_t> {
auto it = resources_.find(filename); auto it = resources_.find(filename);
if (it == resources_.end()) { if (it == resources_.end()) {
return {}; return {};
@@ -255,15 +255,15 @@ auto Pack::getResource(const std::string& filename) -> std::vector<uint8_t> {
} }
return result; return result;
} }
// Check if a resource exists // Check if a resource exists
auto Pack::hasResource(const std::string& filename) const -> bool { auto Pack::hasResource(const std::string& filename) const -> bool {
return resources_.find(filename) != resources_.end(); return resources_.find(filename) != resources_.end();
} }
// Get list of all resources // Get list of all resources
auto Pack::getResourceList() const -> std::vector<std::string> { auto Pack::getResourceList() const -> std::vector<std::string> {
std::vector<std::string> list; std::vector<std::string> list;
list.reserve(resources_.size()); list.reserve(resources_.size());
for (const auto& [name, entry] : resources_) { for (const auto& [name, entry] : resources_) {
@@ -271,10 +271,10 @@ auto Pack::getResourceList() const -> std::vector<std::string> {
} }
std::ranges::sort(list); std::ranges::sort(list);
return list; return list;
} }
// Calculate overall pack checksum for validation // Calculate overall pack checksum for validation
auto Pack::calculatePackChecksum() const -> uint32_t { auto Pack::calculatePackChecksum() const -> uint32_t {
if (!loaded_ || data_.empty()) { if (!loaded_ || data_.empty()) {
return 0; return 0;
} }
@@ -298,6 +298,6 @@ auto Pack::calculatePackChecksum() const -> uint32_t {
} }
return global_checksum; return global_checksum;
} }
} // namespace Resource } // namespace Resource

View File

@@ -11,19 +11,19 @@
namespace Resource { namespace Resource {
// Entry metadata for each resource in the pack // Entry metadata for each resource in the pack
struct ResourceEntry { struct ResourceEntry {
std::string filename; // Relative path within pack std::string filename; // Relative path within pack
uint64_t offset{0}; // Byte offset in data block uint64_t offset{0}; // Byte offset in data block
uint64_t size{0}; // Size in bytes uint64_t size{0}; // Size in bytes
uint32_t checksum{0}; // CRC32 checksum for verification uint32_t checksum{0}; // CRC32 checksum for verification
}; };
// Resource pack file format // Resource pack file format
// Header: "JDDI" (4 bytes) + Version (4 bytes) // Header: "JDDI" (4 bytes) + Version (4 bytes)
// Metadata: Count + array of ResourceEntry // Metadata: Count + array of ResourceEntry
// Data: Encrypted data block // Data: Encrypted data block
class Pack { class Pack {
public: public:
Pack() = default; Pack() = default;
~Pack() = default; ~Pack() = default;
@@ -63,6 +63,6 @@ class Pack {
std::unordered_map<std::string, ResourceEntry> resources_; // Member variables std::unordered_map<std::string, ResourceEntry> resources_; // Member variables
std::vector<uint8_t> data_; // Encrypted data block std::vector<uint8_t> data_; // Encrypted data block
bool loaded_{false}; bool loaded_{false};
}; };
} // namespace Resource } // namespace Resource

View File

@@ -5,8 +5,8 @@
#include "game/scene_manager.hpp" // Para SceneManager #include "game/scene_manager.hpp" // Para SceneManager
namespace GlobalEvents { namespace GlobalEvents {
// Comprueba los eventos que se pueden producir en cualquier sección del juego // Comprueba los eventos que se pueden producir en cualquier sección del juego
void handle(const SDL_Event& event) { void handle(const SDL_Event& event) {
// Evento de salida de la aplicación // Evento de salida de la aplicación
if (event.type == SDL_EVENT_QUIT) { if (event.type == SDL_EVENT_QUIT) {
SceneManager::current = SceneManager::Scene::QUIT; SceneManager::current = SceneManager::Scene::QUIT;
@@ -18,5 +18,5 @@ void handle(const SDL_Event& event) {
} }
Mouse::handleEvent(event); Mouse::handleEvent(event);
} }
} // namespace GlobalEvents } // namespace GlobalEvents

View File

@@ -3,6 +3,6 @@
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
namespace GlobalEvents { namespace GlobalEvents {
// Comprueba los eventos que se pueden producir en cualquier sección del juego // Comprueba los eventos que se pueden producir en cualquier sección del juego
void handle(const SDL_Event& event); void handle(const SDL_Event& event);
} // namespace GlobalEvents } // namespace GlobalEvents

View File

@@ -8,116 +8,95 @@
// Forward declarations from Options namespace // Forward declarations from Options namespace
namespace Options { namespace Options {
// enum class ControlScheme; // enum class ControlScheme;
enum class NotificationPosition; enum class NotificationPosition;
} // namespace Options } // namespace Options
namespace Defaults { namespace Defaults::Canvas {
constexpr int WIDTH = GameCanvas::WIDTH; // Ancho del canvas del juego (256)
constexpr int HEIGHT = GameCanvas::HEIGHT; // Alto del canvas del juego (192)
} // namespace Defaults::Canvas
// --- CANVAS --- namespace Defaults::Window {
// Dimensiones del canvas del juego (usa GameCanvas como fuente única) constexpr int ZOOM = 2; // Zoom de la ventana por defecto
namespace Canvas { } // namespace Defaults::Window
constexpr int WIDTH = GameCanvas::WIDTH; // Ancho del canvas del juego (256)
constexpr int HEIGHT = GameCanvas::HEIGHT; // Alto del canvas del juego (192)
} // namespace Canvas
// --- WINDOW --- namespace Defaults::Video {
namespace Window { constexpr bool FULLSCREEN = false; // Modo de pantalla completa por defecto (false = ventana)
constexpr int ZOOM = 2; // Zoom de la ventana por defecto constexpr Screen::Filter FILTER = Screen::Filter::NEAREST; // Filtro por defecto
} // namespace Window constexpr bool VERTICAL_SYNC = true; // Vsync activado por defecto
constexpr bool POSTFX = false; // PostFX desactivado por defecto
constexpr bool INTEGER_SCALE = true; // Escalado entero activado por defecto
constexpr bool KEEP_ASPECT = true; // Mantener aspecto activado por defecto
constexpr const char* PALETTE_NAME = "zx-spectrum"; // Paleta por defecto
} // namespace Defaults::Video
// --- VIDEO --- namespace Defaults::Border {
namespace Video { constexpr bool ENABLED = true; // Borde activado por defecto
constexpr bool FULLSCREEN = false; // Modo de pantalla completa por defecto (false = ventana) constexpr int WIDTH = 32; // Ancho del borde por defecto
constexpr Screen::Filter FILTER = Screen::Filter::NEAREST; // Filtro por defecto constexpr int HEIGHT = 24; // Alto del borde por defectoF
constexpr bool VERTICAL_SYNC = true; // Vsync activado por defecto } // namespace Defaults::Border
constexpr bool POSTFX = false; // PostFX desactivado por defecto
constexpr bool INTEGER_SCALE = true; // Escalado entero activado por defecto
constexpr bool KEEP_ASPECT = true; // Mantener aspecto activado por defecto
constexpr const char* PALETTE_NAME = "zx-spectrum"; // Paleta por defecto
} // namespace Video
// --- BORDER --- namespace Defaults::Audio {
namespace Border { constexpr float VOLUME = 1.0F; // Volumen por defecto
constexpr bool ENABLED = true; // Borde activado por defecto constexpr bool ENABLED = true; // Audio por defecto
constexpr int WIDTH = 32; // Ancho del borde por defecto } // namespace Defaults::Audio
constexpr int HEIGHT = 24; // Alto del borde por defecto
} // namespace Border
// --- AUDIO --- namespace Defaults::Music {
namespace Audio { constexpr float VOLUME = 0.8F; // Volumen por defecto de la musica
constexpr float VOLUME = 1.0F; // Volumen por defecto constexpr bool ENABLED = true; // Musica habilitada por defecto
constexpr bool ENABLED = true; // Audio por defecto } // namespace Defaults::Music
} // namespace Audio
// --- MUSIC --- namespace Defaults::Sound {
namespace Music { constexpr float VOLUME = 1.0F; // Volumen por defecto de los efectos de sonido
constexpr float VOLUME = 0.8F; // Volumen por defecto de la musica constexpr bool ENABLED = true; // Sonido habilitado por defecto
constexpr bool ENABLED = true; // Musica habilitada por defecto } // namespace Defaults::Sound
} // namespace Music
// --- SOUND --- namespace Defaults::Cheat {
namespace Sound { constexpr bool INFINITE_LIVES = false; // Vidas infinitas desactivadas por defecto
constexpr float VOLUME = 1.0F; // Volumen por defecto de los efectos de sonido constexpr bool INVINCIBLE = false; // Invencibilidad desactivada por defecto
constexpr bool ENABLED = true; // Sonido habilitado por defecto constexpr bool JAIL_IS_OPEN = false; // Jail abierta desactivada por defecto
} // namespace Sound constexpr bool ALTERNATE_SKIN = false; // Skin alternativa desactivada por defecto
} // namespace Defaults::Cheat
// --- CHEATS --- namespace Defaults::Stats {
namespace Cheat { constexpr int ROOMS = 0; // Habitaciones visitadas por defecto
constexpr bool INFINITE_LIVES = false; // Vidas infinitas desactivadas por defecto constexpr int ITEMS = 0; // Items obtenidos por defecto
constexpr bool INVINCIBLE = false; // Invencibilidad desactivada por defecto constexpr const char* WORST_NIGHTMARE = ""; // Habitación con más muertes por defecto
constexpr bool JAIL_IS_OPEN = false; // Jail abierta desactivada por defecto } // namespace Defaults::Stats
constexpr bool ALTERNATE_SKIN = false; // Skin alternativa desactivada por defecto
} // namespace Cheat
// --- STATS --- namespace Defaults::Controls {
namespace Stats { constexpr SDL_Scancode KEY_LEFT = SDL_SCANCODE_LEFT; // Tecla izquierda por defecto
constexpr int ROOMS = 0; // Habitaciones visitadas por defecto constexpr SDL_Scancode KEY_RIGHT = SDL_SCANCODE_RIGHT; // Tecla derecha por defecto
constexpr int ITEMS = 0; // Items obtenidos por defecto constexpr SDL_Scancode KEY_JUMP = SDL_SCANCODE_UP; // Tecla salto por defecto
constexpr const char* WORST_NIGHTMARE = ""; // Habitación con más muertes por defecto
} // namespace Stats
// --- CONTROLS --- constexpr int GAMEPAD_BUTTON_LEFT = SDL_GAMEPAD_BUTTON_DPAD_LEFT; // Botón izquierda por defecto
namespace Controls { constexpr int GAMEPAD_BUTTON_RIGHT = SDL_GAMEPAD_BUTTON_DPAD_RIGHT; // Botón derecha por defecto
constexpr SDL_Scancode KEY_LEFT = SDL_SCANCODE_LEFT; // Tecla izquierda por defecto constexpr int GAMEPAD_BUTTON_JUMP = SDL_GAMEPAD_BUTTON_WEST; // Botón salto por defecto
constexpr SDL_Scancode KEY_RIGHT = SDL_SCANCODE_RIGHT; // Tecla derecha por defecto } // namespace Defaults::Controls
constexpr SDL_Scancode KEY_JUMP = SDL_SCANCODE_UP; // Tecla salto por defecto
constexpr int GAMEPAD_BUTTON_LEFT = SDL_GAMEPAD_BUTTON_DPAD_LEFT; // Botón izquierda por defecto namespace Defaults::Kiosk {
constexpr int GAMEPAD_BUTTON_RIGHT = SDL_GAMEPAD_BUTTON_DPAD_RIGHT; // Botón derecha por defecto constexpr bool ENABLED = false; // Modo kiosko desactivado por defecto
constexpr int GAMEPAD_BUTTON_JUMP = SDL_GAMEPAD_BUTTON_WEST; // Botón salto por defecto constexpr const char* TEXT = ""; // Texto del modo kiosko por defecto
} // namespace Controls constexpr bool INFINITE_LIVES = false; // Vidas infinitas en modo kiosko desactivadas por defecto
} // namespace Defaults::Kiosk
// --- KIOSK --- namespace Defaults::Game::Room {
namespace Kiosk {
constexpr bool ENABLED = false; // Modo kiosko desactivado por defecto
constexpr const char* TEXT = ""; // Texto del modo kiosko por defecto
constexpr bool INFINITE_LIVES = false; // Vidas infinitas en modo kiosko desactivadas por defecto
} // namespace Kiosk
// --- GAME (posición y habitación inicial) ---
namespace Game {
namespace Room {
#ifdef _DEBUG #ifdef _DEBUG
constexpr const char* INITIAL = "51.yaml"; // Habitación de inicio en debug constexpr const char* INITIAL = "51.yaml"; // Habitación de inicio en debug
#else #else
constexpr const char* INITIAL = "03.yaml"; // Habitación de inicio en release constexpr const char* INITIAL = "03.yaml"; // Habitación de inicio en release
#endif #endif
} // namespace Room } // namespace Defaults::Game::Room
namespace Player { namespace Defaults::Game::Player {
#ifdef _DEBUG #ifdef _DEBUG
constexpr int SPAWN_X = 26 * Tile::SIZE; // Posición X inicial en debug constexpr int SPAWN_X = 26 * Tile::SIZE; // Posición X inicial en debug
constexpr int SPAWN_Y = 10 * Tile::SIZE; // Posición Y inicial en debug constexpr int SPAWN_Y = 10 * Tile::SIZE; // Posición Y inicial en debug
constexpr SDL_FlipMode SPAWN_FLIP = Flip::LEFT; // Orientación inicial en debug constexpr SDL_FlipMode SPAWN_FLIP = Flip::LEFT; // Orientación inicial en debug
#else #else
constexpr int SPAWN_X = 25 * Tile::SIZE; // Posición X inicial en release constexpr int SPAWN_X = 25 * Tile::SIZE; // Posición X inicial en release
constexpr int SPAWN_Y = 13 * Tile::SIZE; // Posición Y inicial en release constexpr int SPAWN_Y = 13 * Tile::SIZE; // Posición Y inicial en release
constexpr SDL_FlipMode SPAWN_FLIP = Flip::LEFT; // Orientación inicial en release constexpr SDL_FlipMode SPAWN_FLIP = Flip::LEFT; // Orientación inicial en release
#endif #endif
} // namespace Player } // namespace Defaults::Game::Player
} // namespace Game
} // namespace Defaults

View File

@@ -13,19 +13,19 @@
namespace Options { namespace Options {
// --- Funciones helper de conversión --- // --- Funciones helper de conversión ---
// Mapa de nombres de filtro // Mapa de nombres de filtro
const std::unordered_map<Screen::Filter, std::string> FILTER_TO_STRING = { const std::unordered_map<Screen::Filter, std::string> FILTER_TO_STRING = {
{Screen::Filter::NEAREST, "nearest"}, {Screen::Filter::NEAREST, "nearest"},
{Screen::Filter::LINEAR, "linear"}}; {Screen::Filter::LINEAR, "linear"}};
const std::unordered_map<std::string, Screen::Filter> STRING_TO_FILTER = { const std::unordered_map<std::string, Screen::Filter> STRING_TO_FILTER = {
{"nearest", Screen::Filter::NEAREST}, {"nearest", Screen::Filter::NEAREST},
{"linear", Screen::Filter::LINEAR}}; {"linear", Screen::Filter::LINEAR}};
// Mapa de scancodes comunes (los más usados para controles de juego) // Mapa de scancodes comunes (los más usados para controles de juego)
const std::unordered_map<SDL_Scancode, std::string> SCANCODE_TO_STRING = { const std::unordered_map<SDL_Scancode, std::string> SCANCODE_TO_STRING = {
// Flechas // Flechas
{SDL_SCANCODE_LEFT, "LEFT"}, {SDL_SCANCODE_LEFT, "LEFT"},
{SDL_SCANCODE_RIGHT, "RIGHT"}, {SDL_SCANCODE_RIGHT, "RIGHT"},
@@ -82,7 +82,7 @@ const std::unordered_map<SDL_Scancode, std::string> SCANCODE_TO_STRING = {
{SDL_SCANCODE_LALT, "LALT"}, {SDL_SCANCODE_LALT, "LALT"},
{SDL_SCANCODE_RALT, "RALT"}}; {SDL_SCANCODE_RALT, "RALT"}};
const std::unordered_map<std::string, SDL_Scancode> STRING_TO_SCANCODE = { const std::unordered_map<std::string, SDL_Scancode> STRING_TO_SCANCODE = {
// Flechas // Flechas
{"LEFT", SDL_SCANCODE_LEFT}, {"LEFT", SDL_SCANCODE_LEFT},
{"RIGHT", SDL_SCANCODE_RIGHT}, {"RIGHT", SDL_SCANCODE_RIGHT},
@@ -139,8 +139,8 @@ const std::unordered_map<std::string, SDL_Scancode> STRING_TO_SCANCODE = {
{"LALT", SDL_SCANCODE_LALT}, {"LALT", SDL_SCANCODE_LALT},
{"RALT", SDL_SCANCODE_RALT}}; {"RALT", SDL_SCANCODE_RALT}};
// Mapa extendido de botones de gamepad (incluye ejes como botones) // Mapa extendido de botones de gamepad (incluye ejes como botones)
const std::unordered_map<int, std::string> GAMEPAD_BUTTON_TO_STRING = { const std::unordered_map<int, std::string> GAMEPAD_BUTTON_TO_STRING = {
{SDL_GAMEPAD_BUTTON_WEST, "WEST"}, {SDL_GAMEPAD_BUTTON_WEST, "WEST"},
{SDL_GAMEPAD_BUTTON_NORTH, "NORTH"}, {SDL_GAMEPAD_BUTTON_NORTH, "NORTH"},
{SDL_GAMEPAD_BUTTON_EAST, "EAST"}, {SDL_GAMEPAD_BUTTON_EAST, "EAST"},
@@ -158,7 +158,7 @@ const std::unordered_map<int, std::string> GAMEPAD_BUTTON_TO_STRING = {
{200, "LEFT_STICK_LEFT"}, {200, "LEFT_STICK_LEFT"},
{201, "LEFT_STICK_RIGHT"}}; {201, "LEFT_STICK_RIGHT"}};
const std::unordered_map<std::string, int> STRING_TO_GAMEPAD_BUTTON = { const std::unordered_map<std::string, int> STRING_TO_GAMEPAD_BUTTON = {
{"WEST", SDL_GAMEPAD_BUTTON_WEST}, {"WEST", SDL_GAMEPAD_BUTTON_WEST},
{"NORTH", SDL_GAMEPAD_BUTTON_NORTH}, {"NORTH", SDL_GAMEPAD_BUTTON_NORTH},
{"EAST", SDL_GAMEPAD_BUTTON_EAST}, {"EAST", SDL_GAMEPAD_BUTTON_EAST},
@@ -176,8 +176,8 @@ const std::unordered_map<std::string, int> STRING_TO_GAMEPAD_BUTTON = {
{"LEFT_STICK_LEFT", 200}, {"LEFT_STICK_LEFT", 200},
{"LEFT_STICK_RIGHT", 201}}; {"LEFT_STICK_RIGHT", 201}};
// Lista de paletas válidas // Lista de paletas válidas
const std::vector<std::string> VALID_PALETTES = { const std::vector<std::string> VALID_PALETTES = {
"black-and-white", "black-and-white",
"green-phosphor", "green-phosphor",
"island-joy-16", "island-joy-16",
@@ -194,33 +194,33 @@ const std::vector<std::string> VALID_PALETTES = {
"zx-spectrum-adjusted", "zx-spectrum-adjusted",
"zxarne-5-2"}; "zxarne-5-2"};
// Funciones helper de conversión // Funciones helper de conversión
auto filterToString(Screen::Filter filter) -> std::string { auto filterToString(Screen::Filter filter) -> std::string {
auto it = FILTER_TO_STRING.find(filter); auto it = FILTER_TO_STRING.find(filter);
if (it != FILTER_TO_STRING.end()) { if (it != FILTER_TO_STRING.end()) {
return it->second; return it->second;
} }
return "nearest"; return "nearest";
} }
auto stringToFilter(const std::string& str) -> Screen::Filter { auto stringToFilter(const std::string& str) -> Screen::Filter {
auto it = STRING_TO_FILTER.find(str); auto it = STRING_TO_FILTER.find(str);
if (it != STRING_TO_FILTER.end()) { if (it != STRING_TO_FILTER.end()) {
return it->second; return it->second;
} }
return Defaults::Video::FILTER; return Defaults::Video::FILTER;
} }
auto scancodeToString(SDL_Scancode scancode) -> std::string { auto scancodeToString(SDL_Scancode scancode) -> std::string {
auto it = SCANCODE_TO_STRING.find(scancode); auto it = SCANCODE_TO_STRING.find(scancode);
if (it != SCANCODE_TO_STRING.end()) { if (it != SCANCODE_TO_STRING.end()) {
return it->second; return it->second;
} }
// Fallback: devolver el código numérico como string // Fallback: devolver el código numérico como string
return std::to_string(static_cast<int>(scancode)); return std::to_string(static_cast<int>(scancode));
} }
auto stringToScancode(const std::string& str, SDL_Scancode default_value) -> SDL_Scancode { auto stringToScancode(const std::string& str, SDL_Scancode default_value) -> SDL_Scancode {
auto it = STRING_TO_SCANCODE.find(str); auto it = STRING_TO_SCANCODE.find(str);
if (it != STRING_TO_SCANCODE.end()) { if (it != STRING_TO_SCANCODE.end()) {
return it->second; return it->second;
@@ -232,18 +232,18 @@ auto stringToScancode(const std::string& str, SDL_Scancode default_value) -> SDL
} catch (...) { } catch (...) {
return default_value; return default_value;
} }
} }
auto gamepadButtonToString(int button) -> std::string { auto gamepadButtonToString(int button) -> std::string {
auto it = GAMEPAD_BUTTON_TO_STRING.find(button); auto it = GAMEPAD_BUTTON_TO_STRING.find(button);
if (it != GAMEPAD_BUTTON_TO_STRING.end()) { if (it != GAMEPAD_BUTTON_TO_STRING.end()) {
return it->second; return it->second;
} }
// Fallback: devolver el código numérico como string // Fallback: devolver el código numérico como string
return std::to_string(button); return std::to_string(button);
} }
auto stringToGamepadButton(const std::string& str, int default_value) -> int { auto stringToGamepadButton(const std::string& str, int default_value) -> int {
auto it = STRING_TO_GAMEPAD_BUTTON.find(str); auto it = STRING_TO_GAMEPAD_BUTTON.find(str);
if (it != STRING_TO_GAMEPAD_BUTTON.end()) { if (it != STRING_TO_GAMEPAD_BUTTON.end()) {
return it->second; return it->second;
@@ -254,18 +254,18 @@ auto stringToGamepadButton(const std::string& str, int default_value) -> int {
} catch (...) { } catch (...) {
return default_value; return default_value;
} }
} }
auto isValidPalette(const std::string& palette) -> bool { auto isValidPalette(const std::string& palette) -> bool {
std::string lower_palette = palette; std::string lower_palette = palette;
std::ranges::transform(lower_palette, lower_palette.begin(), ::tolower); std::ranges::transform(lower_palette, lower_palette.begin(), ::tolower);
return std::ranges::any_of(VALID_PALETTES, [&lower_palette](const auto& valid) { return valid == lower_palette; }); return std::ranges::any_of(VALID_PALETTES, [&lower_palette](const auto& valid) { return valid == lower_palette; });
} }
// --- Funciones helper para loadFromFile() --- // --- Funciones helper para loadFromFile() ---
// Carga configuración de ventana desde YAML // Carga configuración de ventana desde YAML
void loadWindowConfigFromYaml(const fkyaml::node& yaml) { void loadWindowConfigFromYaml(const fkyaml::node& yaml) {
if (yaml.contains("window")) { if (yaml.contains("window")) {
const auto& win = yaml["window"]; const auto& win = yaml["window"];
if (win.contains("zoom")) { if (win.contains("zoom")) {
@@ -277,10 +277,10 @@ void loadWindowConfigFromYaml(const fkyaml::node& yaml) {
} }
} }
} }
} }
// Carga configuración de borde desde YAML // Carga configuración de borde desde YAML
void loadBorderConfigFromYaml(const fkyaml::node& border) { void loadBorderConfigFromYaml(const fkyaml::node& border) {
if (border.contains("enabled")) { if (border.contains("enabled")) {
try { try {
video.border.enabled = border["enabled"].get_value<bool>(); video.border.enabled = border["enabled"].get_value<bool>();
@@ -306,10 +306,10 @@ void loadBorderConfigFromYaml(const fkyaml::node& border) {
video.border.height = Defaults::Border::HEIGHT; video.border.height = Defaults::Border::HEIGHT;
} }
} }
} }
// Carga los campos básicos de configuración de video // Carga los campos básicos de configuración de video
void loadBasicVideoFieldsFromYaml(const fkyaml::node& vid) { void loadBasicVideoFieldsFromYaml(const fkyaml::node& vid) {
// fullscreen (antes era "mode") // fullscreen (antes era "mode")
if (vid.contains("fullscreen")) { if (vid.contains("fullscreen")) {
try { try {
@@ -373,10 +373,10 @@ void loadBasicVideoFieldsFromYaml(const fkyaml::node& vid) {
video.palette = Defaults::Video::PALETTE_NAME; video.palette = Defaults::Video::PALETTE_NAME;
} }
} }
} }
// Carga configuración de video desde YAML // Carga configuración de video desde YAML
void loadVideoConfigFromYaml(const fkyaml::node& yaml) { void loadVideoConfigFromYaml(const fkyaml::node& yaml) {
if (yaml.contains("video")) { if (yaml.contains("video")) {
const auto& vid = yaml["video"]; const auto& vid = yaml["video"];
loadBasicVideoFieldsFromYaml(vid); loadBasicVideoFieldsFromYaml(vid);
@@ -386,10 +386,10 @@ void loadVideoConfigFromYaml(const fkyaml::node& yaml) {
loadBorderConfigFromYaml(vid["border"]); loadBorderConfigFromYaml(vid["border"]);
} }
} }
} }
// Carga controles de teclado desde YAML // Carga controles de teclado desde YAML
void loadKeyboardControlsFromYaml(const fkyaml::node& yaml) { void loadKeyboardControlsFromYaml(const fkyaml::node& yaml) {
if (yaml.contains("keyboard_controls")) { if (yaml.contains("keyboard_controls")) {
const auto& ctrl = yaml["keyboard_controls"]; const auto& ctrl = yaml["keyboard_controls"];
@@ -420,10 +420,10 @@ void loadKeyboardControlsFromYaml(const fkyaml::node& yaml) {
} }
} }
} }
} }
// Carga controles de gamepad desde YAML // Carga controles de gamepad desde YAML
void loadGamepadControlsFromYaml(const fkyaml::node& yaml) { void loadGamepadControlsFromYaml(const fkyaml::node& yaml) {
if (yaml.contains("gamepad_controls")) { if (yaml.contains("gamepad_controls")) {
const auto& gp = yaml["gamepad_controls"]; const auto& gp = yaml["gamepad_controls"];
@@ -454,10 +454,10 @@ void loadGamepadControlsFromYaml(const fkyaml::node& yaml) {
} }
} }
} }
} }
// Carga configuración del modo kiosko desde YAML // Carga configuración del modo kiosko desde YAML
void loadKioskConfigFromYaml(const fkyaml::node& yaml) { void loadKioskConfigFromYaml(const fkyaml::node& yaml) {
if (yaml.contains("kiosk")) { if (yaml.contains("kiosk")) {
const auto& k = yaml["kiosk"]; const auto& k = yaml["kiosk"];
@@ -485,24 +485,24 @@ void loadKioskConfigFromYaml(const fkyaml::node& yaml) {
} }
} }
} }
} }
// Crea e inicializa las opciones del programa // Crea e inicializa las opciones del programa
void init() { void init() {
#ifdef _DEBUG #ifdef _DEBUG
console = true; console = true;
#else #else
console = false; console = false;
#endif #endif
} }
// Establece la ruta del fichero de configuración // Establece la ruta del fichero de configuración
void setConfigFile(const std::string& path) { void setConfigFile(const std::string& path) {
config_file_path = path; config_file_path = path;
} }
// Carga las opciones desde el fichero configurado // Carga las opciones desde el fichero configurado
auto loadFromFile() -> bool { auto loadFromFile() -> bool {
// Versión esperada del fichero // Versión esperada del fichero
const std::string CONFIG_VERSION = Texts::VERSION; const std::string CONFIG_VERSION = Texts::VERSION;
version = ""; version = "";
@@ -566,10 +566,10 @@ auto loadFromFile() -> bool {
saveToFile(); saveToFile();
return true; return true;
} }
} }
// Guarda las opciones al fichero configurado // Guarda las opciones al fichero configurado
auto saveToFile() -> bool { auto saveToFile() -> bool {
// Abre el fichero para escritura // Abre el fichero para escritura
std::ofstream file(config_file_path); std::ofstream file(config_file_path);
if (!file.is_open()) { if (!file.is_open()) {
@@ -647,22 +647,24 @@ auto saveToFile() -> bool {
} }
return true; return true;
}
// Establece la ruta del fichero de PostFX
void setPostFXFile(const std::string& path) {
postfx_file_path = path;
}
// Helper: extrae un campo float de un nodo YAML si existe, ignorando errores de conversión
static void parseFloatField(const fkyaml::node& node, const std::string& key, float& target) {
if (node.contains(key)) {
try { target = node[key].get_value<float>(); } catch (...) {}
} }
}
// Carga los presets de PostFX desde el fichero // Establece la ruta del fichero de PostFX
auto loadPostFXFromFile() -> bool { void setPostFXFile(const std::string& path) {
postfx_file_path = path;
}
// Helper: extrae un campo float de un nodo YAML si existe, ignorando errores de conversión
static void parseFloatField(const fkyaml::node& node, const std::string& key, float& target) {
if (node.contains(key)) {
try {
target = node[key].get_value<float>();
} catch (...) {}
}
}
// Carga los presets de PostFX desde el fichero
auto loadPostFXFromFile() -> bool {
postfx_presets.clear(); postfx_presets.clear();
current_postfx_preset = 0; current_postfx_preset = 0;
@@ -710,10 +712,10 @@ auto loadPostFXFromFile() -> bool {
} }
return savePostFXToFile(); return savePostFXToFile();
} }
} }
// Guarda los presets de PostFX por defecto // Guarda los presets de PostFX por defecto
auto savePostFXToFile() -> bool { auto savePostFXToFile() -> bool {
if (postfx_file_path.empty()) { if (postfx_file_path.empty()) {
return false; return false;
} }
@@ -794,6 +796,6 @@ auto savePostFXToFile() -> bool {
current_postfx_preset = 0; current_postfx_preset = 0;
return true; return true;
} }
} // namespace Options } // namespace Options

View File

@@ -15,22 +15,22 @@
// --- Namespace Options: gestión de configuración y opciones del juego --- // --- Namespace Options: gestión de configuración y opciones del juego ---
namespace Options { namespace Options {
// Estructura para las opciones de control de teclado // Estructura para las opciones de control de teclado
struct KeyboardControls { struct KeyboardControls {
SDL_Scancode key_left{Defaults::Controls::KEY_LEFT}; // Tecla para mover a la izquierda SDL_Scancode key_left{Defaults::Controls::KEY_LEFT}; // Tecla para mover a la izquierda
SDL_Scancode key_right{Defaults::Controls::KEY_RIGHT}; // Tecla para mover a la derecha SDL_Scancode key_right{Defaults::Controls::KEY_RIGHT}; // Tecla para mover a la derecha
SDL_Scancode key_jump{Defaults::Controls::KEY_JUMP}; // Tecla para saltar SDL_Scancode key_jump{Defaults::Controls::KEY_JUMP}; // Tecla para saltar
}; };
// Estructura para las opciones de control del gamepad/joystick // Estructura para las opciones de control del gamepad/joystick
struct GamepadControls { struct GamepadControls {
int button_left{Defaults::Controls::GAMEPAD_BUTTON_LEFT}; // Botón para mover a la izquierda (por defecto: DPAD_LEFT) int button_left{Defaults::Controls::GAMEPAD_BUTTON_LEFT}; // Botón para mover a la izquierda (por defecto: DPAD_LEFT)
int button_right{Defaults::Controls::GAMEPAD_BUTTON_RIGHT}; // Botón para mover a la derecha (por defecto: DPAD_RIGHT) int button_right{Defaults::Controls::GAMEPAD_BUTTON_RIGHT}; // Botón para mover a la derecha (por defecto: DPAD_RIGHT)
int button_jump{Defaults::Controls::GAMEPAD_BUTTON_JUMP}; // Botón para saltar (por defecto: WEST/X button) int button_jump{Defaults::Controls::GAMEPAD_BUTTON_JUMP}; // Botón para saltar (por defecto: WEST/X button)
}; };
// Estructura para albergar trucos // Estructura para albergar trucos
struct Cheat { struct Cheat {
enum class State : bool { enum class State : bool {
DISABLED = false, DISABLED = false,
ENABLED = true ENABLED = true
@@ -45,38 +45,38 @@ struct Cheat {
[[nodiscard]] auto enabled() const -> bool { [[nodiscard]] auto enabled() const -> bool {
return infinite_lives == State::ENABLED || invincible == State::ENABLED || jail_is_open == State::ENABLED; return infinite_lives == State::ENABLED || invincible == State::ENABLED || jail_is_open == State::ENABLED;
} }
}; };
// Estructura para almacenar estadísticas // Estructura para almacenar estadísticas
struct Stats { struct Stats {
int rooms{Defaults::Stats::ROOMS}; // Cantidad de habitaciones visitadas int rooms{Defaults::Stats::ROOMS}; // Cantidad de habitaciones visitadas
int items{Defaults::Stats::ITEMS}; // Cantidad de items obtenidos int items{Defaults::Stats::ITEMS}; // Cantidad de items obtenidos
std::string worst_nightmare{Defaults::Stats::WORST_NIGHTMARE}; // Habitación con más muertes acumuladas std::string worst_nightmare{Defaults::Stats::WORST_NIGHTMARE}; // Habitación con más muertes acumuladas
}; };
// Estructura para el modo kiosko // Estructura para el modo kiosko
struct Kiosk { struct Kiosk {
bool enabled{Defaults::Kiosk::ENABLED}; // Indica si el modo kiosko está activo bool enabled{Defaults::Kiosk::ENABLED}; // Indica si el modo kiosko está activo
std::string text{Defaults::Kiosk::TEXT}; // Texto a mostrar en el modo kiosko std::string text{Defaults::Kiosk::TEXT}; // Texto a mostrar en el modo kiosko
bool infinite_lives{Defaults::Kiosk::INFINITE_LIVES}; // Indica si el jugador tiene vidas infinitas en modo kiosko bool infinite_lives{Defaults::Kiosk::INFINITE_LIVES}; // Indica si el jugador tiene vidas infinitas en modo kiosko
}; };
// Estructura con opciones de la ventana // Estructura con opciones de la ventana
struct Window { struct Window {
std::string caption{Texts::WINDOW_CAPTION}; // Texto que aparece en la barra de título de la ventana std::string caption{Texts::WINDOW_CAPTION}; // Texto que aparece en la barra de título de la ventana
int zoom{Defaults::Window::ZOOM}; // Zoom de la ventana int zoom{Defaults::Window::ZOOM}; // Zoom de la ventana
int max_zoom{Defaults::Window::ZOOM}; // Máximo tamaño de zoom para la ventana int max_zoom{Defaults::Window::ZOOM}; // Máximo tamaño de zoom para la ventana
}; };
// Estructura para gestionar el borde de la pantalla // Estructura para gestionar el borde de la pantalla
struct Border { struct Border {
bool enabled{Defaults::Border::ENABLED}; // Indica si se ha de mostrar el borde bool enabled{Defaults::Border::ENABLED}; // Indica si se ha de mostrar el borde
float width{Defaults::Border::WIDTH}; // Ancho del borde float width{Defaults::Border::WIDTH}; // Ancho del borde
float height{Defaults::Border::HEIGHT}; // Alto del borde float height{Defaults::Border::HEIGHT}; // Alto del borde
}; };
// Estructura para las opciones de video // Estructura para las opciones de video
struct Video { struct Video {
bool fullscreen{Defaults::Video::FULLSCREEN}; // Contiene el valor del modo de pantalla completa bool fullscreen{Defaults::Video::FULLSCREEN}; // Contiene el valor del modo de pantalla completa
Screen::Filter filter{Defaults::Video::FILTER}; // Filtro usado para el escalado de la imagen Screen::Filter filter{Defaults::Video::FILTER}; // Filtro usado para el escalado de la imagen
bool vertical_sync{Defaults::Video::VERTICAL_SYNC}; // Indica si se quiere usar vsync o no bool vertical_sync{Defaults::Video::VERTICAL_SYNC}; // Indica si se quiere usar vsync o no
@@ -86,36 +86,36 @@ struct Video {
Border border{}; // Borde de la pantalla Border border{}; // Borde de la pantalla
std::string palette{Defaults::Video::PALETTE_NAME}; // Paleta de colores a usar en el juego std::string palette{Defaults::Video::PALETTE_NAME}; // Paleta de colores a usar en el juego
std::string info; // Información sobre el modo de vídeo std::string info; // Información sobre el modo de vídeo
}; };
// Estructura para las opciones de musica // Estructura para las opciones de musica
struct Music { struct Music {
bool enabled{Defaults::Music::ENABLED}; // Indica si la música suena o no bool enabled{Defaults::Music::ENABLED}; // Indica si la música suena o no
float volume{Defaults::Music::VOLUME}; // Volumen al que suena la música float volume{Defaults::Music::VOLUME}; // Volumen al que suena la música
}; };
// Estructura para las opciones de sonido // Estructura para las opciones de sonido
struct Sound { struct Sound {
bool enabled{Defaults::Sound::ENABLED}; // Indica si los sonidos suenan o no bool enabled{Defaults::Sound::ENABLED}; // Indica si los sonidos suenan o no
float volume{Defaults::Sound::VOLUME}; // Volumen al que suenan los sonidos (0 a 128 internamente) float volume{Defaults::Sound::VOLUME}; // Volumen al que suenan los sonidos (0 a 128 internamente)
}; };
// Estructura para las opciones de audio // Estructura para las opciones de audio
struct Audio { struct Audio {
Music music{}; // Opciones para la música Music music{}; // Opciones para la música
Sound sound{}; // Opciones para los efectos de sonido Sound sound{}; // Opciones para los efectos de sonido
bool enabled{Defaults::Audio::ENABLED}; // Indica si el audio está activo o no bool enabled{Defaults::Audio::ENABLED}; // Indica si el audio está activo o no
float volume{Defaults::Audio::VOLUME}; // Volumen al que suenan el audio (0-128 internamente) float volume{Defaults::Audio::VOLUME}; // Volumen al que suenan el audio (0-128 internamente)
}; };
// Estructura para las opciones de juego // Estructura para las opciones de juego
struct Game { struct Game {
float width{Defaults::Canvas::WIDTH}; // Ancho de la resolucion del juego float width{Defaults::Canvas::WIDTH}; // Ancho de la resolucion del juego
float height{Defaults::Canvas::HEIGHT}; // Alto de la resolucion del juego float height{Defaults::Canvas::HEIGHT}; // Alto de la resolucion del juego
}; };
// Estructura para un preset de PostFX // Estructura para un preset de PostFX
struct PostFXPreset { struct PostFXPreset {
std::string name; // Nombre del preset std::string name; // Nombre del preset
float vignette{0.6F}; // Intensidad de la viñeta (0.0 = ninguna, 1.0 = máxima) float vignette{0.6F}; // Intensidad de la viñeta (0.0 = ninguna, 1.0 = máxima)
float scanlines{0.7F}; // Intensidad de las scanlines (0.0 = desactivadas, 1.0 = máximas) float scanlines{0.7F}; // Intensidad de las scanlines (0.0 = desactivadas, 1.0 = máximas)
@@ -124,36 +124,36 @@ struct PostFXPreset {
float gamma{0.0F}; // Corrección gamma input 2.4 / output 2.2 (0.0 = off, 1.0 = plena) float gamma{0.0F}; // Corrección gamma input 2.4 / output 2.2 (0.0 = off, 1.0 = plena)
float curvature{0.0F}; // Distorsión barrel CRT (0.0 = plana, 1.0 = máxima curvatura) float curvature{0.0F}; // Distorsión barrel CRT (0.0 = plana, 1.0 = máxima curvatura)
float bleeding{0.0F}; // Sangrado de color NTSC horizontal Y/C (0.0 = off, 1.0 = máximo) float bleeding{0.0F}; // Sangrado de color NTSC horizontal Y/C (0.0 = off, 1.0 = máximo)
}; };
// --- Variables globales --- // --- Variables globales ---
inline std::string version{}; // Versión del fichero de configuración. Sirve para saber si las opciones son compatibles inline std::string version{}; // Versión del fichero de configuración. Sirve para saber si las opciones son compatibles
inline bool console{false}; // Indica si ha de mostrar información por la consola de texto inline bool console{false}; // Indica si ha de mostrar información por la consola de texto
inline Cheat cheats{}; // Contiene trucos y ventajas para el juego inline Cheat cheats{}; // Contiene trucos y ventajas para el juego
inline Game game{}; // Opciones de juego inline Game game{}; // Opciones de juego
inline Video video{}; // Opciones de video inline Video video{}; // Opciones de video
inline Stats stats{}; // Datos con las estadisticas de juego inline Stats stats{}; // Datos con las estadisticas de juego
inline Window window{}; // Opciones relativas a la ventana inline Window window{}; // Opciones relativas a la ventana
inline Audio audio{}; // Opciones relativas al audio inline Audio audio{}; // Opciones relativas al audio
inline KeyboardControls keyboard_controls{}; // Teclas usadas para jugar inline KeyboardControls keyboard_controls{}; // Teclas usadas para jugar
inline GamepadControls gamepad_controls{}; // Botones del gamepad usados para jugar inline GamepadControls gamepad_controls{}; // Botones del gamepad usados para jugar
inline Kiosk kiosk{}; // Opciones del modo kiosko inline Kiosk kiosk{}; // Opciones del modo kiosko
// Ruta completa del fichero de configuración (establecida mediante setConfigFile) // Ruta completa del fichero de configuración (establecida mediante setConfigFile)
inline std::string config_file_path{}; inline std::string config_file_path{};
// --- Variables PostFX --- // --- Variables PostFX ---
inline std::vector<PostFXPreset> postfx_presets{}; // Lista de presets de PostFX inline std::vector<PostFXPreset> postfx_presets{}; // Lista de presets de PostFX
inline int current_postfx_preset{0}; // Índice del preset de PostFX actual inline int current_postfx_preset{0}; // Índice del preset de PostFX actual
inline std::string postfx_file_path{}; // Ruta del fichero postfx.yaml inline std::string postfx_file_path{}; // Ruta del fichero postfx.yaml
// --- Funciones públicas --- // --- Funciones públicas ---
void init(); // Crea e inicializa las opciones del programa void init(); // Crea e inicializa las opciones del programa
void setConfigFile(const std::string& path); // Establece la ruta del fichero de configuración void setConfigFile(const std::string& path); // Establece la ruta del fichero de configuración
auto loadFromFile() -> bool; // Carga las opciones desde el fichero configurado auto loadFromFile() -> bool; // Carga las opciones desde el fichero configurado
auto saveToFile() -> bool; // Guarda las opciones al fichero configurado auto saveToFile() -> bool; // Guarda las opciones al fichero configurado
void setPostFXFile(const std::string& path); // Establece la ruta del fichero de PostFX void setPostFXFile(const std::string& path); // Establece la ruta del fichero de PostFX
auto loadPostFXFromFile() -> bool; // Carga los presets de PostFX desde el fichero auto loadPostFXFromFile() -> bool; // Carga los presets de PostFX desde el fichero
auto savePostFXToFile() -> bool; // Guarda los presets de PostFX por defecto auto savePostFXToFile() -> bool; // Guarda los presets de PostFX por defecto
} // namespace Options } // namespace Options

View File

@@ -9,8 +9,8 @@
namespace SceneManager { namespace SceneManager {
// --- Escenas del programa --- // --- Escenas del programa ---
enum class Scene { enum class Scene {
LOGO, // Pantalla del logo LOGO, // Pantalla del logo
LOADING_SCREEN, // Pantalla de carga LOADING_SCREEN, // Pantalla de carga
TITLE, // Pantalla de título/menú principal TITLE, // Pantalla de título/menú principal
@@ -21,24 +21,24 @@ enum class Scene {
ENDING, // Final del juego (ending 1) ENDING, // Final del juego (ending 1)
ENDING2, // Final del juego (ending 2) ENDING2, // Final del juego (ending 2)
QUIT // Salir del programa QUIT // Salir del programa
}; };
// --- Opciones para transiciones entre escenas --- // --- Opciones para transiciones entre escenas ---
enum class Options { enum class Options {
NONE, // Sin opciones especiales NONE, // Sin opciones especiales
LOGO_TO_LOADING_SCREEN, // Del logo a la intro LOGO_TO_LOADING_SCREEN, // Del logo a la intro
LOGO_TO_TITLE, // Del logo al título LOGO_TO_TITLE, // Del logo al título
TITLE_WITH_LOADING_SCREEN, // Al título mostrando pantalla de carga TITLE_WITH_LOADING_SCREEN, // Al título mostrando pantalla de carga
TITLE_WITHOUT_LOADING_SCREEN // Al título sin pantalla de carga TITLE_WITHOUT_LOADING_SCREEN // Al título sin pantalla de carga
}; };
// --- Variables de estado globales --- // --- Variables de estado globales ---
#ifdef _DEBUG #ifdef _DEBUG
inline Scene current = Scene::GAME; // Escena actual inline Scene current = Scene::GAME; // Escena actual
inline Options options = Options::LOGO_TO_LOADING_SCREEN; // Opciones de la escena actual inline Options options = Options::LOGO_TO_LOADING_SCREEN; // Opciones de la escena actual
#else #else
inline Scene current = Scene::LOGO; // Escena actual inline Scene current = Scene::LOGO; // Escena actual
inline Options options = Options::LOGO_TO_LOADING_SCREEN; // Opciones de la escena actual inline Options options = Options::LOGO_TO_LOADING_SCREEN; // Opciones de la escena actual
#endif #endif
} // namespace SceneManager } // namespace SceneManager

View File

@@ -4,48 +4,48 @@
// Textos // Textos
namespace Texts { namespace Texts {
constexpr const char* WINDOW_CAPTION = "© 2022 JailDoctor's Dilemma — JailDesigner"; constexpr const char* WINDOW_CAPTION = "© 2022 JailDoctor's Dilemma — JailDesigner";
constexpr const char* COPYRIGHT = "@2022 JailDesigner"; constexpr const char* COPYRIGHT = "@2022 JailDesigner";
constexpr const char* VERSION = "1.10"; // Versión por defecto constexpr const char* VERSION = "1.10"; // Versión por defecto
} // namespace Texts } // namespace Texts
// Tamaño de bloque // Tamaño de bloque
namespace Tile { namespace Tile {
constexpr int SIZE = 8; constexpr int SIZE = 8;
constexpr int HALF_SIZE = SIZE / 2; constexpr int HALF_SIZE = SIZE / 2;
} // namespace Tile } // namespace Tile
namespace PlayArea { namespace PlayArea {
constexpr int TOP = (0 * Tile::SIZE); constexpr int TOP = (0 * Tile::SIZE);
constexpr int BOTTOM = (16 * Tile::SIZE); constexpr int BOTTOM = (16 * Tile::SIZE);
constexpr int LEFT = (0 * Tile::SIZE); constexpr int LEFT = (0 * Tile::SIZE);
constexpr int RIGHT = (32 * Tile::SIZE); constexpr int RIGHT = (32 * Tile::SIZE);
constexpr int WIDTH = RIGHT - LEFT; constexpr int WIDTH = RIGHT - LEFT;
constexpr int HEIGHT = BOTTOM - TOP; constexpr int HEIGHT = BOTTOM - TOP;
constexpr int CENTER_X = LEFT + (WIDTH / 2); constexpr int CENTER_X = LEFT + (WIDTH / 2);
constexpr int CENTER_FIRST_QUARTER_X = (WIDTH / 4); constexpr int CENTER_FIRST_QUARTER_X = (WIDTH / 4);
constexpr int CENTER_THIRD_QUARTER_X = (WIDTH / 4) * 3; constexpr int CENTER_THIRD_QUARTER_X = (WIDTH / 4) * 3;
constexpr int CENTER_Y = TOP + (HEIGHT / 2); constexpr int CENTER_Y = TOP + (HEIGHT / 2);
constexpr int FIRST_QUARTER_Y = HEIGHT / 4; constexpr int FIRST_QUARTER_Y = HEIGHT / 4;
constexpr int THIRD_QUARTER_Y = (HEIGHT / 4) * 3; constexpr int THIRD_QUARTER_Y = (HEIGHT / 4) * 3;
} // namespace PlayArea } // namespace PlayArea
namespace GameCanvas { namespace GameCanvas {
constexpr int WIDTH = 256; constexpr int WIDTH = 256;
constexpr int HEIGHT = 192; constexpr int HEIGHT = 192;
constexpr int CENTER_X = WIDTH / 2; constexpr int CENTER_X = WIDTH / 2;
constexpr int FIRST_QUARTER_X = WIDTH / 4; constexpr int FIRST_QUARTER_X = WIDTH / 4;
constexpr int THIRD_QUARTER_X = (WIDTH / 4) * 3; constexpr int THIRD_QUARTER_X = (WIDTH / 4) * 3;
constexpr int CENTER_Y = HEIGHT / 2; constexpr int CENTER_Y = HEIGHT / 2;
constexpr int FIRST_QUARTER_Y = HEIGHT / 4; constexpr int FIRST_QUARTER_Y = HEIGHT / 4;
constexpr int THIRD_QUARTER_Y = (HEIGHT / 4) * 3; constexpr int THIRD_QUARTER_Y = (HEIGHT / 4) * 3;
} // namespace GameCanvas } // namespace GameCanvas
namespace Collision { namespace Collision {
constexpr int NONE = -1; constexpr int NONE = -1;
} // namespace Collision } // namespace Collision
namespace Flip { namespace Flip {
constexpr SDL_FlipMode LEFT = SDL_FLIP_HORIZONTAL; constexpr SDL_FlipMode LEFT = SDL_FLIP_HORIZONTAL;
constexpr SDL_FlipMode RIGHT = SDL_FLIP_NONE; constexpr SDL_FlipMode RIGHT = SDL_FLIP_NONE;
} // namespace Flip } // namespace Flip

View File

@@ -22,110 +22,110 @@
namespace Easing { namespace Easing {
// LINEAR // LINEAR
inline auto linear(float t) -> float { inline auto linear(float t) -> float {
return t; return t;
} }
// QUAD (Cuadrática: t^2) // QUAD (Cuadrática: t^2)
inline auto quadIn(float t) -> float { inline auto quadIn(float t) -> float {
return t * t; return t * t;
} }
inline auto quadOut(float t) -> float { inline auto quadOut(float t) -> float {
return t * (2.0F - t); return t * (2.0F - t);
} }
inline auto quadInOut(float t) -> float { inline auto quadInOut(float t) -> float {
if (t < 0.5F) { if (t < 0.5F) {
return 2.0F * t * t; return 2.0F * t * t;
} }
return -1.0F + ((4.0F - 2.0F * t) * t); return -1.0F + ((4.0F - 2.0F * t) * t);
} }
// CUBIC (Cúbica: t^3) // CUBIC (Cúbica: t^3)
inline auto cubicIn(float t) -> float { inline auto cubicIn(float t) -> float {
return t * t * t; return t * t * t;
} }
inline auto cubicOut(float t) -> float { inline auto cubicOut(float t) -> float {
const float F = t - 1.0F; const float F = t - 1.0F;
return (F * F * F) + 1.0F; return (F * F * F) + 1.0F;
} }
inline auto cubicInOut(float t) -> float { inline auto cubicInOut(float t) -> float {
if (t < 0.5F) { if (t < 0.5F) {
return 4.0F * t * t * t; return 4.0F * t * t * t;
} }
const float F = ((2.0F * t) - 2.0F); const float F = ((2.0F * t) - 2.0F);
return (0.5F * F * F * F) + 1.0F; return (0.5F * F * F * F) + 1.0F;
} }
// QUART (Cuártica: t^4) // QUART (Cuártica: t^4)
inline auto quartIn(float t) -> float { inline auto quartIn(float t) -> float {
return t * t * t * t; return t * t * t * t;
} }
inline auto quartOut(float t) -> float { inline auto quartOut(float t) -> float {
const float F = t - 1.0F; const float F = t - 1.0F;
return 1.0F - (F * F * F * F); return 1.0F - (F * F * F * F);
} }
inline auto quartInOut(float t) -> float { inline auto quartInOut(float t) -> float {
if (t < 0.5F) { if (t < 0.5F) {
return 8.0F * t * t * t * t; return 8.0F * t * t * t * t;
} }
const float F = t - 1.0F; const float F = t - 1.0F;
return 1.0F - (8.0F * F * F * F * F); return 1.0F - (8.0F * F * F * F * F);
} }
// QUINT (Quíntica: t^5) // QUINT (Quíntica: t^5)
inline auto quintIn(float t) -> float { inline auto quintIn(float t) -> float {
return t * t * t * t * t; return t * t * t * t * t;
} }
inline auto quintOut(float t) -> float { inline auto quintOut(float t) -> float {
const float F = t - 1.0F; const float F = t - 1.0F;
return (F * F * F * F * F) + 1.0F; return (F * F * F * F * F) + 1.0F;
} }
inline auto quintInOut(float t) -> float { inline auto quintInOut(float t) -> float {
if (t < 0.5F) { if (t < 0.5F) {
return 16.0F * t * t * t * t * t; return 16.0F * t * t * t * t * t;
} }
const float F = ((2.0F * t) - 2.0F); const float F = ((2.0F * t) - 2.0F);
return (0.5F * F * F * F * F * F) + 1.0F; return (0.5F * F * F * F * F * F) + 1.0F;
} }
// SINE (Sinusoidal) // SINE (Sinusoidal)
inline auto sineIn(float t) -> float { inline auto sineIn(float t) -> float {
return 1.0F - std::cos(t * std::numbers::pi_v<float> * 0.5F); return 1.0F - std::cos(t * std::numbers::pi_v<float> * 0.5F);
} }
inline auto sineOut(float t) -> float { inline auto sineOut(float t) -> float {
return std::sin(t * std::numbers::pi_v<float> * 0.5F); return std::sin(t * std::numbers::pi_v<float> * 0.5F);
} }
inline auto sineInOut(float t) -> float { inline auto sineInOut(float t) -> float {
return 0.5F * (1.0F - std::cos(std::numbers::pi_v<float> * t)); return 0.5F * (1.0F - std::cos(std::numbers::pi_v<float> * t));
} }
// EXPO (Exponencial) // EXPO (Exponencial)
inline auto expoIn(float t) -> float { inline auto expoIn(float t) -> float {
if (t == 0.0F) { if (t == 0.0F) {
return 0.0F; return 0.0F;
} }
return std::pow(2.0F, 10.0F * (t - 1.0F)); return std::pow(2.0F, 10.0F * (t - 1.0F));
} }
inline auto expoOut(float t) -> float { inline auto expoOut(float t) -> float {
if (t == 1.0F) { if (t == 1.0F) {
return 1.0F; return 1.0F;
} }
return 1.0F - std::pow(2.0F, -10.0F * t); return 1.0F - std::pow(2.0F, -10.0F * t);
} }
inline auto expoInOut(float t) -> float { inline auto expoInOut(float t) -> float {
if (t == 0.0F || t == 1.0F) { if (t == 0.0F || t == 1.0F) {
return t; return t;
} }
@@ -134,37 +134,37 @@ inline auto expoInOut(float t) -> float {
return 0.5F * std::pow(2.0F, (20.0F * t) - 10.0F); return 0.5F * std::pow(2.0F, (20.0F * t) - 10.0F);
} }
return 0.5F * (2.0F - std::pow(2.0F, (-20.0F * t) + 10.0F)); return 0.5F * (2.0F - std::pow(2.0F, (-20.0F * t) + 10.0F));
} }
// CIRC (Circular) // CIRC (Circular)
inline auto circIn(float t) -> float { inline auto circIn(float t) -> float {
return 1.0F - std::sqrt(1.0F - (t * t)); return 1.0F - std::sqrt(1.0F - (t * t));
} }
inline auto circOut(float t) -> float { inline auto circOut(float t) -> float {
const float F = t - 1.0F; const float F = t - 1.0F;
return std::sqrt(1.0F - (F * F)); return std::sqrt(1.0F - (F * F));
} }
inline auto circInOut(float t) -> float { inline auto circInOut(float t) -> float {
if (t < 0.5F) { if (t < 0.5F) {
return 0.5F * (1.0F - std::sqrt(1.0F - (4.0F * t * t))); return 0.5F * (1.0F - std::sqrt(1.0F - (4.0F * t * t)));
} }
const float F = (2.0F * t) - 2.0F; const float F = (2.0F * t) - 2.0F;
return 0.5F * (std::sqrt(1.0F - (F * F)) + 1.0F); return 0.5F * (std::sqrt(1.0F - (F * F)) + 1.0F);
} }
// BACK (Overshoot - retrocede antes de avanzar) // BACK (Overshoot - retrocede antes de avanzar)
inline auto backIn(float t, float overshoot = 1.70158F) -> float { inline auto backIn(float t, float overshoot = 1.70158F) -> float {
return t * t * ((overshoot + 1.0F) * t - overshoot); return t * t * ((overshoot + 1.0F) * t - overshoot);
} }
inline auto backOut(float t, float overshoot = 1.70158F) -> float { inline auto backOut(float t, float overshoot = 1.70158F) -> float {
const float F = t - 1.0F; const float F = t - 1.0F;
return (F * F * ((overshoot + 1.0F) * F + overshoot)) + 1.0F; return (F * F * ((overshoot + 1.0F) * F + overshoot)) + 1.0F;
} }
inline auto backInOut(float t, float overshoot = 1.70158F) -> float { inline auto backInOut(float t, float overshoot = 1.70158F) -> float {
const float S = overshoot * 1.525F; const float S = overshoot * 1.525F;
if (t < 0.5F) { if (t < 0.5F) {
@@ -174,10 +174,10 @@ inline auto backInOut(float t, float overshoot = 1.70158F) -> float {
const float F = (2.0F * t) - 2.0F; const float F = (2.0F * t) - 2.0F;
return 0.5F * (F * F * ((S + 1.0F) * F + S) + 2.0F); return 0.5F * (F * F * ((S + 1.0F) * F + S) + 2.0F);
} }
// ELASTIC (Oscilación elástica - efecto de resorte) // ELASTIC (Oscilación elástica - efecto de resorte)
inline auto elasticIn(float t, float amplitude = 1.0F, float period = 0.3F) -> float { inline auto elasticIn(float t, float amplitude = 1.0F, float period = 0.3F) -> float {
if (t == 0.0F || t == 1.0F) { if (t == 0.0F || t == 1.0F) {
return t; return t;
} }
@@ -186,9 +186,9 @@ inline auto elasticIn(float t, float amplitude = 1.0F, float period = 0.3F) -> f
const float F = t - 1.0F; const float F = t - 1.0F;
return -(amplitude * std::pow(2.0F, 10.0F * F) * return -(amplitude * std::pow(2.0F, 10.0F * F) *
std::sin((F - S) * (2.0F * std::numbers::pi_v<float>) / period)); std::sin((F - S) * (2.0F * std::numbers::pi_v<float>) / period));
} }
inline auto elasticOut(float t, float amplitude = 1.0F, float period = 0.3F) -> float { inline auto elasticOut(float t, float amplitude = 1.0F, float period = 0.3F) -> float {
if (t == 0.0F || t == 1.0F) { if (t == 0.0F || t == 1.0F) {
return t; return t;
} }
@@ -197,9 +197,9 @@ inline auto elasticOut(float t, float amplitude = 1.0F, float period = 0.3F) ->
return (amplitude * std::pow(2.0F, -10.0F * t) * return (amplitude * std::pow(2.0F, -10.0F * t) *
std::sin((t - S) * (2.0F * std::numbers::pi_v<float>) / period)) + std::sin((t - S) * (2.0F * std::numbers::pi_v<float>) / period)) +
1.0F; 1.0F;
} }
inline auto elasticInOut(float t, float amplitude = 1.0F, float period = 0.3F) -> float { inline auto elasticInOut(float t, float amplitude = 1.0F, float period = 0.3F) -> float {
if (t == 0.0F || t == 1.0F) { if (t == 0.0F || t == 1.0F) {
return t; return t;
} }
@@ -215,10 +215,10 @@ inline auto elasticInOut(float t, float amplitude = 1.0F, float period = 0.3F) -
return (0.5F * amplitude * std::pow(2.0F, -10.0F * F) * return (0.5F * amplitude * std::pow(2.0F, -10.0F * F) *
std::sin((F - S) * (2.0F * std::numbers::pi_v<float>) / period)) + std::sin((F - S) * (2.0F * std::numbers::pi_v<float>) / period)) +
1.0F; 1.0F;
} }
// BOUNCE (Rebote - simula física de rebote) // BOUNCE (Rebote - simula física de rebote)
inline auto bounceOut(float t) -> float { inline auto bounceOut(float t) -> float {
const float N1 = 7.5625F; const float N1 = 7.5625F;
const float D1 = 2.75F; const float D1 = 2.75F;
@@ -235,17 +235,17 @@ inline auto bounceOut(float t) -> float {
} }
const float F = t - (2.625F / D1); const float F = t - (2.625F / D1);
return (N1 * F * F) + 0.984375F; return (N1 * F * F) + 0.984375F;
} }
inline auto bounceIn(float t) -> float { inline auto bounceIn(float t) -> float {
return 1.0F - bounceOut(1.0F - t); return 1.0F - bounceOut(1.0F - t);
} }
inline auto bounceInOut(float t) -> float { inline auto bounceInOut(float t) -> float {
if (t < 0.5F) { if (t < 0.5F) {
return 0.5F * bounceIn(2.0F * t); return 0.5F * bounceIn(2.0F * t);
} }
return (0.5F * bounceOut((2.0F * t) - 1.0F)) + 0.5F; return (0.5F * bounceOut((2.0F * t) - 1.0F)) + 0.5F;
} }
} // namespace Easing } // namespace Easing