clang-format
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
BasedOnStyle: Google
|
||||
IndentWidth: 4
|
||||
IndentAccessModifiers: true
|
||||
NamespaceIndentation: All
|
||||
IndentAccessModifiers: false
|
||||
ColumnLimit: 0 # Sin límite de longitud de línea
|
||||
BreakBeforeBraces: Attach # Llaves en la misma línea
|
||||
AllowShortIfStatementsOnASingleLine: true
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
|
||||
namespace GlobalInputs {
|
||||
|
||||
// Funciones internas
|
||||
namespace {
|
||||
void handleQuit() {
|
||||
// Funciones internas
|
||||
namespace {
|
||||
void handleQuit() {
|
||||
// En la escena GAME el comportamiento es siempre el mismo (con o sin modo kiosko)
|
||||
if (SceneManager::current == SceneManager::Scene::GAME) {
|
||||
const std::string CODE = "PRESS AGAIN TO RETURN TO MENU";
|
||||
@@ -49,9 +49,9 @@ void handleQuit() {
|
||||
} else {
|
||||
Notifier::get()->show({CODE}, Notifier::Style::DEFAULT, -1, true, CODE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handleSkipSection() {
|
||||
void handleSkipSection() {
|
||||
switch (SceneManager::current) {
|
||||
case SceneManager::Scene::LOGO:
|
||||
case SceneManager::Scene::LOADING_SCREEN:
|
||||
@@ -67,68 +67,68 @@ void handleSkipSection() {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handleToggleBorder() {
|
||||
void handleToggleBorder() {
|
||||
Screen::get()->toggleBorder();
|
||||
Notifier::get()->show({"BORDER " + std::string(Options::video.border.enabled ? "ENABLED" : "DISABLED")});
|
||||
}
|
||||
}
|
||||
|
||||
void handleToggleVideoMode() {
|
||||
void handleToggleVideoMode() {
|
||||
Screen::get()->toggleVideoMode();
|
||||
Notifier::get()->show({"FULLSCREEN " + std::string(static_cast<int>(Options::video.fullscreen) == 0 ? "DISABLED" : "ENABLED")});
|
||||
}
|
||||
}
|
||||
|
||||
void handleDecWindowZoom() {
|
||||
void handleDecWindowZoom() {
|
||||
if (Screen::get()->decWindowZoom()) {
|
||||
Notifier::get()->show({"WINDOW ZOOM x" + std::to_string(Options::window.zoom)});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handleIncWindowZoom() {
|
||||
void handleIncWindowZoom() {
|
||||
if (Screen::get()->incWindowZoom()) {
|
||||
Notifier::get()->show({"WINDOW ZOOM x" + std::to_string(Options::window.zoom)});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handleTogglePostFX() {
|
||||
void handleTogglePostFX() {
|
||||
Screen::get()->togglePostFX();
|
||||
Notifier::get()->show({"POSTFX " + std::string(Options::video.postfx ? "ENABLED" : "DISABLED")});
|
||||
}
|
||||
}
|
||||
|
||||
void handleNextPostFXPreset() {
|
||||
void handleNextPostFXPreset() {
|
||||
if (!Options::postfx_presets.empty()) {
|
||||
Options::current_postfx_preset = (Options::current_postfx_preset + 1) % static_cast<int>(Options::postfx_presets.size());
|
||||
Screen::get()->reloadPostFX();
|
||||
Notifier::get()->show({"POSTFX " + Options::postfx_presets[static_cast<size_t>(Options::current_postfx_preset)].name});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handleNextPalette() {
|
||||
void handleNextPalette() {
|
||||
Screen::get()->nextPalette();
|
||||
Notifier::get()->show({"PALETTE " + Options::video.palette});
|
||||
}
|
||||
}
|
||||
|
||||
void handlePreviousPalette() {
|
||||
void handlePreviousPalette() {
|
||||
Screen::get()->previousPalette();
|
||||
Notifier::get()->show({"PALETTE " + Options::video.palette});
|
||||
}
|
||||
}
|
||||
|
||||
void handleToggleIntegerScale() {
|
||||
void handleToggleIntegerScale() {
|
||||
Screen::get()->toggleIntegerScale();
|
||||
Screen::get()->setVideoMode(Options::video.fullscreen);
|
||||
Notifier::get()->show({"INTEGER SCALE " + std::string(Options::video.integer_scale ? "ENABLED" : "DISABLED")});
|
||||
}
|
||||
}
|
||||
|
||||
void handleToggleVSync() {
|
||||
void handleToggleVSync() {
|
||||
Screen::get()->toggleVSync();
|
||||
Notifier::get()->show({"V-SYNC " + std::string(Options::video.vertical_sync ? "ENABLED" : "DISABLED")});
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
void handleShowDebugInfo() {
|
||||
void handleShowDebugInfo() {
|
||||
Screen::get()->toggleDebugInfo();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void handleToggleDebug() {
|
||||
@@ -138,8 +138,8 @@ void handleToggleDebug() {
|
||||
*/
|
||||
#endif
|
||||
|
||||
// Detecta qué acción global ha sido presionada (si alguna)
|
||||
auto getPressedAction() -> InputAction {
|
||||
// Detecta qué acción global ha sido presionada (si alguna)
|
||||
auto getPressedAction() -> InputAction {
|
||||
if (Input::get()->checkAction(InputAction::EXIT, Input::DO_NOT_ALLOW_REPEAT)) {
|
||||
return InputAction::EXIT;
|
||||
}
|
||||
@@ -185,14 +185,14 @@ auto getPressedAction() -> InputAction {
|
||||
return InputAction::SHOW_DEBUG_INFO;
|
||||
}
|
||||
return InputAction::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
// Funciones públicas
|
||||
// Funciones públicas
|
||||
|
||||
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
|
||||
void handle() {
|
||||
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
|
||||
void handle() {
|
||||
// Salida de administrador en modo kiosko (Ctrl+Shift+Alt+Q)
|
||||
if (Options::kiosk.enabled) {
|
||||
SDL_Keymod mod = SDL_GetModState();
|
||||
@@ -271,5 +271,5 @@ void handle() {
|
||||
// No se presionó ninguna acción global
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace GlobalInputs
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
namespace GlobalInputs {
|
||||
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
|
||||
void handle();
|
||||
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
|
||||
void handle();
|
||||
} // namespace GlobalInputs
|
||||
@@ -1,11 +1,11 @@
|
||||
#include "core/input/mouse.hpp"
|
||||
|
||||
namespace Mouse {
|
||||
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ó
|
||||
bool cursor_visible = true; // Estado del 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ó
|
||||
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) {
|
||||
last_mouse_move_time = SDL_GetTicks();
|
||||
if (!cursor_visible) {
|
||||
@@ -13,13 +13,13 @@ void handleEvent(const SDL_Event& event) {
|
||||
cursor_visible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateCursorVisibility() {
|
||||
void updateCursorVisibility() {
|
||||
Uint32 current_time = SDL_GetTicks();
|
||||
if (cursor_visible && (current_time - last_mouse_move_time > cursor_hide_time)) {
|
||||
SDL_HideCursor();
|
||||
cursor_visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace Mouse
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
namespace Mouse {
|
||||
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 bool cursor_visible; // Estado del 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 bool cursor_visible; // Estado del cursor
|
||||
|
||||
void handleEvent(const SDL_Event& event);
|
||||
void updateCursorVisibility();
|
||||
void handleEvent(const SDL_Event& event);
|
||||
void updateCursorVisibility();
|
||||
} // namespace Mouse
|
||||
@@ -7,15 +7,15 @@
|
||||
|
||||
namespace GIF {
|
||||
|
||||
// Función inline para reemplazar el macro READ.
|
||||
// Actualiza el puntero 'buffer' tras copiar 'size' bytes a 'dst'.
|
||||
inline void readBytes(const uint8_t*& buffer, void* dst, size_t size) {
|
||||
// Función inline para reemplazar el macro READ.
|
||||
// Actualiza el puntero 'buffer' tras copiar 'size' bytes a 'dst'.
|
||||
inline void readBytes(const uint8_t*& buffer, void* dst, size_t size) {
|
||||
std::memcpy(dst, buffer, size);
|
||||
buffer += size;
|
||||
}
|
||||
}
|
||||
|
||||
// Inicializa el diccionario LZW con los valores iniciales
|
||||
inline void initializeDictionary(std::vector<DictionaryEntry>& dictionary, int code_length, int& dictionary_ind) {
|
||||
// Inicializa el diccionario LZW con los valores iniciales
|
||||
inline void initializeDictionary(std::vector<DictionaryEntry>& dictionary, int code_length, int& dictionary_ind) {
|
||||
int size = 1 << code_length;
|
||||
dictionary.resize(1 << (code_length + 1));
|
||||
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_ind += 2; // Reservamos espacio para clear y stop codes
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// 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 {
|
||||
int code = 0;
|
||||
for (int i = 0; i < (code_length + 1); i++) {
|
||||
if (input_length <= 0) {
|
||||
@@ -43,19 +43,19 @@ inline auto readNextCode(const uint8_t*& input, int& input_length, unsigned int&
|
||||
code |= (bit << i);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
// Encuentra el primer byte de una cadena del diccionario
|
||||
inline auto findFirstByte(const std::vector<DictionaryEntry>& dictionary, int code) -> uint8_t {
|
||||
// Encuentra el primer byte de una cadena del diccionario
|
||||
inline auto findFirstByte(const std::vector<DictionaryEntry>& dictionary, int code) -> uint8_t {
|
||||
int ptr = code;
|
||||
while (dictionary[ptr].prev != -1) {
|
||||
ptr = dictionary[ptr].prev;
|
||||
}
|
||||
return dictionary[ptr].byte;
|
||||
}
|
||||
}
|
||||
|
||||
// Agrega una nueva entrada al diccionario
|
||||
inline void addDictionaryEntry(std::vector<DictionaryEntry>& dictionary, int& dictionary_ind, int& code_length, int prev, int code) {
|
||||
// Agrega una nueva entrada al diccionario
|
||||
inline void addDictionaryEntry(std::vector<DictionaryEntry>& dictionary, int& dictionary_ind, int& code_length, int prev, int code) {
|
||||
uint8_t first_byte;
|
||||
if (code == dictionary_ind) {
|
||||
first_byte = findFirstByte(dictionary, prev);
|
||||
@@ -72,10 +72,10 @@ inline void addDictionaryEntry(std::vector<DictionaryEntry>& dictionary, int& di
|
||||
code_length++;
|
||||
dictionary.resize(1 << (code_length + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Escribe la cadena decodificada al buffer de salida
|
||||
inline auto writeDecodedString(const std::vector<DictionaryEntry>& dictionary, int code, uint8_t*& out) -> int {
|
||||
// Escribe la cadena decodificada al buffer de salida
|
||||
inline auto writeDecodedString(const std::vector<DictionaryEntry>& dictionary, int code, uint8_t*& out) -> int {
|
||||
int cur_code = code;
|
||||
int match_len = dictionary[cur_code].len;
|
||||
while (cur_code != -1) {
|
||||
@@ -88,9 +88,9 @@ inline auto writeDecodedString(const std::vector<DictionaryEntry>& dictionary, i
|
||||
}
|
||||
out += 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.
|
||||
if (code_length < 2 || code_length > 12) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
uint8_t block_size = *buffer;
|
||||
buffer++;
|
||||
@@ -157,9 +157,9 @@ auto Gif::readSubBlocks(const uint8_t*& buffer) -> std::vector<uint8_t> {
|
||||
buffer++;
|
||||
}
|
||||
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;
|
||||
// Lee 9 bytes para el image descriptor.
|
||||
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());
|
||||
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];
|
||||
std::memcpy(header, buffer, 6);
|
||||
buffer += 6;
|
||||
@@ -197,9 +197,9 @@ auto Gif::loadPalette(const uint8_t* buffer) -> std::vector<uint32_t> {
|
||||
}
|
||||
}
|
||||
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")
|
||||
uint8_t header[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>{};
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace GIF
|
||||
|
||||
@@ -5,66 +5,66 @@
|
||||
|
||||
namespace GIF {
|
||||
|
||||
// Constantes definidas con constexpr, en lugar de macros
|
||||
constexpr uint8_t EXTENSION_INTRODUCER = 0x21;
|
||||
constexpr uint8_t IMAGE_DESCRIPTOR = 0x2C;
|
||||
constexpr uint8_t TRAILER = 0x3B;
|
||||
constexpr uint8_t GRAPHIC_CONTROL = 0xF9;
|
||||
constexpr uint8_t APPLICATION_EXTENSION = 0xFF;
|
||||
constexpr uint8_t COMMENT_EXTENSION = 0xFE;
|
||||
constexpr uint8_t PLAINTEXT_EXTENSION = 0x01;
|
||||
// Constantes definidas con constexpr, en lugar de macros
|
||||
constexpr uint8_t EXTENSION_INTRODUCER = 0x21;
|
||||
constexpr uint8_t IMAGE_DESCRIPTOR = 0x2C;
|
||||
constexpr uint8_t TRAILER = 0x3B;
|
||||
constexpr uint8_t GRAPHIC_CONTROL = 0xF9;
|
||||
constexpr uint8_t APPLICATION_EXTENSION = 0xFF;
|
||||
constexpr uint8_t COMMENT_EXTENSION = 0xFE;
|
||||
constexpr uint8_t PLAINTEXT_EXTENSION = 0x01;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct ScreenDescriptor {
|
||||
struct ScreenDescriptor {
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
uint8_t fields;
|
||||
uint8_t background_color_index;
|
||||
uint8_t pixel_aspect_ratio;
|
||||
};
|
||||
};
|
||||
|
||||
struct RGB {
|
||||
struct RGB {
|
||||
uint8_t r, g, b;
|
||||
};
|
||||
};
|
||||
|
||||
struct ImageDescriptor {
|
||||
struct ImageDescriptor {
|
||||
uint16_t image_left_position;
|
||||
uint16_t image_top_position;
|
||||
uint16_t image_width;
|
||||
uint16_t image_height;
|
||||
uint8_t fields;
|
||||
};
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
struct DictionaryEntry {
|
||||
struct DictionaryEntry {
|
||||
uint8_t byte;
|
||||
int prev;
|
||||
int len;
|
||||
};
|
||||
};
|
||||
|
||||
struct Extension {
|
||||
struct Extension {
|
||||
uint8_t extension_code;
|
||||
uint8_t block_size;
|
||||
};
|
||||
};
|
||||
|
||||
struct GraphicControlExtension {
|
||||
struct GraphicControlExtension {
|
||||
uint8_t fields;
|
||||
uint16_t delay_time;
|
||||
uint8_t transparent_color_index;
|
||||
};
|
||||
};
|
||||
|
||||
struct ApplicationExtension {
|
||||
struct ApplicationExtension {
|
||||
uint8_t application_id[8];
|
||||
uint8_t version[3];
|
||||
};
|
||||
};
|
||||
|
||||
struct PlaintextExtension {
|
||||
struct PlaintextExtension {
|
||||
uint16_t left, top, width, height;
|
||||
uint8_t cell_width, cell_height;
|
||||
uint8_t foreground_color, background_color;
|
||||
};
|
||||
};
|
||||
|
||||
class Gif {
|
||||
class Gif {
|
||||
public:
|
||||
// Descompone (uncompress) el bloque comprimido usando LZW.
|
||||
// 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.
|
||||
static auto processGifStream(const uint8_t* buffer, uint16_t& w, uint16_t& h) -> std::vector<uint8_t>;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace GIF
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
class Surface;
|
||||
class Text;
|
||||
namespace Rendering {
|
||||
class ShaderBackend;
|
||||
class ShaderBackend;
|
||||
}
|
||||
|
||||
class Screen {
|
||||
|
||||
@@ -162,17 +162,17 @@ fragment float4 postfx_fs(PostVOut in [[stage_in]],
|
||||
|
||||
namespace Rendering {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Destructor
|
||||
// ---------------------------------------------------------------------------
|
||||
SDL3GPUShader::~SDL3GPUShader() {
|
||||
// ---------------------------------------------------------------------------
|
||||
// Destructor
|
||||
// ---------------------------------------------------------------------------
|
||||
SDL3GPUShader::~SDL3GPUShader() {
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// init
|
||||
// ---------------------------------------------------------------------------
|
||||
auto SDL3GPUShader::init(SDL_Window* window,
|
||||
// ---------------------------------------------------------------------------
|
||||
// init
|
||||
// ---------------------------------------------------------------------------
|
||||
auto SDL3GPUShader::init(SDL_Window* window,
|
||||
SDL_Texture* texture,
|
||||
const std::string& /*vertex_source*/,
|
||||
const std::string& /*fragment_source*/) -> bool {
|
||||
@@ -281,12 +281,12 @@ auto SDL3GPUShader::init(SDL_Window* window,
|
||||
is_initialized_ = true;
|
||||
SDL_Log("SDL3GPUShader: initialized OK (%dx%d)", tex_width_, tex_height_);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// createPipeline
|
||||
// ---------------------------------------------------------------------------
|
||||
auto SDL3GPUShader::createPipeline() -> bool {
|
||||
// ---------------------------------------------------------------------------
|
||||
// createPipeline
|
||||
// ---------------------------------------------------------------------------
|
||||
auto SDL3GPUShader::createPipeline() -> bool {
|
||||
const SDL_GPUTextureFormat SWAPCHAIN_FMT = SDL_GetGPUSwapchainTextureFormat(device_, window_);
|
||||
|
||||
#ifdef __APPLE__
|
||||
@@ -332,12 +332,12 @@ auto SDL3GPUShader::createPipeline() -> bool {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// uploadPixels — copies ARGB8888 CPU pixels into the GPU transfer buffer
|
||||
// ---------------------------------------------------------------------------
|
||||
void SDL3GPUShader::uploadPixels(const Uint32* pixels, int width, int height) {
|
||||
// ---------------------------------------------------------------------------
|
||||
// uploadPixels — copies ARGB8888 CPU pixels into the GPU transfer buffer
|
||||
// ---------------------------------------------------------------------------
|
||||
void SDL3GPUShader::uploadPixels(const Uint32* pixels, int width, int height) {
|
||||
if (!is_initialized_ || (upload_buffer_ == nullptr)) { return; }
|
||||
|
||||
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));
|
||||
SDL_UnmapGPUTransferBuffer(device_, upload_buffer_);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// render — upload scene texture + PostFX pass → swapchain
|
||||
// ---------------------------------------------------------------------------
|
||||
void SDL3GPUShader::render() {
|
||||
// ---------------------------------------------------------------------------
|
||||
// render — upload scene texture + PostFX pass → swapchain
|
||||
// ---------------------------------------------------------------------------
|
||||
void SDL3GPUShader::render() {
|
||||
if (!is_initialized_) { return; }
|
||||
|
||||
SDL_GPUCommandBuffer* cmd = SDL_AcquireGPUCommandBuffer(device_);
|
||||
@@ -439,12 +439,12 @@ void SDL3GPUShader::render() {
|
||||
}
|
||||
|
||||
SDL_SubmitGPUCommandBuffer(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// cleanup — libera pipeline/texturas/buffer pero mantiene device + swapchain
|
||||
// ---------------------------------------------------------------------------
|
||||
void SDL3GPUShader::cleanup() {
|
||||
// ---------------------------------------------------------------------------
|
||||
// cleanup — libera pipeline/texturas/buffer pero mantiene device + swapchain
|
||||
// ---------------------------------------------------------------------------
|
||||
void SDL3GPUShader::cleanup() {
|
||||
is_initialized_ = false;
|
||||
|
||||
if (device_ != nullptr) {
|
||||
@@ -468,12 +468,12 @@ void SDL3GPUShader::cleanup() {
|
||||
}
|
||||
// device_ y el claim de la ventana se mantienen vivos
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// destroy — limpieza completa incluyendo device y swapchain (solo al cerrar)
|
||||
// ---------------------------------------------------------------------------
|
||||
void SDL3GPUShader::destroy() {
|
||||
// ---------------------------------------------------------------------------
|
||||
// destroy — limpieza completa incluyendo device y swapchain (solo al cerrar)
|
||||
// ---------------------------------------------------------------------------
|
||||
void SDL3GPUShader::destroy() {
|
||||
cleanup();
|
||||
|
||||
if (device_ != nullptr) {
|
||||
@@ -484,12 +484,12 @@ void SDL3GPUShader::destroy() {
|
||||
device_ = nullptr;
|
||||
}
|
||||
window_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Shader creation helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
auto SDL3GPUShader::createShaderMSL(SDL_GPUDevice* device,
|
||||
// ---------------------------------------------------------------------------
|
||||
// Shader creation helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
auto SDL3GPUShader::createShaderMSL(SDL_GPUDevice* device,
|
||||
const char* msl_source,
|
||||
const char* entrypoint,
|
||||
SDL_GPUShaderStage stage,
|
||||
@@ -508,9 +508,9 @@ auto SDL3GPUShader::createShaderMSL(SDL_GPUDevice* device,
|
||||
SDL_Log("SDL3GPUShader: MSL shader '%s' failed: %s", entrypoint, SDL_GetError());
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
}
|
||||
|
||||
auto SDL3GPUShader::createShaderSPIRV(SDL_GPUDevice* device,
|
||||
auto SDL3GPUShader::createShaderSPIRV(SDL_GPUDevice* device,
|
||||
const uint8_t* spv_code,
|
||||
size_t spv_size,
|
||||
const char* entrypoint,
|
||||
@@ -530,9 +530,9 @@ auto SDL3GPUShader::createShaderSPIRV(SDL_GPUDevice* device,
|
||||
SDL_Log("SDL3GPUShader: SPIRV shader '%s' failed: %s", entrypoint, SDL_GetError());
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL3GPUShader::setPostFXParams(const PostFXParams& p) {
|
||||
void SDL3GPUShader::setPostFXParams(const PostFXParams& p) {
|
||||
uniforms_.vignette_strength = p.vignette;
|
||||
uniforms_.scanline_strength = p.scanlines;
|
||||
uniforms_.chroma_strength = p.chroma;
|
||||
@@ -540,17 +540,17 @@ void SDL3GPUShader::setPostFXParams(const PostFXParams& p) {
|
||||
uniforms_.gamma_strength = p.gamma;
|
||||
uniforms_.curvature = p.curvature;
|
||||
uniforms_.bleeding = p.bleeding;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL3GPUShader::setVSync(bool vsync) {
|
||||
void SDL3GPUShader::setVSync(bool vsync) {
|
||||
vsync_ = vsync;
|
||||
if (device_ != nullptr && window_ != nullptr) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Rendering
|
||||
|
||||
@@ -21,14 +21,14 @@ struct PostFXUniforms {
|
||||
|
||||
namespace Rendering {
|
||||
|
||||
/**
|
||||
/**
|
||||
* @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.
|
||||
* Pipeline: Surface pixels (CPU) → SDL_GPUTransferBuffer → SDL_GPUTexture (scene)
|
||||
* → PostFX render pass → swapchain → present
|
||||
*/
|
||||
class SDL3GPUShader : public ShaderBackend {
|
||||
class SDL3GPUShader : public ShaderBackend {
|
||||
public:
|
||||
SDL3GPUShader() = default;
|
||||
~SDL3GPUShader() override;
|
||||
@@ -88,6 +88,6 @@ class SDL3GPUShader : public ShaderBackend {
|
||||
bool is_initialized_ = false;
|
||||
bool vsync_ = true;
|
||||
bool integer_scale_ = false;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace Rendering
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
|
||||
namespace Rendering {
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Parámetros de intensidad de los efectos PostFX
|
||||
* 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 scanlines = 0.0F; // Intensidad de las scanlines
|
||||
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 curvature = 0.0F; // Curvatura barrel CRT
|
||||
float bleeding = 0.0F; // Sangrado de color NTSC
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Interfaz abstracta para backends de renderizado con shaders
|
||||
*
|
||||
* Esta interfaz define el contrato que todos los backends de shaders
|
||||
* deben cumplir (OpenGL, Metal, Vulkan, etc.)
|
||||
*/
|
||||
class ShaderBackend {
|
||||
class ShaderBackend {
|
||||
public:
|
||||
virtual ~ShaderBackend() = default;
|
||||
|
||||
@@ -87,6 +87,6 @@ class ShaderBackend {
|
||||
* @return true si usa aceleración (OpenGL/Metal/Vulkan)
|
||||
*/
|
||||
[[nodiscard]] virtual auto isHardwareAccelerated() const -> bool = 0;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace Rendering
|
||||
|
||||
@@ -24,26 +24,26 @@ struct JA_Sound_t; // lines 18-18
|
||||
|
||||
namespace Resource {
|
||||
|
||||
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
|
||||
Cache* Cache::cache = nullptr;
|
||||
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
|
||||
Cache* Cache::cache = nullptr;
|
||||
|
||||
// [SINGLETON] Crearemos el objeto cache con esta función estática
|
||||
void Cache::init() { Cache::cache = new Cache(); }
|
||||
// [SINGLETON] Crearemos el objeto cache con esta función estática
|
||||
void Cache::init() { Cache::cache = new Cache(); }
|
||||
|
||||
// [SINGLETON] Destruiremos el objeto cache con esta función estática
|
||||
void Cache::destroy() { delete Cache::cache; }
|
||||
// [SINGLETON] Destruiremos el objeto cache con esta función estática
|
||||
void Cache::destroy() { delete Cache::cache; }
|
||||
|
||||
// [SINGLETON] Con este método obtenemos el objeto cache y podemos trabajar con él
|
||||
auto Cache::get() -> Cache* { return Cache::cache; }
|
||||
// [SINGLETON] Con este método obtenemos el objeto cache y podemos trabajar con él
|
||||
auto Cache::get() -> Cache* { return Cache::cache; }
|
||||
|
||||
// Constructor
|
||||
Cache::Cache()
|
||||
// Constructor
|
||||
Cache::Cache()
|
||||
: loading_text_(Screen::get()->getText()) {
|
||||
load();
|
||||
}
|
||||
}
|
||||
|
||||
// Vacia todos los vectores de recursos
|
||||
void Cache::clear() {
|
||||
// Vacia todos los vectores de recursos
|
||||
void Cache::clear() {
|
||||
clearSounds();
|
||||
clearMusics();
|
||||
surfaces_.clear();
|
||||
@@ -51,10 +51,10 @@ void Cache::clear() {
|
||||
text_files_.clear();
|
||||
texts_.clear();
|
||||
animations_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Carga todos los recursos
|
||||
void Cache::load() {
|
||||
// Carga todos los recursos
|
||||
void Cache::load() {
|
||||
calculateTotal();
|
||||
Screen::get()->setBorderColor(static_cast<Uint8>(PaletteColor::BLACK));
|
||||
std::cout << "\n** LOADING RESOURCES" << '\n';
|
||||
@@ -67,16 +67,16 @@ void Cache::load() {
|
||||
loadRooms();
|
||||
createText();
|
||||
std::cout << "\n** RESOURCES LOADED" << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
// Recarga todos los recursos
|
||||
void Cache::reload() {
|
||||
// Recarga todos los recursos
|
||||
void Cache::reload() {
|
||||
clear();
|
||||
load();
|
||||
}
|
||||
}
|
||||
|
||||
// Obtiene el sonido a partir de un nombre
|
||||
auto Cache::getSound(const std::string& name) -> JA_Sound_t* {
|
||||
// Obtiene el sonido a partir de un nombre
|
||||
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; });
|
||||
|
||||
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';
|
||||
throw std::runtime_error("Sonido no encontrado: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
// Obtiene la música a partir de un nombre
|
||||
auto Cache::getMusic(const std::string& name) -> JA_Music_t* {
|
||||
// Obtiene la música a partir de un nombre
|
||||
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; });
|
||||
|
||||
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';
|
||||
throw std::runtime_error("Música no encontrada: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
// Obtiene la surface a partir de un nombre
|
||||
auto Cache::getSurface(const std::string& name) -> std::shared_ptr<Surface> {
|
||||
// Obtiene la surface a partir de un nombre
|
||||
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; });
|
||||
|
||||
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';
|
||||
throw std::runtime_error("Imagen no encontrada: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
// Obtiene la paleta a partir de un nombre
|
||||
auto Cache::getPalette(const std::string& name) -> Palette {
|
||||
// Obtiene la paleta a partir de un nombre
|
||||
auto Cache::getPalette(const std::string& name) -> Palette {
|
||||
auto it = std::ranges::find_if(palettes_, [&name](const auto& t) { return t.name == name; });
|
||||
|
||||
if (it != palettes_.end()) {
|
||||
@@ -121,10 +121,10 @@ auto Cache::getPalette(const std::string& name) -> Palette {
|
||||
|
||||
std::cerr << "Error: Paleta no encontrada " << name << '\n';
|
||||
throw std::runtime_error("Paleta no encontrada: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
// Obtiene el fichero de texto a partir de un nombre
|
||||
auto Cache::getTextFile(const std::string& name) -> std::shared_ptr<Text::File> {
|
||||
// Obtiene el fichero de texto a partir de un nombre
|
||||
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; });
|
||||
|
||||
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';
|
||||
throw std::runtime_error("TextFile no encontrado: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
// Obtiene el objeto de texto a partir de un nombre
|
||||
auto Cache::getText(const std::string& name) -> std::shared_ptr<Text> {
|
||||
// Obtiene el objeto de texto a partir de un nombre
|
||||
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; });
|
||||
|
||||
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';
|
||||
throw std::runtime_error("Texto no encontrado: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
// Obtiene los datos de animación parseados a partir de un nombre
|
||||
auto Cache::getAnimationData(const std::string& name) -> const AnimationResource& {
|
||||
// Obtiene los datos de animación parseados a partir de un nombre
|
||||
auto Cache::getAnimationData(const std::string& name) -> const AnimationResource& {
|
||||
auto it = std::ranges::find_if(animations_, [&name](const auto& a) { return a.name == name; });
|
||||
|
||||
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';
|
||||
throw std::runtime_error("Animación no encontrada: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
// Obtiene la habitación a partir de un nombre
|
||||
auto Cache::getRoom(const std::string& name) -> std::shared_ptr<Room::Data> {
|
||||
// Obtiene la habitación a partir de un nombre
|
||||
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; });
|
||||
|
||||
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';
|
||||
throw std::runtime_error("Habitación no encontrada: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
// Obtiene todas las habitaciones
|
||||
auto Cache::getRooms() -> std::vector<RoomResource>& {
|
||||
// Obtiene todas las habitaciones
|
||||
auto Cache::getRooms() -> std::vector<RoomResource>& {
|
||||
return rooms_;
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
// 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) {
|
||||
std::cerr << "\n[ ERROR ] Failed to load " << asset_type << ": " << getFileName(file_path) << '\n';
|
||||
std::cerr << "[ ERROR ] Path: " << file_path << '\n';
|
||||
std::cerr << "[ ERROR ] Reason: " << e.what() << '\n';
|
||||
std::cerr << "[ ERROR ] Check config/assets.yaml configuration\n";
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// Carga los sonidos
|
||||
void Cache::loadSounds() {
|
||||
// Carga los sonidos
|
||||
void Cache::loadSounds() {
|
||||
std::cout << "\n>> SOUND FILES" << '\n';
|
||||
auto list = List::get()->getListByType(List::Type::SOUND);
|
||||
sounds_.clear();
|
||||
@@ -218,10 +218,10 @@ void Cache::loadSounds() {
|
||||
throwLoadError("SOUND", l, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Carga las musicas
|
||||
void Cache::loadMusics() {
|
||||
// Carga las musicas
|
||||
void Cache::loadMusics() {
|
||||
std::cout << "\n>> MUSIC FILES" << '\n';
|
||||
auto list = List::get()->getListByType(List::Type::MUSIC);
|
||||
musics_.clear();
|
||||
@@ -253,10 +253,10 @@ void Cache::loadMusics() {
|
||||
throwLoadError("MUSIC", l, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Carga las texturas
|
||||
void Cache::loadSurfaces() {
|
||||
// Carga las texturas
|
||||
void Cache::loadSurfaces() {
|
||||
std::cout << "\n>> SURFACES" << '\n';
|
||||
auto list = List::get()->getListByType(List::Type::BITMAP);
|
||||
surfaces_.clear();
|
||||
@@ -280,10 +280,10 @@ void Cache::loadSurfaces() {
|
||||
getSurface("ending4.gif")->setTransparentColor();
|
||||
getSurface("ending5.gif")->setTransparentColor();
|
||||
getSurface("standard.gif")->setTransparentColor(16);
|
||||
}
|
||||
}
|
||||
|
||||
// Carga las paletas
|
||||
void Cache::loadPalettes() {
|
||||
// Carga las paletas
|
||||
void Cache::loadPalettes() {
|
||||
std::cout << "\n>> PALETTES" << '\n';
|
||||
auto list = List::get()->getListByType(List::Type::PALETTE);
|
||||
palettes_.clear();
|
||||
@@ -297,10 +297,10 @@ void Cache::loadPalettes() {
|
||||
throwLoadError("PALETTE", l, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Carga los ficheros de texto
|
||||
void Cache::loadTextFiles() {
|
||||
// Carga los ficheros de texto
|
||||
void Cache::loadTextFiles() {
|
||||
std::cout << "\n>> TEXT FILES" << '\n';
|
||||
auto list = List::get()->getListByType(List::Type::FONT);
|
||||
text_files_.clear();
|
||||
@@ -314,10 +314,10 @@ void Cache::loadTextFiles() {
|
||||
throwLoadError("FONT", l, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Carga las animaciones
|
||||
void Cache::loadAnimations() {
|
||||
// Carga las animaciones
|
||||
void Cache::loadAnimations() {
|
||||
std::cout << "\n>> ANIMATIONS" << '\n';
|
||||
auto list = List::get()->getListByType(List::Type::ANIMATION);
|
||||
animations_.clear();
|
||||
@@ -340,10 +340,10 @@ void Cache::loadAnimations() {
|
||||
throwLoadError("ANIMATION", l, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Carga las habitaciones desde archivos YAML
|
||||
void Cache::loadRooms() {
|
||||
// Carga las habitaciones desde archivos YAML
|
||||
void Cache::loadRooms() {
|
||||
std::cout << "\n>> ROOMS" << '\n';
|
||||
auto list = List::get()->getListByType(List::Type::ROOM);
|
||||
rooms_.clear();
|
||||
@@ -358,9 +358,9 @@ void Cache::loadRooms() {
|
||||
throwLoadError("ROOM", l, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cache::createText() {
|
||||
void Cache::createText() {
|
||||
struct ResourceInfo {
|
||||
std::string key; // Identificador del recurso
|
||||
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))});
|
||||
printWithDots("Text : ", res_info.key, "[ DONE ]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Vacía el vector de sonidos
|
||||
void Cache::clearSounds() {
|
||||
// Vacía el vector de sonidos
|
||||
void Cache::clearSounds() {
|
||||
// Itera sobre el vector y libera los recursos asociados a cada JA_Sound_t
|
||||
for (auto& sound : sounds_) {
|
||||
if (sound.sound != nullptr) {
|
||||
@@ -392,10 +392,10 @@ void Cache::clearSounds() {
|
||||
}
|
||||
}
|
||||
sounds_.clear(); // Limpia el vector después de liberar todos los recursos
|
||||
}
|
||||
}
|
||||
|
||||
// Vacía el vector de musicas
|
||||
void Cache::clearMusics() {
|
||||
// Vacía el vector de musicas
|
||||
void Cache::clearMusics() {
|
||||
// Itera sobre el vector y libera los recursos asociados a cada JA_Music_t
|
||||
for (auto& music : musics_) {
|
||||
if (music.music != nullptr) {
|
||||
@@ -404,10 +404,10 @@ void Cache::clearMusics() {
|
||||
}
|
||||
}
|
||||
musics_.clear(); // Limpia el vector después de liberar todos los recursos
|
||||
}
|
||||
}
|
||||
|
||||
// Calcula el numero de recursos para cargar
|
||||
void Cache::calculateTotal() {
|
||||
// Calcula el numero de recursos para cargar
|
||||
void Cache::calculateTotal() {
|
||||
std::vector<List::Type> asset_types = {
|
||||
List::Type::SOUND,
|
||||
List::Type::MUSIC,
|
||||
@@ -424,10 +424,10 @@ void Cache::calculateTotal() {
|
||||
}
|
||||
|
||||
count_ = ResourceCount{.total = total, .loaded = 0};
|
||||
}
|
||||
}
|
||||
|
||||
// Muestra el progreso de carga
|
||||
void Cache::renderProgress() {
|
||||
// Muestra el progreso de carga
|
||||
void Cache::renderProgress() {
|
||||
constexpr float X_PADDING = 60.0F;
|
||||
constexpr float Y_PADDING = 10.0F;
|
||||
constexpr float BAR_HEIGHT = 5.0F;
|
||||
@@ -470,10 +470,10 @@ void Cache::renderProgress() {
|
||||
surface->fillRect(&rect_full, BAR_COLOR);
|
||||
|
||||
Screen::get()->render();
|
||||
}
|
||||
}
|
||||
|
||||
// Comprueba los eventos de la pantalla de carga
|
||||
void Cache::checkEvents() {
|
||||
// Comprueba los eventos de la pantalla de carga
|
||||
void Cache::checkEvents() {
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
@@ -487,15 +487,15 @@ void Cache::checkEvents() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Actualiza el progreso de carga
|
||||
void Cache::updateLoadingProgress(int steps) {
|
||||
// Actualiza el progreso de carga
|
||||
void Cache::updateLoadingProgress(int steps) {
|
||||
count_.add(1);
|
||||
if (count_.loaded % steps == 0 || count_.loaded == count_.total) {
|
||||
renderProgress();
|
||||
}
|
||||
checkEvents();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Resource
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace Resource {
|
||||
|
||||
class Cache {
|
||||
class Cache {
|
||||
public:
|
||||
static void init(); // Inicialización singleton
|
||||
static void destroy(); // Destrucción singleton
|
||||
@@ -88,6 +88,6 @@ class Cache {
|
||||
|
||||
ResourceCount count_{}; // Contador de recursos
|
||||
std::shared_ptr<Text> loading_text_; // Texto para la pantalla de carga
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace Resource
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
|
||||
namespace Resource::Helper {
|
||||
|
||||
static bool resource_system_initialized = false;
|
||||
static bool resource_system_initialized = false;
|
||||
|
||||
// Initialize the resource system
|
||||
auto initializeResourceSystem(const std::string& pack_file, bool enable_fallback)
|
||||
// Initialize the resource system
|
||||
auto initializeResourceSystem(const std::string& pack_file, bool enable_fallback)
|
||||
-> bool {
|
||||
if (resource_system_initialized) {
|
||||
std::cout << "ResourceHelper: Already initialized\n";
|
||||
@@ -35,19 +35,19 @@ auto initializeResourceSystem(const std::string& pack_file, bool enable_fallback
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
// Shutdown the resource system
|
||||
void shutdownResourceSystem() {
|
||||
// Shutdown the resource system
|
||||
void shutdownResourceSystem() {
|
||||
if (resource_system_initialized) {
|
||||
Loader::get().shutdown();
|
||||
resource_system_initialized = false;
|
||||
std::cout << "ResourceHelper: Shutdown complete\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load a file
|
||||
auto loadFile(const std::string& filepath) -> std::vector<uint8_t> {
|
||||
// Load a file
|
||||
auto loadFile(const std::string& filepath) -> std::vector<uint8_t> {
|
||||
if (!resource_system_initialized) {
|
||||
std::cerr << "ResourceHelper: System not initialized, loading from filesystem\n";
|
||||
// Fallback to direct filesystem access
|
||||
@@ -80,10 +80,10 @@ auto loadFile(const std::string& filepath) -> std::vector<uint8_t> {
|
||||
|
||||
// Load from filesystem
|
||||
return Loader::get().loadResource(filepath);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a file exists
|
||||
auto fileExists(const std::string& filepath) -> bool {
|
||||
// Check if a file exists
|
||||
auto fileExists(const std::string& filepath) -> bool {
|
||||
if (!resource_system_initialized) {
|
||||
return std::filesystem::exists(filepath);
|
||||
}
|
||||
@@ -98,10 +98,10 @@ auto fileExists(const std::string& filepath) -> bool {
|
||||
|
||||
// Check filesystem
|
||||
return std::filesystem::exists(filepath);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert asset path to pack path
|
||||
auto getPackPath(const std::string& asset_path) -> std::string {
|
||||
// Convert asset path to pack path
|
||||
auto getPackPath(const std::string& asset_path) -> std::string {
|
||||
std::string path = asset_path;
|
||||
|
||||
// Convert backslashes to forward slashes
|
||||
@@ -142,10 +142,10 @@ auto getPackPath(const std::string& asset_path) -> std::string {
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if file should use resource pack
|
||||
auto shouldUseResourcePack(const std::string& filepath) -> bool {
|
||||
// Check if file should use resource pack
|
||||
auto shouldUseResourcePack(const std::string& filepath) -> bool {
|
||||
std::string path = filepath;
|
||||
std::ranges::replace(path, '\\', '/');
|
||||
|
||||
@@ -169,14 +169,14 @@ auto shouldUseResourcePack(const std::string& filepath) -> bool {
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if pack is loaded
|
||||
auto isPackLoaded() -> bool {
|
||||
// Check if pack is loaded
|
||||
auto isPackLoaded() -> bool {
|
||||
if (!resource_system_initialized) {
|
||||
return false;
|
||||
}
|
||||
return Loader::get().isPackLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Resource::Helper
|
||||
|
||||
@@ -9,30 +9,30 @@
|
||||
|
||||
namespace Resource::Helper {
|
||||
|
||||
// Initialize the resource system
|
||||
// pack_file: Path to resources.pack
|
||||
// enable_fallback: Allow loading from filesystem if pack not available
|
||||
auto initializeResourceSystem(const std::string& pack_file = "resources.pack",
|
||||
// Initialize the resource system
|
||||
// pack_file: Path to resources.pack
|
||||
// enable_fallback: Allow loading from filesystem if pack not available
|
||||
auto initializeResourceSystem(const std::string& pack_file = "resources.pack",
|
||||
bool enable_fallback = true) -> bool;
|
||||
|
||||
// Shutdown the resource system
|
||||
void shutdownResourceSystem();
|
||||
// Shutdown the resource system
|
||||
void shutdownResourceSystem();
|
||||
|
||||
// Load a file (tries pack first, then filesystem if fallback enabled)
|
||||
auto loadFile(const std::string& filepath) -> std::vector<uint8_t>;
|
||||
// Load a file (tries pack first, then filesystem if fallback enabled)
|
||||
auto loadFile(const std::string& filepath) -> std::vector<uint8_t>;
|
||||
|
||||
// Check if a file exists
|
||||
auto fileExists(const std::string& filepath) -> bool;
|
||||
// Check if a file exists
|
||||
auto fileExists(const std::string& filepath) -> bool;
|
||||
|
||||
// Convert an asset path to a pack path
|
||||
// Example: "data/music/title.ogg" -> "music/title.ogg"
|
||||
auto getPackPath(const std::string& asset_path) -> std::string;
|
||||
// Convert an asset path to a pack path
|
||||
// Example: "data/music/title.ogg" -> "music/title.ogg"
|
||||
auto getPackPath(const std::string& asset_path) -> std::string;
|
||||
|
||||
// Check if a file should use the resource pack
|
||||
// Returns false for config/ files (always from filesystem)
|
||||
auto shouldUseResourcePack(const std::string& filepath) -> bool;
|
||||
// Check if a file should use the resource pack
|
||||
// Returns false for config/ files (always from filesystem)
|
||||
auto shouldUseResourcePack(const std::string& filepath) -> bool;
|
||||
|
||||
// Check if pack is loaded
|
||||
auto isPackLoaded() -> bool;
|
||||
// Check if pack is loaded
|
||||
auto isPackLoaded() -> bool;
|
||||
|
||||
} // namespace Resource::Helper
|
||||
|
||||
@@ -16,23 +16,23 @@
|
||||
|
||||
namespace Resource {
|
||||
|
||||
// Singleton
|
||||
List* List::instance = nullptr;
|
||||
// Singleton
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void List::destroy() {
|
||||
void List::destroy() {
|
||||
delete List::instance;
|
||||
}
|
||||
}
|
||||
|
||||
auto List::get() -> List* {
|
||||
auto List::get() -> List* {
|
||||
return List::instance;
|
||||
}
|
||||
}
|
||||
|
||||
// Añade un elemento al mapa (función auxiliar)
|
||||
void List::addToMap(const std::string& file_path, Type type, bool required, bool absolute) {
|
||||
// Añade un elemento al mapa (función auxiliar)
|
||||
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 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});
|
||||
}
|
||||
}
|
||||
|
||||
// Añade un elemento a la lista
|
||||
void List::add(const std::string& file_path, Type type, bool required, bool absolute) {
|
||||
// Añade un elemento a la lista
|
||||
void List::add(const std::string& file_path, Type type, bool required, bool absolute) {
|
||||
addToMap(file_path, type, required, absolute);
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
// 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) {
|
||||
std::ifstream file(config_file_path);
|
||||
if (!file.is_open()) {
|
||||
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
|
||||
loadFromString(buffer.str(), prefix, system_folder);
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
// 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) {
|
||||
try {
|
||||
// Parsear YAML
|
||||
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",
|
||||
e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Devuelve la ruta completa a un fichero (búsqueda O(1))
|
||||
auto List::get(const std::string& filename) const -> std::string {
|
||||
// Devuelve la ruta completa a un fichero (búsqueda O(1))
|
||||
auto List::get(const std::string& filename) const -> std::string {
|
||||
auto it = file_list_.find(filename);
|
||||
if (it != file_list_.end()) {
|
||||
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());
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// Carga datos del archivo
|
||||
auto List::loadData(const std::string& filename) const -> std::vector<uint8_t> {
|
||||
// Carga datos del archivo
|
||||
auto List::loadData(const std::string& filename) const -> std::vector<uint8_t> {
|
||||
auto it = file_list_.find(filename);
|
||||
if (it != file_list_.end()) {
|
||||
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());
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// Verifica si un recurso existe
|
||||
auto List::exists(const std::string& filename) const -> bool {
|
||||
// Verifica si un recurso existe
|
||||
auto List::exists(const std::string& filename) const -> bool {
|
||||
return file_list_.find(filename) != file_list_.end();
|
||||
}
|
||||
}
|
||||
|
||||
// Parsea string a Type
|
||||
auto List::parseAssetType(const std::string& type_str) -> Type {
|
||||
// Parsea string a Type
|
||||
auto List::parseAssetType(const std::string& type_str) -> Type {
|
||||
if (type_str == "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);
|
||||
}
|
||||
}
|
||||
|
||||
// Devuelve el nombre del tipo de recurso
|
||||
auto List::getTypeName(Type type) -> std::string {
|
||||
// Devuelve el nombre del tipo de recurso
|
||||
auto List::getTypeName(Type type) -> std::string {
|
||||
switch (type) {
|
||||
case Type::DATA:
|
||||
return "DATA";
|
||||
@@ -256,10 +256,10 @@ auto List::getTypeName(Type type) -> std::string {
|
||||
default:
|
||||
return "ERROR";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Devuelve la lista de recursos de un tipo
|
||||
auto List::getListByType(Type type) const -> std::vector<std::string> {
|
||||
// Devuelve la lista de recursos de un tipo
|
||||
auto List::getListByType(Type type) const -> std::vector<std::string> {
|
||||
std::vector<std::string> 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);
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
// Reemplaza variables en las rutas
|
||||
auto List::replaceVariables(const std::string& path, const std::string& prefix, const std::string& system_folder) -> std::string {
|
||||
// Reemplaza variables en las rutas
|
||||
auto List::replaceVariables(const std::string& path, const std::string& prefix, const std::string& system_folder) -> std::string {
|
||||
std::string result = path;
|
||||
|
||||
// Reemplazar ${PREFIX}
|
||||
@@ -293,10 +293,10 @@ auto List::replaceVariables(const std::string& path, const std::string& prefix,
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Parsea las opciones de una línea de configuración
|
||||
auto List::parseOptions(const std::string& options, bool& required, bool& absolute) -> void {
|
||||
// Parsea las opciones de una línea de configuración
|
||||
auto List::parseOptions(const std::string& options, bool& required, bool& absolute) -> void {
|
||||
if (options.empty()) {
|
||||
return;
|
||||
}
|
||||
@@ -315,6 +315,6 @@ auto List::parseOptions(const std::string& options, bool& required, bool& absolu
|
||||
absolute = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Resource
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
namespace Resource {
|
||||
|
||||
// --- Clase List: gestor optimizado de recursos (singleton) ---
|
||||
class List {
|
||||
// --- Clase List: gestor optimizado de recursos (singleton) ---
|
||||
class List {
|
||||
public:
|
||||
// --- Enums ---
|
||||
enum class Type : int {
|
||||
@@ -71,6 +71,6 @@ class List {
|
||||
|
||||
// --- Instancia singleton ---
|
||||
static List* instance; // Instancia única de List
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace Resource
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
|
||||
namespace Resource {
|
||||
|
||||
// Get singleton instance
|
||||
auto Loader::get() -> Loader& {
|
||||
// Get singleton instance
|
||||
auto Loader::get() -> Loader& {
|
||||
static Loader instance_;
|
||||
return instance_;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize with a pack file
|
||||
auto Loader::initialize(const std::string& pack_file, bool enable_fallback)
|
||||
// Initialize with a pack file
|
||||
auto Loader::initialize(const std::string& pack_file, bool enable_fallback)
|
||||
-> bool {
|
||||
if (initialized_) {
|
||||
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";
|
||||
initialized_ = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Load a resource
|
||||
auto Loader::loadResource(const std::string& filename) -> std::vector<uint8_t> {
|
||||
// Load a resource
|
||||
auto Loader::loadResource(const std::string& filename) -> std::vector<uint8_t> {
|
||||
if (!initialized_) {
|
||||
std::cerr << "Loader: Not initialized\n";
|
||||
return {};
|
||||
@@ -78,10 +78,10 @@ auto Loader::loadResource(const std::string& filename) -> std::vector<uint8_t> {
|
||||
|
||||
std::cerr << "Loader: Resource not found: " << filename << '\n';
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a resource exists
|
||||
auto Loader::resourceExists(const std::string& filename) -> bool {
|
||||
// Check if a resource exists
|
||||
auto Loader::resourceExists(const std::string& filename) -> bool {
|
||||
if (!initialized_) {
|
||||
return false;
|
||||
}
|
||||
@@ -99,30 +99,30 @@ auto Loader::resourceExists(const std::string& filename) -> bool {
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if pack is loaded
|
||||
auto Loader::isPackLoaded() const -> bool {
|
||||
// Check if pack is loaded
|
||||
auto Loader::isPackLoaded() const -> bool {
|
||||
return resource_pack_ && resource_pack_->isLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
// Get pack statistics
|
||||
auto Loader::getPackResourceCount() const -> size_t {
|
||||
// Get pack statistics
|
||||
auto Loader::getPackResourceCount() const -> size_t {
|
||||
if (resource_pack_ && resource_pack_->isLoaded()) {
|
||||
return resource_pack_->getResourceCount();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
void Loader::shutdown() {
|
||||
// Cleanup
|
||||
void Loader::shutdown() {
|
||||
resource_pack_.reset();
|
||||
initialized_ = false;
|
||||
std::cout << "Loader: Shutdown complete\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Load from filesystem
|
||||
auto Loader::loadFromFilesystem(const std::string& filepath)
|
||||
// Load from filesystem
|
||||
auto Loader::loadFromFilesystem(const std::string& filepath)
|
||||
-> std::vector<uint8_t> {
|
||||
std::ifstream file(filepath, std::ios::binary | std::ios::ate);
|
||||
if (!file) {
|
||||
@@ -139,15 +139,15 @@ auto Loader::loadFromFilesystem(const std::string& filepath)
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if file exists on filesystem
|
||||
auto Loader::fileExistsOnFilesystem(const std::string& filepath) -> bool {
|
||||
// Check if file exists on filesystem
|
||||
auto Loader::fileExistsOnFilesystem(const std::string& filepath) -> bool {
|
||||
return std::filesystem::exists(filepath);
|
||||
}
|
||||
}
|
||||
|
||||
// Validate pack integrity
|
||||
auto Loader::validatePack() const -> bool {
|
||||
// Validate pack integrity
|
||||
auto Loader::validatePack() const -> bool {
|
||||
if (!initialized_ || !resource_pack_ || !resource_pack_->isLoaded()) {
|
||||
std::cerr << "Loader: Cannot validate - pack not loaded\n";
|
||||
return false;
|
||||
@@ -165,10 +165,10 @@ auto Loader::validatePack() const -> bool {
|
||||
<< '\n';
|
||||
std::cout << "Loader: Pack validation successful\n";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Load assets.yaml from pack
|
||||
auto Loader::loadAssetsConfig() const -> std::string {
|
||||
// Load assets.yaml from pack
|
||||
auto Loader::loadAssetsConfig() const -> std::string {
|
||||
if (!initialized_ || !resource_pack_ || !resource_pack_->isLoaded()) {
|
||||
std::cerr << "Loader: Cannot load assets config - pack not loaded\n";
|
||||
return "";
|
||||
@@ -194,6 +194,6 @@ auto Loader::loadAssetsConfig() const -> std::string {
|
||||
<< " bytes)\n";
|
||||
|
||||
return config_content;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Resource
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
|
||||
namespace Resource {
|
||||
|
||||
// Singleton class for loading resources from pack or filesystem
|
||||
class Loader {
|
||||
// Singleton class for loading resources from pack or filesystem
|
||||
class Loader {
|
||||
public:
|
||||
static auto get() -> Loader&; // Singleton instance access
|
||||
|
||||
@@ -43,6 +43,6 @@ class Loader {
|
||||
std::unique_ptr<Pack> resource_pack_; // Member variables
|
||||
bool fallback_to_files_{true};
|
||||
bool initialized_{false};
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace Resource
|
||||
|
||||
@@ -12,32 +12,32 @@
|
||||
|
||||
namespace Resource {
|
||||
|
||||
// Calculate CRC32 checksum for data verification
|
||||
auto Pack::calculateChecksum(const std::vector<uint8_t>& data) -> uint32_t {
|
||||
// Calculate CRC32 checksum for data verification
|
||||
auto Pack::calculateChecksum(const std::vector<uint8_t>& data) -> uint32_t {
|
||||
uint32_t checksum = 0x12345678;
|
||||
for (unsigned char byte : data) {
|
||||
checksum = ((checksum << 5) + checksum) + byte;
|
||||
}
|
||||
return checksum;
|
||||
}
|
||||
}
|
||||
|
||||
// XOR encryption (symmetric - same function for encrypt/decrypt)
|
||||
void Pack::encryptData(std::vector<uint8_t>& data, const std::string& key) {
|
||||
// XOR encryption (symmetric - same function for encrypt/decrypt)
|
||||
void Pack::encryptData(std::vector<uint8_t>& data, const std::string& key) {
|
||||
if (key.empty()) {
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < data.size(); ++i) {
|
||||
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
|
||||
encryptData(data, key);
|
||||
}
|
||||
}
|
||||
|
||||
// Read entire file into memory
|
||||
auto Pack::readFile(const std::string& filepath) -> std::vector<uint8_t> {
|
||||
// Read entire file into memory
|
||||
auto Pack::readFile(const std::string& filepath) -> std::vector<uint8_t> {
|
||||
std::ifstream file(filepath, std::ios::binary | std::ios::ate);
|
||||
if (!file) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Add a single file to the pack
|
||||
auto Pack::addFile(const std::string& filepath, const std::string& pack_name)
|
||||
// Add a single file to the pack
|
||||
auto Pack::addFile(const std::string& filepath, const std::string& pack_name)
|
||||
-> bool {
|
||||
auto file_data = readFile(filepath);
|
||||
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";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Add all files from a directory recursively
|
||||
auto Pack::addDirectory(const std::string& dir_path,
|
||||
// Add all files from a directory recursively
|
||||
auto Pack::addDirectory(const std::string& dir_path,
|
||||
const std::string& base_path) -> bool {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
@@ -114,10 +114,10 @@ auto Pack::addDirectory(const std::string& dir_path,
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Save the pack to a file
|
||||
auto Pack::savePack(const std::string& pack_file) -> bool {
|
||||
// Save the pack to a file
|
||||
auto Pack::savePack(const std::string& pack_file) -> bool {
|
||||
std::ofstream file(pack_file, std::ios::binary);
|
||||
if (!file) {
|
||||
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";
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Load a pack from a file
|
||||
auto Pack::loadPack(const std::string& pack_file) -> bool {
|
||||
// Load a pack from a file
|
||||
auto Pack::loadPack(const std::string& pack_file) -> bool {
|
||||
std::ifstream file(pack_file, std::ios::binary);
|
||||
if (!file) {
|
||||
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";
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Get a resource by name
|
||||
auto Pack::getResource(const std::string& filename) -> std::vector<uint8_t> {
|
||||
// Get a resource by name
|
||||
auto Pack::getResource(const std::string& filename) -> std::vector<uint8_t> {
|
||||
auto it = resources_.find(filename);
|
||||
if (it == resources_.end()) {
|
||||
return {};
|
||||
@@ -255,15 +255,15 @@ auto Pack::getResource(const std::string& filename) -> std::vector<uint8_t> {
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a resource exists
|
||||
auto Pack::hasResource(const std::string& filename) const -> bool {
|
||||
// Check if a resource exists
|
||||
auto Pack::hasResource(const std::string& filename) const -> bool {
|
||||
return resources_.find(filename) != resources_.end();
|
||||
}
|
||||
}
|
||||
|
||||
// Get list of all resources
|
||||
auto Pack::getResourceList() const -> std::vector<std::string> {
|
||||
// Get list of all resources
|
||||
auto Pack::getResourceList() const -> std::vector<std::string> {
|
||||
std::vector<std::string> list;
|
||||
list.reserve(resources_.size());
|
||||
for (const auto& [name, entry] : resources_) {
|
||||
@@ -271,10 +271,10 @@ auto Pack::getResourceList() const -> std::vector<std::string> {
|
||||
}
|
||||
std::ranges::sort(list);
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate overall pack checksum for validation
|
||||
auto Pack::calculatePackChecksum() const -> uint32_t {
|
||||
// Calculate overall pack checksum for validation
|
||||
auto Pack::calculatePackChecksum() const -> uint32_t {
|
||||
if (!loaded_ || data_.empty()) {
|
||||
return 0;
|
||||
}
|
||||
@@ -298,6 +298,6 @@ auto Pack::calculatePackChecksum() const -> uint32_t {
|
||||
}
|
||||
|
||||
return global_checksum;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Resource
|
||||
|
||||
@@ -11,19 +11,19 @@
|
||||
|
||||
namespace Resource {
|
||||
|
||||
// Entry metadata for each resource in the pack
|
||||
struct ResourceEntry {
|
||||
// Entry metadata for each resource in the pack
|
||||
struct ResourceEntry {
|
||||
std::string filename; // Relative path within pack
|
||||
uint64_t offset{0}; // Byte offset in data block
|
||||
uint64_t size{0}; // Size in bytes
|
||||
uint32_t checksum{0}; // CRC32 checksum for verification
|
||||
};
|
||||
};
|
||||
|
||||
// Resource pack file format
|
||||
// Header: "JDDI" (4 bytes) + Version (4 bytes)
|
||||
// Metadata: Count + array of ResourceEntry
|
||||
// Data: Encrypted data block
|
||||
class Pack {
|
||||
// Resource pack file format
|
||||
// Header: "JDDI" (4 bytes) + Version (4 bytes)
|
||||
// Metadata: Count + array of ResourceEntry
|
||||
// Data: Encrypted data block
|
||||
class Pack {
|
||||
public:
|
||||
Pack() = default;
|
||||
~Pack() = default;
|
||||
@@ -63,6 +63,6 @@ class Pack {
|
||||
std::unordered_map<std::string, ResourceEntry> resources_; // Member variables
|
||||
std::vector<uint8_t> data_; // Encrypted data block
|
||||
bool loaded_{false};
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace Resource
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
#include "game/scene_manager.hpp" // Para SceneManager
|
||||
|
||||
namespace GlobalEvents {
|
||||
// Comprueba los eventos que se pueden producir en cualquier sección del juego
|
||||
void handle(const SDL_Event& event) {
|
||||
// Comprueba los eventos que se pueden producir en cualquier sección del juego
|
||||
void handle(const SDL_Event& event) {
|
||||
// Evento de salida de la aplicación
|
||||
if (event.type == SDL_EVENT_QUIT) {
|
||||
SceneManager::current = SceneManager::Scene::QUIT;
|
||||
@@ -18,5 +18,5 @@ void handle(const SDL_Event& event) {
|
||||
}
|
||||
|
||||
Mouse::handleEvent(event);
|
||||
}
|
||||
}
|
||||
} // namespace GlobalEvents
|
||||
@@ -3,6 +3,6 @@
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
namespace GlobalEvents {
|
||||
// Comprueba los eventos que se pueden producir en cualquier sección del juego
|
||||
void handle(const SDL_Event& event);
|
||||
// Comprueba los eventos que se pueden producir en cualquier sección del juego
|
||||
void handle(const SDL_Event& event);
|
||||
} // namespace GlobalEvents
|
||||
@@ -8,116 +8,95 @@
|
||||
|
||||
// Forward declarations from Options namespace
|
||||
namespace Options {
|
||||
// enum class ControlScheme;
|
||||
enum class NotificationPosition;
|
||||
// enum class ControlScheme;
|
||||
enum class NotificationPosition;
|
||||
} // 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 ---
|
||||
// Dimensiones del canvas del juego (usa GameCanvas como fuente única)
|
||||
namespace Canvas {
|
||||
constexpr int WIDTH = GameCanvas::WIDTH; // Ancho del canvas del juego (256)
|
||||
constexpr int HEIGHT = GameCanvas::HEIGHT; // Alto del canvas del juego (192)
|
||||
} // namespace Canvas
|
||||
namespace Defaults::Window {
|
||||
constexpr int ZOOM = 2; // Zoom de la ventana por defecto
|
||||
} // namespace Defaults::Window
|
||||
|
||||
// --- WINDOW ---
|
||||
namespace Window {
|
||||
constexpr int ZOOM = 2; // Zoom de la ventana por defecto
|
||||
} // namespace Window
|
||||
namespace Defaults::Video {
|
||||
constexpr bool FULLSCREEN = false; // Modo de pantalla completa por defecto (false = ventana)
|
||||
constexpr Screen::Filter FILTER = Screen::Filter::NEAREST; // Filtro por defecto
|
||||
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 Video {
|
||||
constexpr bool FULLSCREEN = false; // Modo de pantalla completa por defecto (false = ventana)
|
||||
constexpr Screen::Filter FILTER = Screen::Filter::NEAREST; // Filtro por defecto
|
||||
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 Video
|
||||
namespace Defaults::Border {
|
||||
constexpr bool ENABLED = true; // Borde activado por defecto
|
||||
constexpr int WIDTH = 32; // Ancho del borde por defecto
|
||||
constexpr int HEIGHT = 24; // Alto del borde por defectoF
|
||||
} // namespace Defaults::Border
|
||||
|
||||
// --- BORDER ---
|
||||
namespace Border {
|
||||
constexpr bool ENABLED = true; // Borde activado por defecto
|
||||
constexpr int WIDTH = 32; // Ancho del borde por defecto
|
||||
constexpr int HEIGHT = 24; // Alto del borde por defecto
|
||||
} // namespace Border
|
||||
namespace Defaults::Audio {
|
||||
constexpr float VOLUME = 1.0F; // Volumen por defecto
|
||||
constexpr bool ENABLED = true; // Audio por defecto
|
||||
} // namespace Defaults::Audio
|
||||
|
||||
// --- AUDIO ---
|
||||
namespace Audio {
|
||||
constexpr float VOLUME = 1.0F; // Volumen por defecto
|
||||
constexpr bool ENABLED = true; // Audio por defecto
|
||||
} // namespace Audio
|
||||
namespace Defaults::Music {
|
||||
constexpr float VOLUME = 0.8F; // Volumen por defecto de la musica
|
||||
constexpr bool ENABLED = true; // Musica habilitada por defecto
|
||||
} // namespace Defaults::Music
|
||||
|
||||
// --- MUSIC ---
|
||||
namespace Music {
|
||||
constexpr float VOLUME = 0.8F; // Volumen por defecto de la musica
|
||||
constexpr bool ENABLED = true; // Musica habilitada por defecto
|
||||
} // namespace Music
|
||||
namespace Defaults::Sound {
|
||||
constexpr float VOLUME = 1.0F; // Volumen por defecto de los efectos de sonido
|
||||
constexpr bool ENABLED = true; // Sonido habilitado por defecto
|
||||
} // namespace Defaults::Sound
|
||||
|
||||
// --- SOUND ---
|
||||
namespace Sound {
|
||||
constexpr float VOLUME = 1.0F; // Volumen por defecto de los efectos de sonido
|
||||
constexpr bool ENABLED = true; // Sonido habilitado por defecto
|
||||
} // namespace Sound
|
||||
namespace Defaults::Cheat {
|
||||
constexpr bool INFINITE_LIVES = false; // Vidas infinitas desactivadas por defecto
|
||||
constexpr bool INVINCIBLE = false; // Invencibilidad desactivada por defecto
|
||||
constexpr bool JAIL_IS_OPEN = false; // Jail abierta desactivada por defecto
|
||||
constexpr bool ALTERNATE_SKIN = false; // Skin alternativa desactivada por defecto
|
||||
} // namespace Defaults::Cheat
|
||||
|
||||
// --- CHEATS ---
|
||||
namespace Cheat {
|
||||
constexpr bool INFINITE_LIVES = false; // Vidas infinitas desactivadas por defecto
|
||||
constexpr bool INVINCIBLE = false; // Invencibilidad desactivada por defecto
|
||||
constexpr bool JAIL_IS_OPEN = false; // Jail abierta desactivada por defecto
|
||||
constexpr bool ALTERNATE_SKIN = false; // Skin alternativa desactivada por defecto
|
||||
} // namespace Cheat
|
||||
namespace Defaults::Stats {
|
||||
constexpr int ROOMS = 0; // Habitaciones visitadas por defecto
|
||||
constexpr int ITEMS = 0; // Items obtenidos por defecto
|
||||
constexpr const char* WORST_NIGHTMARE = ""; // Habitación con más muertes por defecto
|
||||
} // namespace Defaults::Stats
|
||||
|
||||
// --- STATS ---
|
||||
namespace Stats {
|
||||
constexpr int ROOMS = 0; // Habitaciones visitadas por defecto
|
||||
constexpr int ITEMS = 0; // Items obtenidos por defecto
|
||||
constexpr const char* WORST_NIGHTMARE = ""; // Habitación con más muertes por defecto
|
||||
} // namespace Stats
|
||||
namespace Defaults::Controls {
|
||||
constexpr SDL_Scancode KEY_LEFT = SDL_SCANCODE_LEFT; // Tecla izquierda por defecto
|
||||
constexpr SDL_Scancode KEY_RIGHT = SDL_SCANCODE_RIGHT; // Tecla derecha por defecto
|
||||
constexpr SDL_Scancode KEY_JUMP = SDL_SCANCODE_UP; // Tecla salto por defecto
|
||||
|
||||
// --- CONTROLS ---
|
||||
namespace Controls {
|
||||
constexpr SDL_Scancode KEY_LEFT = SDL_SCANCODE_LEFT; // Tecla izquierda por defecto
|
||||
constexpr SDL_Scancode KEY_RIGHT = SDL_SCANCODE_RIGHT; // Tecla derecha por defecto
|
||||
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
|
||||
constexpr int GAMEPAD_BUTTON_RIGHT = SDL_GAMEPAD_BUTTON_DPAD_RIGHT; // Botón derecha por defecto
|
||||
constexpr int GAMEPAD_BUTTON_JUMP = SDL_GAMEPAD_BUTTON_WEST; // Botón salto por defecto
|
||||
} // namespace Defaults::Controls
|
||||
|
||||
constexpr int GAMEPAD_BUTTON_LEFT = SDL_GAMEPAD_BUTTON_DPAD_LEFT; // Botón izquierda por defecto
|
||||
constexpr int GAMEPAD_BUTTON_RIGHT = SDL_GAMEPAD_BUTTON_DPAD_RIGHT; // Botón derecha por defecto
|
||||
constexpr int GAMEPAD_BUTTON_JUMP = SDL_GAMEPAD_BUTTON_WEST; // Botón salto por defecto
|
||||
} // namespace Controls
|
||||
namespace Defaults::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 Defaults::Kiosk
|
||||
|
||||
// --- KIOSK ---
|
||||
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 {
|
||||
namespace Defaults::Game::Room {
|
||||
#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
|
||||
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
|
||||
} // namespace Room
|
||||
} // namespace Defaults::Game::Room
|
||||
|
||||
namespace Player {
|
||||
namespace Defaults::Game::Player {
|
||||
#ifdef _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 SDL_FlipMode SPAWN_FLIP = Flip::LEFT; // Orientación 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 SDL_FlipMode SPAWN_FLIP = Flip::LEFT; // Orientación inicial en debug
|
||||
#else
|
||||
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 SDL_FlipMode SPAWN_FLIP = Flip::LEFT; // Orientación 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 SDL_FlipMode SPAWN_FLIP = Flip::LEFT; // Orientación inicial en release
|
||||
#endif
|
||||
} // namespace Player
|
||||
|
||||
} // namespace Game
|
||||
|
||||
} // namespace Defaults
|
||||
} // namespace Defaults::Game::Player
|
||||
|
||||
@@ -13,19 +13,19 @@
|
||||
|
||||
namespace Options {
|
||||
|
||||
// --- Funciones helper de conversión ---
|
||||
// --- Funciones helper de conversión ---
|
||||
|
||||
// Mapa de nombres de filtro
|
||||
const std::unordered_map<Screen::Filter, std::string> FILTER_TO_STRING = {
|
||||
// Mapa de nombres de filtro
|
||||
const std::unordered_map<Screen::Filter, std::string> FILTER_TO_STRING = {
|
||||
{Screen::Filter::NEAREST, "nearest"},
|
||||
{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},
|
||||
{"linear", Screen::Filter::LINEAR}};
|
||||
|
||||
// Mapa de scancodes comunes (los más usados para controles de juego)
|
||||
const std::unordered_map<SDL_Scancode, std::string> SCANCODE_TO_STRING = {
|
||||
// Mapa de scancodes comunes (los más usados para controles de juego)
|
||||
const std::unordered_map<SDL_Scancode, std::string> SCANCODE_TO_STRING = {
|
||||
// Flechas
|
||||
{SDL_SCANCODE_LEFT, "LEFT"},
|
||||
{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_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
|
||||
{"LEFT", SDL_SCANCODE_LEFT},
|
||||
{"RIGHT", SDL_SCANCODE_RIGHT},
|
||||
@@ -139,8 +139,8 @@ const std::unordered_map<std::string, SDL_Scancode> STRING_TO_SCANCODE = {
|
||||
{"LALT", SDL_SCANCODE_LALT},
|
||||
{"RALT", SDL_SCANCODE_RALT}};
|
||||
|
||||
// Mapa extendido de botones de gamepad (incluye ejes como botones)
|
||||
const std::unordered_map<int, std::string> GAMEPAD_BUTTON_TO_STRING = {
|
||||
// Mapa extendido de botones de gamepad (incluye ejes como botones)
|
||||
const std::unordered_map<int, std::string> GAMEPAD_BUTTON_TO_STRING = {
|
||||
{SDL_GAMEPAD_BUTTON_WEST, "WEST"},
|
||||
{SDL_GAMEPAD_BUTTON_NORTH, "NORTH"},
|
||||
{SDL_GAMEPAD_BUTTON_EAST, "EAST"},
|
||||
@@ -158,7 +158,7 @@ const std::unordered_map<int, std::string> GAMEPAD_BUTTON_TO_STRING = {
|
||||
{200, "LEFT_STICK_LEFT"},
|
||||
{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},
|
||||
{"NORTH", SDL_GAMEPAD_BUTTON_NORTH},
|
||||
{"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_RIGHT", 201}};
|
||||
|
||||
// Lista de paletas válidas
|
||||
const std::vector<std::string> VALID_PALETTES = {
|
||||
// Lista de paletas válidas
|
||||
const std::vector<std::string> VALID_PALETTES = {
|
||||
"black-and-white",
|
||||
"green-phosphor",
|
||||
"island-joy-16",
|
||||
@@ -194,33 +194,33 @@ const std::vector<std::string> VALID_PALETTES = {
|
||||
"zx-spectrum-adjusted",
|
||||
"zxarne-5-2"};
|
||||
|
||||
// Funciones helper de conversión
|
||||
auto filterToString(Screen::Filter filter) -> std::string {
|
||||
// Funciones helper de conversión
|
||||
auto filterToString(Screen::Filter filter) -> std::string {
|
||||
auto it = FILTER_TO_STRING.find(filter);
|
||||
if (it != FILTER_TO_STRING.end()) {
|
||||
return it->second;
|
||||
}
|
||||
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);
|
||||
if (it != STRING_TO_FILTER.end()) {
|
||||
return it->second;
|
||||
}
|
||||
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);
|
||||
if (it != SCANCODE_TO_STRING.end()) {
|
||||
return it->second;
|
||||
}
|
||||
// Fallback: devolver el código numérico como string
|
||||
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);
|
||||
if (it != STRING_TO_SCANCODE.end()) {
|
||||
return it->second;
|
||||
@@ -232,18 +232,18 @@ auto stringToScancode(const std::string& str, SDL_Scancode default_value) -> SDL
|
||||
} catch (...) {
|
||||
return default_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto gamepadButtonToString(int button) -> std::string {
|
||||
auto gamepadButtonToString(int button) -> std::string {
|
||||
auto it = GAMEPAD_BUTTON_TO_STRING.find(button);
|
||||
if (it != GAMEPAD_BUTTON_TO_STRING.end()) {
|
||||
return it->second;
|
||||
}
|
||||
// Fallback: devolver el código numérico como string
|
||||
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);
|
||||
if (it != STRING_TO_GAMEPAD_BUTTON.end()) {
|
||||
return it->second;
|
||||
@@ -254,18 +254,18 @@ auto stringToGamepadButton(const std::string& str, int default_value) -> int {
|
||||
} catch (...) {
|
||||
return default_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto isValidPalette(const std::string& palette) -> bool {
|
||||
auto isValidPalette(const std::string& palette) -> bool {
|
||||
std::string lower_palette = palette;
|
||||
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; });
|
||||
}
|
||||
}
|
||||
|
||||
// --- Funciones helper para loadFromFile() ---
|
||||
// --- Funciones helper para loadFromFile() ---
|
||||
|
||||
// Carga configuración de ventana desde YAML
|
||||
void loadWindowConfigFromYaml(const fkyaml::node& yaml) {
|
||||
// Carga configuración de ventana desde YAML
|
||||
void loadWindowConfigFromYaml(const fkyaml::node& yaml) {
|
||||
if (yaml.contains("window")) {
|
||||
const auto& win = yaml["window"];
|
||||
if (win.contains("zoom")) {
|
||||
@@ -277,10 +277,10 @@ void loadWindowConfigFromYaml(const fkyaml::node& yaml) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Carga configuración de borde desde YAML
|
||||
void loadBorderConfigFromYaml(const fkyaml::node& border) {
|
||||
// Carga configuración de borde desde YAML
|
||||
void loadBorderConfigFromYaml(const fkyaml::node& border) {
|
||||
if (border.contains("enabled")) {
|
||||
try {
|
||||
video.border.enabled = border["enabled"].get_value<bool>();
|
||||
@@ -306,10 +306,10 @@ void loadBorderConfigFromYaml(const fkyaml::node& border) {
|
||||
video.border.height = Defaults::Border::HEIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Carga los campos básicos de configuración de video
|
||||
void loadBasicVideoFieldsFromYaml(const fkyaml::node& vid) {
|
||||
// Carga los campos básicos de configuración de video
|
||||
void loadBasicVideoFieldsFromYaml(const fkyaml::node& vid) {
|
||||
// fullscreen (antes era "mode")
|
||||
if (vid.contains("fullscreen")) {
|
||||
try {
|
||||
@@ -373,10 +373,10 @@ void loadBasicVideoFieldsFromYaml(const fkyaml::node& vid) {
|
||||
video.palette = Defaults::Video::PALETTE_NAME;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Carga configuración de video desde YAML
|
||||
void loadVideoConfigFromYaml(const fkyaml::node& yaml) {
|
||||
// Carga configuración de video desde YAML
|
||||
void loadVideoConfigFromYaml(const fkyaml::node& yaml) {
|
||||
if (yaml.contains("video")) {
|
||||
const auto& vid = yaml["video"];
|
||||
loadBasicVideoFieldsFromYaml(vid);
|
||||
@@ -386,10 +386,10 @@ void loadVideoConfigFromYaml(const fkyaml::node& yaml) {
|
||||
loadBorderConfigFromYaml(vid["border"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Carga controles de teclado desde YAML
|
||||
void loadKeyboardControlsFromYaml(const fkyaml::node& yaml) {
|
||||
// Carga controles de teclado desde YAML
|
||||
void loadKeyboardControlsFromYaml(const fkyaml::node& yaml) {
|
||||
if (yaml.contains("keyboard_controls")) {
|
||||
const auto& ctrl = yaml["keyboard_controls"];
|
||||
|
||||
@@ -420,10 +420,10 @@ void loadKeyboardControlsFromYaml(const fkyaml::node& yaml) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Carga controles de gamepad desde YAML
|
||||
void loadGamepadControlsFromYaml(const fkyaml::node& yaml) {
|
||||
// Carga controles de gamepad desde YAML
|
||||
void loadGamepadControlsFromYaml(const fkyaml::node& yaml) {
|
||||
if (yaml.contains("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
|
||||
void loadKioskConfigFromYaml(const fkyaml::node& yaml) {
|
||||
// Carga configuración del modo kiosko desde YAML
|
||||
void loadKioskConfigFromYaml(const fkyaml::node& yaml) {
|
||||
if (yaml.contains("kiosk")) {
|
||||
const auto& k = yaml["kiosk"];
|
||||
|
||||
@@ -485,24 +485,24 @@ void loadKioskConfigFromYaml(const fkyaml::node& yaml) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Crea e inicializa las opciones del programa
|
||||
void init() {
|
||||
// Crea e inicializa las opciones del programa
|
||||
void init() {
|
||||
#ifdef _DEBUG
|
||||
console = true;
|
||||
#else
|
||||
console = false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Establece la ruta del fichero de configuración
|
||||
void setConfigFile(const std::string& path) {
|
||||
// Establece la ruta del fichero de configuración
|
||||
void setConfigFile(const std::string& path) {
|
||||
config_file_path = path;
|
||||
}
|
||||
}
|
||||
|
||||
// Carga las opciones desde el fichero configurado
|
||||
auto loadFromFile() -> bool {
|
||||
// Carga las opciones desde el fichero configurado
|
||||
auto loadFromFile() -> bool {
|
||||
// Versión esperada del fichero
|
||||
const std::string CONFIG_VERSION = Texts::VERSION;
|
||||
version = "";
|
||||
@@ -566,10 +566,10 @@ auto loadFromFile() -> bool {
|
||||
saveToFile();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Guarda las opciones al fichero configurado
|
||||
auto saveToFile() -> bool {
|
||||
// Guarda las opciones al fichero configurado
|
||||
auto saveToFile() -> bool {
|
||||
// Abre el fichero para escritura
|
||||
std::ofstream file(config_file_path);
|
||||
if (!file.is_open()) {
|
||||
@@ -647,22 +647,24 @@ auto saveToFile() -> bool {
|
||||
}
|
||||
|
||||
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
|
||||
auto loadPostFXFromFile() -> bool {
|
||||
// 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
|
||||
auto loadPostFXFromFile() -> bool {
|
||||
postfx_presets.clear();
|
||||
current_postfx_preset = 0;
|
||||
|
||||
@@ -710,10 +712,10 @@ auto loadPostFXFromFile() -> bool {
|
||||
}
|
||||
return savePostFXToFile();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Guarda los presets de PostFX por defecto
|
||||
auto savePostFXToFile() -> bool {
|
||||
// Guarda los presets de PostFX por defecto
|
||||
auto savePostFXToFile() -> bool {
|
||||
if (postfx_file_path.empty()) {
|
||||
return false;
|
||||
}
|
||||
@@ -794,6 +796,6 @@ auto savePostFXToFile() -> bool {
|
||||
current_postfx_preset = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Options
|
||||
|
||||
@@ -15,22 +15,22 @@
|
||||
// --- Namespace Options: gestión de configuración y opciones del juego ---
|
||||
namespace Options {
|
||||
|
||||
// Estructura para las opciones de control de teclado
|
||||
struct KeyboardControls {
|
||||
// Estructura para las opciones de control de teclado
|
||||
struct KeyboardControls {
|
||||
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_jump{Defaults::Controls::KEY_JUMP}; // Tecla para saltar
|
||||
};
|
||||
};
|
||||
|
||||
// Estructura para las opciones de control del gamepad/joystick
|
||||
struct GamepadControls {
|
||||
// Estructura para las opciones de control del gamepad/joystick
|
||||
struct GamepadControls {
|
||||
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_jump{Defaults::Controls::GAMEPAD_BUTTON_JUMP}; // Botón para saltar (por defecto: WEST/X button)
|
||||
};
|
||||
};
|
||||
|
||||
// Estructura para albergar trucos
|
||||
struct Cheat {
|
||||
// Estructura para albergar trucos
|
||||
struct Cheat {
|
||||
enum class State : bool {
|
||||
DISABLED = false,
|
||||
ENABLED = true
|
||||
@@ -45,38 +45,38 @@ struct Cheat {
|
||||
[[nodiscard]] auto enabled() const -> bool {
|
||||
return infinite_lives == State::ENABLED || invincible == State::ENABLED || jail_is_open == State::ENABLED;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Estructura para almacenar estadísticas
|
||||
struct Stats {
|
||||
// Estructura para almacenar estadísticas
|
||||
struct Stats {
|
||||
int rooms{Defaults::Stats::ROOMS}; // Cantidad de habitaciones visitadas
|
||||
int items{Defaults::Stats::ITEMS}; // Cantidad de items obtenidos
|
||||
std::string worst_nightmare{Defaults::Stats::WORST_NIGHTMARE}; // Habitación con más muertes acumuladas
|
||||
};
|
||||
};
|
||||
|
||||
// Estructura para el modo kiosko
|
||||
struct Kiosk {
|
||||
// Estructura para el modo kiosko
|
||||
struct Kiosk {
|
||||
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
|
||||
bool infinite_lives{Defaults::Kiosk::INFINITE_LIVES}; // Indica si el jugador tiene vidas infinitas en modo kiosko
|
||||
};
|
||||
};
|
||||
|
||||
// Estructura con opciones de la ventana
|
||||
struct Window {
|
||||
// Estructura con opciones de la ventana
|
||||
struct Window {
|
||||
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 max_zoom{Defaults::Window::ZOOM}; // Máximo tamaño de zoom para la ventana
|
||||
};
|
||||
};
|
||||
|
||||
// Estructura para gestionar el borde de la pantalla
|
||||
struct Border {
|
||||
// Estructura para gestionar el borde de la pantalla
|
||||
struct Border {
|
||||
bool enabled{Defaults::Border::ENABLED}; // Indica si se ha de mostrar el borde
|
||||
float width{Defaults::Border::WIDTH}; // Ancho del borde
|
||||
float height{Defaults::Border::HEIGHT}; // Alto del borde
|
||||
};
|
||||
};
|
||||
|
||||
// Estructura para las opciones de video
|
||||
struct Video {
|
||||
// Estructura para las opciones de video
|
||||
struct Video {
|
||||
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
|
||||
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
|
||||
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
|
||||
};
|
||||
};
|
||||
|
||||
// Estructura para las opciones de musica
|
||||
struct Music {
|
||||
// Estructura para las opciones de musica
|
||||
struct Music {
|
||||
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
|
||||
};
|
||||
};
|
||||
|
||||
// Estructura para las opciones de sonido
|
||||
struct Sound {
|
||||
// Estructura para las opciones de sonido
|
||||
struct Sound {
|
||||
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)
|
||||
};
|
||||
};
|
||||
|
||||
// Estructura para las opciones de audio
|
||||
struct Audio {
|
||||
// Estructura para las opciones de audio
|
||||
struct Audio {
|
||||
Music music{}; // Opciones para la música
|
||||
Sound sound{}; // Opciones para los efectos de sonido
|
||||
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)
|
||||
};
|
||||
};
|
||||
|
||||
// Estructura para las opciones de juego
|
||||
struct Game {
|
||||
// Estructura para las opciones de juego
|
||||
struct Game {
|
||||
float width{Defaults::Canvas::WIDTH}; // Ancho de la resolucion del juego
|
||||
float height{Defaults::Canvas::HEIGHT}; // Alto de la resolucion del juego
|
||||
};
|
||||
};
|
||||
|
||||
// Estructura para un preset de PostFX
|
||||
struct PostFXPreset {
|
||||
// Estructura para un preset de PostFX
|
||||
struct PostFXPreset {
|
||||
std::string name; // Nombre del preset
|
||||
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)
|
||||
@@ -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 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)
|
||||
};
|
||||
};
|
||||
|
||||
// --- Variables globales ---
|
||||
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 Cheat cheats{}; // Contiene trucos y ventajas para el juego
|
||||
inline Game game{}; // Opciones de juego
|
||||
inline Video video{}; // Opciones de video
|
||||
inline Stats stats{}; // Datos con las estadisticas de juego
|
||||
inline Window window{}; // Opciones relativas a la ventana
|
||||
inline Audio audio{}; // Opciones relativas al audio
|
||||
inline KeyboardControls keyboard_controls{}; // Teclas usadas para jugar
|
||||
inline GamepadControls gamepad_controls{}; // Botones del gamepad usados para jugar
|
||||
inline Kiosk kiosk{}; // Opciones del modo kiosko
|
||||
// --- Variables globales ---
|
||||
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 Cheat cheats{}; // Contiene trucos y ventajas para el juego
|
||||
inline Game game{}; // Opciones de juego
|
||||
inline Video video{}; // Opciones de video
|
||||
inline Stats stats{}; // Datos con las estadisticas de juego
|
||||
inline Window window{}; // Opciones relativas a la ventana
|
||||
inline Audio audio{}; // Opciones relativas al audio
|
||||
inline KeyboardControls keyboard_controls{}; // Teclas usadas para jugar
|
||||
inline GamepadControls gamepad_controls{}; // Botones del gamepad usados para jugar
|
||||
inline Kiosk kiosk{}; // Opciones del modo kiosko
|
||||
|
||||
// Ruta completa del fichero de configuración (establecida mediante setConfigFile)
|
||||
inline std::string config_file_path{};
|
||||
// Ruta completa del fichero de configuración (establecida mediante setConfigFile)
|
||||
inline std::string config_file_path{};
|
||||
|
||||
// --- Variables 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 std::string postfx_file_path{}; // Ruta del fichero postfx.yaml
|
||||
// --- Variables 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 std::string postfx_file_path{}; // Ruta del fichero postfx.yaml
|
||||
|
||||
// --- Funciones públicas ---
|
||||
void init(); // Crea e inicializa las opciones del programa
|
||||
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 saveToFile() -> bool; // Guarda las opciones al fichero configurado
|
||||
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 savePostFXToFile() -> bool; // Guarda los presets de PostFX por defecto
|
||||
// --- Funciones públicas ---
|
||||
void init(); // Crea e inicializa las opciones del programa
|
||||
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 saveToFile() -> bool; // Guarda las opciones al fichero configurado
|
||||
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 savePostFXToFile() -> bool; // Guarda los presets de PostFX por defecto
|
||||
|
||||
} // namespace Options
|
||||
@@ -9,8 +9,8 @@
|
||||
|
||||
namespace SceneManager {
|
||||
|
||||
// --- Escenas del programa ---
|
||||
enum class Scene {
|
||||
// --- Escenas del programa ---
|
||||
enum class Scene {
|
||||
LOGO, // Pantalla del logo
|
||||
LOADING_SCREEN, // Pantalla de carga
|
||||
TITLE, // Pantalla de título/menú principal
|
||||
@@ -21,24 +21,24 @@ enum class Scene {
|
||||
ENDING, // Final del juego (ending 1)
|
||||
ENDING2, // Final del juego (ending 2)
|
||||
QUIT // Salir del programa
|
||||
};
|
||||
};
|
||||
|
||||
// --- Opciones para transiciones entre escenas ---
|
||||
enum class Options {
|
||||
// --- Opciones para transiciones entre escenas ---
|
||||
enum class Options {
|
||||
NONE, // Sin opciones especiales
|
||||
LOGO_TO_LOADING_SCREEN, // Del logo a la intro
|
||||
LOGO_TO_TITLE, // Del logo al título
|
||||
TITLE_WITH_LOADING_SCREEN, // Al título mostrando pantalla de carga
|
||||
TITLE_WITHOUT_LOADING_SCREEN // Al título sin pantalla de carga
|
||||
};
|
||||
};
|
||||
|
||||
// --- Variables de estado globales ---
|
||||
#ifdef _DEBUG
|
||||
inline Scene current = Scene::GAME; // Escena actual
|
||||
inline Options options = Options::LOGO_TO_LOADING_SCREEN; // Opciones de la escena actual
|
||||
inline Scene current = Scene::GAME; // Escena actual
|
||||
inline Options options = Options::LOGO_TO_LOADING_SCREEN; // Opciones de la escena actual
|
||||
#else
|
||||
inline Scene current = Scene::LOGO; // Escena actual
|
||||
inline Options options = Options::LOGO_TO_LOADING_SCREEN; // Opciones de la escena actual
|
||||
inline Scene current = Scene::LOGO; // Escena actual
|
||||
inline Options options = Options::LOGO_TO_LOADING_SCREEN; // Opciones de la escena actual
|
||||
#endif
|
||||
|
||||
} // namespace SceneManager
|
||||
|
||||
@@ -4,48 +4,48 @@
|
||||
|
||||
// Textos
|
||||
namespace Texts {
|
||||
constexpr const char* WINDOW_CAPTION = "© 2022 JailDoctor's Dilemma — JailDesigner";
|
||||
constexpr const char* COPYRIGHT = "@2022 JailDesigner";
|
||||
constexpr const char* VERSION = "1.10"; // Versión por defecto
|
||||
constexpr const char* WINDOW_CAPTION = "© 2022 JailDoctor's Dilemma — JailDesigner";
|
||||
constexpr const char* COPYRIGHT = "@2022 JailDesigner";
|
||||
constexpr const char* VERSION = "1.10"; // Versión por defecto
|
||||
} // namespace Texts
|
||||
|
||||
// Tamaño de bloque
|
||||
namespace Tile {
|
||||
constexpr int SIZE = 8;
|
||||
constexpr int HALF_SIZE = SIZE / 2;
|
||||
constexpr int SIZE = 8;
|
||||
constexpr int HALF_SIZE = SIZE / 2;
|
||||
} // namespace Tile
|
||||
|
||||
namespace PlayArea {
|
||||
constexpr int TOP = (0 * Tile::SIZE);
|
||||
constexpr int BOTTOM = (16 * Tile::SIZE);
|
||||
constexpr int LEFT = (0 * Tile::SIZE);
|
||||
constexpr int RIGHT = (32 * Tile::SIZE);
|
||||
constexpr int WIDTH = RIGHT - LEFT;
|
||||
constexpr int HEIGHT = BOTTOM - TOP;
|
||||
constexpr int CENTER_X = LEFT + (WIDTH / 2);
|
||||
constexpr int CENTER_FIRST_QUARTER_X = (WIDTH / 4);
|
||||
constexpr int CENTER_THIRD_QUARTER_X = (WIDTH / 4) * 3;
|
||||
constexpr int CENTER_Y = TOP + (HEIGHT / 2);
|
||||
constexpr int FIRST_QUARTER_Y = HEIGHT / 4;
|
||||
constexpr int THIRD_QUARTER_Y = (HEIGHT / 4) * 3;
|
||||
constexpr int TOP = (0 * Tile::SIZE);
|
||||
constexpr int BOTTOM = (16 * Tile::SIZE);
|
||||
constexpr int LEFT = (0 * Tile::SIZE);
|
||||
constexpr int RIGHT = (32 * Tile::SIZE);
|
||||
constexpr int WIDTH = RIGHT - LEFT;
|
||||
constexpr int HEIGHT = BOTTOM - TOP;
|
||||
constexpr int CENTER_X = LEFT + (WIDTH / 2);
|
||||
constexpr int CENTER_FIRST_QUARTER_X = (WIDTH / 4);
|
||||
constexpr int CENTER_THIRD_QUARTER_X = (WIDTH / 4) * 3;
|
||||
constexpr int CENTER_Y = TOP + (HEIGHT / 2);
|
||||
constexpr int FIRST_QUARTER_Y = HEIGHT / 4;
|
||||
constexpr int THIRD_QUARTER_Y = (HEIGHT / 4) * 3;
|
||||
} // namespace PlayArea
|
||||
|
||||
namespace GameCanvas {
|
||||
constexpr int WIDTH = 256;
|
||||
constexpr int HEIGHT = 192;
|
||||
constexpr int CENTER_X = WIDTH / 2;
|
||||
constexpr int FIRST_QUARTER_X = WIDTH / 4;
|
||||
constexpr int THIRD_QUARTER_X = (WIDTH / 4) * 3;
|
||||
constexpr int CENTER_Y = HEIGHT / 2;
|
||||
constexpr int FIRST_QUARTER_Y = HEIGHT / 4;
|
||||
constexpr int THIRD_QUARTER_Y = (HEIGHT / 4) * 3;
|
||||
constexpr int WIDTH = 256;
|
||||
constexpr int HEIGHT = 192;
|
||||
constexpr int CENTER_X = WIDTH / 2;
|
||||
constexpr int FIRST_QUARTER_X = WIDTH / 4;
|
||||
constexpr int THIRD_QUARTER_X = (WIDTH / 4) * 3;
|
||||
constexpr int CENTER_Y = HEIGHT / 2;
|
||||
constexpr int FIRST_QUARTER_Y = HEIGHT / 4;
|
||||
constexpr int THIRD_QUARTER_Y = (HEIGHT / 4) * 3;
|
||||
} // namespace GameCanvas
|
||||
|
||||
namespace Collision {
|
||||
constexpr int NONE = -1;
|
||||
constexpr int NONE = -1;
|
||||
} // namespace Collision
|
||||
|
||||
namespace Flip {
|
||||
constexpr SDL_FlipMode LEFT = SDL_FLIP_HORIZONTAL;
|
||||
constexpr SDL_FlipMode RIGHT = SDL_FLIP_NONE;
|
||||
constexpr SDL_FlipMode LEFT = SDL_FLIP_HORIZONTAL;
|
||||
constexpr SDL_FlipMode RIGHT = SDL_FLIP_NONE;
|
||||
} // namespace Flip
|
||||
@@ -22,110 +22,110 @@
|
||||
|
||||
namespace Easing {
|
||||
|
||||
// LINEAR
|
||||
inline auto linear(float t) -> float {
|
||||
// LINEAR
|
||||
inline auto linear(float t) -> float {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
// QUAD (Cuadrática: t^2)
|
||||
inline auto quadIn(float t) -> float {
|
||||
// QUAD (Cuadrática: t^2)
|
||||
inline auto quadIn(float t) -> float {
|
||||
return t * t;
|
||||
}
|
||||
}
|
||||
|
||||
inline auto quadOut(float t) -> float {
|
||||
inline auto quadOut(float t) -> float {
|
||||
return t * (2.0F - t);
|
||||
}
|
||||
}
|
||||
|
||||
inline auto quadInOut(float t) -> float {
|
||||
inline auto quadInOut(float t) -> float {
|
||||
if (t < 0.5F) {
|
||||
return 2.0F * t * t;
|
||||
}
|
||||
return -1.0F + ((4.0F - 2.0F * t) * t);
|
||||
}
|
||||
}
|
||||
|
||||
// CUBIC (Cúbica: t^3)
|
||||
inline auto cubicIn(float t) -> float {
|
||||
// CUBIC (Cúbica: t^3)
|
||||
inline auto cubicIn(float t) -> float {
|
||||
return t * t * t;
|
||||
}
|
||||
}
|
||||
|
||||
inline auto cubicOut(float t) -> float {
|
||||
inline auto cubicOut(float t) -> float {
|
||||
const float F = t - 1.0F;
|
||||
return (F * F * F) + 1.0F;
|
||||
}
|
||||
}
|
||||
|
||||
inline auto cubicInOut(float t) -> float {
|
||||
inline auto cubicInOut(float t) -> float {
|
||||
if (t < 0.5F) {
|
||||
return 4.0F * t * t * t;
|
||||
}
|
||||
const float F = ((2.0F * t) - 2.0F);
|
||||
return (0.5F * F * F * F) + 1.0F;
|
||||
}
|
||||
}
|
||||
|
||||
// QUART (Cuártica: t^4)
|
||||
inline auto quartIn(float t) -> float {
|
||||
// QUART (Cuártica: t^4)
|
||||
inline auto quartIn(float t) -> float {
|
||||
return t * t * t * t;
|
||||
}
|
||||
}
|
||||
|
||||
inline auto quartOut(float t) -> float {
|
||||
inline auto quartOut(float t) -> float {
|
||||
const float F = t - 1.0F;
|
||||
return 1.0F - (F * F * F * F);
|
||||
}
|
||||
}
|
||||
|
||||
inline auto quartInOut(float t) -> float {
|
||||
inline auto quartInOut(float t) -> float {
|
||||
if (t < 0.5F) {
|
||||
return 8.0F * t * t * t * t;
|
||||
}
|
||||
const float F = t - 1.0F;
|
||||
return 1.0F - (8.0F * F * F * F * F);
|
||||
}
|
||||
}
|
||||
|
||||
// QUINT (Quíntica: t^5)
|
||||
inline auto quintIn(float t) -> float {
|
||||
// QUINT (Quíntica: t^5)
|
||||
inline auto quintIn(float t) -> float {
|
||||
return t * t * t * t * t;
|
||||
}
|
||||
}
|
||||
|
||||
inline auto quintOut(float t) -> float {
|
||||
inline auto quintOut(float t) -> float {
|
||||
const float F = t - 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) {
|
||||
return 16.0F * t * t * t * t * t;
|
||||
}
|
||||
const float F = ((2.0F * t) - 2.0F);
|
||||
return (0.5F * F * F * F * F * F) + 1.0F;
|
||||
}
|
||||
}
|
||||
|
||||
// SINE (Sinusoidal)
|
||||
inline auto sineIn(float t) -> float {
|
||||
// SINE (Sinusoidal)
|
||||
inline auto sineIn(float t) -> float {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
// EXPO (Exponencial)
|
||||
inline auto expoIn(float t) -> float {
|
||||
// EXPO (Exponencial)
|
||||
inline auto expoIn(float t) -> float {
|
||||
if (t == 0.0F) {
|
||||
return 0.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) {
|
||||
return 1.0F;
|
||||
}
|
||||
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) {
|
||||
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 * (2.0F - std::pow(2.0F, (-20.0F * t) + 10.0F));
|
||||
}
|
||||
}
|
||||
|
||||
// CIRC (Circular)
|
||||
inline auto circIn(float t) -> float {
|
||||
// CIRC (Circular)
|
||||
inline auto circIn(float t) -> float {
|
||||
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;
|
||||
return std::sqrt(1.0F - (F * F));
|
||||
}
|
||||
}
|
||||
|
||||
inline auto circInOut(float t) -> float {
|
||||
inline auto circInOut(float t) -> float {
|
||||
if (t < 0.5F) {
|
||||
return 0.5F * (1.0F - std::sqrt(1.0F - (4.0F * t * t)));
|
||||
}
|
||||
const float F = (2.0F * t) - 2.0F;
|
||||
return 0.5F * (std::sqrt(1.0F - (F * F)) + 1.0F);
|
||||
}
|
||||
}
|
||||
|
||||
// BACK (Overshoot - retrocede antes de avanzar)
|
||||
inline auto backIn(float t, float overshoot = 1.70158F) -> float {
|
||||
// BACK (Overshoot - retrocede antes de avanzar)
|
||||
inline auto backIn(float t, float overshoot = 1.70158F) -> float {
|
||||
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;
|
||||
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;
|
||||
|
||||
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;
|
||||
return 0.5F * (F * F * ((S + 1.0F) * F + S) + 2.0F);
|
||||
}
|
||||
}
|
||||
|
||||
// ELASTIC (Oscilación elástica - efecto de resorte)
|
||||
inline auto elasticIn(float t, float amplitude = 1.0F, float period = 0.3F) -> float {
|
||||
// ELASTIC (Oscilación elástica - efecto de resorte)
|
||||
inline auto elasticIn(float t, float amplitude = 1.0F, float period = 0.3F) -> float {
|
||||
if (t == 0.0F || t == 1.0F) {
|
||||
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;
|
||||
return -(amplitude * std::pow(2.0F, 10.0F * F) *
|
||||
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) {
|
||||
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) *
|
||||
std::sin((t - S) * (2.0F * std::numbers::pi_v<float>) / period)) +
|
||||
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) {
|
||||
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) *
|
||||
std::sin((F - S) * (2.0F * std::numbers::pi_v<float>) / period)) +
|
||||
1.0F;
|
||||
}
|
||||
}
|
||||
|
||||
// BOUNCE (Rebote - simula física de rebote)
|
||||
inline auto bounceOut(float t) -> float {
|
||||
// BOUNCE (Rebote - simula física de rebote)
|
||||
inline auto bounceOut(float t) -> float {
|
||||
const float N1 = 7.5625F;
|
||||
const float D1 = 2.75F;
|
||||
|
||||
@@ -235,17 +235,17 @@ inline auto bounceOut(float t) -> float {
|
||||
}
|
||||
const float F = t - (2.625F / D1);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
inline auto bounceInOut(float t) -> float {
|
||||
inline auto bounceInOut(float t) -> float {
|
||||
if (t < 0.5F) {
|
||||
return 0.5F * bounceIn(2.0F * t);
|
||||
}
|
||||
return (0.5F * bounceOut((2.0F * t) - 1.0F)) + 0.5F;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Easing
|
||||
|
||||
Reference in New Issue
Block a user