clang-format

This commit is contained in:
2026-03-23 08:58:31 +01:00
parent 302b86ddb4
commit 3ca744ee46
88 changed files with 7147 additions and 7090 deletions

View File

@@ -6,6 +6,7 @@ project(coffee_crisis_arcade_edition VERSION 2.00)
# Establecer estándar de C++ # Establecer estándar de C++
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Establece la política CMP0072 para indicar cómo se debe seleccionar la implementación de OpenGL. # Establece la política CMP0072 para indicar cómo se debe seleccionar la implementación de OpenGL.
# En este caso, se elige la opción "GLVND", que utiliza bibliotecas modernas y modulares (libOpenGL, libGLX), # En este caso, se elige la opción "GLVND", que utiliza bibliotecas modernas y modulares (libOpenGL, libGLX),
@@ -176,3 +177,60 @@ endif()
# Especificar la ubicación del ejecutable # Especificar la ubicación del ejecutable
set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}) set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR})
# --- 5. STATIC ANALYSIS TARGETS ---
find_program(CLANG_TIDY_EXE NAMES clang-tidy)
find_program(CLANG_FORMAT_EXE NAMES clang-format)
# Recopilar todos los archivos fuente, excluyendo external/
file(GLOB_RECURSE ALL_SOURCE_FILES
"${CMAKE_SOURCE_DIR}/source/*.cpp"
"${CMAKE_SOURCE_DIR}/source/*.hpp"
"${CMAKE_SOURCE_DIR}/source/*.h"
)
list(FILTER ALL_SOURCE_FILES EXCLUDE REGEX ".*/external/.*")
# Targets de clang-tidy
if(CLANG_TIDY_EXE)
add_custom_target(tidy
COMMAND ${CLANG_TIDY_EXE}
-p ${CMAKE_BINARY_DIR}
${ALL_SOURCE_FILES}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Running clang-tidy..."
)
add_custom_target(tidy-fix
COMMAND ${CLANG_TIDY_EXE}
-p ${CMAKE_BINARY_DIR}
--fix
${ALL_SOURCE_FILES}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Running clang-tidy with fixes..."
)
else()
message(STATUS "clang-tidy no encontrado - targets 'tidy' y 'tidy-fix' no disponibles")
endif()
# Targets de clang-format
if(CLANG_FORMAT_EXE)
add_custom_target(format
COMMAND ${CLANG_FORMAT_EXE}
-i
${ALL_SOURCE_FILES}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Running clang-format..."
)
add_custom_target(format-check
COMMAND ${CLANG_FORMAT_EXE}
--dry-run
--Werror
${ALL_SOURCE_FILES}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Checking clang-format..."
)
else()
message(STATUS "clang-format no encontrado - targets 'format' y 'format-check' no disponibles")
endif()

View File

@@ -116,8 +116,8 @@ constexpr auto Color::HSV_TO_RGB(HSV hsv) -> Color {
// Implementaciones del namespace Colors // Implementaciones del namespace Colors
namespace Colors { namespace Colors {
// Obtiene un color del vector de colores imitando al Coche Fantástico // Obtiene un color del vector de colores imitando al Coche Fantástico
auto getColorLikeKnightRider(const std::vector<Color>& colors, int counter) -> Color { auto getColorLikeKnightRider(const std::vector<Color>& colors, int counter) -> Color {
int cycle_length = (colors.size() * 2) - 2; int cycle_length = (colors.size() * 2) - 2;
size_t n = counter % cycle_length; size_t n = counter % cycle_length;
@@ -129,9 +129,9 @@ auto getColorLikeKnightRider(const std::vector<Color>& colors, int counter) -> C
} }
return colors[index]; return colors[index];
} }
auto generateMirroredCycle(Color base, ColorCycleStyle style) -> Cycle { auto generateMirroredCycle(Color base, ColorCycleStyle style) -> Cycle {
Cycle result{}; Cycle result{};
HSV base_hsv = Color::RGB_TO_HSV(base); HSV base_hsv = Color::RGB_TO_HSV(base);
@@ -182,5 +182,5 @@ auto generateMirroredCycle(Color base, ColorCycleStyle style) -> Cycle {
} }
return result; return result;
} }
} // namespace Colors } // namespace Colors

View File

@@ -137,25 +137,25 @@ enum class ColorCycleStyle {
// --- Namespace Colors: constantes y utilidades de color --- // --- Namespace Colors: constantes y utilidades de color ---
namespace Colors { namespace Colors {
// --- Constantes --- // --- Constantes ---
constexpr size_t CYCLE_SIZE = 6; // Mitad del ciclo espejado constexpr size_t CYCLE_SIZE = 6; // Mitad del ciclo espejado
// --- Alias --- // --- Alias ---
using Cycle = std::array<Color, 2 * CYCLE_SIZE>; using Cycle = std::array<Color, 2 * CYCLE_SIZE>;
// --- Colores predefinidos --- // --- Colores predefinidos ---
constexpr Color NO_COLOR_MOD = Color(0XFF, 0XFF, 0XFF); constexpr Color NO_COLOR_MOD = Color(0XFF, 0XFF, 0XFF);
constexpr Color SHADOW_TEXT = Color(0X43, 0X43, 0X4F); constexpr Color SHADOW_TEXT = Color(0X43, 0X43, 0X4F);
constexpr Color TITLE_SHADOW_TEXT = Color(0x14, 0x87, 0xc4); constexpr Color TITLE_SHADOW_TEXT = Color(0x14, 0x87, 0xc4);
constexpr Color ORANGE_TEXT = Color(0XFF, 0X7A, 0X00); constexpr Color ORANGE_TEXT = Color(0XFF, 0X7A, 0X00);
constexpr Color FLASH = Color(0XFF, 0XFF, 0XFF); constexpr Color FLASH = Color(0XFF, 0XFF, 0XFF);
constexpr Color BLUE_SKY = Color(0X02, 0X88, 0XD1); constexpr Color BLUE_SKY = Color(0X02, 0X88, 0XD1);
constexpr Color PINK_SKY = Color(0XFF, 0X6B, 0X97); constexpr Color PINK_SKY = Color(0XFF, 0X6B, 0X97);
constexpr Color GREEN_SKY = Color(0X00, 0X79, 0X6B); constexpr Color GREEN_SKY = Color(0X00, 0X79, 0X6B);
// --- Funciones --- // --- Funciones ---
auto getColorLikeKnightRider(const std::vector<Color>& colors, int counter) -> Color; auto getColorLikeKnightRider(const std::vector<Color>& colors, int counter) -> Color;
auto generateMirroredCycle(Color base, ColorCycleStyle style = ColorCycleStyle::SUBTLE_PULSE) -> Cycle; auto generateMirroredCycle(Color base, ColorCycleStyle style = ColorCycleStyle::SUBTLE_PULSE) -> Cycle;
} // namespace Colors } // namespace Colors

View File

@@ -3,9 +3,10 @@
#include <algorithm> // Para std::max #include <algorithm> // Para std::max
class Cooldown { class Cooldown {
public: public:
Cooldown(float first_delay_s = 0.0F, float repeat_delay_s = 0.0F) Cooldown(float first_delay_s = 0.0F, float repeat_delay_s = 0.0F)
: first_delay_s_(first_delay_s), repeat_delay_s_(repeat_delay_s) {} : first_delay_s_(first_delay_s),
repeat_delay_s_(repeat_delay_s) {}
// Llamar cada frame con delta en segundos (float) // Llamar cada frame con delta en segundos (float)
void update(float delta_s) { void update(float delta_s) {
@@ -40,7 +41,7 @@ public:
// Fuerza un valor en segundos (útil para tests o resets) // Fuerza un valor en segundos (útil para tests o resets)
void forceSet(float seconds) { remaining_s_ = seconds > 0.0F ? seconds : 0.0F; } void forceSet(float seconds) { remaining_s_ = seconds > 0.0F ? seconds : 0.0F; }
private: private:
float first_delay_s_; float first_delay_s_;
float repeat_delay_s_; float repeat_delay_s_;
float remaining_s_{0.0F}; float remaining_s_{0.0F};

View File

@@ -11,232 +11,232 @@
// --- Namespace GameDefaults: configuración centralizada con valores por defecto del juego --- // --- Namespace GameDefaults: configuración centralizada con valores por defecto del juego ---
namespace GameDefaults { namespace GameDefaults {
// --- GAME --- // --- GAME ---
namespace Game { namespace Game {
constexpr float WIDTH = 320.0F; constexpr float WIDTH = 320.0F;
constexpr float HEIGHT = 256.0F; constexpr float HEIGHT = 256.0F;
constexpr int NAME_ENTRY_IDLE_TIME = 10; constexpr int NAME_ENTRY_IDLE_TIME = 10;
constexpr int NAME_ENTRY_TOTAL_TIME = 60; constexpr int NAME_ENTRY_TOTAL_TIME = 60;
constexpr bool HIT_STOP = false; constexpr bool HIT_STOP = false;
constexpr int HIT_STOP_MS = 500; constexpr int HIT_STOP_MS = 500;
constexpr const char* ITEM_TEXT_OUTLINE_COLOR = "FFFFFF00"; // 255, 255, 255, 0 constexpr const char* ITEM_TEXT_OUTLINE_COLOR = "FFFFFF00"; // 255, 255, 255, 0
// Play area por defecto // Play area por defecto
constexpr float PLAY_AREA_X = 0.0F; constexpr float PLAY_AREA_X = 0.0F;
constexpr float PLAY_AREA_Y = 0.0F; constexpr float PLAY_AREA_Y = 0.0F;
constexpr float PLAY_AREA_W = 320.0F; constexpr float PLAY_AREA_W = 320.0F;
constexpr float PLAY_AREA_H = 216.0F; constexpr float PLAY_AREA_H = 216.0F;
} // namespace Game } // namespace Game
// --- FADE --- // --- FADE ---
namespace Fade { namespace Fade {
constexpr const char* COLOR = "1F2B30"; constexpr const char* COLOR = "1F2B30";
constexpr float NUM_SQUARES_WIDTH = 160.0F; constexpr float NUM_SQUARES_WIDTH = 160.0F;
constexpr float NUM_SQUARES_HEIGHT = 128.0F; constexpr float NUM_SQUARES_HEIGHT = 128.0F;
constexpr int RANDOM_SQUARES_DURATION_MS = 1; constexpr int RANDOM_SQUARES_DURATION_MS = 1;
constexpr int POST_DURATION_MS = 80; constexpr int POST_DURATION_MS = 80;
constexpr float VENETIAN_SIZE = 12.0F; constexpr float VENETIAN_SIZE = 12.0F;
} // namespace Fade } // namespace Fade
// --- SCOREBOARD --- // --- SCOREBOARD ---
namespace Scoreboard { namespace Scoreboard {
constexpr float RECT_X = 0.0F; constexpr float RECT_X = 0.0F;
constexpr float RECT_Y = 216.0F; constexpr float RECT_Y = 216.0F;
constexpr float RECT_W = 320.0F; constexpr float RECT_W = 320.0F;
constexpr float RECT_H = 40.0F; constexpr float RECT_H = 40.0F;
constexpr bool SEPARATOR_AUTOCOLOR = true; constexpr bool SEPARATOR_AUTOCOLOR = true;
constexpr const char* SEPARATOR_COLOR = "0D1A2B"; constexpr const char* SEPARATOR_COLOR = "0D1A2B";
constexpr const char* EASY_COLOR = "4B692F"; constexpr const char* EASY_COLOR = "4B692F";
constexpr const char* NORMAL_COLOR = "2E3F47"; constexpr const char* NORMAL_COLOR = "2E3F47";
constexpr const char* HARD_COLOR = "76428A"; constexpr const char* HARD_COLOR = "76428A";
constexpr bool TEXT_AUTOCOLOR = true; constexpr bool TEXT_AUTOCOLOR = true;
constexpr const char* TEXT_COLOR1 = "FFFFFF"; constexpr const char* TEXT_COLOR1 = "FFFFFF";
constexpr const char* TEXT_COLOR2 = "FFFFFF"; constexpr const char* TEXT_COLOR2 = "FFFFFF";
constexpr int SKIP_COUNTDOWN_VALUE = 8; constexpr int SKIP_COUNTDOWN_VALUE = 8;
} // namespace Scoreboard } // namespace Scoreboard
// --- TITLE --- // --- TITLE ---
namespace Title { namespace Title {
constexpr int PRESS_START_POSITION = 180; constexpr int PRESS_START_POSITION = 180;
constexpr float DURATION_S = 14.0F; constexpr float DURATION_S = 14.0F;
constexpr int ARCADE_EDITION_POSITION = 123; constexpr int ARCADE_EDITION_POSITION = 123;
constexpr int TITLE_C_C_POSITION = 80; constexpr int TITLE_C_C_POSITION = 80;
constexpr const char* BG_COLOR = "41526F"; constexpr const char* BG_COLOR = "41526F";
} // namespace Title } // namespace Title
// --- BACKGROUND --- // --- BACKGROUND ---
namespace Background { namespace Background {
constexpr const char* ATTENUATE_COLOR = "FFFFFF00"; constexpr const char* ATTENUATE_COLOR = "FFFFFF00";
} }
// --- BALLOONS --- // --- BALLOONS ---
namespace Balloon { namespace Balloon {
// Configuración de física para cada nivel de globo // Configuración de física para cada nivel de globo
struct BalloonSettings { struct BalloonSettings {
float vel; float vel;
float grav; float grav;
constexpr BalloonSettings(float v, float g) constexpr BalloonSettings(float v, float g)
: vel(v), : vel(v),
grav(g) {} grav(g) {}
}; };
// Valores para deltaTime en segundos: vel en pixels/s, grav en pixels/s² (aceleración) // Valores para deltaTime en segundos: vel en pixels/s, grav en pixels/s² (aceleración)
constexpr std::array<BalloonSettings, 4> SETTINGS = {{ constexpr std::array<BalloonSettings, 4> SETTINGS = {{
BalloonSettings(165.0F, 320.0F), // Globo 0: vel=165 pixels/s, grav=320 pixels/s² BalloonSettings(165.0F, 320.0F), // Globo 0: vel=165 pixels/s, grav=320 pixels/s²
BalloonSettings(222.0F, 360.0F), // Globo 1: vel=222 pixels/s, grav=360 pixels/s² BalloonSettings(222.0F, 360.0F), // Globo 1: vel=222 pixels/s, grav=360 pixels/s²
BalloonSettings(282.0F, 360.0F), // Globo 2: vel=282 pixels/s, grav=360 pixels/s² BalloonSettings(282.0F, 360.0F), // Globo 2: vel=282 pixels/s, grav=360 pixels/s²
BalloonSettings(327.0F, 360.0F) // Globo 3: vel=327 pixels/s, grav=360 pixels/s² BalloonSettings(327.0F, 360.0F) // Globo 3: vel=327 pixels/s, grav=360 pixels/s²
}}; }};
constexpr std::array<const char*, 4> COLORS = { constexpr std::array<const char*, 4> COLORS = {
"blue", "blue",
"orange", "orange",
"red", "red",
"green"}; "green"};
constexpr bool BOUNCING_SOUND = false; constexpr bool BOUNCING_SOUND = false;
} // namespace Balloon } // namespace Balloon
// --- NOTIFICATION --- // --- NOTIFICATION ---
namespace Notification { namespace Notification {
constexpr Notifier::Position POS_V = Notifier::Position::TOP; constexpr Notifier::Position POS_V = Notifier::Position::TOP;
constexpr Notifier::Position POS_H = Notifier::Position::LEFT; constexpr Notifier::Position POS_H = Notifier::Position::LEFT;
constexpr bool SOUND = false; constexpr bool SOUND = false;
constexpr const char* COLOR = "303030"; constexpr const char* COLOR = "303030";
} // namespace Notification } // namespace Notification
// --- SERVICE MENU --- // --- SERVICE MENU ---
namespace ServiceMenu { namespace ServiceMenu {
constexpr const char* TITLE_COLOR = "99FF62"; constexpr const char* TITLE_COLOR = "99FF62";
constexpr const char* TEXT_COLOR = "FFFFFF"; constexpr const char* TEXT_COLOR = "FFFFFF";
constexpr const char* SELECTED_COLOR = "FFDC44"; constexpr const char* SELECTED_COLOR = "FFDC44";
constexpr const char* BG_COLOR = "000F00F5"; constexpr const char* BG_COLOR = "000F00F5";
constexpr bool DROP_SHADOW = false; constexpr bool DROP_SHADOW = false;
// WindowMessage defaults // WindowMessage defaults
namespace WindowMessage { namespace WindowMessage {
constexpr const char* BG_COLOR = "141E32F0"; // Color(20, 30, 50, 240) constexpr const char* BG_COLOR = "141E32F0"; // Color(20, 30, 50, 240)
constexpr const char* BORDER_COLOR = "6496C8FF"; // Color(100, 150, 200, 255) constexpr const char* BORDER_COLOR = "6496C8FF"; // Color(100, 150, 200, 255)
constexpr const char* TITLE_COLOR = "6496C8FF"; // Color(100, 150, 200, 255) constexpr const char* TITLE_COLOR = "6496C8FF"; // Color(100, 150, 200, 255)
constexpr const char* TEXT_COLOR = "DCDCDCFF"; // Color(220, 220, 220, 255) constexpr const char* TEXT_COLOR = "DCDCDCFF"; // Color(220, 220, 220, 255)
constexpr float PADDING = 15.0F; constexpr float PADDING = 15.0F;
constexpr float LINE_SPACING = 5.0F; constexpr float LINE_SPACING = 5.0F;
constexpr float TITLE_SEPARATOR_SPACING = 10.0F; // Cambiado a float constexpr float TITLE_SEPARATOR_SPACING = 10.0F; // Cambiado a float
constexpr float MIN_WIDTH = 250.0F; constexpr float MIN_WIDTH = 250.0F;
constexpr float MIN_HEIGHT = 32.0F; // Cambiado a float constexpr float MIN_HEIGHT = 32.0F; // Cambiado a float
constexpr float MAX_WIDTH_RATIO = 0.8F; // Nuevo constexpr float MAX_WIDTH_RATIO = 0.8F; // Nuevo
constexpr float MAX_HEIGHT_RATIO = 0.8F; // Nuevo constexpr float MAX_HEIGHT_RATIO = 0.8F; // Nuevo
constexpr float TEXT_SAFETY_MARGIN = 15.0F; constexpr float TEXT_SAFETY_MARGIN = 15.0F;
constexpr float ANIMATION_DURATION = 0.3F; constexpr float ANIMATION_DURATION = 0.3F;
} // namespace WindowMessage } // namespace WindowMessage
} // namespace ServiceMenu } // namespace ServiceMenu
// --- INTRO --- // --- INTRO ---
namespace Intro { namespace Intro {
constexpr const char* BG_COLOR = "4664BD"; constexpr const char* BG_COLOR = "4664BD";
constexpr const char* CARD_COLOR = "CBDBFC"; constexpr const char* CARD_COLOR = "CBDBFC";
constexpr const char* SHADOW_COLOR = "00000080"; constexpr const char* SHADOW_COLOR = "00000080";
constexpr int TEXT_DISTANCE_FROM_BOTTOM = 48; constexpr int TEXT_DISTANCE_FROM_BOTTOM = 48;
} // namespace Intro } // namespace Intro
// --- DEBUG --- // --- DEBUG ---
namespace Debug { namespace Debug {
constexpr const char* COLOR = "00FFFF"; constexpr const char* COLOR = "00FFFF";
} }
// --- RESOURCE --- // --- RESOURCE ---
namespace Resource { namespace Resource {
constexpr const char* COLOR = "FFFFFF"; constexpr const char* COLOR = "FFFFFF";
} }
// --- TABE --- // --- TABE ---
namespace Tabe { namespace Tabe {
constexpr float MIN_SPAWN_TIME = 2.0F; constexpr float MIN_SPAWN_TIME = 2.0F;
constexpr float MAX_SPAWN_TIME = 3.0F; constexpr float MAX_SPAWN_TIME = 3.0F;
} // namespace Tabe } // namespace Tabe
// --- PLAYER --- // --- PLAYER ---
namespace Player { namespace Player {
namespace DefaultShirt { namespace DefaultShirt {
// Player 0 (Jugador 1) // Player 0 (Jugador 1)
constexpr const char* PLAYER0_DARKEST = "028ECFFF"; // 2, 142, 207, 255 constexpr const char* PLAYER0_DARKEST = "028ECFFF"; // 2, 142, 207, 255
constexpr const char* PLAYER0_DARK = "0297DBFF"; // 2, 151, 219, 255 constexpr const char* PLAYER0_DARK = "0297DBFF"; // 2, 151, 219, 255
constexpr const char* PLAYER0_BASE = "029FE8FF"; // 2, 159, 232, 255 constexpr const char* PLAYER0_BASE = "029FE8FF"; // 2, 159, 232, 255
constexpr const char* PLAYER0_LIGHT = "03A9F4FF"; // 3, 169, 244, 255 constexpr const char* PLAYER0_LIGHT = "03A9F4FF"; // 3, 169, 244, 255
// Player 1 (Jugador 2) // Player 1 (Jugador 2)
constexpr const char* PLAYER1_DARKEST = "8E8E8EFF"; // 142, 142, 142, 255 constexpr const char* PLAYER1_DARKEST = "8E8E8EFF"; // 142, 142, 142, 255
constexpr const char* PLAYER1_DARK = "AEADADFF"; // 174, 173, 173, 255 constexpr const char* PLAYER1_DARK = "AEADADFF"; // 174, 173, 173, 255
constexpr const char* PLAYER1_BASE = "E4E4E4FF"; // 228, 228, 228, 255 constexpr const char* PLAYER1_BASE = "E4E4E4FF"; // 228, 228, 228, 255
constexpr const char* PLAYER1_LIGHT = "F7F1F1FF"; // 247, 241, 241, 255 constexpr const char* PLAYER1_LIGHT = "F7F1F1FF"; // 247, 241, 241, 255
} // namespace DefaultShirt } // namespace DefaultShirt
namespace OneCoffeeShirt { namespace OneCoffeeShirt {
// Player 0 (Jugador 1) // Player 0 (Jugador 1)
constexpr const char* PLAYER0_DARKEST = "3D9C70FF"; // 61, 156, 112, 255 constexpr const char* PLAYER0_DARKEST = "3D9C70FF"; // 61, 156, 112, 255
constexpr const char* PLAYER0_DARK = "4FA370FF"; // 79, 163, 112, 255 constexpr const char* PLAYER0_DARK = "4FA370FF"; // 79, 163, 112, 255
constexpr const char* PLAYER0_BASE = "5DDE70FF"; // 93, 222, 112, 255 constexpr const char* PLAYER0_BASE = "5DDE70FF"; // 93, 222, 112, 255
constexpr const char* PLAYER0_LIGHT = "7DF25CFF"; // 125, 242, 92, 255 constexpr const char* PLAYER0_LIGHT = "7DF25CFF"; // 125, 242, 92, 255
// Player 1 (Jugador 2) // Player 1 (Jugador 2)
constexpr const char* PLAYER1_DARKEST = "2E8B57FF"; // 46, 139, 87, 255 constexpr const char* PLAYER1_DARKEST = "2E8B57FF"; // 46, 139, 87, 255
constexpr const char* PLAYER1_DARK = "3CB371FF"; // 60, 179, 113, 255 constexpr const char* PLAYER1_DARK = "3CB371FF"; // 60, 179, 113, 255
constexpr const char* PLAYER1_BASE = "48D181FF"; // 72, 209, 129, 255 constexpr const char* PLAYER1_BASE = "48D181FF"; // 72, 209, 129, 255
constexpr const char* PLAYER1_LIGHT = "55EF8DFF"; // 85, 239, 141, 255 constexpr const char* PLAYER1_LIGHT = "55EF8DFF"; // 85, 239, 141, 255
} // namespace OneCoffeeShirt } // namespace OneCoffeeShirt
namespace TwoCoffeeShirt { namespace TwoCoffeeShirt {
// Player 0 (Jugador 1) // Player 0 (Jugador 1)
constexpr const char* PLAYER0_DARKEST = "D6A41AFF"; // 214, 164, 26, 255 constexpr const char* PLAYER0_DARKEST = "D6A41AFF"; // 214, 164, 26, 255
constexpr const char* PLAYER0_DARK = "E3AE1BFF"; // 227, 174, 27, 255 constexpr const char* PLAYER0_DARK = "E3AE1BFF"; // 227, 174, 27, 255
constexpr const char* PLAYER0_BASE = "EFB71DFF"; // 239, 183, 29, 255 constexpr const char* PLAYER0_BASE = "EFB71DFF"; // 239, 183, 29, 255
constexpr const char* PLAYER0_LIGHT = "FCC11EFF"; // 252, 193, 30, 255 constexpr const char* PLAYER0_LIGHT = "FCC11EFF"; // 252, 193, 30, 255
// Player 1 (Jugador 2) // Player 1 (Jugador 2)
constexpr const char* PLAYER1_DARKEST = "E08500FF"; // 224, 133, 0, 255 constexpr const char* PLAYER1_DARKEST = "E08500FF"; // 224, 133, 0, 255
constexpr const char* PLAYER1_DARK = "FA7D00FF"; // 250, 125, 0, 255 constexpr const char* PLAYER1_DARK = "FA7D00FF"; // 250, 125, 0, 255
constexpr const char* PLAYER1_BASE = "FAA200FF"; // 250, 162, 0, 255 constexpr const char* PLAYER1_BASE = "FAA200FF"; // 250, 162, 0, 255
constexpr const char* PLAYER1_LIGHT = "FA8500FF"; // 250, 133, 0, 255 constexpr const char* PLAYER1_LIGHT = "FA8500FF"; // 250, 133, 0, 255
} // namespace TwoCoffeeShirt } // namespace TwoCoffeeShirt
namespace OutlineColor { namespace OutlineColor {
// Player 0 (Jugador 1) // Player 0 (Jugador 1)
constexpr const char* PLAYER0 = "66323FFF"; constexpr const char* PLAYER0 = "66323FFF";
// Player 1 (Jugador 2) // Player 1 (Jugador 2)
constexpr const char* PLAYER1 = "422028FF"; constexpr const char* PLAYER1 = "422028FF";
} // namespace OutlineColor } // namespace OutlineColor
} // namespace Player } // namespace Player
// --- OPTIONS --- // --- OPTIONS ---
namespace Options { namespace Options {
// Window // Window
constexpr const char* WINDOW_CAPTION = "© 2025 Coffee Crisis Arcade Edition — JailDesigner"; constexpr const char* WINDOW_CAPTION = "© 2025 Coffee Crisis Arcade Edition — JailDesigner";
constexpr int WINDOW_ZOOM = 2; constexpr int WINDOW_ZOOM = 2;
constexpr int WINDOW_MAX_ZOOM = 2; constexpr int WINDOW_MAX_ZOOM = 2;
// Video // Video
constexpr SDL_ScaleMode VIDEO_SCALE_MODE = SDL_ScaleMode::SDL_SCALEMODE_NEAREST; constexpr SDL_ScaleMode VIDEO_SCALE_MODE = SDL_ScaleMode::SDL_SCALEMODE_NEAREST;
constexpr bool VIDEO_FULLSCREEN = false; constexpr bool VIDEO_FULLSCREEN = false;
constexpr bool VIDEO_VSYNC = true; constexpr bool VIDEO_VSYNC = true;
constexpr bool VIDEO_INTEGER_SCALE = true; constexpr bool VIDEO_INTEGER_SCALE = true;
constexpr bool VIDEO_SHADERS = false; constexpr bool VIDEO_SHADERS = false;
// Music // Music
constexpr bool MUSIC_ENABLED = true; constexpr bool MUSIC_ENABLED = true;
constexpr int MUSIC_VOLUME = 100; constexpr int MUSIC_VOLUME = 100;
// Sound // Sound
constexpr bool SOUND_ENABLED = true; constexpr bool SOUND_ENABLED = true;
constexpr int SOUND_VOLUME = 100; constexpr int SOUND_VOLUME = 100;
// Audio // Audio
constexpr bool AUDIO_ENABLED = true; constexpr bool AUDIO_ENABLED = true;
constexpr int AUDIO_VOLUME = 100; constexpr int AUDIO_VOLUME = 100;
// Settings // Settings
constexpr bool SETTINGS_AUTOFIRE = true; constexpr bool SETTINGS_AUTOFIRE = true;
constexpr bool SETTINGS_SHUTDOWN_ENABLED = false; constexpr bool SETTINGS_SHUTDOWN_ENABLED = false;
constexpr const char* PARAMS_FILE = "param_320x256.txt"; constexpr const char* PARAMS_FILE = "param_320x256.txt";
} // namespace Options } // namespace Options
} // namespace GameDefaults } // namespace GameDefaults

View File

@@ -12,7 +12,7 @@
#include "ui/window_message.hpp" #include "ui/window_message.hpp"
namespace Options { namespace Options {
struct Gamepad; struct Gamepad;
} }
// --- Clase DefineButtons: configuración de botones de gamepad --- // --- Clase DefineButtons: configuración de botones de gamepad ---

View File

@@ -4,35 +4,35 @@
namespace Difficulty { namespace Difficulty {
static std::vector<Info> difficulties_list; static std::vector<Info> difficulties_list;
void init() { void init() {
difficulties_list = { difficulties_list = {
{.code = Code::EASY, .name = "Easy"}, {.code = Code::EASY, .name = "Easy"},
{.code = Code::NORMAL, .name = "Normal"}, {.code = Code::NORMAL, .name = "Normal"},
{.code = Code::HARD, .name = "Hard"}}; {.code = Code::HARD, .name = "Hard"}};
} }
auto getDifficulties() -> std::vector<Info>& { auto getDifficulties() -> std::vector<Info>& {
return difficulties_list; return difficulties_list;
} }
auto getNameFromCode(Code code) -> std::string { auto getNameFromCode(Code code) -> std::string {
for (const auto& difficulty : difficulties_list) { for (const auto& difficulty : difficulties_list) {
if (difficulty.code == code) { if (difficulty.code == code) {
return difficulty.name; return difficulty.name;
} }
} }
return !difficulties_list.empty() ? difficulties_list.front().name : "Unknown"; return !difficulties_list.empty() ? difficulties_list.front().name : "Unknown";
} }
auto getCodeFromName(const std::string& name) -> Code { auto getCodeFromName(const std::string& name) -> Code {
for (const auto& difficulty : difficulties_list) { for (const auto& difficulty : difficulties_list) {
if (difficulty.name == name) { if (difficulty.name == name) {
return difficulty.code; return difficulty.code;
} }
} }
return !difficulties_list.empty() ? difficulties_list.front().code : Code::NORMAL; return !difficulties_list.empty() ? difficulties_list.front().code : Code::NORMAL;
} }
} // namespace Difficulty } // namespace Difficulty

View File

@@ -5,24 +5,24 @@
namespace Difficulty { namespace Difficulty {
// --- Enums --- // --- Enums ---
enum class Code { enum class Code {
EASY = 0, // Dificultad fácil EASY = 0, // Dificultad fácil
NORMAL = 1, // Dificultad normal NORMAL = 1, // Dificultad normal
HARD = 2, // Dificultad difícil HARD = 2, // Dificultad difícil
}; };
// --- Estructuras --- // --- Estructuras ---
struct Info { struct Info {
Code code; // Código de dificultad Code code; // Código de dificultad
std::string name; // Nombre traducible std::string name; // Nombre traducible
}; };
// --- Funciones --- // --- Funciones ---
void init(); // Inicializa la lista de dificultades con sus valores por defecto void init(); // Inicializa la lista de dificultades con sus valores por defecto
auto getDifficulties() -> std::vector<Info>&; // Devuelve una referencia al vector de todas las dificultades auto getDifficulties() -> std::vector<Info>&; // Devuelve una referencia al vector de todas las dificultades
auto getNameFromCode(Code code) -> std::string; // Obtiene el nombre de una dificultad a partir de su código auto getNameFromCode(Code code) -> std::string; // Obtiene el nombre de una dificultad a partir de su código
auto getCodeFromName(const std::string& name) -> Code; // Obtiene el código de una dificultad a partir de su nombre auto getCodeFromName(const std::string& name) -> Code; // Obtiene el código de una dificultad a partir de su nombre
} // namespace Difficulty } // namespace Difficulty

View File

@@ -4,7 +4,7 @@
#include <string> // Para string #include <string> // Para string
namespace Lang { namespace Lang {
enum class Code : int; enum class Code : int;
} }
// --- Clase Director: gestor principal de la aplicación --- // --- Clase Director: gestor principal de la aplicación ---

View File

@@ -223,14 +223,14 @@ void Fade::updateRandomSquare2Fade() {
squares_to_activate = total_squares; squares_to_activate = total_squares;
} }
for (int i = 0; i < squares_to_activate; ++i) { for (int i = 0; i < squares_to_activate; ++i) {
if (square_age_[i] == -1) {square_age_[i] = elapsed_time;} if (square_age_[i] == -1) { square_age_[i] = elapsed_time; }
} }
} else { } else {
squares_to_activate = total_squares; squares_to_activate = total_squares;
float activation_progress = static_cast<float>(elapsed_time) / activation_time; float activation_progress = static_cast<float>(elapsed_time) / activation_time;
int squares_starting_transition = std::min(total_squares, std::max(1, static_cast<int>(activation_progress * total_squares))); int squares_starting_transition = std::min(total_squares, std::max(1, static_cast<int>(activation_progress * total_squares)));
for (int i = 0; i < squares_starting_transition; ++i) { for (int i = 0; i < squares_starting_transition; ++i) {
if (square_age_[i] == -1) {square_age_[i] = elapsed_time;} if (square_age_[i] == -1) { square_age_[i] = elapsed_time; }
} }
} }
@@ -515,7 +515,6 @@ void Fade::activate() {
} }
} }
// Establece el color del fade // Establece el color del fade
void Fade::setColor(Uint8 r, Uint8 g, Uint8 b) { void Fade::setColor(Uint8 r, Uint8 g, Uint8 b) {
r_ = r; r_ = r;

View File

@@ -16,8 +16,8 @@
#include "ui/service_menu.hpp" // Para ServiceMenu #include "ui/service_menu.hpp" // Para ServiceMenu
namespace GlobalEvents { namespace GlobalEvents {
// Comprueba los eventos de Input y muestra notificaciones // Comprueba los eventos de Input y muestra notificaciones
void handleInputEvents(const SDL_Event& event) { void handleInputEvents(const SDL_Event& event) {
static auto* input_ = Input::get(); static auto* input_ = Input::get();
auto message = input_->handleEvent(event); auto message = input_->handleEvent(event);
@@ -38,10 +38,10 @@ void handleInputEvents(const SDL_Event& event) {
Options::gamepad_manager.resyncGamepadsWithPlayers(); Options::gamepad_manager.resyncGamepadsWithPlayers();
Notifier::get()->show({message}); Notifier::get()->show({message});
ServiceMenu::get()->refresh(); ServiceMenu::get()->refresh();
} }
// Comprueba los eventos que se pueden producir en cualquier sección del juego // Comprueba los eventos que se pueden producir en cualquier sección del juego
void handle(const SDL_Event& event) { void handle(const SDL_Event& event) {
switch (event.type) { switch (event.type) {
case SDL_EVENT_QUIT: // Evento de salida de la aplicación case SDL_EVENT_QUIT: // Evento de salida de la aplicación
Section::name = Section::Name::QUIT; Section::name = Section::Name::QUIT;
@@ -64,5 +64,5 @@ void handle(const SDL_Event& event) {
ServiceMenu::get()->handleEvent(event); ServiceMenu::get()->handleEvent(event);
Mouse::handleEvent(event); Mouse::handleEvent(event);
handleInputEvents(event); handleInputEvents(event);
} }
} // namespace GlobalEvents } // namespace GlobalEvents

View File

@@ -4,6 +4,6 @@
// --- Namespace GlobalEvents: maneja eventos globales del juego --- // --- Namespace GlobalEvents: maneja eventos globales del juego ---
namespace GlobalEvents { namespace GlobalEvents {
// --- Funciones --- // --- Funciones ---
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); // Comprueba los eventos que se pueden producir en cualquier sección del juego
} // namespace GlobalEvents } // namespace GlobalEvents

View File

@@ -19,8 +19,8 @@
#include "utils.hpp" // Para boolToOnOff #include "utils.hpp" // Para boolToOnOff
namespace GlobalInputs { namespace GlobalInputs {
// Termina // Termina
void quit() { void quit() {
const std::string CODE = "QUIT"; const std::string CODE = "QUIT";
if (Notifier::get()->checkCode(CODE)) { if (Notifier::get()->checkCode(CODE)) {
// Si la notificación de salir está activa, cambia de sección // Si la notificación de salir está activa, cambia de sección
@@ -30,10 +30,10 @@ void quit() {
// Si la notificación de salir no está activa, muestra la notificación // Si la notificación de salir no está activa, muestra la notificación
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 01"), std::string()}, -1, CODE); Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 01"), std::string()}, -1, CODE);
} }
} }
// Reinicia // Reinicia
void reset() { void reset() {
const std::string CODE = "RESET"; const std::string CODE = "RESET";
if (Notifier::get()->checkCode(CODE)) { if (Notifier::get()->checkCode(CODE)) {
Section::name = Section::Name::RESET; Section::name = Section::Name::RESET;
@@ -41,35 +41,35 @@ void reset() {
} else { } else {
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 03"), std::string()}, -1, CODE); Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 03"), std::string()}, -1, CODE);
} }
} }
// Activa o desactiva el audio // Activa o desactiva el audio
void toggleAudio() { void toggleAudio() {
Options::audio.enabled = !Options::audio.enabled; Options::audio.enabled = !Options::audio.enabled;
Audio::get()->enable(Options::audio.enabled); Audio::get()->enable(Options::audio.enabled);
Notifier::get()->show({"Audio " + boolToOnOff(Options::audio.enabled)}); Notifier::get()->show({"Audio " + boolToOnOff(Options::audio.enabled)});
} }
// Cambia el modo de escalado entero // Cambia el modo de escalado entero
void toggleIntegerScale() { void toggleIntegerScale() {
Screen::get()->toggleIntegerScale(); Screen::get()->toggleIntegerScale();
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 12") + " " + boolToOnOff(Options::video.integer_scale)}); Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 12") + " " + boolToOnOff(Options::video.integer_scale)});
} }
// Activa / desactiva el vsync // Activa / desactiva el vsync
void toggleVSync() { void toggleVSync() {
Screen::get()->toggleVSync(); Screen::get()->toggleVSync();
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 14") + " " + boolToOnOff(Options::video.vsync)}); Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 14") + " " + boolToOnOff(Options::video.vsync)});
} }
// Activa o desactiva los shaders // Activa o desactiva los shaders
void toggleShaders() { void toggleShaders() {
Screen::get()->toggleShaders(); Screen::get()->toggleShaders();
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 13") + " " + boolToOnOff(Options::video.shaders)}); Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 13") + " " + boolToOnOff(Options::video.shaders)});
} }
// Cambia al siguiente idioma // Cambia al siguiente idioma
void setNextLang() { void setNextLang() {
const std::string CODE = "LANG"; const std::string CODE = "LANG";
const auto NEXT_LANG_CODE = Lang::getNextLangCode(Options::settings.language); const auto NEXT_LANG_CODE = Lang::getNextLangCode(Options::settings.language);
const auto NEXT_LANG_NAME = Lang::getLangName(NEXT_LANG_CODE); const auto NEXT_LANG_NAME = Lang::getLangName(NEXT_LANG_CODE);
@@ -84,16 +84,16 @@ void setNextLang() {
// Si la notificación de cambiar idioma no está activa, muestra la notificación // Si la notificación de cambiar idioma no está activa, muestra la notificación
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 04") + NEXT_LANG_NAME, std::string()}, -1, CODE); Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 04") + NEXT_LANG_NAME, std::string()}, -1, CODE);
} }
} }
// Cambia el modo de disparo // Cambia el modo de disparo
void toggleFireMode() { void toggleFireMode() {
Options::settings.autofire = !Options::settings.autofire; Options::settings.autofire = !Options::settings.autofire;
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 08") + " " + boolToOnOff(Options::settings.autofire)}); Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 08") + " " + boolToOnOff(Options::settings.autofire)});
} }
// Salta una sección del juego // Salta una sección del juego
void skipSection() { void skipSection() {
switch (Section::name) { switch (Section::name) {
case Section::Name::INTRO: case Section::Name::INTRO:
Audio::get()->stopMusic(); Audio::get()->stopMusic();
@@ -109,36 +109,36 @@ void skipSection() {
default: default:
break; break;
} }
} }
// Activa el menu de servicio // Activa el menu de servicio
void toggleServiceMenu() { void toggleServiceMenu() {
ServiceMenu::get()->toggle(); ServiceMenu::get()->toggle();
} }
// Cambia el modo de pantalla completa // Cambia el modo de pantalla completa
void toggleFullscreen() { void toggleFullscreen() {
Screen::get()->toggleFullscreen(); Screen::get()->toggleFullscreen();
const std::string MODE = Options::video.fullscreen ? Lang::getText("[NOTIFICATIONS] 11") : Lang::getText("[NOTIFICATIONS] 10"); const std::string MODE = Options::video.fullscreen ? Lang::getText("[NOTIFICATIONS] 11") : Lang::getText("[NOTIFICATIONS] 10");
Notifier::get()->show({MODE}); Notifier::get()->show({MODE});
} }
// Reduce el tamaño de la ventana // Reduce el tamaño de la ventana
void decWindowSize() { void decWindowSize() {
if (Screen::get()->decWindowSize()) { if (Screen::get()->decWindowSize()) {
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 09") + " x" + std::to_string(Options::window.zoom)}); Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 09") + " x" + std::to_string(Options::window.zoom)});
} }
} }
// Aumenta el tamaño de la ventana // Aumenta el tamaño de la ventana
void incWindowSize() { void incWindowSize() {
if (Screen::get()->incWindowSize()) { if (Screen::get()->incWindowSize()) {
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 09") + " x" + std::to_string(Options::window.zoom)}); Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 09") + " x" + std::to_string(Options::window.zoom)});
} }
} }
// Comprueba el boton de servicio // Comprueba el boton de servicio
auto checkServiceButton() -> bool { auto checkServiceButton() -> bool {
// Teclado // Teclado
if (Input::get()->checkAction(Input::Action::SERVICE, Input::DO_NOT_ALLOW_REPEAT, Input::CHECK_KEYBOARD)) { if (Input::get()->checkAction(Input::Action::SERVICE, Input::DO_NOT_ALLOW_REPEAT, Input::CHECK_KEYBOARD)) {
toggleServiceMenu(); toggleServiceMenu();
@@ -154,10 +154,10 @@ auto checkServiceButton() -> bool {
} }
return false; return false;
} }
// Comprueba las entradas para elementos del sistema // Comprueba las entradas para elementos del sistema
auto checkSystemInputs() -> bool { auto checkSystemInputs() -> bool {
using Action = Input::Action; using Action = Input::Action;
static const std::vector<std::pair<Action, std::function<void()>>> ACTIONS = { static const std::vector<std::pair<Action, std::function<void()>>> ACTIONS = {
@@ -184,25 +184,25 @@ auto checkSystemInputs() -> bool {
} }
return false; return false;
}); });
} }
// Comprueba el resto de entradas // Comprueba el resto de entradas
auto checkOtherInputs() -> bool { auto checkOtherInputs() -> bool {
// Saltar sección // Saltar sección
if ((Input::get()->checkAnyButton()) && !ServiceMenu::get()->isEnabled()) { if ((Input::get()->checkAnyButton()) && !ServiceMenu::get()->isEnabled()) {
skipSection(); skipSection();
return true; return true;
} }
return false; return false;
} }
// Comprueba las entradas del Menu de Servicio // Comprueba las entradas del Menu de Servicio
inline auto checkServiceMenuInputs() -> bool { inline auto checkServiceMenuInputs() -> bool {
return ServiceMenu::get()->checkInput(); return ServiceMenu::get()->checkInput();
} }
// Comprueba los inputs que se pueden introducir en cualquier sección del juego // Comprueba los inputs que se pueden introducir en cualquier sección del juego
auto check() -> bool { auto check() -> bool {
if (checkServiceButton()) { if (checkServiceButton()) {
return true; return true;
} }
@@ -216,5 +216,5 @@ auto check() -> bool {
return true; return true;
} }
return false; return false;
} }
} // namespace GlobalInputs } // namespace GlobalInputs

View File

@@ -2,6 +2,6 @@
// --- Namespace GlobalInputs: gestiona inputs globales del juego --- // --- Namespace GlobalInputs: gestiona inputs globales del juego ---
namespace GlobalInputs { namespace GlobalInputs {
// --- Funciones --- // --- Funciones ---
auto check() -> bool; // Comprueba los inputs que se pueden introducir en cualquier sección del juego auto check() -> bool; // Comprueba los inputs que se pueden introducir en cualquier sección del juego
} // namespace GlobalInputs } // namespace GlobalInputs

View File

@@ -16,16 +16,16 @@
using json = nlohmann::json; using json = nlohmann::json;
namespace Lang { namespace Lang {
std::unordered_map<std::string, std::string> texts; std::unordered_map<std::string, std::string> texts;
// Vector con los idiomas soportados // Vector con los idiomas soportados
std::vector<Language> languages = { std::vector<Language> languages = {
{Code::SPANISH, "Castellano", "es_ES.json"}, {Code::SPANISH, "Castellano", "es_ES.json"},
{Code::VALENCIAN, "Balooncia", "ba_BA.json"}, {Code::VALENCIAN, "Balooncia", "ba_BA.json"},
{Code::ENGLISH, "Ingles", "en_UK.json"}}; {Code::ENGLISH, "Ingles", "en_UK.json"}};
// Inicializa los textos del juego en el idioma seleccionado // Inicializa los textos del juego en el idioma seleccionado
auto loadFromFile(const std::string& file_path) -> bool { auto loadFromFile(const std::string& file_path) -> bool {
texts.clear(); texts.clear();
// Intentar cargar desde ResourceHelper primero // Intentar cargar desde ResourceHelper primero
@@ -56,19 +56,19 @@ auto loadFromFile(const std::string& file_path) -> bool {
} }
return true; return true;
} }
// Obtiene el texto por clave // Obtiene el texto por clave
auto getText(const std::string& key) -> std::string { auto getText(const std::string& key) -> std::string {
auto it = texts.find(key); auto it = texts.find(key);
if (it != texts.end()) { if (it != texts.end()) {
return it->second; return it->second;
} }
return "[missing text: " + key + "]"; return "[missing text: " + key + "]";
} }
// Obtiene el código del siguiente idioma disponible // Obtiene el código del siguiente idioma disponible
auto getNextLangCode(Code lang) -> Code { auto getNextLangCode(Code lang) -> Code {
for (size_t i = 0; i < languages.size(); ++i) { for (size_t i = 0; i < languages.size(); ++i) {
if (languages[i].code == lang) { if (languages[i].code == lang) {
return languages[(i + 1) % languages.size()].code; return languages[(i + 1) % languages.size()].code;
@@ -76,10 +76,10 @@ auto getNextLangCode(Code lang) -> Code {
} }
// Si no se encuentra, devuelve el primero por defecto // Si no se encuentra, devuelve el primero por defecto
return languages[0].code; return languages[0].code;
} }
// Obtiene un idioma del vector de idiomas a partir de un código // Obtiene un idioma del vector de idiomas a partir de un código
auto getLanguage(Code code) -> Language { auto getLanguage(Code code) -> Language {
for (const auto& lang : languages) { for (const auto& lang : languages) {
if (lang.code == code) { if (lang.code == code) {
return lang; return lang;
@@ -87,10 +87,10 @@ auto getLanguage(Code code) -> Language {
} }
// Si no se encuentra, devuelve el primero por defecto // Si no se encuentra, devuelve el primero por defecto
return languages[0]; return languages[0];
} }
// Devuelve el código de un idioma a partir de un nombre // Devuelve el código de un idioma a partir de un nombre
auto getCodeFromName(const std::string& name) -> Code { auto getCodeFromName(const std::string& name) -> Code {
for (const auto& lang : languages) { for (const auto& lang : languages) {
if (lang.name == name) { if (lang.name == name) {
return lang.code; return lang.code;
@@ -98,10 +98,10 @@ auto getCodeFromName(const std::string& name) -> Code {
} }
// Si no se encuentra, devuelve el primero por defecto // Si no se encuentra, devuelve el primero por defecto
return languages[0].code; return languages[0].code;
} }
// Devuelve el nombre de un idioma a partir de un código // Devuelve el nombre de un idioma a partir de un código
auto getNameFromCode(Code code) -> std::string { auto getNameFromCode(Code code) -> std::string {
for (const auto& lang : languages) { for (const auto& lang : languages) {
if (lang.code == code) { if (lang.code == code) {
return lang.name; return lang.name;
@@ -109,10 +109,10 @@ auto getNameFromCode(Code code) -> std::string {
} }
// Si no se encuentra, devuelve el nombre del primer idioma por defecto // Si no se encuentra, devuelve el nombre del primer idioma por defecto
return languages[0].name; return languages[0].name;
} }
// Actualiza los nombres de los idiomas // Actualiza los nombres de los idiomas
void updateLanguageNames() { void updateLanguageNames() {
for (auto& lang : languages) { for (auto& lang : languages) {
switch (lang.code) { switch (lang.code) {
case Code::SPANISH: case Code::SPANISH:
@@ -129,10 +129,10 @@ void updateLanguageNames() {
break; break;
} }
} }
} }
// Actualiza los nombres de las dificultades // Actualiza los nombres de las dificultades
void updateDifficultyNames() { void updateDifficultyNames() {
// 1. Pide una referencia MODIFICABLE a la lista de dificultades // 1. Pide una referencia MODIFICABLE a la lista de dificultades
auto& difficulties = Difficulty::getDifficulties(); auto& difficulties = Difficulty::getDifficulties();
@@ -151,10 +151,10 @@ void updateDifficultyNames() {
break; break;
} }
} }
} }
// Obtiene una fichero a partir de un lang::Code // Obtiene una fichero a partir de un lang::Code
auto getLanguageFileName(Lang::Code code) -> std::string { auto getLanguageFileName(Lang::Code code) -> std::string {
for (const auto& lang : languages) { for (const auto& lang : languages) {
if (lang.code == code) { if (lang.code == code) {
return Asset::get()->get(lang.file_name); return Asset::get()->get(lang.file_name);
@@ -162,18 +162,18 @@ auto getLanguageFileName(Lang::Code code) -> std::string {
} }
// Si no se encuentra, devuelve el fichero del primer idioma por defecto // Si no se encuentra, devuelve el fichero del primer idioma por defecto
return Asset::get()->get(languages[0].file_name); return Asset::get()->get(languages[0].file_name);
} }
// Establece el idioma // Establece el idioma
void setLanguage(Code code) { void setLanguage(Code code) {
Options::settings.language = code; Options::settings.language = code;
loadFromFile(Asset::get()->get(getLanguage(code).file_name)); loadFromFile(Asset::get()->get(getLanguage(code).file_name));
updateLanguageNames(); updateLanguageNames();
updateDifficultyNames(); updateDifficultyNames();
} }
// Obtiene una fichero a partir de un Code // Obtiene una fichero a partir de un Code
auto getLangFile(Code code) -> std::string { auto getLangFile(Code code) -> std::string {
switch (code) { switch (code) {
case Code::VALENCIAN: case Code::VALENCIAN:
return Asset::get()->get("ba_BA.json"); return Asset::get()->get("ba_BA.json");
@@ -185,10 +185,10 @@ auto getLangFile(Code code) -> std::string {
return Asset::get()->get("en_UK.json"); return Asset::get()->get("en_UK.json");
break; break;
} }
} }
// Obtiene una cadena a partir de un Code // Obtiene una cadena a partir de un Code
auto getLangName(Code code) -> std::string { auto getLangName(Code code) -> std::string {
switch (code) { switch (code) {
case Code::VALENCIAN: case Code::VALENCIAN:
return " \"ba_BA\""; return " \"ba_BA\"";
@@ -200,5 +200,5 @@ auto getLangName(Code code) -> std::string {
return " \"en_UK\""; return " \"en_UK\"";
break; break;
} }
} }
} // namespace Lang } // namespace Lang

View File

@@ -5,15 +5,15 @@
// --- Namespace Lang: gestión de idiomas y textos --- // --- Namespace Lang: gestión de idiomas y textos ---
namespace Lang { namespace Lang {
// --- Enums --- // --- Enums ---
enum class Code : int { enum class Code : int {
SPANISH = 0, // Español SPANISH = 0, // Español
VALENCIAN = 1, // Valenciano VALENCIAN = 1, // Valenciano
ENGLISH = 2 // Inglés ENGLISH = 2 // Inglés
}; };
// --- Estructuras --- // --- Estructuras ---
struct Language { struct Language {
Code code; // Código que identifica al idioma Code code; // Código que identifica al idioma
std::string name; // Nombre que identifica el idioma std::string name; // Nombre que identifica el idioma
std::string file_name; // Nombre del fichero con los textos std::string file_name; // Nombre del fichero con los textos
@@ -22,18 +22,18 @@ struct Language {
: code(c), : code(c),
name(std::move(n)), name(std::move(n)),
file_name(std::move(fn)) {} file_name(std::move(fn)) {}
}; };
// --- Funciones --- // --- Funciones ---
auto loadFromFile(const std::string& file_path) -> bool; // Carga los textos desde el fichero JSON especificado auto loadFromFile(const std::string& file_path) -> bool; // Carga los textos desde el fichero JSON especificado
auto getText(const std::string& key) -> std::string; // Obtiene el texto por clave auto getText(const std::string& key) -> std::string; // Obtiene el texto por clave
auto getNextLangCode(Code current_lang) -> Code; // Obtiene el código del siguiente idioma (circular) auto getNextLangCode(Code current_lang) -> Code; // Obtiene el código del siguiente idioma (circular)
auto getLanguage(Code code) -> Language; // Obtiene el idioma correspondiente al código proporcionado auto getLanguage(Code code) -> Language; // Obtiene el idioma correspondiente al código proporcionado
auto getCodeFromName(const std::string& name) -> Code; // Devuelve el código de un idioma a partir de un nombre auto getCodeFromName(const std::string& name) -> Code; // Devuelve el código de un idioma a partir de un nombre
auto getNameFromCode(Code code) -> std::string; // Devuelve el nombre de un idioma a partir de un código auto getNameFromCode(Code code) -> std::string; // Devuelve el nombre de un idioma a partir de un código
void updateLanguageNames(); // Actualiza los nombres de los idiomas void updateLanguageNames(); // Actualiza los nombres de los idiomas
auto getLanguageFileName(Code code) -> std::string; // Obtiene el nombre del fichero de textos asociado a un código de idioma auto getLanguageFileName(Code code) -> std::string; // Obtiene el nombre del fichero de textos asociado a un código de idioma
void setLanguage(Code code); // Establece el idioma actual void setLanguage(Code code); // Establece el idioma actual
auto getLangFile(Code code) -> std::string; // Obtiene una fichero a partir de un Code auto getLangFile(Code code) -> std::string; // Obtiene una fichero a partir de un Code
auto getLangName(Code code) -> std::string; // Obtiene una cadena a partir de un Code auto getLangName(Code code) -> std::string; // Obtiene una cadena a partir de un Code
} // namespace Lang } // namespace Lang

View File

@@ -252,8 +252,7 @@ auto ManageHiScoreTable::verifyChecksum(SDL_IOStream* file, const std::string& f
unsigned int calculated_checksum = calculateChecksum(temp_table); unsigned int calculated_checksum = calculateChecksum(temp_table);
if (stored_checksum != calculated_checksum) { if (stored_checksum != calculated_checksum) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Checksum mismatch in %s (stored: 0x%08X, calculated: 0x%08X) - file is corrupted", SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Checksum mismatch in %s (stored: 0x%08X, calculated: 0x%08X) - file is corrupted", getFileName(file_path).c_str(), stored_checksum, calculated_checksum);
getFileName(file_path).c_str(), stored_checksum, calculated_checksum);
return false; return false;
} }
return true; return true;

View File

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

View File

@@ -4,12 +4,12 @@
// --- Namespace Mouse: gestión del ratón --- // --- Namespace Mouse: gestión del ratón ---
namespace Mouse { namespace Mouse {
// --- Variables de estado del cursor --- // --- Variables de estado del cursor ---
extern Uint32 cursor_hide_time; // Tiempo en milisegundos para ocultar el cursor tras inactividad extern Uint32 cursor_hide_time; // Tiempo en milisegundos para ocultar el cursor tras inactividad
extern Uint32 last_mouse_move_time; // Última vez (en ms) que el ratón se movió extern Uint32 last_mouse_move_time; // Última vez (en ms) que el ratón se movió
extern bool cursor_visible; // Indica si el cursor está visible extern bool cursor_visible; // Indica si el cursor está visible
// --- Funciones --- // --- Funciones ---
void handleEvent(const SDL_Event& event); // Procesa eventos de ratón (movimiento, clic, etc.) void handleEvent(const SDL_Event& event); // Procesa eventos de ratón (movimiento, clic, etc.)
void updateCursorVisibility(); // Actualiza la visibilidad del cursor según la inactividad void updateCursorVisibility(); // Actualiza la visibilidad del cursor según la inactividad
} // namespace Mouse } // namespace Mouse

View File

@@ -20,26 +20,26 @@
#include "utils.hpp" // Para stringToBool, boolToString, getFileName #include "utils.hpp" // Para stringToBool, boolToString, getFileName
namespace Options { namespace Options {
// --- Variables globales --- // --- Variables globales ---
Window window; // Opciones de la ventana Window window; // Opciones de la ventana
Settings settings; // Opciones del juego Settings settings; // Opciones del juego
Video video; // Opciones de vídeo Video video; // Opciones de vídeo
Audio audio; // Opciones de audio Audio audio; // Opciones de audio
GamepadManager gamepad_manager; // Opciones de mando para cada jugador GamepadManager gamepad_manager; // Opciones de mando para cada jugador
Keyboard keyboard; // Opciones para el teclado Keyboard keyboard; // Opciones para el teclado
PendingChanges pending_changes; // Opciones que se aplican al cerrar PendingChanges pending_changes; // Opciones que se aplican al cerrar
// Declaraciones // Declaraciones
auto set(const std::string& var, const std::string& value) -> bool; auto set(const std::string& var, const std::string& value) -> bool;
// Establece el fichero de configuración // Establece el fichero de configuración
void setConfigFile(const std::string& file_path) { settings.config_file = file_path; }; void setConfigFile(const std::string& file_path) { settings.config_file = file_path; };
// Establece el fichero de configuración de mandos // Establece el fichero de configuración de mandos
void setControllersFile(const std::string& file_path) { settings.controllers_file = file_path; }; void setControllersFile(const std::string& file_path) { settings.controllers_file = file_path; };
// Inicializa las opciones del programa // Inicializa las opciones del programa
void init() { void init() {
// Dificultades // Dificultades
Difficulty::init(); Difficulty::init();
@@ -51,10 +51,10 @@ void init() {
pending_changes.new_language = settings.language; pending_changes.new_language = settings.language;
pending_changes.new_difficulty = settings.difficulty; pending_changes.new_difficulty = settings.difficulty;
pending_changes.has_pending_changes = false; pending_changes.has_pending_changes = false;
} }
// Carga el fichero de configuración // Carga el fichero de configuración
auto loadFromFile() -> bool { auto loadFromFile() -> bool {
// 1. Inicializa las opciones con valores por defecto. // 1. Inicializa las opciones con valores por defecto.
init(); init();
@@ -104,10 +104,10 @@ auto loadFromFile() -> bool {
} }
return true; return true;
} }
// Guarda el fichero de configuración // Guarda el fichero de configuración
auto saveToFile() -> bool { auto saveToFile() -> bool {
std::ofstream file(settings.config_file); std::ofstream file(settings.config_file);
if (!file.good()) { if (!file.good()) {
@@ -170,10 +170,10 @@ auto saveToFile() -> bool {
file.close(); file.close();
return true; return true;
} }
// Función auxiliar para analizar la configuración del mando y reducir duplicación // Función auxiliar para analizar la configuración del mando y reducir duplicación
void parseAndSetController(const std::string& var, const std::string& value) { void parseAndSetController(const std::string& var, const std::string& value) {
size_t first_dot = var.find('.'); size_t first_dot = var.find('.');
size_t second_dot = var.find('.', first_dot + 1); size_t second_dot = var.find('.', first_dot + 1);
@@ -189,9 +189,9 @@ void parseAndSetController(const std::string& var, const std::string& value) {
} catch (const std::exception&) { } catch (const std::exception&) {
// Error en parsing // Error en parsing
} }
} }
auto set(const std::string& var, const std::string& value) -> bool { auto set(const std::string& var, const std::string& value) -> bool {
// Clausula de protección: ignora líneas vacías o comentarios // Clausula de protección: ignora líneas vacías o comentarios
if (var.empty() || var.starts_with("#")) { if (var.empty() || var.starts_with("#")) {
return true; return true;
@@ -265,54 +265,54 @@ auto set(const std::string& var, const std::string& value) -> bool {
// Si la clave no se encontró en el mapa ni en la lógica de mandos // Si la clave no se encontró en el mapa ni en la lógica de mandos
return false; return false;
} }
// Asigna el teclado al jugador // Asigna el teclado al jugador
void setKeyboardToPlayer(Player::Id player_id) { void setKeyboardToPlayer(Player::Id player_id) {
keyboard.player_id = player_id; keyboard.player_id = player_id;
} }
// Intercambia el teclado de jugador // Intercambia el teclado de jugador
void swapKeyboard() { void swapKeyboard() {
keyboard.player_id = keyboard.player_id == Player::Id::PLAYER1 ? Player::Id::PLAYER2 : Player::Id::PLAYER1; keyboard.player_id = keyboard.player_id == Player::Id::PLAYER1 ? Player::Id::PLAYER2 : Player::Id::PLAYER1;
} }
// Intercambia los jugadores asignados a los dos primeros mandos // Intercambia los jugadores asignados a los dos primeros mandos
void swapControllers() { void swapControllers() {
gamepad_manager.swapPlayers(); gamepad_manager.swapPlayers();
} }
// Averigua quien está usando el teclado // Averigua quien está usando el teclado
auto getPlayerWhoUsesKeyboard() -> Player::Id { auto getPlayerWhoUsesKeyboard() -> Player::Id {
return keyboard.player_id; return keyboard.player_id;
} }
// Aplica los cambios pendientes copiando los valores a sus variables // Aplica los cambios pendientes copiando los valores a sus variables
void applyPendingChanges() { void applyPendingChanges() {
if (pending_changes.has_pending_changes) { if (pending_changes.has_pending_changes) {
settings.language = pending_changes.new_language; settings.language = pending_changes.new_language;
settings.difficulty = pending_changes.new_difficulty; settings.difficulty = pending_changes.new_difficulty;
pending_changes.has_pending_changes = false; pending_changes.has_pending_changes = false;
} }
} }
void checkPendingChanges() { void checkPendingChanges() {
pending_changes.has_pending_changes = settings.language != pending_changes.new_language || pending_changes.has_pending_changes = settings.language != pending_changes.new_language ||
settings.difficulty != pending_changes.new_difficulty; settings.difficulty != pending_changes.new_difficulty;
} }
// Buscar y asignar un mando disponible por nombre // Buscar y asignar un mando disponible por nombre
auto assignGamepadByName(const std::string& gamepad_name_to_find, Player::Id player_id) -> bool { auto assignGamepadByName(const std::string& gamepad_name_to_find, Player::Id player_id) -> bool {
auto found_gamepad = Input::get()->findAvailableGamepadByName(gamepad_name_to_find); auto found_gamepad = Input::get()->findAvailableGamepadByName(gamepad_name_to_find);
if (found_gamepad) { if (found_gamepad) {
return gamepad_manager.assignGamepadToPlayer(player_id, found_gamepad, found_gamepad->name); return gamepad_manager.assignGamepadToPlayer(player_id, found_gamepad, found_gamepad->name);
} }
return false; return false;
} }
// Obtener información de un gamepad específico // Obtener información de un gamepad específico
auto getGamepadInfo(Player::Id player_id) -> std::string { auto getGamepadInfo(Player::Id player_id) -> std::string {
try { try {
const auto& gamepad = gamepad_manager.getGamepad(player_id); const auto& gamepad = gamepad_manager.getGamepad(player_id);
return "Player " + std::to_string(static_cast<int>(player_id)) + return "Player " + std::to_string(static_cast<int>(player_id)) +
@@ -320,10 +320,10 @@ auto getGamepadInfo(Player::Id player_id) -> std::string {
} catch (const std::exception&) { } catch (const std::exception&) {
return "Invalid player"; return "Invalid player";
} }
} }
// Asigna los mandos físicos basándose en la configuración actual. // Asigna los mandos físicos basándose en la configuración actual.
void GamepadManager::assignAndLinkGamepads() { void GamepadManager::assignAndLinkGamepads() {
// 1. Obtenemos los mandos físicos conectados. // 1. Obtenemos los mandos físicos conectados.
auto physical_gamepads = Input::get()->getGamepads(); auto physical_gamepads = Input::get()->getGamepads();
@@ -346,10 +346,10 @@ void GamepadManager::assignAndLinkGamepads() {
// Pasada 3: Limpia los datos de los slots que se quedaron sin mando. // Pasada 3: Limpia los datos de los slots que se quedaron sin mando.
clearUnassignedGamepadSlots(); clearUnassignedGamepadSlots();
} }
// --- PRIMERA PASADA: Intenta asignar mandos basándose en la ruta guardada --- // --- PRIMERA PASADA: Intenta asignar mandos basándose en la ruta guardada ---
void GamepadManager::assignGamepadsByPath( void GamepadManager::assignGamepadsByPath(
const std::array<std::string, MAX_PLAYERS>& desired_paths, const std::array<std::string, MAX_PLAYERS>& desired_paths,
const std::vector<std::shared_ptr<Input::Gamepad>>& physical_gamepads, const std::vector<std::shared_ptr<Input::Gamepad>>& physical_gamepads,
std::vector<std::shared_ptr<Input::Gamepad>>& assigned_instances) { std::vector<std::shared_ptr<Input::Gamepad>>& assigned_instances) {
@@ -372,10 +372,10 @@ void GamepadManager::assignGamepadsByPath(
} }
} }
} }
} }
// --- SEGUNDA PASADA: Asigna los mandos físicos restantes a los jugadores libres --- // --- SEGUNDA PASADA: Asigna los mandos físicos restantes a los jugadores libres ---
void GamepadManager::assignRemainingGamepads( void GamepadManager::assignRemainingGamepads(
const std::vector<std::shared_ptr<Input::Gamepad>>& physical_gamepads, const std::vector<std::shared_ptr<Input::Gamepad>>& physical_gamepads,
std::vector<std::shared_ptr<Input::Gamepad>>& assigned_instances) { std::vector<std::shared_ptr<Input::Gamepad>>& assigned_instances) {
for (size_t i = 0; i < MAX_PLAYERS; ++i) { for (size_t i = 0; i < MAX_PLAYERS; ++i) {
@@ -397,10 +397,10 @@ void GamepadManager::assignRemainingGamepads(
} }
} }
} }
} }
// --- TERCERA PASADA: Limpia la información "fantasma" de los slots no asignados --- // --- TERCERA PASADA: Limpia la información "fantasma" de los slots no asignados ---
void GamepadManager::clearUnassignedGamepadSlots() { void GamepadManager::clearUnassignedGamepadSlots() {
// Recorremos los slots de jugador una última vez. // Recorremos los slots de jugador una última vez.
for (auto& gamepad_config : gamepads_) { for (auto& gamepad_config : gamepads_) {
// Si un slot no tiene una instancia física enlazada (instance == nullptr), // Si un slot no tiene una instancia física enlazada (instance == nullptr),
@@ -412,21 +412,21 @@ void GamepadManager::clearUnassignedGamepadSlots() {
gamepad_config.path = ""; gamepad_config.path = "";
} }
} }
} }
// Función auxiliar para comprobar si un mando físico ya está en la lista de asignados. // Función auxiliar para comprobar si un mando físico ya está en la lista de asignados.
// Devuelve 'true' si ya ha sido asignado, 'false' en caso contrario. // Devuelve 'true' si ya ha sido asignado, 'false' en caso contrario.
auto GamepadManager::isGamepadAssigned( auto GamepadManager::isGamepadAssigned(
const std::shared_ptr<Input::Gamepad>& physical_gamepad, const std::shared_ptr<Input::Gamepad>& physical_gamepad,
const std::vector<std::shared_ptr<Input::Gamepad>>& assigned_instances) -> bool { const std::vector<std::shared_ptr<Input::Gamepad>>& assigned_instances) -> bool {
return std::ranges::any_of(assigned_instances, return std::ranges::any_of(assigned_instances,
[&physical_gamepad](const auto& assigned) { [&physical_gamepad](const auto& assigned) {
return assigned == physical_gamepad; return assigned == physical_gamepad;
}); });
} }
// Convierte un player id a texto segun Lang // Convierte un player id a texto segun Lang
auto playerIdToString(Player::Id player_id) -> std::string { auto playerIdToString(Player::Id player_id) -> std::string {
switch (player_id) { switch (player_id) {
case Player::Id::PLAYER1: case Player::Id::PLAYER1:
return Lang::getText("[SERVICE_MENU] PLAYER1"); return Lang::getText("[SERVICE_MENU] PLAYER1");
@@ -435,10 +435,10 @@ auto playerIdToString(Player::Id player_id) -> std::string {
default: default:
return ""; return "";
} }
} }
// Convierte un texto a player id segun Lang // Convierte un texto a player id segun Lang
auto stringToPlayerId(const std::string& name) -> Player::Id { auto stringToPlayerId(const std::string& name) -> Player::Id {
if (name == Lang::getText("[SERVICE_MENU] PLAYER1")) { if (name == Lang::getText("[SERVICE_MENU] PLAYER1")) {
return Player::Id::PLAYER1; return Player::Id::PLAYER1;
} }
@@ -446,5 +446,5 @@ auto stringToPlayerId(const std::string& name) -> Player::Id {
return Player::Id::PLAYER2; return Player::Id::PLAYER2;
} }
return Player::Id::NO_PLAYER; return Player::Id::NO_PLAYER;
} }
} // namespace Options } // namespace Options

View File

@@ -23,40 +23,40 @@
// --- Namespace Options: gestión de configuración y opciones del juego --- // --- Namespace Options: gestión de configuración y opciones del juego ---
namespace Options { namespace Options {
// --- Estructuras --- // --- Estructuras ---
struct Window { struct Window {
std::string caption = GameDefaults::Options::WINDOW_CAPTION; // Texto que aparece en la barra de título de la ventana std::string caption = GameDefaults::Options::WINDOW_CAPTION; // Texto que aparece en la barra de título de la ventana
int zoom = GameDefaults::Options::WINDOW_ZOOM; // Valor por el que se multiplica el tamaño de la ventana int zoom = GameDefaults::Options::WINDOW_ZOOM; // Valor por el que se multiplica el tamaño de la ventana
int max_zoom = GameDefaults::Options::WINDOW_MAX_ZOOM; // Tamaño máximo para que la ventana no sea mayor que la pantalla int max_zoom = GameDefaults::Options::WINDOW_MAX_ZOOM; // Tamaño máximo para que la ventana no sea mayor que la pantalla
}; };
struct Video { struct Video {
SDL_ScaleMode scale_mode = GameDefaults::Options::VIDEO_SCALE_MODE; // Filtro usado para el escalado de la imagen SDL_ScaleMode scale_mode = GameDefaults::Options::VIDEO_SCALE_MODE; // Filtro usado para el escalado de la imagen
bool fullscreen = GameDefaults::Options::VIDEO_FULLSCREEN; // Indica si se usa pantalla completa bool fullscreen = GameDefaults::Options::VIDEO_FULLSCREEN; // Indica si se usa pantalla completa
bool vsync = GameDefaults::Options::VIDEO_VSYNC; // Indica si se usa vsync bool vsync = GameDefaults::Options::VIDEO_VSYNC; // Indica si se usa vsync
bool integer_scale = GameDefaults::Options::VIDEO_INTEGER_SCALE; // Indica si se usa escalado entero bool integer_scale = GameDefaults::Options::VIDEO_INTEGER_SCALE; // Indica si se usa escalado entero
bool shaders = GameDefaults::Options::VIDEO_SHADERS; // Indica si se usan shaders para los filtros de vídeo bool shaders = GameDefaults::Options::VIDEO_SHADERS; // Indica si se usan shaders para los filtros de vídeo
std::string info; // Información sobre el modo de vídeo std::string info; // Información sobre el modo de vídeo
}; };
struct Music { struct Music {
bool enabled = GameDefaults::Options::MUSIC_ENABLED; // Indica si la música suena o no bool enabled = GameDefaults::Options::MUSIC_ENABLED; // Indica si la música suena o no
int volume = GameDefaults::Options::MUSIC_VOLUME; // Volumen de la música int volume = GameDefaults::Options::MUSIC_VOLUME; // Volumen de la música
}; };
struct Sound { struct Sound {
bool enabled = GameDefaults::Options::SOUND_ENABLED; // Indica si los sonidos suenan o no bool enabled = GameDefaults::Options::SOUND_ENABLED; // Indica si los sonidos suenan o no
int volume = GameDefaults::Options::SOUND_VOLUME; // Volumen de los sonidos int volume = GameDefaults::Options::SOUND_VOLUME; // Volumen de los sonidos
}; };
struct Audio { struct Audio {
Music music; // Opciones para la música Music music; // Opciones para la música
Sound sound; // Opciones para los efectos de sonido Sound sound; // Opciones para los efectos de sonido
bool enabled = GameDefaults::Options::AUDIO_ENABLED; // Indica si el audio está activo o no bool enabled = GameDefaults::Options::AUDIO_ENABLED; // Indica si el audio está activo o no
int volume = GameDefaults::Options::AUDIO_VOLUME; // Volumen general del audio int volume = GameDefaults::Options::AUDIO_VOLUME; // Volumen general del audio
}; };
struct Settings { struct Settings {
int config_version = 2; // Versión del archivo de configuración int config_version = 2; // Versión del archivo de configuración
Difficulty::Code difficulty = Difficulty::Code::NORMAL; // Dificultad del juego Difficulty::Code difficulty = Difficulty::Code::NORMAL; // Dificultad del juego
Lang::Code language = Lang::Code::VALENCIAN; // Idioma usado en el juego Lang::Code language = Lang::Code::VALENCIAN; // Idioma usado en el juego
@@ -73,9 +73,9 @@ struct Settings {
glowing_entries.at(0) = ManageHiScoreTable::NO_ENTRY; glowing_entries.at(0) = ManageHiScoreTable::NO_ENTRY;
glowing_entries.at(1) = ManageHiScoreTable::NO_ENTRY; glowing_entries.at(1) = ManageHiScoreTable::NO_ENTRY;
} }
}; };
struct Gamepad { struct Gamepad {
std::shared_ptr<Input::Gamepad> instance = nullptr; // Referencia al mando std::shared_ptr<Input::Gamepad> instance = nullptr; // Referencia al mando
std::string name; // Nombre del mando std::string name; // Nombre del mando
std::string path; // Ruta física del dispositivo std::string path; // Ruta física del dispositivo
@@ -83,10 +83,10 @@ struct Gamepad {
Gamepad(Player::Id custom_player_id = Player::Id::NO_PLAYER) Gamepad(Player::Id custom_player_id = Player::Id::NO_PLAYER)
: player_id(custom_player_id) {} : player_id(custom_player_id) {}
}; };
// --- Clases --- // --- Clases ---
class GamepadManager { class GamepadManager {
public: public:
void init() { void init() {
gamepads_[0] = Gamepad(Player::Id::PLAYER1); gamepads_[0] = Gamepad(Player::Id::PLAYER1);
@@ -251,9 +251,9 @@ class GamepadManager {
[[nodiscard]] static auto isGamepadAssigned( [[nodiscard]] static auto isGamepadAssigned(
const std::shared_ptr<Input::Gamepad>& physical_gamepad, const std::shared_ptr<Input::Gamepad>& physical_gamepad,
const std::vector<std::shared_ptr<Input::Gamepad>>& assigned_instances) -> bool; const std::vector<std::shared_ptr<Input::Gamepad>>& assigned_instances) -> bool;
}; };
struct Keyboard { struct Keyboard {
Player::Id player_id = Player::Id::PLAYER1; // Jugador asociado al teclado Player::Id player_id = Player::Id::PLAYER1; // Jugador asociado al teclado
std::vector<std::shared_ptr<Player>> players; // Punteros a los jugadores std::vector<std::shared_ptr<Player>> players; // Punteros a los jugadores
@@ -267,36 +267,36 @@ struct Keyboard {
player->setUsesKeyboard(player->getId() == player_id); player->setUsesKeyboard(player->getId() == player_id);
} }
} }
}; };
struct PendingChanges { struct PendingChanges {
Lang::Code new_language = Lang::Code::VALENCIAN; // Idioma en espera de aplicar Lang::Code new_language = Lang::Code::VALENCIAN; // Idioma en espera de aplicar
Difficulty::Code new_difficulty = Difficulty::Code::NORMAL; // Dificultad en espera de aplicar Difficulty::Code new_difficulty = Difficulty::Code::NORMAL; // Dificultad en espera de aplicar
bool has_pending_changes = false; // Indica si hay cambios pendientes bool has_pending_changes = false; // Indica si hay cambios pendientes
}; };
// --- Variables --- // --- Variables ---
extern Window window; // Opciones de la ventana extern Window window; // Opciones de la ventana
extern Settings settings; // Opciones del juego extern Settings settings; // Opciones del juego
extern Video video; // Opciones de vídeo extern Video video; // Opciones de vídeo
extern Audio audio; // Opciones de audio extern Audio audio; // Opciones de audio
extern GamepadManager gamepad_manager; // Manager de mandos para cada jugador extern GamepadManager gamepad_manager; // Manager de mandos para cada jugador
extern Keyboard keyboard; // Opciones para el teclado extern Keyboard keyboard; // Opciones para el teclado
extern PendingChanges pending_changes; // Opciones que se aplican al cerrar extern PendingChanges pending_changes; // Opciones que se aplican al cerrar
// --- Funciones --- // --- Funciones ---
void init(); // Inicializa las opciones del programa void init(); // Inicializa las opciones del programa
void setConfigFile(const std::string& file_path); // Establece el fichero de configuración void setConfigFile(const std::string& file_path); // Establece el fichero de configuración
void setControllersFile(const std::string& file_path); // Establece el fichero de configuración de mandos void setControllersFile(const std::string& file_path); // Establece el fichero de configuración de mandos
auto loadFromFile() -> bool; // Carga el fichero de configuración auto loadFromFile() -> bool; // Carga el fichero de configuración
auto saveToFile() -> bool; // Guarda el fichero de configuración auto saveToFile() -> bool; // Guarda el fichero de configuración
void setKeyboardToPlayer(Player::Id player_id); // Asigna el teclado al jugador void setKeyboardToPlayer(Player::Id player_id); // Asigna el teclado al jugador
void swapKeyboard(); // Intercambia el teclado de jugador void swapKeyboard(); // Intercambia el teclado de jugador
void swapControllers(); // Intercambia los jugadores asignados a los dos primeros mandos void swapControllers(); // Intercambia los jugadores asignados a los dos primeros mandos
auto getPlayerWhoUsesKeyboard() -> Player::Id; // Averigua quién está usando el teclado auto getPlayerWhoUsesKeyboard() -> Player::Id; // Averigua quién está usando el teclado
auto playerIdToString(Player::Id player_id) -> std::string; // Convierte un player id a texto segun Lang auto playerIdToString(Player::Id player_id) -> std::string; // Convierte un player id a texto segun Lang
auto stringToPlayerId(const std::string& name) -> Player::Id; // Convierte un texto a player id segun Lang auto stringToPlayerId(const std::string& name) -> Player::Id; // Convierte un texto a player id segun Lang
void applyPendingChanges(); // Aplica los cambios pendientes copiando los valores a sus variables void applyPendingChanges(); // Aplica los cambios pendientes copiando los valores a sus variables
void checkPendingChanges(); // Verifica si hay cambios pendientes void checkPendingChanges(); // Verifica si hay cambios pendientes
auto assignGamepadByName(const std::string& gamepad_name, Player::Id player_id) -> bool; // Buscar y asignar un mando disponible por nombre auto assignGamepadByName(const std::string& gamepad_name, Player::Id player_id) -> bool; // Buscar y asignar un mando disponible por nombre
} // namespace Options } // namespace Options

View File

@@ -20,7 +20,7 @@ Param param;
// Declaraciones de funciones privadas // Declaraciones de funciones privadas
namespace { namespace {
auto setParams(const std::string& var, const std::string& value) -> bool; auto setParams(const std::string& var, const std::string& value) -> bool;
} }
// Implementación del método privado de Param // Implementación del método privado de Param
@@ -85,7 +85,7 @@ void loadParamsFromFile(const std::string& file_path) {
// Implementación local de setParams // Implementación local de setParams
namespace { namespace {
auto setParams(const std::string& var, const std::string& value) -> bool { auto setParams(const std::string& var, const std::string& value) -> bool {
// Mapas estáticos para diferentes tipos de parámetros // Mapas estáticos para diferentes tipos de parámetros
static const std::unordered_map<std::string, std::function<void(const std::string&)>> INT_PARAMS = { static const std::unordered_map<std::string, std::function<void(const std::string&)>> INT_PARAMS = {
{"game.width", [](const std::string& v) { param.game.width = std::stoi(v); }}, {"game.width", [](const std::string& v) { param.game.width = std::stoi(v); }},
@@ -273,5 +273,5 @@ auto setParams(const std::string& var, const std::string& value) -> bool {
} }
return false; // Parámetro no encontrado return false; // Parámetro no encontrado
} }
} // namespace } // namespace

View File

@@ -11,12 +11,12 @@
namespace Rendering { namespace Rendering {
OpenGLShader::~OpenGLShader() { OpenGLShader::~OpenGLShader() {
cleanup(); cleanup();
} }
#ifndef __APPLE__ #ifndef __APPLE__
auto OpenGLShader::initGLExtensions() -> bool { auto OpenGLShader::initGLExtensions() -> bool {
glCreateShader = (PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader"); glCreateShader = (PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader");
glShaderSource = (PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource"); glShaderSource = (PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource");
glCompileShader = (PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader"); glCompileShader = (PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader");
@@ -50,10 +50,10 @@ auto OpenGLShader::initGLExtensions() -> bool {
(glGenVertexArrays != nullptr) && (glBindVertexArray != nullptr) && (glDeleteVertexArrays != nullptr) && (glGenVertexArrays != nullptr) && (glBindVertexArray != nullptr) && (glDeleteVertexArrays != nullptr) &&
(glGenBuffers != nullptr) && (glBindBuffer != nullptr) && (glBufferData != nullptr) && (glDeleteBuffers != nullptr) && (glGenBuffers != nullptr) && (glBindBuffer != nullptr) && (glBufferData != nullptr) && (glDeleteBuffers != nullptr) &&
(glVertexAttribPointer != nullptr) && (glEnableVertexAttribArray != nullptr); (glVertexAttribPointer != nullptr) && (glEnableVertexAttribArray != nullptr);
} }
#endif #endif
void OpenGLShader::checkGLError(const char* operation) { void OpenGLShader::checkGLError(const char* operation) {
GLenum error = glGetError(); GLenum error = glGetError();
if (error != GL_NO_ERROR) { if (error != GL_NO_ERROR) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
@@ -61,9 +61,9 @@ void OpenGLShader::checkGLError(const char* operation) {
operation, operation,
error); error);
} }
} }
auto OpenGLShader::compileShader(const std::string& source, GLenum shader_type) -> GLuint { auto OpenGLShader::compileShader(const std::string& source, GLenum shader_type) -> GLuint {
if (source.empty()) { if (source.empty()) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"ERROR: El código fuente del shader está vacío"); "ERROR: El código fuente del shader está vacío");
@@ -104,9 +104,9 @@ auto OpenGLShader::compileShader(const std::string& source, GLenum shader_type)
} }
return shader_id; return shader_id;
} }
auto OpenGLShader::linkProgram(GLuint vertex_shader, GLuint fragment_shader) -> GLuint { auto OpenGLShader::linkProgram(GLuint vertex_shader, GLuint fragment_shader) -> GLuint {
GLuint program = glCreateProgram(); GLuint program = glCreateProgram();
if (program == 0) { if (program == 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
@@ -145,9 +145,9 @@ auto OpenGLShader::linkProgram(GLuint vertex_shader, GLuint fragment_shader) ->
checkGLError("glValidateProgram"); checkGLError("glValidateProgram");
return program; return program;
} }
void OpenGLShader::createQuadGeometry() { void OpenGLShader::createQuadGeometry() {
// Datos del quad: posición (x, y) + coordenadas de textura (u, v) // Datos del quad: posición (x, y) + coordenadas de textura (u, v)
// Formato: x, y, u, v // Formato: x, y, u, v
std::array<float, 16> vertices = { std::array<float, 16> vertices = {
@@ -210,9 +210,9 @@ void OpenGLShader::createQuadGeometry() {
// Desvincular // Desvincular
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0); glBindVertexArray(0);
} }
auto OpenGLShader::getTextureID(SDL_Texture* texture) -> GLuint { auto OpenGLShader::getTextureID(SDL_Texture* texture) -> GLuint {
if (texture == nullptr) { if (texture == nullptr) {
return 1; return 1;
} }
@@ -238,9 +238,9 @@ auto OpenGLShader::getTextureID(SDL_Texture* texture) -> GLuint {
} }
return texture_id; return texture_id;
} }
auto OpenGLShader::init(SDL_Window* window, auto OpenGLShader::init(SDL_Window* window,
SDL_Texture* texture, SDL_Texture* texture,
const std::string& vertex_source, const std::string& vertex_source,
const std::string& fragment_source) -> bool { const std::string& fragment_source) -> bool {
@@ -363,9 +363,9 @@ auto OpenGLShader::init(SDL_Window* window,
*/ */
Logger::info("OpenGL 3.3 Shader Backend inicializado correctamente"); Logger::info("OpenGL 3.3 Shader Backend inicializado correctamente");
return true; return true;
} }
void OpenGLShader::render() { void OpenGLShader::render() {
if (!is_initialized_ || program_id_ == 0) { if (!is_initialized_ || program_id_ == 0) {
// Fallback: renderizado SDL normal // Fallback: renderizado SDL normal
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 255); SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 255);
@@ -469,9 +469,9 @@ void OpenGLShader::render() {
} }
glBindVertexArray(old_vao); glBindVertexArray(old_vao);
glViewport(old_viewport[0], old_viewport[1], old_viewport[2], old_viewport[3]); glViewport(old_viewport[0], old_viewport[1], old_viewport[2], old_viewport[3]);
} }
void OpenGLShader::setTextureSize(float width, float height) { void OpenGLShader::setTextureSize(float width, float height) {
if (!is_initialized_ || program_id_ == 0) { if (!is_initialized_ || program_id_ == 0) {
return; return;
} }
@@ -490,9 +490,9 @@ void OpenGLShader::setTextureSize(float width, float height) {
} }
glUseProgram(old_program); glUseProgram(old_program);
} }
void OpenGLShader::cleanup() { void OpenGLShader::cleanup() {
if (vao_ != 0) { if (vao_ != 0) {
glDeleteVertexArrays(1, &vao_); glDeleteVertexArrays(1, &vao_);
vao_ = 0; vao_ = 0;
@@ -517,6 +517,6 @@ void OpenGLShader::cleanup() {
window_ = nullptr; window_ = nullptr;
renderer_ = nullptr; renderer_ = nullptr;
back_buffer_ = nullptr; back_buffer_ = nullptr;
} }
} // namespace Rendering } // namespace Rendering

View File

@@ -10,7 +10,7 @@
namespace Rendering { namespace Rendering {
/** /**
* @brief Backend de shaders usando OpenGL 3.3 Core Profile * @brief Backend de shaders usando OpenGL 3.3 Core Profile
* *
* Implementa el renderizado de shaders usando APIs modernas de OpenGL: * Implementa el renderizado de shaders usando APIs modernas de OpenGL:
@@ -18,7 +18,7 @@ namespace Rendering {
* - VBO (Vertex Buffer Objects) * - VBO (Vertex Buffer Objects)
* - Shaders GLSL #version 330 core * - Shaders GLSL #version 330 core
*/ */
class OpenGLShader : public ShaderBackend { class OpenGLShader : public ShaderBackend {
public: public:
OpenGLShader() = default; OpenGLShader() = default;
~OpenGLShader() override; ~OpenGLShader() override;
@@ -93,6 +93,6 @@ class OpenGLShader : public ShaderBackend {
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = nullptr; PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = nullptr;
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = nullptr; PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = nullptr;
#endif #endif
}; };
} // namespace Rendering } // namespace Rendering

View File

@@ -6,13 +6,13 @@
namespace Rendering { namespace Rendering {
/** /**
* @brief Interfaz abstracta para backends de renderizado con shaders * @brief Interfaz abstracta para backends de renderizado con shaders
* *
* Esta interfaz define el contrato que todos los backends de shaders * Esta interfaz define el contrato que todos los backends de shaders
* deben cumplir (OpenGL, Metal, Vulkan, etc.) * deben cumplir (OpenGL, Metal, Vulkan, etc.)
*/ */
class ShaderBackend { class ShaderBackend {
public: public:
virtual ~ShaderBackend() = default; virtual ~ShaderBackend() = default;
@@ -51,6 +51,6 @@ class ShaderBackend {
* @return true si usa aceleración (OpenGL/Metal/Vulkan) * @return true si usa aceleración (OpenGL/Metal/Vulkan)
*/ */
[[nodiscard]] virtual auto isHardwareAccelerated() const -> bool = 0; [[nodiscard]] virtual auto isHardwareAccelerated() const -> bool = 0;
}; };
} // namespace Rendering } // namespace Rendering

View File

@@ -28,15 +28,15 @@ struct JA_Sound_t; // lines 12-12
// Helper para cargar archivos de audio desde pack o filesystem en memoria // Helper para cargar archivos de audio desde pack o filesystem en memoria
namespace { namespace {
struct AudioData { struct AudioData {
std::vector<uint8_t> data; std::vector<uint8_t> data;
std::string filepath; std::string filepath;
}; };
auto loadAudioData(const std::string& file_path) -> AudioData { auto loadAudioData(const std::string& file_path) -> AudioData {
auto resource_data = ResourceHelper::loadFile(file_path); auto resource_data = ResourceHelper::loadFile(file_path);
return AudioData{.data = std::move(resource_data), .filepath = file_path}; return AudioData{.data = std::move(resource_data), .filepath = file_path};
} }
} // namespace } // namespace
// Declaraciones de funciones que necesitas implementar en otros archivos // Declaraciones de funciones que necesitas implementar en otros archivos

View File

@@ -8,9 +8,9 @@
#include "resource_loader.hpp" // Para ResourceLoader #include "resource_loader.hpp" // Para ResourceLoader
namespace ResourceHelper { namespace ResourceHelper {
static bool resource_system_initialized = false; static bool resource_system_initialized = false;
auto initializeResourceSystem(const std::string& pack_file, bool enable_fallback) -> bool { auto initializeResourceSystem(const std::string& pack_file, bool enable_fallback) -> bool {
auto& loader = ResourceLoader::getInstance(); auto& loader = ResourceLoader::getInstance();
resource_system_initialized = loader.initialize(pack_file, enable_fallback); resource_system_initialized = loader.initialize(pack_file, enable_fallback);
@@ -21,16 +21,16 @@ auto initializeResourceSystem(const std::string& pack_file, bool enable_fallback
} }
return true; // Always return true as fallback is acceptable return true; // Always return true as fallback is acceptable
} }
void shutdownResourceSystem() { void shutdownResourceSystem() {
if (resource_system_initialized) { if (resource_system_initialized) {
ResourceLoader::getInstance().shutdown(); ResourceLoader::getInstance().shutdown();
resource_system_initialized = false; resource_system_initialized = false;
} }
} }
auto loadFile(const std::string& filepath) -> std::vector<uint8_t> { auto loadFile(const std::string& filepath) -> std::vector<uint8_t> {
if (resource_system_initialized && shouldUseResourcePack(filepath)) { if (resource_system_initialized && shouldUseResourcePack(filepath)) {
auto& loader = ResourceLoader::getInstance(); auto& loader = ResourceLoader::getInstance();
std::string pack_path = getPackPath(filepath); std::string pack_path = getPackPath(filepath);
@@ -56,9 +56,9 @@ auto loadFile(const std::string& filepath) -> std::vector<uint8_t> {
} }
return data; return data;
} }
auto shouldUseResourcePack(const std::string& filepath) -> bool { auto shouldUseResourcePack(const std::string& filepath) -> bool {
// Archivos que NO van al pack: // Archivos que NO van al pack:
// - config/ (ahora está fuera de data/) // - config/ (ahora está fuera de data/)
// - archivos absolutos del sistema // - archivos absolutos del sistema
@@ -73,9 +73,9 @@ auto shouldUseResourcePack(const std::string& filepath) -> bool {
} }
return false; return false;
} }
auto getPackPath(const std::string& asset_path) -> std::string { auto getPackPath(const std::string& asset_path) -> std::string {
std::string pack_path = asset_path; std::string pack_path = asset_path;
// Normalizar separadores de path a '/' // Normalizar separadores de path a '/'
@@ -94,5 +94,5 @@ auto getPackPath(const std::string& asset_path) -> std::string {
} }
return pack_path; return pack_path;
} }
} // namespace ResourceHelper } // namespace ResourceHelper

View File

@@ -8,24 +8,24 @@
// Helper functions para integrar ResourceLoader con el sistema existente // Helper functions para integrar ResourceLoader con el sistema existente
namespace ResourceHelper { namespace ResourceHelper {
// Inicializa ResourceLoader (llamar al inicio del programa) // Inicializa ResourceLoader (llamar al inicio del programa)
auto initializeResourceSystem(const std::string& pack_file = "resources.pack", bool enable_fallback = true) -> bool; auto initializeResourceSystem(const std::string& pack_file = "resources.pack", bool enable_fallback = true) -> bool;
// Cierra ResourceLoader // Cierra ResourceLoader
void shutdownResourceSystem(); void shutdownResourceSystem();
// Carga un archivo usando ResourceLoader o fallback a filesystem // Carga un archivo usando ResourceLoader o fallback a filesystem
auto loadFile(const std::string& filepath) -> std::vector<uint8_t>; auto loadFile(const std::string& filepath) -> std::vector<uint8_t>;
// Verifica si un archivo debería cargarse del pack vs filesystem // Verifica si un archivo debería cargarse del pack vs filesystem
auto shouldUseResourcePack(const std::string& filepath) -> bool; auto shouldUseResourcePack(const std::string& filepath) -> bool;
// Convierte ruta Asset a ruta relativa para ResourceLoader // Convierte ruta Asset a ruta relativa para ResourceLoader
auto getPackPath(const std::string& asset_path) -> std::string; auto getPackPath(const std::string& asset_path) -> std::string;
// Wrappea la carga de archivos para mantener compatibilidad // Wrappea la carga de archivos para mantener compatibilidad
template <typename T> template <typename T>
auto loadResourceFile(const std::string& asset_path, T* (*loader_func)(const char*)) -> T* { auto loadResourceFile(const std::string& asset_path, T* (*loader_func)(const char*)) -> T* {
auto data = loadFile(asset_path); auto data = loadFile(asset_path);
if (data.empty()) { if (data.empty()) {
return loader_func(asset_path.c_str()); return loader_func(asset_path.c_str());
@@ -41,5 +41,5 @@ auto loadResourceFile(const std::string& asset_path, T* (*loader_func)(const cha
std::filesystem::remove(temp_path); std::filesystem::remove(temp_path);
return result; return result;
} }
} // namespace ResourceHelper } // namespace ResourceHelper

View File

@@ -14,7 +14,7 @@ class ServiceMenu;
class Text; class Text;
namespace Rendering { namespace Rendering {
class ShaderBackend; class ShaderBackend;
} }
// --- Clase Screen: gestiona la ventana, el renderizador y los efectos visuales globales (singleton) --- // --- Clase Screen: gestiona la ventana, el renderizador y los efectos visuales globales (singleton) ---

View File

@@ -7,8 +7,8 @@
*/ */
namespace Section { namespace Section {
// --- Enumeraciones de secciones del programa --- // --- Enumeraciones de secciones del programa ---
enum class Name { enum class Name {
RESET, // Inicialización RESET, // Inicialización
LOGO, // Pantalla de logo LOGO, // Pantalla de logo
INTRO, // Introducción INTRO, // Introducción
@@ -19,10 +19,10 @@ enum class Name {
INSTRUCTIONS, // Instrucciones INSTRUCTIONS, // Instrucciones
CREDITS, // Créditos CREDITS, // Créditos
QUIT, // Salir del juego QUIT, // Salir del juego
}; };
// --- Opciones para la sección actual --- // --- Opciones para la sección actual ---
enum class Options { enum class Options {
GAME_PLAY_1P, // Iniciar el juego con el jugador 1 GAME_PLAY_1P, // Iniciar el juego con el jugador 1
GAME_PLAY_2P, // Iniciar el juego con el jugador 2 GAME_PLAY_2P, // Iniciar el juego con el jugador 2
GAME_PLAY_BOTH, // Iniciar el juego con los dos jugadores GAME_PLAY_BOTH, // Iniciar el juego con los dos jugadores
@@ -33,16 +33,16 @@ enum class Options {
HI_SCORE_AFTER_PLAYING, // Mostrar récord tras jugar HI_SCORE_AFTER_PLAYING, // Mostrar récord tras jugar
SHUTDOWN, // Apagar el sistema SHUTDOWN, // Apagar el sistema
NONE, // Sin opción NONE, // Sin opción
}; };
// --- Modos para el Attract Mode --- // --- Modos para el Attract Mode ---
enum class AttractMode { enum class AttractMode {
TITLE_TO_DEMO, // Pasar de título a demo TITLE_TO_DEMO, // Pasar de título a demo
TITLE_TO_LOGO, // Pasar de título a logo TITLE_TO_LOGO, // Pasar de título a logo
}; };
// --- Variables globales de estado --- // --- Variables globales de estado ---
inline Name name = Name::RESET; inline Name name = Name::RESET;
inline Options options = Options::NONE; inline Options options = Options::NONE;
inline AttractMode attract_mode = AttractMode::TITLE_TO_DEMO; inline AttractMode attract_mode = AttractMode::TITLE_TO_DEMO;
} // namespace Section } // namespace Section

View File

@@ -31,7 +31,7 @@ class Texture;
struct Path; struct Path;
namespace Difficulty { namespace Difficulty {
enum class Code; enum class Code;
} // namespace Difficulty } // namespace Difficulty
// --- Clase Game: núcleo principal del gameplay --- // --- Clase Game: núcleo principal del gameplay ---

View File

@@ -18,7 +18,7 @@ class Text;
class TiledBG; class TiledBG;
namespace Options { namespace Options {
struct Gamepad; struct Gamepad;
} // namespace Options } // namespace Options
// --- Clase Title: pantalla de título y menú principal del juego --- // --- Clase Title: pantalla de título y menú principal del juego ---

View File

@@ -16,8 +16,8 @@
namespace SystemShutdown { namespace SystemShutdown {
#ifndef _WIN32 #ifndef _WIN32
// Función auxiliar para sistemas Unix-like // Función auxiliar para sistemas Unix-like
auto executeUnixShutdown(const char* command, const std::vector<char*>& args) -> ShutdownResult { auto executeUnixShutdown(const char* command, const std::vector<char*>& args) -> ShutdownResult {
pid_t pid = fork(); pid_t pid = fork();
if (pid == 0) { if (pid == 0) {
@@ -34,23 +34,23 @@ auto executeUnixShutdown(const char* command, const std::vector<char*>& args) ->
} else { } else {
return ShutdownResult::ERROR_FORK_FAILED; return ShutdownResult::ERROR_FORK_FAILED;
} }
} }
#endif #endif
// Implementación de las funciones públicas // Implementación de las funciones públicas
auto shutdownSystem() -> ShutdownResult { auto shutdownSystem() -> ShutdownResult {
ShutdownConfig config; ShutdownConfig config;
return shutdownSystem(config); return shutdownSystem(config);
} }
auto shutdownSystem(int delay_seconds, bool force_apps) -> ShutdownResult { auto shutdownSystem(int delay_seconds, bool force_apps) -> ShutdownResult {
ShutdownConfig config; ShutdownConfig config;
config.delay_seconds = delay_seconds; config.delay_seconds = delay_seconds;
config.force_close_apps = force_apps; config.force_close_apps = force_apps;
return shutdownSystem(config); return shutdownSystem(config);
} }
auto shutdownSystem(const ShutdownConfig& config) -> ShutdownResult { auto shutdownSystem(const ShutdownConfig& config) -> ShutdownResult {
#ifdef _WIN32 #ifdef _WIN32
// Windows: Usar CreateProcess // Windows: Usar CreateProcess
STARTUPINFOA si = {0}; STARTUPINFOA si = {0};
@@ -117,9 +117,9 @@ auto shutdownSystem(const ShutdownConfig& config) -> ShutdownResult {
#else #else
return ShutdownResult::ERROR_UNSUPPORTED; return ShutdownResult::ERROR_UNSUPPORTED;
#endif #endif
} }
auto resultToString(ShutdownResult result) -> const char* { auto resultToString(ShutdownResult result) -> const char* {
switch (result) { switch (result) {
case ShutdownResult::SUCCESS: case ShutdownResult::SUCCESS:
return "Apagado iniciado exitosamente"; return "Apagado iniciado exitosamente";
@@ -134,17 +134,17 @@ auto resultToString(ShutdownResult result) -> const char* {
default: default:
return "Error desconocido"; return "Error desconocido";
} }
} }
auto isShutdownSupported() -> bool { auto isShutdownSupported() -> bool {
#if defined(_WIN32) || defined(__APPLE__) || defined(__linux__) #if defined(_WIN32) || defined(__APPLE__) || defined(__linux__)
return true; return true;
#else #else
return false; return false;
#endif #endif
} }
auto getRequiredPermissions() -> const char* { auto getRequiredPermissions() -> const char* {
#ifdef _WIN32 #ifdef _WIN32
return "Requiere permisos de Administrador en Windows"; return "Requiere permisos de Administrador en Windows";
#elif defined(__APPLE__) || defined(__linux__) #elif defined(__APPLE__) || defined(__linux__)
@@ -152,6 +152,6 @@ auto getRequiredPermissions() -> const char* {
#else #else
return "Sistema no soportado"; return "Sistema no soportado";
#endif #endif
} }
} // namespace SystemShutdown } // namespace SystemShutdown

View File

@@ -3,31 +3,31 @@
// --- Namespace SystemShutdown: utilidad multiplataforma para apagar el sistema de forma segura --- // --- Namespace SystemShutdown: utilidad multiplataforma para apagar el sistema de forma segura ---
namespace SystemShutdown { namespace SystemShutdown {
// --- Enums --- // --- Enums ---
enum class ShutdownResult { enum class ShutdownResult {
SUCCESS = 0, // Éxito SUCCESS = 0, // Éxito
ERROR_PERMISSION, // Error de permisos insuficientes ERROR_PERMISSION, // Error de permisos insuficientes
ERROR_SYSTEM_CALL, // Error en la llamada al sistema ERROR_SYSTEM_CALL, // Error en la llamada al sistema
ERROR_FORK_FAILED, // Error al crear proceso hijo (Unix) ERROR_FORK_FAILED, // Error al crear proceso hijo (Unix)
ERROR_UNSUPPORTED // Sistema operativo no soportado ERROR_UNSUPPORTED // Sistema operativo no soportado
}; };
// --- Estructuras --- // --- Estructuras ---
struct ShutdownConfig { struct ShutdownConfig {
int delay_seconds{5}; // Segundos de retraso antes del apagado int delay_seconds{5}; // Segundos de retraso antes del apagado
bool force_close_apps{true}; // Forzar cierre de aplicaciones bool force_close_apps{true}; // Forzar cierre de aplicaciones
const char* shutdown_message{"El sistema se apagará..."}; // Mensaje mostrado durante el apagado const char* shutdown_message{"El sistema se apagará..."}; // Mensaje mostrado durante el apagado
// Constructor con valores por defecto // Constructor con valores por defecto
ShutdownConfig() = default; ShutdownConfig() = default;
}; };
// --- Funciones --- // --- Funciones ---
auto shutdownSystem() -> ShutdownResult; // Apaga el sistema con configuración por defecto auto shutdownSystem() -> ShutdownResult; // Apaga el sistema con configuración por defecto
auto shutdownSystem(const ShutdownConfig& config) -> ShutdownResult; // Apaga el sistema con configuración personalizada auto shutdownSystem(const ShutdownConfig& config) -> ShutdownResult; // Apaga el sistema con configuración personalizada
auto shutdownSystem(int delay_seconds, bool force_apps = true) -> ShutdownResult; // Apaga el sistema con parámetros simples auto shutdownSystem(int delay_seconds, bool force_apps = true) -> ShutdownResult; // Apaga el sistema con parámetros simples
auto resultToString(ShutdownResult result) -> const char*; // Convierte un código de resultado a string descriptivo auto resultToString(ShutdownResult result) -> const char*; // Convierte un código de resultado a string descriptivo
auto isShutdownSupported() -> bool; // Verifica si el sistema actual soporta apagado programático auto isShutdownSupported() -> bool; // Verifica si el sistema actual soporta apagado programático
auto getRequiredPermissions() -> const char*; // Obtiene información sobre los permisos necesarios auto getRequiredPermissions() -> const char*; // Obtiene información sobre los permisos necesarios
} // namespace SystemShutdown } // namespace SystemShutdown

View File

@@ -20,8 +20,8 @@
namespace SystemUtils { namespace SystemUtils {
// Función auxiliar para crear una carpeta individual // Función auxiliar para crear una carpeta individual
auto createSingleFolder(const std::string& path, int permissions) -> Result { auto createSingleFolder(const std::string& path, int permissions) -> Result {
struct stat st = {.st_dev = 0}; struct stat st = {.st_dev = 0};
// Verificar si ya existe // Verificar si ya existe
@@ -51,10 +51,10 @@ auto createSingleFolder(const std::string& path, int permissions) -> Result {
} }
return Result::SUCCESS; return Result::SUCCESS;
} }
// Función auxiliar para crear carpetas padre recursivamente // Función auxiliar para crear carpetas padre recursivamente
auto createParentFolders(const std::string& path, int permissions) -> Result { auto createParentFolders(const std::string& path, int permissions) -> Result {
size_t pos = 0; size_t pos = 0;
while ((pos = path.find('/', pos + 1)) != std::string::npos) { while ((pos = path.find('/', pos + 1)) != std::string::npos) {
@@ -68,24 +68,24 @@ auto createParentFolders(const std::string& path, int permissions) -> Result {
} }
return Result::SUCCESS; return Result::SUCCESS;
} }
auto createApplicationFolder(const std::string& app_name, std::string& out_path) -> Result { auto createApplicationFolder(const std::string& app_name, std::string& out_path) -> Result {
FolderConfig config; FolderConfig config;
return createApplicationFolder(app_name, out_path, config); return createApplicationFolder(app_name, out_path, config);
} }
auto createApplicationFolder(const std::string& app_name, std::string& out_path, const FolderConfig& config) -> Result { auto createApplicationFolder(const std::string& app_name, std::string& out_path, const FolderConfig& config) -> Result {
out_path = getApplicationDataPath(app_name); out_path = getApplicationDataPath(app_name);
return createFolder(out_path, config); return createFolder(out_path, config);
} }
auto createFolder(const std::string& path) -> Result { auto createFolder(const std::string& path) -> Result {
FolderConfig config; FolderConfig config;
return createFolder(path, config); return createFolder(path, config);
} }
auto createFolder(const std::string& path, const FolderConfig& config) -> Result { auto createFolder(const std::string& path, const FolderConfig& config) -> Result {
if (path.empty()) { if (path.empty()) {
return Result::INVALID_PATH; return Result::INVALID_PATH;
} }
@@ -105,9 +105,9 @@ auto createFolder(const std::string& path, const FolderConfig& config) -> Result
// Crear la carpeta final // Crear la carpeta final
return createSingleFolder(path, config.permissions); return createSingleFolder(path, config.permissions);
} }
auto getApplicationDataPath(const std::string& app_name) -> std::string { auto getApplicationDataPath(const std::string& app_name) -> std::string {
#ifdef _WIN32 #ifdef _WIN32
char* appdata = getenv("APPDATA"); char* appdata = getenv("APPDATA");
if (appdata) { if (appdata) {
@@ -128,14 +128,14 @@ auto getApplicationDataPath(const std::string& app_name) -> std::string {
std::string home = getHomeDirectory(); std::string home = getHomeDirectory();
return home + "/." + app_name; return home + "/." + app_name;
#endif #endif
} }
auto folderExists(const std::string& path) -> bool { auto folderExists(const std::string& path) -> bool {
struct stat st = {.st_dev = 0}; struct stat st = {.st_dev = 0};
return (stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode)); return (stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode));
} }
auto resultToString(Result result) -> const char* { auto resultToString(Result result) -> const char* {
switch (result) { switch (result) {
case Result::SUCCESS: case Result::SUCCESS:
return "Operación exitosa"; return "Operación exitosa";
@@ -152,9 +152,9 @@ auto resultToString(Result result) -> const char* {
default: default:
return "Error no identificado"; return "Error no identificado";
} }
} }
auto getHomeDirectory() -> std::string { auto getHomeDirectory() -> std::string {
#ifdef _WIN32 #ifdef _WIN32
char* userprofile = getenv("USERPROFILE"); char* userprofile = getenv("USERPROFILE");
if (userprofile) { if (userprofile) {
@@ -174,9 +174,9 @@ auto getHomeDirectory() -> std::string {
} }
return "/tmp"; return "/tmp";
#endif #endif
} }
auto getTempDirectory() -> std::string { auto getTempDirectory() -> std::string {
#ifdef _WIN32 #ifdef _WIN32
char* temp = getenv("TEMP"); char* temp = getenv("TEMP");
if (temp) { if (temp) {
@@ -186,6 +186,6 @@ auto getTempDirectory() -> std::string {
#else #else
return "/tmp"; return "/tmp";
#endif #endif
} }
} // namespace SystemUtils } // namespace SystemUtils

View File

@@ -4,35 +4,35 @@
// --- Namespace SystemUtils: utilidades multiplataforma para operaciones del sistema --- // --- Namespace SystemUtils: utilidades multiplataforma para operaciones del sistema ---
namespace SystemUtils { namespace SystemUtils {
// --- Enums --- // --- Enums ---
enum class Result { // Códigos de resultado para operaciones del sistema enum class Result { // Códigos de resultado para operaciones del sistema
SUCCESS = 0, SUCCESS = 0,
PERMISSION_DENIED, // Sin permisos para crear la carpeta PERMISSION_DENIED, // Sin permisos para crear la carpeta
PATH_TOO_LONG, // Ruta demasiado larga PATH_TOO_LONG, // Ruta demasiado larga
ALREADY_EXISTS, // Ya existe (solo si se considera error) ALREADY_EXISTS, // Ya existe (solo si se considera error)
INVALID_PATH, // Ruta inválida INVALID_PATH, // Ruta inválida
UNKNOWN_ERROR // Error desconocido UNKNOWN_ERROR // Error desconocido
}; };
// --- Estructuras --- // --- Estructuras ---
struct FolderConfig { // Configuración para creación de carpetas struct FolderConfig { // Configuración para creación de carpetas
bool create_parents{true}; // Crear carpetas padre si no existen bool create_parents{true}; // Crear carpetas padre si no existen
bool fail_if_exists{false}; // Fallar si la carpeta ya existe bool fail_if_exists{false}; // Fallar si la carpeta ya existe
int permissions{0755}; // Permisos Unix (ignorado en Windows) int permissions{0755}; // Permisos Unix (ignorado en Windows)
// Constructor con valores por defecto // Constructor con valores por defecto
FolderConfig() = default; FolderConfig() = default;
}; };
// --- Funciones --- // --- Funciones ---
auto createApplicationFolder(const std::string& app_name, std::string& out_path) -> Result; // Crea la carpeta del sistema donde guardar datos de la aplicación auto createApplicationFolder(const std::string& app_name, std::string& out_path) -> Result; // Crea la carpeta del sistema donde guardar datos de la aplicación
auto createApplicationFolder(const std::string& app_name, std::string& out_path, const FolderConfig& config) -> Result; // Crea la carpeta del sistema con configuración personalizada auto createApplicationFolder(const std::string& app_name, std::string& out_path, const FolderConfig& config) -> Result; // Crea la carpeta del sistema con configuración personalizada
auto createFolder(const std::string& path) -> Result; // Crea una carpeta en la ruta especificada auto createFolder(const std::string& path) -> Result; // Crea una carpeta en la ruta especificada
auto createFolder(const std::string& path, const FolderConfig& config) -> Result; // Crea una carpeta con configuración personalizada auto createFolder(const std::string& path, const FolderConfig& config) -> Result; // Crea una carpeta con configuración personalizada
auto getApplicationDataPath(const std::string& app_name) -> std::string; // Obtiene la ruta de datos de la aplicación (sin crearla) auto getApplicationDataPath(const std::string& app_name) -> std::string; // Obtiene la ruta de datos de la aplicación (sin crearla)
auto folderExists(const std::string& path) -> bool; // Verifica si una carpeta existe auto folderExists(const std::string& path) -> bool; // Verifica si una carpeta existe
auto resultToString(Result result) -> const char*; // Convierte un código de resultado a string descriptivo auto resultToString(Result result) -> const char*; // Convierte un código de resultado a string descriptivo
auto getHomeDirectory() -> std::string; // Obtiene el directorio home del usuario auto getHomeDirectory() -> std::string; // Obtiene el directorio home del usuario
auto getTempDirectory() -> std::string; // Obtiene el directorio temporal del sistema auto getTempDirectory() -> std::string; // Obtiene el directorio temporal del sistema
} // namespace SystemUtils } // namespace SystemUtils

View File

@@ -5,51 +5,51 @@
namespace Logger { namespace Logger {
// Colores ANSI // Colores ANSI
inline constexpr const char* RESET = "\033[0m"; inline constexpr const char* RESET = "\033[0m";
inline constexpr const char* RED = "\033[31m"; inline constexpr const char* RED = "\033[31m";
inline constexpr const char* GREEN = "\033[32m"; inline constexpr const char* GREEN = "\033[32m";
inline constexpr const char* YELLOW = "\033[33m"; inline constexpr const char* YELLOW = "\033[33m";
inline constexpr const char* BLUE = "\033[34m"; inline constexpr const char* BLUE = "\033[34m";
inline constexpr const char* MAGENTA = "\033[35m"; inline constexpr const char* MAGENTA = "\033[35m";
inline constexpr const char* CYAN = "\033[36m"; inline constexpr const char* CYAN = "\033[36m";
inline constexpr const char* WHITE = "\033[37m"; inline constexpr const char* WHITE = "\033[37m";
// Ancho total global para alineación // Ancho total global para alineación
inline constexpr size_t TOTAL_WIDTH = 52; inline constexpr size_t TOTAL_WIDTH = 52;
// Sección // Sección
inline void section(const std::string& title, const std::string& color = CYAN) { inline void section(const std::string& title, const std::string& color = CYAN) {
std::cout << "\n" std::cout << "\n"
<< color << color
<< "========================================\n" << "========================================\n"
<< " " << title << "\n" << " " << title << "\n"
<< "========================================" << "========================================"
<< RESET << "\n"; << RESET << "\n";
} }
// Info // Info
inline void info(const std::string& msg, const std::string& color = WHITE) { inline void info(const std::string& msg, const std::string& color = WHITE) {
std::cout << " " << color << msg << RESET << "\n"; std::cout << " " << color << msg << RESET << "\n";
} }
// Put // Put
inline void put(const std::string& msg, const std::string& color = WHITE) { inline void put(const std::string& msg, const std::string& color = WHITE) {
std::cout << color << msg << RESET << "\n"; std::cout << color << msg << RESET << "\n";
} }
// Error // Error
inline void error(const std::string& msg) { inline void error(const std::string& msg) {
std::cout << RED << msg << RESET << "\n"; std::cout << RED << msg << RESET << "\n";
} }
// CR // CR
inline void cr() { inline void cr() {
std::cout << "\n"; std::cout << "\n";
} }
// Dots genérico // Dots genérico
inline void dots(const std::string& prefix, inline void dots(const std::string& prefix,
const std::string& middle, const std::string& middle,
const std::string& suffix, const std::string& suffix,
const std::string& suffix_color = GREEN) { const std::string& suffix_color = GREEN) {
@@ -67,10 +67,10 @@ inline void dots(const std::string& prefix,
std::cout << " " << prefix << field_text std::cout << " " << prefix << field_text
<< suffix_color << suffix << RESET << suffix_color << suffix << RESET
<< "\n"; << "\n";
} }
// Status con true/false, usando dots y sufijos fijos // Status con true/false, usando dots y sufijos fijos
inline void status(const std::string& name, bool ok) { inline void status(const std::string& name, bool ok) {
// Ambos sufijos tienen 9 caracteres → alineación perfecta // Ambos sufijos tienen 9 caracteres → alineación perfecta
constexpr const char* OK_LABEL = "[ OK ]"; constexpr const char* OK_LABEL = "[ OK ]";
constexpr const char* ERROR_LABEL = "[ ERROR ]"; constexpr const char* ERROR_LABEL = "[ ERROR ]";
@@ -80,6 +80,6 @@ inline void status(const std::string& name, bool ok) {
} else { } else {
dots(" ", name, ERROR_LABEL, RED); dots(" ", name, ERROR_LABEL, RED);
} }
} }
} // namespace Logger } // namespace Logger