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
+58
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()
+49 -49
View File
@@ -16,25 +16,25 @@ class Texture;
// --- Estructuras --- // --- Estructuras ---
struct Animation { struct Animation {
static constexpr float DEFAULT_SPEED = 80.0F; static constexpr float DEFAULT_SPEED = 80.0F;
std::string name; // Nombre de la animación std::string name; // Nombre de la animación
std::vector<SDL_FRect> frames; // Frames que componen la animación std::vector<SDL_FRect> frames; // Frames que componen la animación
float speed{DEFAULT_SPEED}; // Velocidad de reproducción (ms entre frames) float speed{DEFAULT_SPEED}; // Velocidad de reproducción (ms entre frames)
int loop{0}; // Frame de vuelta al terminar (-1 para no repetir) int loop{0}; // Frame de vuelta al terminar (-1 para no repetir)
bool completed{false}; // Indica si la animación ha finalizado bool completed{false}; // Indica si la animación ha finalizado
size_t current_frame{0}; // Frame actual en reproducción size_t current_frame{0}; // Frame actual en reproducción
float time_accumulator{0.0F}; // Acumulador de tiempo para animaciones time-based float time_accumulator{0.0F}; // Acumulador de tiempo para animaciones time-based
bool paused{false}; // La animación no avanza bool paused{false}; // La animación no avanza
Animation() = default; Animation() = default;
}; };
struct AnimationConfig { struct AnimationConfig {
float frame_width = 1.0F; float frame_width = 1.0F;
float frame_height = 1.0F; float frame_height = 1.0F;
int frames_per_row = 1; int frames_per_row = 1;
int max_tiles = 1; int max_tiles = 1;
}; };
// --- Tipos --- // --- Tipos ---
@@ -45,44 +45,44 @@ auto loadAnimationsFromFile(const std::string& file_path) -> AnimationsFileBuffe
// --- Clase AnimatedSprite: sprite animado que hereda de MovingSprite --- // --- Clase AnimatedSprite: sprite animado que hereda de MovingSprite ---
class AnimatedSprite : public MovingSprite { class AnimatedSprite : public MovingSprite {
public: public:
// --- Constructores y destructor --- // --- Constructores y destructor ---
AnimatedSprite(std::shared_ptr<Texture> texture, const std::string& file_path); AnimatedSprite(std::shared_ptr<Texture> texture, const std::string& file_path);
AnimatedSprite(std::shared_ptr<Texture> texture, const AnimationsFileBuffer& animations); AnimatedSprite(std::shared_ptr<Texture> texture, const AnimationsFileBuffer& animations);
explicit AnimatedSprite(std::shared_ptr<Texture> texture) explicit AnimatedSprite(std::shared_ptr<Texture> texture)
: MovingSprite(std::move(texture)) {} : MovingSprite(std::move(texture)) {}
~AnimatedSprite() override = default; ~AnimatedSprite() override = default;
// --- Métodos principales --- // --- Métodos principales ---
void update(float delta_time) override; // Actualiza la animación (time-based) void update(float delta_time) override; // Actualiza la animación (time-based)
// --- Control de animaciones --- // --- Control de animaciones ---
void setCurrentAnimation(const std::string& name = "default", bool reset = true); // Establece la animación por nombre void setCurrentAnimation(const std::string& name = "default", bool reset = true); // Establece la animación por nombre
void setCurrentAnimation(int index = 0, bool reset = true); // Establece la animación por índice void setCurrentAnimation(int index = 0, bool reset = true); // Establece la animación por índice
void resetAnimation(); // Reinicia la animación actual void resetAnimation(); // Reinicia la animación actual
void setAnimationSpeed(float value); // Establece la velocidad de la animación void setAnimationSpeed(float value); // Establece la velocidad de la animación
auto getAnimationSpeed() const -> float { return animations_[current_animation_].speed; } // Obtiene la velocidad de la animación actual auto getAnimationSpeed() const -> float { return animations_[current_animation_].speed; } // Obtiene la velocidad de la animación actual
void animtionPause() { animations_[current_animation_].paused = true; } // Detiene la animación void animtionPause() { animations_[current_animation_].paused = true; } // Detiene la animación
void animationResume() { animations_[current_animation_].paused = false; } // Reanuda la animación void animationResume() { animations_[current_animation_].paused = false; } // Reanuda la animación
auto getCurrentAnimationFrame() const -> size_t { return animations_[current_animation_].current_frame; } // Obtiene el numero de frame de la animación actual auto getCurrentAnimationFrame() const -> size_t { return animations_[current_animation_].current_frame; } // Obtiene el numero de frame de la animación actual
// --- Consultas --- // --- Consultas ---
auto animationIsCompleted() -> bool; // Comprueba si la animación ha terminado auto animationIsCompleted() -> bool; // Comprueba si la animación ha terminado
auto getAnimationIndex(const std::string& name) -> int; // Obtiene el índice de una animación por nombre auto getAnimationIndex(const std::string& name) -> int; // Obtiene el índice de una animación por nombre
protected: protected:
// --- Variables de estado --- // --- Variables de estado ---
std::vector<Animation> animations_; // Vector de animaciones disponibles std::vector<Animation> animations_; // Vector de animaciones disponibles
std::unordered_map<std::string, int> animation_indices_; // Mapa para búsqueda rápida por nombre std::unordered_map<std::string, int> animation_indices_; // Mapa para búsqueda rápida por nombre
int current_animation_ = 0; // Índice de la animación activa int current_animation_ = 0; // Índice de la animación activa
// --- Métodos internos --- // --- Métodos internos ---
void animate(float delta_time); // Calcula el frame correspondiente a la animación (time-based) void animate(float delta_time); // Calcula el frame correspondiente a la animación (time-based)
void loadFromAnimationsFileBuffer(const AnimationsFileBuffer& source); // Carga la animación desde un vector de cadenas void loadFromAnimationsFileBuffer(const AnimationsFileBuffer& source); // Carga la animación desde un vector de cadenas
void processConfigLine(const std::string& line, AnimationConfig& config); // Procesa una línea de configuración void processConfigLine(const std::string& line, AnimationConfig& config); // Procesa una línea de configuración
void updateFrameCalculations(AnimationConfig& config); // Actualiza los cálculos basados en las dimensiones del frame void updateFrameCalculations(AnimationConfig& config); // Actualiza los cálculos basados en las dimensiones del frame
auto processAnimationBlock(const AnimationsFileBuffer& source, size_t start_index, const AnimationConfig& config) -> size_t; // Procesa un bloque completo de animación auto processAnimationBlock(const AnimationsFileBuffer& source, size_t start_index, const AnimationConfig& config) -> size_t; // Procesa un bloque completo de animación
static void processAnimationParameter(const std::string& line, Animation& animation, const AnimationConfig& config); // Procesa un parámetro individual de animación static void processAnimationParameter(const std::string& line, Animation& animation, const AnimationConfig& config); // Procesa un parámetro individual de animación
static void parseFramesParameter(const std::string& frames_str, Animation& animation, const AnimationConfig& config); // Parsea el parámetro de frames (lista separada por comas) static void parseFramesParameter(const std::string& frames_str, Animation& animation, const AnimationConfig& config); // Parsea el parámetro de frames (lista separada por comas)
void updateSpriteClip(); // Actualiza el spriteClip con el frame correspondiente void updateSpriteClip(); // Actualiza el spriteClip con el frame correspondiente
}; };
+55 -55
View File
@@ -8,67 +8,67 @@
// --- Clase Asset: gestor optimizado de recursos (singleton) --- // --- Clase Asset: gestor optimizado de recursos (singleton) ---
class Asset { class Asset {
public: public:
// --- Enums --- // --- Enums ---
enum class Type : int { enum class Type : int {
BITMAP, // Imágenes BITMAP, // Imágenes
MUSIC, // Música MUSIC, // Música
SOUND, // Sonidos SOUND, // Sonidos
FONT, // Fuentes FONT, // Fuentes
LANG, // Idiomas LANG, // Idiomas
DATA, // Datos DATA, // Datos
DEMODATA, // Datos de demo DEMODATA, // Datos de demo
ANIMATION, // Animaciones ANIMATION, // Animaciones
PALETTE, // Paletas PALETTE, // Paletas
SIZE, // Tamaño SIZE, // Tamaño
}; };
// --- Métodos de singleton --- // --- Métodos de singleton ---
static void init(const std::string& executable_path); static void init(const std::string& executable_path);
static void destroy(); static void destroy();
static auto get() -> Asset*; static auto get() -> Asset*;
Asset(const Asset&) = delete; Asset(const Asset&) = delete;
auto operator=(const Asset&) -> Asset& = delete; auto operator=(const Asset&) -> Asset& = delete;
// --- Métodos para la gestión de recursos --- // --- Métodos para la gestión de recursos ---
void add(const std::string& file_path, Type type, bool required = true, bool absolute = false); void add(const std::string& file_path, Type type, bool required = true, bool absolute = false);
void loadFromFile(const std::string& config_file_path, const std::string& prefix = "", const std::string& system_folder = ""); // Con soporte para variables void loadFromFile(const std::string& config_file_path, const std::string& prefix = "", const std::string& system_folder = ""); // Con soporte para variables
[[nodiscard]] auto get(const std::string& filename) const -> std::string; // Mantener nombre original [[nodiscard]] auto get(const std::string& filename) const -> std::string; // Mantener nombre original
[[nodiscard]] auto loadData(const std::string& filename) const -> std::vector<uint8_t>; // Carga datos del archivo [[nodiscard]] auto loadData(const std::string& filename) const -> std::vector<uint8_t>; // Carga datos del archivo
[[nodiscard]] auto check() const -> bool; [[nodiscard]] auto check() const -> bool;
[[nodiscard]] auto getListByType(Type type) const -> std::vector<std::string>; [[nodiscard]] auto getListByType(Type type) const -> std::vector<std::string>;
[[nodiscard]] auto exists(const std::string& filename) const -> bool; // Nueva función para verificar existencia [[nodiscard]] auto exists(const std::string& filename) const -> bool; // Nueva función para verificar existencia
private: private:
// --- Estructuras privadas --- // --- Estructuras privadas ---
struct Item { struct Item {
std::string file; // Ruta completa del archivo std::string file; // Ruta completa del archivo
Type type; // Tipo de recurso Type type; // Tipo de recurso
bool required; // Indica si el archivo es obligatorio bool required; // Indica si el archivo es obligatorio
Item(std::string path, Type asset_type, bool is_required) Item(std::string path, Type asset_type, bool is_required)
: file(std::move(path)), : file(std::move(path)),
type(asset_type), type(asset_type),
required(is_required) {} required(is_required) {}
}; };
// --- Variables internas --- // --- Variables internas ---
std::unordered_map<std::string, Item> file_list_; // Mapa para búsqueda O(1) std::unordered_map<std::string, Item> file_list_; // Mapa para búsqueda O(1)
std::string executable_path_; // Ruta del ejecutable std::string executable_path_; // Ruta del ejecutable
// --- Métodos internos --- // --- Métodos internos ---
[[nodiscard]] auto checkFile(const std::string& path) const -> bool; // Verifica si un archivo existe [[nodiscard]] auto checkFile(const std::string& path) const -> bool; // Verifica si un archivo existe
[[nodiscard]] static auto getTypeName(Type type) -> std::string; // Obtiene el nombre del tipo [[nodiscard]] static auto getTypeName(Type type) -> std::string; // Obtiene el nombre del tipo
[[nodiscard]] static auto parseAssetType(const std::string& type_str) -> Type; // Convierte string a tipo [[nodiscard]] static auto parseAssetType(const std::string& type_str) -> Type; // Convierte string a tipo
void addToMap(const std::string& file_path, Type type, bool required, bool absolute); // Añade archivo al mapa void addToMap(const std::string& file_path, Type type, bool required, bool absolute); // Añade archivo al mapa
[[nodiscard]] static auto replaceVariables(const std::string& path, const std::string& prefix, const std::string& system_folder) -> std::string; // Reemplaza variables en la ruta [[nodiscard]] static auto replaceVariables(const std::string& path, const std::string& prefix, const std::string& system_folder) -> std::string; // Reemplaza variables en la ruta
static auto parseOptions(const std::string& options, bool& required, bool& absolute) -> void; // Parsea opciones static auto parseOptions(const std::string& options, bool& required, bool& absolute) -> void; // Parsea opciones
// --- Constructores y destructor privados (singleton) --- // --- Constructores y destructor privados (singleton) ---
explicit Asset(std::string executable_path) // Constructor privado explicit Asset(std::string executable_path) // Constructor privado
: executable_path_(std::move(executable_path)) {} : executable_path_(std::move(executable_path)) {}
~Asset() = default; // Destructor privado ~Asset() = default; // Destructor privado
// --- Instancia singleton --- // --- Instancia singleton ---
static Asset* instance; // Instancia única de Asset static Asset* instance; // Instancia única de Asset
}; };
+14 -14
View File
@@ -7,23 +7,23 @@
// Extensión de Asset que integra ResourceLoader // Extensión de Asset que integra ResourceLoader
class AssetIntegrated : public Asset { class AssetIntegrated : public Asset {
public: public:
// Inicializa Asset con ResourceLoader // Inicializa Asset con ResourceLoader
static void initWithResourcePack(const std::string& executable_path, static void initWithResourcePack(const std::string& executable_path,
const std::string& resource_pack_path = "resources.pack"); const std::string& resource_pack_path = "resources.pack");
// Carga un archivo usando ResourceLoader como primera opción // Carga un archivo usando ResourceLoader como primera opción
static auto loadFile(const std::string& filename) -> std::vector<uint8_t>; static auto loadFile(const std::string& filename) -> std::vector<uint8_t>;
// Verifica si un archivo existe (pack o filesystem) // Verifica si un archivo existe (pack o filesystem)
static auto fileExists(const std::string& filename) -> bool; static auto fileExists(const std::string& filename) -> bool;
// Obtiene la ruta completa para archivos del sistema/config // Obtiene la ruta completa para archivos del sistema/config
static auto getSystemPath(const std::string& filename) -> std::string; static auto getSystemPath(const std::string& filename) -> std::string;
private: private:
static bool resource_pack_enabled; static bool resource_pack_enabled;
// Determina si un archivo debe cargarse del pack o del filesystem // Determina si un archivo debe cargarse del pack o del filesystem
static auto shouldUseResourcePack(const std::string& filepath) -> bool; static auto shouldUseResourcePack(const std::string& filepath) -> bool;
}; };
+85 -85
View File
@@ -5,107 +5,107 @@
// --- Clase Audio: gestor de audio (singleton) --- // --- Clase Audio: gestor de audio (singleton) ---
class Audio { class Audio {
public: public:
// --- Enums --- // --- Enums ---
enum class Group : int { enum class Group : int {
ALL = -1, // Todos los grupos ALL = -1, // Todos los grupos
GAME = 0, // Sonidos del juego GAME = 0, // Sonidos del juego
INTERFACE = 1 // Sonidos de la interfaz INTERFACE = 1 // Sonidos de la interfaz
}; };
enum class MusicState { enum class MusicState {
PLAYING, // Reproduciendo música PLAYING, // Reproduciendo música
PAUSED, // Música pausada PAUSED, // Música pausada
STOPPED, // Música detenida STOPPED, // Música detenida
}; };
// --- Constantes --- // --- Constantes ---
static constexpr int MAX_VOLUME = 100; // Volumen máximo static constexpr int MAX_VOLUME = 100; // Volumen máximo
static constexpr int MIN_VOLUME = 0; // Volumen mínimo static constexpr int MIN_VOLUME = 0; // Volumen mínimo
static constexpr int FREQUENCY = 48000; // Frecuencia de audio static constexpr int FREQUENCY = 48000; // Frecuencia de audio
// --- Métodos de singleton --- // --- Métodos de singleton ---
static void init(); // Inicializa el objeto Audio static void init(); // Inicializa el objeto Audio
static void destroy(); // Libera el objeto Audio static void destroy(); // Libera el objeto Audio
static auto get() -> Audio*; // Obtiene el puntero al objeto Audio static auto get() -> Audio*; // Obtiene el puntero al objeto Audio
Audio(const Audio&) = delete; // Evitar copia Audio(const Audio&) = delete; // Evitar copia
auto operator=(const Audio&) -> Audio& = delete; // Evitar asignación auto operator=(const Audio&) -> Audio& = delete; // Evitar asignación
// --- Método principal --- // --- Método principal ---
static void update(); static void update();
// --- Control de Música --- // --- Control de Música ---
void playMusic(const std::string& name, int loop = -1); // Reproducir música en bucle void playMusic(const std::string& name, int loop = -1); // Reproducir música en bucle
void pauseMusic(); // Pausar reproducción de música void pauseMusic(); // Pausar reproducción de música
void resumeMusic(); // Continua la música pausada void resumeMusic(); // Continua la música pausada
void stopMusic(); // Detener completamente la música void stopMusic(); // Detener completamente la música
void fadeOutMusic(int milliseconds) const; // Fundido de salida de la música void fadeOutMusic(int milliseconds) const; // Fundido de salida de la música
// --- Control de Sonidos --- // --- Control de Sonidos ---
void playSound(const std::string& name, Group group = Group::GAME) const; // Reproducir sonido puntual void playSound(const std::string& name, Group group = Group::GAME) const; // Reproducir sonido puntual
void stopAllSounds() const; // Detener todos los sonidos void stopAllSounds() const; // Detener todos los sonidos
// --- Configuración General --- // --- Configuración General ---
void enable(bool value); // Establecer estado general void enable(bool value); // Establecer estado general
void toggleEnabled() { enabled_ = !enabled_; } // Alternar estado general void toggleEnabled() { enabled_ = !enabled_; } // Alternar estado general
void applySettings(); // Aplica la configuración void applySettings(); // Aplica la configuración
// --- Configuración de Sonidos --- // --- Configuración de Sonidos ---
void enableSound() { sound_enabled_ = true; } // Habilitar sonidos void enableSound() { sound_enabled_ = true; } // Habilitar sonidos
void disableSound() { sound_enabled_ = false; } // Deshabilitar sonidos void disableSound() { sound_enabled_ = false; } // Deshabilitar sonidos
void enableSound(bool value) { sound_enabled_ = value; } // Establecer estado de sonidos void enableSound(bool value) { sound_enabled_ = value; } // Establecer estado de sonidos
void toggleSound() { sound_enabled_ = !sound_enabled_; } // Alternar estado de sonidos void toggleSound() { sound_enabled_ = !sound_enabled_; } // Alternar estado de sonidos
// --- Configuración de Música --- // --- Configuración de Música ---
void enableMusic() { music_enabled_ = true; } // Habilitar música void enableMusic() { music_enabled_ = true; } // Habilitar música
void disableMusic() { music_enabled_ = false; } // Deshabilitar música void disableMusic() { music_enabled_ = false; } // Deshabilitar música
void enableMusic(bool value) { music_enabled_ = value; } // Establecer estado de música void enableMusic(bool value) { music_enabled_ = value; } // Establecer estado de música
void toggleMusic() { music_enabled_ = !music_enabled_; } // Alternar estado de música void toggleMusic() { music_enabled_ = !music_enabled_; } // Alternar estado de música
// --- Control de Volumen --- // --- Control de Volumen ---
void setSoundVolume(int volume, Group group = Group::ALL) const; // Ajustar volumen de efectos void setSoundVolume(int volume, Group group = Group::ALL) const; // Ajustar volumen de efectos
void setMusicVolume(int volume) const; // Ajustar volumen de música void setMusicVolume(int volume) const; // Ajustar volumen de música
// --- Getters para debug --- // --- Getters para debug ---
[[nodiscard]] auto isEnabled() const -> bool { return enabled_; } [[nodiscard]] auto isEnabled() const -> bool { return enabled_; }
[[nodiscard]] auto isSoundEnabled() const -> bool { return sound_enabled_; } [[nodiscard]] auto isSoundEnabled() const -> bool { return sound_enabled_; }
[[nodiscard]] auto isMusicEnabled() const -> bool { return music_enabled_; } [[nodiscard]] auto isMusicEnabled() const -> bool { return music_enabled_; }
[[nodiscard]] auto getMusicState() const -> MusicState { return music_.state; } [[nodiscard]] auto getMusicState() const -> MusicState { return music_.state; }
[[nodiscard]] static auto getRealMusicState() -> MusicState; // Consulta directamente a jailaudio [[nodiscard]] static auto getRealMusicState() -> MusicState; // Consulta directamente a jailaudio
[[nodiscard]] auto getCurrentMusicName() const -> const std::string& { return music_.name; } [[nodiscard]] auto getCurrentMusicName() const -> const std::string& { return music_.name; }
private: private:
// --- Estructuras privadas --- // --- Estructuras privadas ---
struct Music { struct Music {
MusicState state; // Estado actual de la música (reproduciendo, detenido, en pausa) MusicState state; // Estado actual de la música (reproduciendo, detenido, en pausa)
std::string name; // Última pista de música reproducida std::string name; // Última pista de música reproducida
bool loop; // Indica si la última pista de música se debe reproducir en bucle bool loop; // Indica si la última pista de música se debe reproducir en bucle
// Constructor para inicializar la música con valores predeterminados // Constructor para inicializar la música con valores predeterminados
Music() Music()
: state(MusicState::STOPPED), : state(MusicState::STOPPED),
loop(false) {} loop(false) {}
// Constructor para inicializar con valores específicos // Constructor para inicializar con valores específicos
Music(MusicState init_state, std::string init_name, bool init_loop) Music(MusicState init_state, std::string init_name, bool init_loop)
: state(init_state), : state(init_state),
name(std::move(init_name)), name(std::move(init_name)),
loop(init_loop) {} loop(init_loop) {}
}; };
// --- Variables de estado --- // --- Variables de estado ---
Music music_; // Estado de la música Music music_; // Estado de la música
bool enabled_ = true; // Estado general del audio bool enabled_ = true; // Estado general del audio
bool sound_enabled_ = true; // Estado de los efectos de sonido bool sound_enabled_ = true; // Estado de los efectos de sonido
bool music_enabled_ = true; // Estado de la música bool music_enabled_ = true; // Estado de la música
// --- Métodos internos --- // --- Métodos internos ---
void initSDLAudio(); // Inicializa SDL Audio void initSDLAudio(); // Inicializa SDL Audio
// --- Constructores y destructor privados (singleton) --- // --- Constructores y destructor privados (singleton) ---
Audio(); // Constructor privado Audio(); // Constructor privado
~Audio(); // Destructor privado ~Audio(); // Destructor privado
// --- Instancia singleton --- // --- Instancia singleton ---
static Audio* instance; // Instancia única de Audio static Audio* instance; // Instancia única de Audio
}; };
+108 -108
View File
@@ -17,124 +17,124 @@ class AnimatedSprite;
// --- Clase Background: gestiona el fondo de la sección jugable --- // --- Clase Background: gestiona el fondo de la sección jugable ---
class Background { class Background {
public: public:
// --- Enums --- // --- Enums ---
enum class State { enum class State {
NORMAL, // Progresión normal del día NORMAL, // Progresión normal del día
COMPLETED // Reducción gradual de la actividad COMPLETED // Reducción gradual de la actividad
}; };
// --- Tipos --- // --- Tipos ---
using ProgressCallback = std::function<void(float)>; // Callback para sincronización using ProgressCallback = std::function<void(float)>; // Callback para sincronización
// --- Constructor y destructor --- // --- Constructor y destructor ---
Background(float total_progress_to_complete = 6100.0F); // Constructor principal Background(float total_progress_to_complete = 6100.0F); // Constructor principal
~Background(); // Destructor ~Background(); // Destructor
// --- Métodos principales --- // --- Métodos principales ---
void update(float delta_time); // Actualiza la lógica del objeto void update(float delta_time); // Actualiza la lógica del objeto
void render(); // Dibuja el objeto void render(); // Dibuja el objeto
void reset(); // Reinicia la progresión void reset(); // Reinicia la progresión
// --- Configuración --- // --- Configuración ---
void setPos(SDL_FRect pos); // Establece la posición del objeto void setPos(SDL_FRect pos); // Establece la posición del objeto
void setState(State new_state); // Cambia el estado del fondo void setState(State new_state); // Cambia el estado del fondo
void setProgressCallback(ProgressCallback callback); // Establece callback para sincronización void setProgressCallback(ProgressCallback callback); // Establece callback para sincronización
void removeProgressCallback(); // Elimina el callback void removeProgressCallback(); // Elimina el callback
void setManualMode(bool manual); // Activa/desactiva el modo manual void setManualMode(bool manual); // Activa/desactiva el modo manual
void setCloudsSpeed(float value); // Ajusta la velocidad de las nubes void setCloudsSpeed(float value); // Ajusta la velocidad de las nubes
void setGradientNumber(int value); // Establece el degradado de fondo void setGradientNumber(int value); // Establece el degradado de fondo
void setTransition(float value); // Ajusta la transición entre texturas void setTransition(float value); // Ajusta la transición entre texturas
void setSunProgression(float progress); // Establece la posición del sol void setSunProgression(float progress); // Establece la posición del sol
void setMoonProgression(float progress); // Establece la posición de la luna void setMoonProgression(float progress); // Establece la posición de la luna
void setColor(Color color); // Establece el color de atenuación void setColor(Color color); // Establece el color de atenuación
void setAlpha(int alpha); // Ajusta la transparencia del fondo void setAlpha(int alpha); // Ajusta la transparencia del fondo
// --- Control de progresión --- // --- Control de progresión ---
void incrementProgress(float amount = 1.0F); // Incrementa la progresión interna void incrementProgress(float amount = 1.0F); // Incrementa la progresión interna
void setProgress(float absolute_progress); // Establece la progresión absoluta void setProgress(float absolute_progress); // Establece la progresión absoluta
// --- Getters --- // --- Getters ---
[[nodiscard]] auto getProgress() const -> float { return progress_; } // Obtiene el progreso actual [[nodiscard]] auto getProgress() const -> float { return progress_; } // Obtiene el progreso actual
[[nodiscard]] auto getState() const -> State { return state_; } // Obtiene el estado actual [[nodiscard]] auto getState() const -> State { return state_; } // Obtiene el estado actual
[[nodiscard]] auto getCurrentGradient() const -> int { return static_cast<int>(gradient_number_); } // Obtiene el gradiente actual [[nodiscard]] auto getCurrentGradient() const -> int { return static_cast<int>(gradient_number_); } // Obtiene el gradiente actual
private: private:
// --- Constantes --- // --- Constantes ---
static constexpr size_t STAGES = 4; // Número de etapas static constexpr size_t STAGES = 4; // Número de etapas
static constexpr float MINIMUM_COMPLETED_PROGRESS_PERCENTAGE = 0.05F; // Porcentaje mínimo completado (10%) static constexpr float MINIMUM_COMPLETED_PROGRESS_PERCENTAGE = 0.05F; // Porcentaje mínimo completado (10%)
static constexpr float SUN_COMPLETION_FACTOR = 0.5F; // Factor de completado del sol static constexpr float SUN_COMPLETION_FACTOR = 0.5F; // Factor de completado del sol
static constexpr float COMPLETION_TRANSITION_DURATION_S = 3.0F; // Duración de la transición de completado en segundos static constexpr float COMPLETION_TRANSITION_DURATION_S = 3.0F; // Duración de la transición de completado en segundos
// --- Objetos y punteros --- // --- Objetos y punteros ---
SDL_Renderer* renderer_; // Renderizador de la ventana SDL_Renderer* renderer_; // Renderizador de la ventana
SDL_Texture* canvas_; // Textura para componer el fondo SDL_Texture* canvas_; // Textura para componer el fondo
SDL_Texture* color_texture_; // Textura para atenuar el fondo SDL_Texture* color_texture_; // Textura para atenuar el fondo
std::shared_ptr<Texture> buildings_texture_; // Textura de edificios std::shared_ptr<Texture> buildings_texture_; // Textura de edificios
std::shared_ptr<Texture> top_clouds_texture_; // Textura de nubes superiores std::shared_ptr<Texture> top_clouds_texture_; // Textura de nubes superiores
std::shared_ptr<Texture> bottom_clouds_texture_; // Textura de nubes inferiores std::shared_ptr<Texture> bottom_clouds_texture_; // Textura de nubes inferiores
std::shared_ptr<Texture> gradients_texture_; // Textura de gradientes std::shared_ptr<Texture> gradients_texture_; // Textura de gradientes
std::shared_ptr<Texture> sun_texture_; // Textura del sol std::shared_ptr<Texture> sun_texture_; // Textura del sol
std::shared_ptr<Texture> moon_texture_; // Textura de la luna std::shared_ptr<Texture> moon_texture_; // Textura de la luna
std::unique_ptr<MovingSprite> top_clouds_sprite_a_; // Sprite de nubes superiores A std::unique_ptr<MovingSprite> top_clouds_sprite_a_; // Sprite de nubes superiores A
std::unique_ptr<MovingSprite> top_clouds_sprite_b_; // Sprite de nubes superiores B std::unique_ptr<MovingSprite> top_clouds_sprite_b_; // Sprite de nubes superiores B
std::unique_ptr<MovingSprite> bottom_clouds_sprite_a_; // Sprite de nubes inferiores A std::unique_ptr<MovingSprite> bottom_clouds_sprite_a_; // Sprite de nubes inferiores A
std::unique_ptr<MovingSprite> bottom_clouds_sprite_b_; // Sprite de nubes inferiores B std::unique_ptr<MovingSprite> bottom_clouds_sprite_b_; // Sprite de nubes inferiores B
std::unique_ptr<Sprite> buildings_sprite_; // Sprite de edificios std::unique_ptr<Sprite> buildings_sprite_; // Sprite de edificios
std::unique_ptr<Sprite> gradient_sprite_; // Sprite de gradiente std::unique_ptr<Sprite> gradient_sprite_; // Sprite de gradiente
std::unique_ptr<Sprite> sun_sprite_; // Sprite del sol std::unique_ptr<Sprite> sun_sprite_; // Sprite del sol
std::unique_ptr<Sprite> moon_sprite_; // Sprite de la luna std::unique_ptr<Sprite> moon_sprite_; // Sprite de la luna
std::unique_ptr<AnimatedSprite> grass_sprite_; // Sprite con la hierba std::unique_ptr<AnimatedSprite> grass_sprite_; // Sprite con la hierba
// --- Variables de configuración --- // --- Variables de configuración ---
const float total_progress_to_complete_; // Progreso total para completar const float total_progress_to_complete_; // Progreso total para completar
const float progress_per_stage_; // Progreso por etapa const float progress_per_stage_; // Progreso por etapa
const float sun_completion_progress_; // Progreso de completado del sol const float sun_completion_progress_; // Progreso de completado del sol
const float minimum_completed_progress_; // Progreso mínimo calculado dinámicamente const float minimum_completed_progress_; // Progreso mínimo calculado dinámicamente
ProgressCallback progress_callback_; // Callback para notificar cambios de progreso ProgressCallback progress_callback_; // Callback para notificar cambios de progreso
// --- Variables de estado --- // --- Variables de estado ---
std::vector<SDL_FPoint> sun_path_; // Recorrido del sol std::vector<SDL_FPoint> sun_path_; // Recorrido del sol
std::vector<SDL_FPoint> moon_path_; // Recorrido de la luna std::vector<SDL_FPoint> moon_path_; // Recorrido de la luna
std::array<SDL_FRect, STAGES> gradient_rect_; // Fondos degradados std::array<SDL_FRect, STAGES> gradient_rect_; // Fondos degradados
std::array<SDL_FRect, 4> top_clouds_rect_; // Nubes superiores std::array<SDL_FRect, 4> top_clouds_rect_; // Nubes superiores
std::array<SDL_FRect, 4> bottom_clouds_rect_; // Nubes inferiores std::array<SDL_FRect, 4> bottom_clouds_rect_; // Nubes inferiores
SDL_FRect rect_; // Tamaño del objeto SDL_FRect rect_; // Tamaño del objeto
SDL_FRect src_rect_; // Parte del objeto para copiar en pantalla SDL_FRect src_rect_; // Parte del objeto para copiar en pantalla
SDL_FRect dst_rect_; // Posición en pantalla donde se copia el objeto SDL_FRect dst_rect_; // Posición en pantalla donde se copia el objeto
Color attenuate_color_; // Color de atenuación Color attenuate_color_; // Color de atenuación
State state_ = State::NORMAL; // Estado actual State state_ = State::NORMAL; // Estado actual
float progress_ = 0.0F; // Progresión interna float progress_ = 0.0F; // Progresión interna
float clouds_speed_ = 0; // Velocidad de las nubes float clouds_speed_ = 0; // Velocidad de las nubes
float transition_ = 0; // Porcentaje de transición float transition_ = 0; // Porcentaje de transición
float current_alpha_float_ = 0.0F; // Acumulador para el valor alfa preciso float current_alpha_float_ = 0.0F; // Acumulador para el valor alfa preciso
size_t gradient_number_ = 0; // Índice de fondo degradado size_t gradient_number_ = 0; // Índice de fondo degradado
size_t alpha_color_texture_ = 0; // Transparencia de atenuación size_t alpha_color_texture_ = 0; // Transparencia de atenuación
size_t previous_alpha_color_texture_ = 0; // Transparencia anterior size_t previous_alpha_color_texture_ = 0; // Transparencia anterior
size_t sun_index_ = 0; // Índice del recorrido del sol size_t sun_index_ = 0; // Índice del recorrido del sol
size_t moon_index_ = 0; // Índice del recorrido de la luna size_t moon_index_ = 0; // Índice del recorrido de la luna
int base_ = 0; // Posición base del fondo int base_ = 0; // Posición base del fondo
Uint8 alpha_ = 0; // Transparencia entre fases Uint8 alpha_ = 0; // Transparencia entre fases
bool manual_mode_ = false; // Si está en modo manual bool manual_mode_ = false; // Si está en modo manual
// --- Variables para transición suave de completado --- // --- Variables para transición suave de completado ---
float completion_transition_timer_ = 0.0F; // Timer para la transición de completado float completion_transition_timer_ = 0.0F; // Timer para la transición de completado
float completion_initial_progress_ = 0.0F; // Progreso inicial al entrar en estado completado float completion_initial_progress_ = 0.0F; // Progreso inicial al entrar en estado completado
// --- Métodos internos --- // --- Métodos internos ---
void initializePaths(); // Inicializa las rutas del sol y la luna void initializePaths(); // Inicializa las rutas del sol y la luna
void initializeRects(); // Inicializa los rectángulos de gradientes y nubes void initializeRects(); // Inicializa los rectángulos de gradientes y nubes
void initializeSprites(); // Crea los sprites void initializeSprites(); // Crea los sprites
void initializeSpriteProperties(); // Configura las propiedades iniciales de los sprites void initializeSpriteProperties(); // Configura las propiedades iniciales de los sprites
void initializeTextures(); // Inicializa las texturas de renderizado void initializeTextures(); // Inicializa las texturas de renderizado
void updateProgression(float delta_time); // Actualiza la progresión y calcula transiciones void updateProgression(float delta_time); // Actualiza la progresión y calcula transiciones
void updateCloudsSpeed(); // Actualiza la velocidad de las nubes según el estado void updateCloudsSpeed(); // Actualiza la velocidad de las nubes según el estado
void renderGradient(); // Dibuja el gradiente de fondo void renderGradient(); // Dibuja el gradiente de fondo
void renderTopClouds(); // Dibuja las nubes superiores void renderTopClouds(); // Dibuja las nubes superiores
void renderBottomClouds(); // Dibuja las nubes inferiores void renderBottomClouds(); // Dibuja las nubes inferiores
void fillCanvas(); // Compone todos los elementos en la textura void fillCanvas(); // Compone todos los elementos en la textura
void updateAlphaColorTexture(float delta_time); // Actualiza el alpha de la textura de atenuación void updateAlphaColorTexture(float delta_time); // Actualiza el alpha de la textura de atenuación
void updateClouds(float delta_time); // Actualiza el movimiento de las nubes (time-based) void updateClouds(float delta_time); // Actualiza el movimiento de las nubes (time-based)
void createSunPath(); // Precalcula el recorrido del sol void createSunPath(); // Precalcula el recorrido del sol
void createMoonPath(); // Precalcula el recorrido de la luna void createMoonPath(); // Precalcula el recorrido de la luna
}; };
+264 -264
View File
@@ -15,291 +15,291 @@ class Texture;
// --- Clase Balloon --- // --- Clase Balloon ---
class Balloon { class Balloon {
public: public:
// --- Constantes relacionadas con globos --- // --- Constantes relacionadas con globos ---
static constexpr int MAX_BOUNCE = 10; // Cantidad de elementos del vector de deformación static constexpr int MAX_BOUNCE = 10; // Cantidad de elementos del vector de deformación
static constexpr std::array<int, 4> SCORE = {50, 100, 200, 400}; static constexpr std::array<int, 4> SCORE = {50, 100, 200, 400};
static constexpr std::array<int, 4> POWER = {1, 3, 7, 15}; static constexpr std::array<int, 4> POWER = {1, 3, 7, 15};
static constexpr std::array<int, 4> MENACE = {1, 2, 4, 8}; static constexpr std::array<int, 4> MENACE = {1, 2, 4, 8};
static constexpr std::array<int, 5> WIDTH = {10, 16, 26, 48, 49}; static constexpr std::array<int, 5> WIDTH = {10, 16, 26, 48, 49};
static constexpr std::array<std::string_view, 4> BOUNCING_SOUND = { static constexpr std::array<std::string_view, 4> BOUNCING_SOUND = {
"balloon_bounce0.wav", "balloon_bounce0.wav",
"balloon_bounce1.wav", "balloon_bounce1.wav",
"balloon_bounce2.wav", "balloon_bounce2.wav",
"balloon_bounce3.wav"}; "balloon_bounce3.wav"};
static constexpr std::array<std::string_view, 4> POPPING_SOUND = { static constexpr std::array<std::string_view, 4> POPPING_SOUND = {
"balloon_pop0.wav", "balloon_pop0.wav",
"balloon_pop1.wav", "balloon_pop1.wav",
"balloon_pop2.wav", "balloon_pop2.wav",
"balloon_pop3.wav"}; "balloon_pop3.wav"};
// Velocidades horizontales en pixels/segundo (convertidas desde 0.7 pixels/frame a 60fps) // Velocidades horizontales en pixels/segundo (convertidas desde 0.7 pixels/frame a 60fps)
static constexpr float VELX_POSITIVE = 0.7F * 60.0F; // 42 pixels/segundo static constexpr float VELX_POSITIVE = 0.7F * 60.0F; // 42 pixels/segundo
static constexpr float VELX_NEGATIVE = -0.7F * 60.0F; // -42 pixels/segundo static constexpr float VELX_NEGATIVE = -0.7F * 60.0F; // -42 pixels/segundo
// Multiplicadores de tempo del juego (sin cambios, son puros multiplicadores) // Multiplicadores de tempo del juego (sin cambios, son puros multiplicadores)
static constexpr std::array<float, 5> GAME_TEMPO = {0.60F, 0.70F, 0.80F, 0.90F, 1.00F}; static constexpr std::array<float, 5> GAME_TEMPO = {0.60F, 0.70F, 0.80F, 0.90F, 1.00F};
static constexpr int POWERBALL_SCREENPOWER_MINIMUM = 10; static constexpr int POWERBALL_SCREENPOWER_MINIMUM = 10;
static constexpr int POWERBALL_COUNTER = 8; static constexpr int POWERBALL_COUNTER = 8;
// --- Enums --- // --- Enums ---
enum class Size : Uint8 { enum class Size : Uint8 {
SMALL = 0, // Tamaño pequeño SMALL = 0, // Tamaño pequeño
MEDIUM = 1, // Tamaño mediano MEDIUM = 1, // Tamaño mediano
LARGE = 2, // Tamaño grande LARGE = 2, // Tamaño grande
EXTRALARGE = 3, // Tamaño extra grande EXTRALARGE = 3, // Tamaño extra grande
}; };
enum class Type : Uint8 { enum class Type : Uint8 {
BALLOON = 0, // Globo normal BALLOON = 0, // Globo normal
FLOATER = 1, // Globo flotante FLOATER = 1, // Globo flotante
POWERBALL = 2, // Globo de poder POWERBALL = 2, // Globo de poder
}; };
// --- Estructura para manejo de sonido --- // --- Estructura para manejo de sonido ---
struct Sound { struct Sound {
std::string bouncing_file; // Archivo de sonido al rebotar std::string bouncing_file; // Archivo de sonido al rebotar
std::string popping_file; // Archivo de sonido al explotar std::string popping_file; // Archivo de sonido al explotar
bool bouncing_enabled = false; // Si debe sonar el globo al rebotar bool bouncing_enabled = false; // Si debe sonar el globo al rebotar
bool poping_enabled = true; // Si debe sonar el globo al explotar bool poping_enabled = true; // Si debe sonar el globo al explotar
bool enabled = true; // Indica si los globos deben hacer algun sonido bool enabled = true; // Indica si los globos deben hacer algun sonido
}; };
// --- Estructura de configuración para inicialización --- // --- Estructura de configuración para inicialización ---
struct Config { struct Config {
float x = 0.0F; float x = 0.0F;
float y = 0.0F; float y = 0.0F;
Type type = Type::BALLOON; Type type = Type::BALLOON;
Size size = Size::EXTRALARGE; Size size = Size::EXTRALARGE;
float vel_x = VELX_POSITIVE; float vel_x = VELX_POSITIVE;
float game_tempo = GAME_TEMPO.at(0); float game_tempo = GAME_TEMPO.at(0);
float creation_counter = 0.0F; float creation_counter = 0.0F;
SDL_FRect play_area = {.x = 0.0F, .y = 0.0F, .w = 0.0F, .h = 0.0F}; SDL_FRect play_area = {.x = 0.0F, .y = 0.0F, .w = 0.0F, .h = 0.0F};
std::shared_ptr<Texture> texture = nullptr; std::shared_ptr<Texture> texture = nullptr;
std::vector<std::string> animation; std::vector<std::string> animation;
Sound sound; Sound sound;
}; };
// --- Constructores y destructor --- // --- Constructores y destructor ---
Balloon(const Config& config); Balloon(const Config& config);
~Balloon() = default; ~Balloon() = default;
// --- Métodos principales --- // --- Métodos principales ---
void alignTo(int x); // Centra el globo en la posición X void alignTo(int x); // Centra el globo en la posición X
void render(); // Pinta el globo en la pantalla void render(); // Pinta el globo en la pantalla
void move(float delta_time); // Actualiza la posición y estados del globo (time-based) void move(float delta_time); // Actualiza la posición y estados del globo (time-based)
void update(float delta_time); // Actualiza el globo (posición, animación, contadores) (time-based) void update(float delta_time); // Actualiza el globo (posición, animación, contadores) (time-based)
void stop(); // Detiene el globo void stop(); // Detiene el globo
void start(); // Pone el globo en movimiento void start(); // Pone el globo en movimiento
void pop(bool should_sound = false); // Explota el globo void pop(bool should_sound = false); // Explota el globo
// --- Métodos de color --- // --- Métodos de color ---
void useReverseColor(); // Pone el color alternativo en el globo void useReverseColor(); // Pone el color alternativo en el globo
void useNormalColor(); // Pone el color normal en el globo void useNormalColor(); // Pone el color normal en el globo
// --- Getters --- // --- Getters ---
[[nodiscard]] auto getPosX() const -> float { return x_; } [[nodiscard]] auto getPosX() const -> float { return x_; }
[[nodiscard]] auto getPosY() const -> float { return y_; } [[nodiscard]] auto getPosY() const -> float { return y_; }
[[nodiscard]] auto getWidth() const -> int { return w_; } [[nodiscard]] auto getWidth() const -> int { return w_; }
[[nodiscard]] auto getHeight() const -> int { return h_; } [[nodiscard]] auto getHeight() const -> int { return h_; }
[[nodiscard]] auto getSize() const -> Size { return size_; } [[nodiscard]] auto getSize() const -> Size { return size_; }
[[nodiscard]] auto getType() const -> Type { return type_; } [[nodiscard]] auto getType() const -> Type { return type_; }
[[nodiscard]] auto getScore() const -> Uint16 { return score_; } [[nodiscard]] auto getScore() const -> Uint16 { return score_; }
auto getCollider() -> Circle& { return collider_; } auto getCollider() -> Circle& { return collider_; }
[[nodiscard]] auto getMenace() const -> Uint8 { return isEnabled() ? menace_ : 0; } [[nodiscard]] auto getMenace() const -> Uint8 { return isEnabled() ? menace_ : 0; }
[[nodiscard]] auto getPower() const -> Uint8 { return power_; } [[nodiscard]] auto getPower() const -> Uint8 { return power_; }
[[nodiscard]] auto isStopped() const -> bool { return stopped_; } [[nodiscard]] auto isStopped() const -> bool { return stopped_; }
[[nodiscard]] auto isPowerBall() const -> bool { return type_ == Type::POWERBALL; } [[nodiscard]] auto isPowerBall() const -> bool { return type_ == Type::POWERBALL; }
[[nodiscard]] auto isInvulnerable() const -> bool { return invulnerable_; } [[nodiscard]] auto isInvulnerable() const -> bool { return invulnerable_; }
[[nodiscard]] auto isBeingCreated() const -> bool { return being_created_; } [[nodiscard]] auto isBeingCreated() const -> bool { return being_created_; }
[[nodiscard]] auto isEnabled() const -> bool { return enabled_; }
[[nodiscard]] auto isUsingReversedColor() const -> bool { return use_reversed_colors_; }
[[nodiscard]] auto canBePopped() const -> bool { return !isBeingCreated(); }
// --- Setters ---
void setVelY(float vel_y) { vy_ = vel_y; }
void setVelX(float vel_x) { vx_ = vel_x; }
void alterVelX(float percent) { vx_ *= percent; }
void setGameTempo(float tempo) { game_tempo_ = tempo; }
void setInvulnerable(bool value) { invulnerable_ = value; }
void setBouncingSound(bool value) { sound_.bouncing_enabled = value; }
void setPoppingSound(bool value) { sound_.poping_enabled = value; }
void setSound(bool value) { sound_.enabled = value; }
private:
// --- Estructura para el efecto de rebote ---
struct BounceEffect {
private:
static constexpr int BOUNCE_FRAMES = 10; // Cantidad de elementos del vector de deformación
// Tablas de valores predefinidos para el efecto de rebote
static constexpr std::array<float, BOUNCE_FRAMES> HORIZONTAL_ZOOM_VALUES = {
1.10F,
1.05F,
1.00F,
0.95F,
0.90F,
0.95F,
1.00F,
1.02F,
1.05F,
1.02F};
static constexpr std::array<float, BOUNCE_FRAMES> VERTICAL_ZOOM_VALUES = {
0.90F,
0.95F,
1.00F,
1.05F,
1.10F,
1.05F,
1.00F,
0.98F,
0.95F,
0.98F};
// Estado del efecto
bool enabled_ = false; // Si el efecto está activo
Uint8 counter_ = 0; // Contador para el efecto
Uint8 speed_ = 2; // Velocidad del efecto
// Valores actuales de transformación
float horizontal_zoom_ = 1.0F; // Zoom en anchura
float verical_zoom_ = 1.0F; // Zoom en altura
float x_offset_ = 0.0F; // Desplazamiento X antes de pintar
float y_offset_ = 0.0F; // Desplazamiento Y antes de pintar
public:
// Constructor por defecto
BounceEffect() = default;
// Reinicia el efecto a sus valores iniciales
void reset() {
counter_ = 0;
horizontal_zoom_ = 1.0F;
verical_zoom_ = 1.0F;
x_offset_ = 0.0F;
y_offset_ = 0.0F;
}
// Aplica la deformación visual al sprite
void apply(AnimatedSprite* sprite) const {
if (sprite != nullptr) {
sprite->setHorizontalZoom(horizontal_zoom_);
sprite->setVerticalZoom(verical_zoom_);
}
}
// Activa el efecto de rebote
void enable(AnimatedSprite* sprite, Size balloon_size) {
// Los globos pequeños no tienen efecto de rebote
if (balloon_size == Size::SMALL) {
return;
}
enabled_ = true;
reset();
apply(sprite);
}
// Detiene el efecto de rebote
void disable(AnimatedSprite* sprite) {
enabled_ = false;
reset();
apply(sprite);
}
// Actualiza el efecto en cada frame
void update(AnimatedSprite* sprite) {
if (!enabled_) {
return;
}
// Calcula el índice basado en el contador y velocidad
const int INDEX = counter_ / speed_;
// Actualiza los valores de zoom desde las tablas predefinidas
horizontal_zoom_ = HORIZONTAL_ZOOM_VALUES.at(INDEX);
verical_zoom_ = VERTICAL_ZOOM_VALUES.at(INDEX);
// Aplica la deformación al sprite
apply(sprite);
// Incrementa el contador y verifica si el efecto debe terminar
if (++counter_ / speed_ >= BOUNCE_FRAMES) {
disable(sprite);
}
}
// Getters para acceso a los valores actuales
[[nodiscard]] auto isEnabled() const -> bool { return enabled_; } [[nodiscard]] auto isEnabled() const -> bool { return enabled_; }
[[nodiscard]] auto isUsingReversedColor() const -> bool { return use_reversed_colors_; } [[nodiscard]] auto getHorizontalZoom() const -> float { return horizontal_zoom_; }
[[nodiscard]] auto canBePopped() const -> bool { return !isBeingCreated(); } [[nodiscard]] auto getVerticalZoom() const -> float { return verical_zoom_; }
[[nodiscard]] auto getXOffset() const -> float { return x_offset_; }
[[nodiscard]] auto getYOffset() const -> float { return y_offset_; }
};
// --- Setters --- // --- Objetos y punteros ---
void setVelY(float vel_y) { vy_ = vel_y; } std::unique_ptr<AnimatedSprite> sprite_; // Sprite del objeto globo
void setVelX(float vel_x) { vx_ = vel_x; }
void alterVelX(float percent) { vx_ *= percent; }
void setGameTempo(float tempo) { game_tempo_ = tempo; }
void setInvulnerable(bool value) { invulnerable_ = value; }
void setBouncingSound(bool value) { sound_.bouncing_enabled = value; }
void setPoppingSound(bool value) { sound_.poping_enabled = value; }
void setSound(bool value) { sound_.enabled = value; }
private: // --- Variables de estado y físicas ---
// --- Estructura para el efecto de rebote --- float x_; // Posición X
struct BounceEffect { float y_; // Posición Y
private: float w_; // Ancho
static constexpr int BOUNCE_FRAMES = 10; // Cantidad de elementos del vector de deformación float h_; // Alto
float vx_; // Velocidad X
float vy_; // Velocidad Y
float gravity_; // Aceleración en Y
float default_vy_; // Velocidad inicial al rebotar
float max_vy_; // Máxima velocidad en Y
bool being_created_; // Si el globo se está creando
bool enabled_ = true; // Si el globo está activo
bool invulnerable_; // Si el globo es invulnerable
bool stopped_; // Si el globo está parado
bool use_reversed_colors_ = false; // Si se usa el color alternativo
Circle collider_; // Círculo de colisión
float creation_counter_; // Temporizador de creación
float creation_counter_ini_; // Valor inicial del temporizador de creación
Uint16 score_; // Puntos al destruir el globo
Type type_; // Tipo de globo
Size size_; // Tamaño de globo
Uint8 menace_; // Amenaza que genera el globo
Uint32 counter_ = 0; // Contador interno
float game_tempo_; // Multiplicador de tempo del juego
float movement_accumulator_ = 0.0F; // Acumulador para movimiento durante creación (deltaTime)
Uint8 power_; // Poder que alberga el globo
SDL_FRect play_area_; // Zona de movimiento del globo
Sound sound_; // Configuración de sonido del globo
BounceEffect bounce_effect_; // Efecto de rebote
// Tablas de valores predefinidos para el efecto de rebote // --- Posicionamiento y transformación ---
static constexpr std::array<float, BOUNCE_FRAMES> HORIZONTAL_ZOOM_VALUES = { void shiftColliders(); // Alinea el círculo de colisión con el sprite
1.10F, void shiftSprite(); // Alinea el sprite en pantalla
1.05F,
1.00F,
0.95F,
0.90F,
0.95F,
1.00F,
1.02F,
1.05F,
1.02F};
static constexpr std::array<float, BOUNCE_FRAMES> VERTICAL_ZOOM_VALUES = { // --- Animación y sonido ---
0.90F, void setAnimation(); // Establece la animación correspondiente
0.95F, void playBouncingSound() const; // Reproduce el sonido de rebote
1.00F, void playPoppingSound() const; // Reproduce el sonido de reventar
1.05F,
1.10F,
1.05F,
1.00F,
0.98F,
0.95F,
0.98F};
// Estado del efecto // --- Movimiento y física ---
bool enabled_ = false; // Si el efecto está activo void handleHorizontalMovement(float delta_time); // Maneja el movimiento horizontal (time-based)
Uint8 counter_ = 0; // Contador para el efecto void handleVerticalMovement(float delta_time); // Maneja el movimiento vertical (time-based)
Uint8 speed_ = 2; // Velocidad del efecto void applyGravity(float delta_time); // Aplica la gravedad al objeto (time-based)
// Valores actuales de transformación // --- Rebote ---
float horizontal_zoom_ = 1.0F; // Zoom en anchura void enableBounceEffect(); // Activa el efecto de rebote
float verical_zoom_ = 1.0F; // Zoom en altura void disableBounceEffect(); // Detiene el efecto de rebote
float x_offset_ = 0.0F; // Desplazamiento X antes de pintar void updateBounceEffect(); // Actualiza el estado del rebote
float y_offset_ = 0.0F; // Desplazamiento Y antes de pintar void handleHorizontalBounce(float min_x, float max_x); // Maneja el rebote horizontal dentro de límites
public: // --- Colisiones ---
// Constructor por defecto [[nodiscard]] auto isOutOfHorizontalBounds(float min_x, float max_x) const -> bool; // Verifica si está fuera de los límites horizontales
BounceEffect() = default; [[nodiscard]] auto shouldCheckTopCollision() const -> bool; // Determina si debe comprobarse la colisión superior
void handleTopCollision(); // Maneja la colisión superior
void handleBottomCollision(); // Maneja la colisión inferior
// Reinicia el efecto a sus valores iniciales // --- Lógica de estado ---
void reset() { void updateState(float delta_time); // Actualiza los estados del globo (time-based)
counter_ = 0;
horizontal_zoom_ = 1.0F;
verical_zoom_ = 1.0F;
x_offset_ = 0.0F;
y_offset_ = 0.0F;
}
// Aplica la deformación visual al sprite
void apply(AnimatedSprite* sprite) const {
if (sprite != nullptr) {
sprite->setHorizontalZoom(horizontal_zoom_);
sprite->setVerticalZoom(verical_zoom_);
}
}
// Activa el efecto de rebote
void enable(AnimatedSprite* sprite, Size balloon_size) {
// Los globos pequeños no tienen efecto de rebote
if (balloon_size == Size::SMALL) {
return;
}
enabled_ = true;
reset();
apply(sprite);
}
// Detiene el efecto de rebote
void disable(AnimatedSprite* sprite) {
enabled_ = false;
reset();
apply(sprite);
}
// Actualiza el efecto en cada frame
void update(AnimatedSprite* sprite) {
if (!enabled_) {
return;
}
// Calcula el índice basado en el contador y velocidad
const int INDEX = counter_ / speed_;
// Actualiza los valores de zoom desde las tablas predefinidas
horizontal_zoom_ = HORIZONTAL_ZOOM_VALUES.at(INDEX);
verical_zoom_ = VERTICAL_ZOOM_VALUES.at(INDEX);
// Aplica la deformación al sprite
apply(sprite);
// Incrementa el contador y verifica si el efecto debe terminar
if (++counter_ / speed_ >= BOUNCE_FRAMES) {
disable(sprite);
}
}
// Getters para acceso a los valores actuales
[[nodiscard]] auto isEnabled() const -> bool { return enabled_; }
[[nodiscard]] auto getHorizontalZoom() const -> float { return horizontal_zoom_; }
[[nodiscard]] auto getVerticalZoom() const -> float { return verical_zoom_; }
[[nodiscard]] auto getXOffset() const -> float { return x_offset_; }
[[nodiscard]] auto getYOffset() const -> float { return y_offset_; }
};
// --- Objetos y punteros ---
std::unique_ptr<AnimatedSprite> sprite_; // Sprite del objeto globo
// --- Variables de estado y físicas ---
float x_; // Posición X
float y_; // Posición Y
float w_; // Ancho
float h_; // Alto
float vx_; // Velocidad X
float vy_; // Velocidad Y
float gravity_; // Aceleración en Y
float default_vy_; // Velocidad inicial al rebotar
float max_vy_; // Máxima velocidad en Y
bool being_created_; // Si el globo se está creando
bool enabled_ = true; // Si el globo está activo
bool invulnerable_; // Si el globo es invulnerable
bool stopped_; // Si el globo está parado
bool use_reversed_colors_ = false; // Si se usa el color alternativo
Circle collider_; // Círculo de colisión
float creation_counter_; // Temporizador de creación
float creation_counter_ini_; // Valor inicial del temporizador de creación
Uint16 score_; // Puntos al destruir el globo
Type type_; // Tipo de globo
Size size_; // Tamaño de globo
Uint8 menace_; // Amenaza que genera el globo
Uint32 counter_ = 0; // Contador interno
float game_tempo_; // Multiplicador de tempo del juego
float movement_accumulator_ = 0.0F; // Acumulador para movimiento durante creación (deltaTime)
Uint8 power_; // Poder que alberga el globo
SDL_FRect play_area_; // Zona de movimiento del globo
Sound sound_; // Configuración de sonido del globo
BounceEffect bounce_effect_; // Efecto de rebote
// --- Posicionamiento y transformación ---
void shiftColliders(); // Alinea el círculo de colisión con el sprite
void shiftSprite(); // Alinea el sprite en pantalla
// --- Animación y sonido ---
void setAnimation(); // Establece la animación correspondiente
void playBouncingSound() const; // Reproduce el sonido de rebote
void playPoppingSound() const; // Reproduce el sonido de reventar
// --- Movimiento y física ---
void handleHorizontalMovement(float delta_time); // Maneja el movimiento horizontal (time-based)
void handleVerticalMovement(float delta_time); // Maneja el movimiento vertical (time-based)
void applyGravity(float delta_time); // Aplica la gravedad al objeto (time-based)
// --- Rebote ---
void enableBounceEffect(); // Activa el efecto de rebote
void disableBounceEffect(); // Detiene el efecto de rebote
void updateBounceEffect(); // Actualiza el estado del rebote
void handleHorizontalBounce(float min_x, float max_x); // Maneja el rebote horizontal dentro de límites
// --- Colisiones ---
[[nodiscard]] auto isOutOfHorizontalBounds(float min_x, float max_x) const -> bool; // Verifica si está fuera de los límites horizontales
[[nodiscard]] auto shouldCheckTopCollision() const -> bool; // Determina si debe comprobarse la colisión superior
void handleTopCollision(); // Maneja la colisión superior
void handleBottomCollision(); // Maneja la colisión inferior
// --- Lógica de estado ---
void updateState(float delta_time); // Actualiza los estados del globo (time-based)
}; };
+76 -76
View File
@@ -12,99 +12,99 @@
// --- Clase BalloonFormations --- // --- Clase BalloonFormations ---
class BalloonFormations { class BalloonFormations {
public: public:
// --- Estructuras --- // --- Estructuras ---
struct SpawnParams { struct SpawnParams {
float x = 0; // Posición en el eje X donde crear el globo float x = 0; // Posición en el eje X donde crear el globo
float y = 0; // Posición en el eje Y donde crear el globo float y = 0; // Posición en el eje Y donde crear el globo
float vel_x = 0.0F; // Velocidad inicial en el eje X float vel_x = 0.0F; // Velocidad inicial en el eje X
Balloon::Type type = Balloon::Type::BALLOON; // Tipo de globo Balloon::Type type = Balloon::Type::BALLOON; // Tipo de globo
Balloon::Size size = Balloon::Size::SMALL; // Tamaño de globo Balloon::Size size = Balloon::Size::SMALL; // Tamaño de globo
float creation_counter = 0.0F; // Temporizador para la creación del globo float creation_counter = 0.0F; // Temporizador para la creación del globo
// Constructor por defecto // Constructor por defecto
SpawnParams() = default; SpawnParams() = default;
// Constructor con parámetros // Constructor con parámetros
SpawnParams(float x, float y, float vel_x, Balloon::Type type, Balloon::Size size, float creation_counter) SpawnParams(float x, float y, float vel_x, Balloon::Type type, Balloon::Size size, float creation_counter)
: x(x), : x(x),
y(y), y(y),
vel_x(vel_x), vel_x(vel_x),
type(type), type(type),
size(size), size(size),
creation_counter(creation_counter) {} creation_counter(creation_counter) {}
}; };
struct Formation { struct Formation {
std::vector<SpawnParams> balloons; // Vector con todas las inicializaciones de los globos de la formación std::vector<SpawnParams> balloons; // Vector con todas las inicializaciones de los globos de la formación
// Constructor con parámetros // Constructor con parámetros
Formation(const std::vector<SpawnParams>& spawn_params) Formation(const std::vector<SpawnParams>& spawn_params)
: balloons(spawn_params) {} : balloons(spawn_params) {}
// Constructor por defecto // Constructor por defecto
Formation() = default; Formation() = default;
}; };
// --- Types --- // --- Types ---
using Pool = std::vector<int>; // Vector de índices a formaciones using Pool = std::vector<int>; // Vector de índices a formaciones
// --- Constructor y destructor --- // --- Constructor y destructor ---
BalloonFormations() { BalloonFormations() {
initFormations(); initFormations();
initFormationPools(); initFormationPools();
} }
~BalloonFormations() = default; ~BalloonFormations() = default;
// --- Getters --- // --- Getters ---
auto getPool(int pool_id) -> const Pool& { auto getPool(int pool_id) -> const Pool& {
return pools_.at(pool_id); return pools_.at(pool_id);
} }
auto getFormationFromPool(int pool_id, int formation_index) -> const Formation& { auto getFormationFromPool(int pool_id, int formation_index) -> const Formation& {
int formation_id = pools_.at(pool_id).at(formation_index); int formation_id = pools_.at(pool_id).at(formation_index);
return formations_.at(formation_id); return formations_.at(formation_id);
} }
[[nodiscard]] auto getFormation(int formation_id) const -> const Formation& { [[nodiscard]] auto getFormation(int formation_id) const -> const Formation& {
return formations_.at(formation_id); return formations_.at(formation_id);
} }
// --- Nuevos getters para información de pools --- // --- Nuevos getters para información de pools ---
[[nodiscard]] auto getPoolCount() const -> size_t { [[nodiscard]] auto getPoolCount() const -> size_t {
return pools_.size(); return pools_.size();
} }
[[nodiscard]] auto getPoolSize(int pool_id) const -> size_t { [[nodiscard]] auto getPoolSize(int pool_id) const -> size_t {
return pools_.at(pool_id).size(); return pools_.at(pool_id).size();
} }
private: private:
// --- Constantes --- // --- Constantes ---
static constexpr int BALLOON_SPAWN_HEIGHT = 208; // Altura desde el suelo en la que aparecen los globos static constexpr int BALLOON_SPAWN_HEIGHT = 208; // Altura desde el suelo en la que aparecen los globos
static constexpr float CREATION_TIME = 5.0F; // Tiempo base de creación de los globos en segundos (300 frames ÷ 60fps = 5.0s) static constexpr float CREATION_TIME = 5.0F; // Tiempo base de creación de los globos en segundos (300 frames ÷ 60fps = 5.0s)
static constexpr float DEFAULT_CREATION_TIME = 3.334F; // Tiempo base de creación de los globos en segundos (200 frames ÷ 60fps = 3.334s) static constexpr float DEFAULT_CREATION_TIME = 3.334F; // Tiempo base de creación de los globos en segundos (200 frames ÷ 60fps = 3.334s)
// --- Variables --- // --- Variables ---
std::vector<Formation> formations_; // Vector con todas las formaciones disponibles std::vector<Formation> formations_; // Vector con todas las formaciones disponibles
std::vector<Pool> pools_; // Vector de pools, cada pool contiene índices a formaciones std::vector<Pool> pools_; // Vector de pools, cada pool contiene índices a formaciones
// --- Métodos internos --- // --- Métodos internos ---
void initFormations(); // Inicializa la lista principal de formaciones de globos disponibles void initFormations(); // Inicializa la lista principal de formaciones de globos disponibles
void initFormationPools(); // Carga los pools desde archivo de configuración void initFormationPools(); // Carga los pools desde archivo de configuración
auto loadFormationsFromFile(const std::string& filename, const std::map<std::string, float>& variables) -> bool; auto loadFormationsFromFile(const std::string& filename, const std::map<std::string, float>& variables) -> bool;
auto parseBalloonLine(const std::string& line, const std::map<std::string, float>& variables) -> std::optional<SpawnParams>; auto parseBalloonLine(const std::string& line, const std::map<std::string, float>& variables) -> std::optional<SpawnParams>;
auto loadPoolsFromFile(const std::string& filename) -> bool; // Nueva función para cargar pools auto loadPoolsFromFile(const std::string& filename) -> bool; // Nueva función para cargar pools
auto parsePoolLine(const std::string& line) -> std::optional<std::pair<int, std::vector<int>>>; // Nueva función para parsear líneas de pools auto parsePoolLine(const std::string& line) -> std::optional<std::pair<int, std::vector<int>>>; // Nueva función para parsear líneas de pools
auto evaluateExpression(const std::string& expr, const std::map<std::string, float>& variables) -> float; auto evaluateExpression(const std::string& expr, const std::map<std::string, float>& variables) -> float;
auto evaluateSimpleExpression(const std::string& expr, const std::map<std::string, float>& variables) -> float; auto evaluateSimpleExpression(const std::string& expr, const std::map<std::string, float>& variables) -> float;
static auto trim(const std::string& str) -> std::string; static auto trim(const std::string& str) -> std::string;
void createFloaterVariants(); void createFloaterVariants();
void loadDefaultFormations(); void loadDefaultFormations();
void loadDefaultPools(); // Nueva función para pools por defecto void loadDefaultPools(); // Nueva función para pools por defecto
// --- Depuración (solo en modo DEBUG) --- // --- Depuración (solo en modo DEBUG) ---
#ifdef _DEBUG #ifdef _DEBUG
void addTestFormation(); void addTestFormation();
#endif #endif
}; };
+76 -76
View File
@@ -22,94 +22,94 @@ using Balloons = std::list<std::shared_ptr<Balloon>>;
// --- Clase BalloonManager: gestiona todos los globos del juego --- // --- Clase BalloonManager: gestiona todos los globos del juego ---
class BalloonManager { class BalloonManager {
public: public:
// --- Constructor y destructor --- // --- Constructor y destructor ---
BalloonManager(IStageInfo* stage_info); BalloonManager(IStageInfo* stage_info);
~BalloonManager() = default; ~BalloonManager() = default;
// --- Métodos principales --- // --- Métodos principales ---
void update(float delta_time); // Actualiza el estado de los globos (time-based) void update(float delta_time); // Actualiza el estado de los globos (time-based)
void render(); // Renderiza los globos en pantalla void render(); // Renderiza los globos en pantalla
// --- Gestión de globos --- // --- Gestión de globos ---
void freeBalloons(); // Libera globos que ya no sirven void freeBalloons(); // Libera globos que ya no sirven
// --- Creación de formaciones enemigas --- // --- Creación de formaciones enemigas ---
void deployRandomFormation(int stage); // Crea una formación de globos aleatoria void deployRandomFormation(int stage); // Crea una formación de globos aleatoria
void deployFormation(int formation_id); // Crea una formación específica void deployFormation(int formation_id); // Crea una formación específica
void deployFormation(int formation_id, float y); // Crea una formación específica con coordenadas void deployFormation(int formation_id, float y); // Crea una formación específica con coordenadas
// --- Creación de globos --- // --- Creación de globos ---
auto createBalloon(Balloon::Config config) -> std::shared_ptr<Balloon>; // Crea un nuevo globo auto createBalloon(Balloon::Config config) -> std::shared_ptr<Balloon>; // Crea un nuevo globo
void createChildBalloon(const std::shared_ptr<Balloon>& balloon, const std::string& direction); // Crea un globo a partir de otro void createChildBalloon(const std::shared_ptr<Balloon>& balloon, const std::string& direction); // Crea un globo a partir de otro
void createPowerBall(); // Crea una PowerBall void createPowerBall(); // Crea una PowerBall
void createTwoBigBalloons(); // Crea dos globos grandes void createTwoBigBalloons(); // Crea dos globos grandes
// --- Control de velocidad y despliegue --- // --- Control de velocidad y despliegue ---
void setBalloonSpeed(float speed); // Ajusta la velocidad de los globos void setBalloonSpeed(float speed); // Ajusta la velocidad de los globos
void setDefaultBalloonSpeed(float speed) { default_balloon_speed_ = speed; }; // Establece la velocidad base void setDefaultBalloonSpeed(float speed) { default_balloon_speed_ = speed; }; // Establece la velocidad base
void resetBalloonSpeed() { setBalloonSpeed(default_balloon_speed_); }; // Restablece la velocidad de los globos void resetBalloonSpeed() { setBalloonSpeed(default_balloon_speed_); }; // Restablece la velocidad de los globos
void updateBalloonDeployCounter(float delta_time); // Actualiza el contador de despliegue (time-based) void updateBalloonDeployCounter(float delta_time); // Actualiza el contador de despliegue (time-based)
auto canPowerBallBeCreated() -> bool; // Indica si se puede crear una PowerBall auto canPowerBallBeCreated() -> bool; // Indica si se puede crear una PowerBall
auto calculateScreenPower() -> int; // Calcula el poder de los globos en pantalla auto calculateScreenPower() -> int; // Calcula el poder de los globos en pantalla
// --- Manipulación de globos existentes --- // --- Manipulación de globos existentes ---
auto popBalloon(const std::shared_ptr<Balloon>& balloon) -> int; // Explosiona un globo, creando otros si aplica auto popBalloon(const std::shared_ptr<Balloon>& balloon) -> int; // Explosiona un globo, creando otros si aplica
auto destroyBalloon(std::shared_ptr<Balloon>& balloon) -> int; // Explosiona un globo sin crear otros auto destroyBalloon(std::shared_ptr<Balloon>& balloon) -> int; // Explosiona un globo sin crear otros
auto destroyAllBalloons() -> int; // Destruye todos los globos auto destroyAllBalloons() -> int; // Destruye todos los globos
void stopAllBalloons(); // Detiene el movimiento de los globos void stopAllBalloons(); // Detiene el movimiento de los globos
void startAllBalloons(); // Reactiva el movimiento de los globos void startAllBalloons(); // Reactiva el movimiento de los globos
// --- Cambios de apariencia --- // --- Cambios de apariencia ---
void reverseColorsToAllBalloons(); // Invierte los colores de los globos void reverseColorsToAllBalloons(); // Invierte los colores de los globos
void normalColorsToAllBalloons(); // Restaura los colores originales void normalColorsToAllBalloons(); // Restaura los colores originales
// --- Configuración de sonido --- // --- Configuración de sonido ---
void setSounds(bool value); // Activa o desactiva los sonidos de los globos void setSounds(bool value); // Activa o desactiva los sonidos de los globos
void setBouncingSounds(bool value); // Activa o desactiva los sonidos de rebote los globos void setBouncingSounds(bool value); // Activa o desactiva los sonidos de rebote los globos
void setPoppingSounds(bool value); // Activa o desactiva los sonidos de los globos al explotar void setPoppingSounds(bool value); // Activa o desactiva los sonidos de los globos al explotar
// --- Configuración de juego --- // --- Configuración de juego ---
void setPlayArea(SDL_FRect play_area) { play_area_ = play_area; }; // Define el área de juego void setPlayArea(SDL_FRect play_area) { play_area_ = play_area; }; // Define el área de juego
void setCreationTimeEnabled(bool value) { creation_time_enabled_ = value; }; // Activa o desactiva el tiempo de creación de globos void setCreationTimeEnabled(bool value) { creation_time_enabled_ = value; }; // Activa o desactiva el tiempo de creación de globos
void enableBalloonDeployment(bool value) { can_deploy_balloons_ = value; }; // Activa o desactiva la generación de globos void enableBalloonDeployment(bool value) { can_deploy_balloons_ = value; }; // Activa o desactiva la generación de globos
// --- Getters --- // --- Getters ---
auto getMenace() -> int; // Obtiene el nivel de amenaza generado por los globos auto getMenace() -> int; // Obtiene el nivel de amenaza generado por los globos
[[nodiscard]] auto getBalloonSpeed() const -> float { return balloon_speed_; } [[nodiscard]] auto getBalloonSpeed() const -> float { return balloon_speed_; }
auto getBalloons() -> Balloons& { return balloons_; } auto getBalloons() -> Balloons& { return balloons_; }
[[nodiscard]] auto getNumBalloons() const -> int { return balloons_.size(); } [[nodiscard]] auto getNumBalloons() const -> int { return balloons_.size(); }
private: private:
// --- Constantes --- // --- Constantes ---
static constexpr float DEFAULT_BALLOON_DEPLOY_DELAY = 5.0F; // 300 frames = 5 segundos static constexpr float DEFAULT_BALLOON_DEPLOY_DELAY = 5.0F; // 300 frames = 5 segundos
static constexpr float POWERBALL_DEPLOY_DELAY = 0.167F; // 10 frames = 0.167 segundos static constexpr float POWERBALL_DEPLOY_DELAY = 0.167F; // 10 frames = 0.167 segundos
static constexpr float BALLOON_POP_DELAY = 0.333F; // 20 frames = 0.333 segundos static constexpr float BALLOON_POP_DELAY = 0.333F; // 20 frames = 0.333 segundos
// --- Objetos y punteros --- // --- Objetos y punteros ---
Balloons balloons_; // Vector con los globos activos Balloons balloons_; // Vector con los globos activos
std::unique_ptr<Explosions> explosions_; // Objeto para gestionar explosiones std::unique_ptr<Explosions> explosions_; // Objeto para gestionar explosiones
std::unique_ptr<BalloonFormations> balloon_formations_; // Objeto para manejar formaciones enemigas std::unique_ptr<BalloonFormations> balloon_formations_; // Objeto para manejar formaciones enemigas
std::vector<std::shared_ptr<Texture>> balloon_textures_; // Texturas de los globos std::vector<std::shared_ptr<Texture>> balloon_textures_; // Texturas de los globos
std::vector<std::shared_ptr<Texture>> explosions_textures_; // Texturas de explosiones std::vector<std::shared_ptr<Texture>> explosions_textures_; // Texturas de explosiones
std::vector<std::vector<std::string>> balloon_animations_; // Animaciones de los globos std::vector<std::vector<std::string>> balloon_animations_; // Animaciones de los globos
std::vector<std::vector<std::string>> explosions_animations_; // Animaciones de las explosiones std::vector<std::vector<std::string>> explosions_animations_; // Animaciones de las explosiones
IStageInfo* stage_info_; // Informacion de la pantalla actual IStageInfo* stage_info_; // Informacion de la pantalla actual
// --- Variables de estado --- // --- Variables de estado ---
SDL_FRect play_area_ = param.game.play_area.rect; SDL_FRect play_area_ = param.game.play_area.rect;
float balloon_speed_ = Balloon::GAME_TEMPO.at(0); float balloon_speed_ = Balloon::GAME_TEMPO.at(0);
float default_balloon_speed_ = Balloon::GAME_TEMPO.at(0); float default_balloon_speed_ = Balloon::GAME_TEMPO.at(0);
float balloon_deploy_counter_ = 0; float balloon_deploy_counter_ = 0;
int power_ball_counter_ = 0; int power_ball_counter_ = 0;
int last_balloon_deploy_ = 0; int last_balloon_deploy_ = 0;
bool power_ball_enabled_ = false; bool power_ball_enabled_ = false;
bool creation_time_enabled_ = true; bool creation_time_enabled_ = true;
bool can_deploy_balloons_ = true; bool can_deploy_balloons_ = true;
bool bouncing_sound_enabled_ = false; // Si debe sonar el globo al rebotar bool bouncing_sound_enabled_ = false; // Si debe sonar el globo al rebotar
bool poping_sound_enabled_ = true; // Si debe sonar el globo al explotar bool poping_sound_enabled_ = true; // Si debe sonar el globo al explotar
bool sound_enabled_ = true; // Indica si los globos deben hacer algun sonido bool sound_enabled_ = true; // Indica si los globos deben hacer algun sonido
// --- Métodos internos --- // --- Métodos internos ---
void init(); void init();
}; };
+53 -53
View File
@@ -10,67 +10,67 @@
// --- Clase Bullet: representa una bala del jugador --- // --- Clase Bullet: representa una bala del jugador ---
class Bullet { class Bullet {
public: public:
// --- Constantes --- // --- Constantes ---
static constexpr float WIDTH = 12.0F; // Anchura de la bala static constexpr float WIDTH = 12.0F; // Anchura de la bala
static constexpr float HEIGHT = 12.0F; // Altura de la bala static constexpr float HEIGHT = 12.0F; // Altura de la bala
// --- Enums --- // --- Enums ---
enum class Type : Uint8 { enum class Type : Uint8 {
UP, // Bala hacia arriba UP, // Bala hacia arriba
LEFT, // Bala hacia la izquierda LEFT, // Bala hacia la izquierda
RIGHT, // Bala hacia la derecha RIGHT, // Bala hacia la derecha
NONE // Sin bala NONE // Sin bala
}; };
enum class MoveStatus : Uint8 { enum class MoveStatus : Uint8 {
OK = 0, // Movimiento normal OK = 0, // Movimiento normal
OUT = 1 // Fuera de los límites OUT = 1 // Fuera de los límites
}; };
enum class Color : Uint8 { enum class Color : Uint8 {
YELLOW, YELLOW,
GREEN, GREEN,
RED, RED,
PURPLE PURPLE
}; };
// --- Constructor y destructor --- // --- Constructor y destructor ---
Bullet(float x, float y, Type type, Color color, int owner); // Constructor principal Bullet(float x, float y, Type type, Color color, int owner); // Constructor principal
~Bullet() = default; // Destructor ~Bullet() = default; // Destructor
// --- Métodos principales --- // --- Métodos principales ---
void render(); // Dibuja la bala en pantalla void render(); // Dibuja la bala en pantalla
auto update(float delta_time) -> MoveStatus; // Actualiza el estado del objeto (time-based) auto update(float delta_time) -> MoveStatus; // Actualiza el estado del objeto (time-based)
void disable(); // Desactiva la bala void disable(); // Desactiva la bala
// --- Getters --- // --- Getters ---
[[nodiscard]] auto isEnabled() const -> bool; // Comprueba si está activa [[nodiscard]] auto isEnabled() const -> bool; // Comprueba si está activa
[[nodiscard]] auto getOwner() const -> int; // Devuelve el identificador del dueño [[nodiscard]] auto getOwner() const -> int; // Devuelve el identificador del dueño
auto getCollider() -> Circle&; // Devuelve el círculo de colisión auto getCollider() -> Circle&; // Devuelve el círculo de colisión
private: private:
// --- Constantes --- // --- Constantes ---
static constexpr float VEL_Y = -180.0F; // Velocidad vertical (pixels/segundo) - era -0.18F pixels/ms static constexpr float VEL_Y = -180.0F; // Velocidad vertical (pixels/segundo) - era -0.18F pixels/ms
static constexpr float VEL_X_LEFT = -120.0F; // Velocidad izquierda (pixels/segundo) - era -0.12F pixels/ms static constexpr float VEL_X_LEFT = -120.0F; // Velocidad izquierda (pixels/segundo) - era -0.12F pixels/ms
static constexpr float VEL_X_RIGHT = 120.0F; // Velocidad derecha (pixels/segundo) - era 0.12F pixels/ms static constexpr float VEL_X_RIGHT = 120.0F; // Velocidad derecha (pixels/segundo) - era 0.12F pixels/ms
static constexpr float VEL_X_CENTER = 0.0F; // Velocidad central static constexpr float VEL_X_CENTER = 0.0F; // Velocidad central
// --- Objetos y punteros --- // --- Objetos y punteros ---
std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los gráficos std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los gráficos
// --- Variables de estado --- // --- Variables de estado ---
Circle collider_; // Círculo de colisión Circle collider_; // Círculo de colisión
Type type_; // Tipo de bala Type type_; // Tipo de bala
int owner_; // Identificador del jugador int owner_; // Identificador del jugador
float pos_x_; // Posición en el eje X float pos_x_; // Posición en el eje X
float pos_y_; // Posición en el eje Y float pos_y_; // Posición en el eje Y
float vel_x_; // Velocidad en el eje X float vel_x_; // Velocidad en el eje X
// --- Métodos internos --- // --- Métodos internos ---
void shiftColliders(); // Ajusta el círculo de colisión void shiftColliders(); // Ajusta el círculo de colisión
void shiftSprite(); // Ajusta el sprite void shiftSprite(); // Ajusta el sprite
auto move(float delta_time) -> MoveStatus; // Mueve la bala y devuelve su estado (time-based) auto move(float delta_time) -> MoveStatus; // Mueve la bala y devuelve su estado (time-based)
static auto calculateVelocity(Type type) -> float; // Calcula la velocidad horizontal de la bala static auto calculateVelocity(Type type) -> float; // Calcula la velocidad horizontal de la bala
static auto buildAnimationString(Type type, Color color) -> std::string; // Construye el string de animación static auto buildAnimationString(Type type, Color color) -> std::string; // Construye el string de animación
}; };
+36 -36
View File
@@ -27,50 +27,50 @@ using Bullets = std::list<std::shared_ptr<Bullet>>;
// La clase utiliza un sistema de callbacks para manejar las colisiones, // La clase utiliza un sistema de callbacks para manejar las colisiones,
// permitiendo que la lógica específica del juego permanezca en Game. // permitiendo que la lógica específica del juego permanezca en Game.
class BulletManager { class BulletManager {
public: public:
// --- Types para callbacks --- // --- Types para callbacks ---
using CollisionCallback = std::function<bool(const std::shared_ptr<Bullet>&)>; using CollisionCallback = std::function<bool(const std::shared_ptr<Bullet>&)>;
using OutOfBoundsCallback = std::function<void(const std::shared_ptr<Bullet>&)>; using OutOfBoundsCallback = std::function<void(const std::shared_ptr<Bullet>&)>;
// --- Constructor y destructor --- // --- Constructor y destructor ---
BulletManager(); BulletManager();
~BulletManager() = default; ~BulletManager() = default;
// --- Métodos principales --- // --- Métodos principales ---
void update(float delta_time); // Actualiza el estado de las balas (time-based) void update(float delta_time); // Actualiza el estado de las balas (time-based)
void render(); // Renderiza las balas en pantalla void render(); // Renderiza las balas en pantalla
// --- Gestión de balas --- // --- Gestión de balas ---
void createBullet(int x, int y, Bullet::Type type, Bullet::Color color, int owner); // Crea una nueva bala void createBullet(int x, int y, Bullet::Type type, Bullet::Color color, int owner); // Crea una nueva bala
void freeBullets(); // Libera balas que ya no sirven void freeBullets(); // Libera balas que ya no sirven
void clearAllBullets(); // Elimina todas las balas void clearAllBullets(); // Elimina todas las balas
// --- Detección de colisiones --- // --- Detección de colisiones ---
void checkCollisions(); // Verifica colisiones de todas las balas void checkCollisions(); // Verifica colisiones de todas las balas
void setTabeCollisionCallback(CollisionCallback callback); // Establece callback para colisión con Tabe void setTabeCollisionCallback(CollisionCallback callback); // Establece callback para colisión con Tabe
void setBalloonCollisionCallback(CollisionCallback callback); // Establece callback para colisión con globos void setBalloonCollisionCallback(CollisionCallback callback); // Establece callback para colisión con globos
void setOutOfBoundsCallback(OutOfBoundsCallback callback); // Establece callback para balas fuera de límites void setOutOfBoundsCallback(OutOfBoundsCallback callback); // Establece callback para balas fuera de límites
// --- Configuración --- // --- Configuración ---
void setPlayArea(SDL_FRect play_area) { play_area_ = play_area; }; // Define el área de juego void setPlayArea(SDL_FRect play_area) { play_area_ = play_area; }; // Define el área de juego
// --- Getters --- // --- Getters ---
auto getBullets() -> Bullets& { return bullets_; } // Obtiene referencia al vector de balas auto getBullets() -> Bullets& { return bullets_; } // Obtiene referencia al vector de balas
[[nodiscard]] auto getNumBullets() const -> int { return bullets_.size(); } // Obtiene el número de balas activas [[nodiscard]] auto getNumBullets() const -> int { return bullets_.size(); } // Obtiene el número de balas activas
private: private:
// --- Objetos y punteros --- // --- Objetos y punteros ---
Bullets bullets_; // Vector con las balas activas Bullets bullets_; // Vector con las balas activas
// --- Variables de configuración --- // --- Variables de configuración ---
SDL_FRect play_area_; // Área de juego para límites SDL_FRect play_area_; // Área de juego para límites
// --- Callbacks para colisiones --- // --- Callbacks para colisiones ---
CollisionCallback tabe_collision_callback_; // Callback para colisión con Tabe CollisionCallback tabe_collision_callback_; // Callback para colisión con Tabe
CollisionCallback balloon_collision_callback_; // Callback para colisión con globos CollisionCallback balloon_collision_callback_; // Callback para colisión con globos
OutOfBoundsCallback out_of_bounds_callback_; // Callback para balas fuera de límites OutOfBoundsCallback out_of_bounds_callback_; // Callback para balas fuera de límites
// --- Métodos internos --- // --- Métodos internos ---
void processBulletUpdate(const std::shared_ptr<Bullet>& bullet, float delta_time); // Procesa actualización individual void processBulletUpdate(const std::shared_ptr<Bullet>& bullet, float delta_time); // Procesa actualización individual
[[nodiscard]] auto isBulletOutOfBounds(const std::shared_ptr<Bullet>& bullet) const -> bool; // Verifica si la bala está fuera de límites [[nodiscard]] auto isBulletOutOfBounds(const std::shared_ptr<Bullet>& bullet) const -> bool; // Verifica si la bala está fuera de límites
}; };
+62 -62
View File
@@ -116,71 +116,71 @@ 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;
size_t index; size_t index;
if (n < colors.size()) { if (n < colors.size()) {
index = n; // Avanza: 0,1,2,3 index = n; // Avanza: 0,1,2,3
} else { } else {
index = 2 * (colors.size() - 1) - n; // Retrocede: 2,1 index = 2 * (colors.size() - 1) - n; // Retrocede: 2,1
}
return colors[index];
}
auto generateMirroredCycle(Color base, ColorCycleStyle style) -> Cycle {
Cycle result{};
HSV base_hsv = Color::RGB_TO_HSV(base);
for (size_t i = 0; i < CYCLE_SIZE; ++i) {
float t = static_cast<float>(i) / (CYCLE_SIZE - 1); // 0 → 1
float hue_shift = 0.0F;
float sat_shift = 0.0F;
float val_shift = 0.0F;
switch (style) {
case ColorCycleStyle::SUBTLE_PULSE:
// Solo brillo suave
val_shift = 0.07F * sinf(t * M_PI);
break;
case ColorCycleStyle::HUE_WAVE:
// Oscilación leve de tono
hue_shift = 15.0F * (t - 0.5F) * 2.0F;
val_shift = 0.05F * sinf(t * M_PI);
break;
case ColorCycleStyle::VIBRANT:
// Cambios fuertes en tono y brillo
hue_shift = 35.0F * sinf(t * M_PI);
val_shift = 0.2F * sinf(t * M_PI);
sat_shift = -0.2F * sinf(t * M_PI);
break;
case ColorCycleStyle::DARKEN_GLOW:
// Se oscurece al centro
val_shift = -0.15F * sinf(t * M_PI);
break;
case ColorCycleStyle::LIGHT_FLASH:
// Se ilumina al centro
val_shift = 0.25F * sinf(t * M_PI);
break;
} }
HSV adjusted = { return colors[index];
.h = fmodf(base_hsv.h + hue_shift + 360.0F, 360.0F),
.s = fminf(1.0F, fmaxf(0.0F, base_hsv.s + sat_shift)),
.v = fminf(1.0F, fmaxf(0.0F, base_hsv.v + val_shift))};
Color c = Color::HSV_TO_RGB(adjusted);
result[i] = c;
result[(2 * CYCLE_SIZE) - 1 - i] = c; // espejo
} }
return result; auto generateMirroredCycle(Color base, ColorCycleStyle style) -> Cycle {
} Cycle result{};
HSV base_hsv = Color::RGB_TO_HSV(base);
for (size_t i = 0; i < CYCLE_SIZE; ++i) {
float t = static_cast<float>(i) / (CYCLE_SIZE - 1); // 0 → 1
float hue_shift = 0.0F;
float sat_shift = 0.0F;
float val_shift = 0.0F;
switch (style) {
case ColorCycleStyle::SUBTLE_PULSE:
// Solo brillo suave
val_shift = 0.07F * sinf(t * M_PI);
break;
case ColorCycleStyle::HUE_WAVE:
// Oscilación leve de tono
hue_shift = 15.0F * (t - 0.5F) * 2.0F;
val_shift = 0.05F * sinf(t * M_PI);
break;
case ColorCycleStyle::VIBRANT:
// Cambios fuertes en tono y brillo
hue_shift = 35.0F * sinf(t * M_PI);
val_shift = 0.2F * sinf(t * M_PI);
sat_shift = -0.2F * sinf(t * M_PI);
break;
case ColorCycleStyle::DARKEN_GLOW:
// Se oscurece al centro
val_shift = -0.15F * sinf(t * M_PI);
break;
case ColorCycleStyle::LIGHT_FLASH:
// Se ilumina al centro
val_shift = 0.25F * sinf(t * M_PI);
break;
}
HSV adjusted = {
.h = fmodf(base_hsv.h + hue_shift + 360.0F, 360.0F),
.s = fminf(1.0F, fmaxf(0.0F, base_hsv.s + sat_shift)),
.v = fminf(1.0F, fmaxf(0.0F, base_hsv.v + val_shift))};
Color c = Color::HSV_TO_RGB(adjusted);
result[i] = c;
result[(2 * CYCLE_SIZE) - 1 - i] = c; // espejo
}
return result;
}
} // namespace Colors } // namespace Colors
+107 -107
View File
@@ -11,119 +11,119 @@
// --- Estructura HSV: define un color en formato HSV --- // --- Estructura HSV: define un color en formato HSV ---
struct HSV { struct HSV {
float h; // Matiz (Hue) float h; // Matiz (Hue)
float s; // Saturación (Saturation) float s; // Saturación (Saturation)
float v; // Valor (Value) float v; // Valor (Value)
}; };
// --- Estructura Color: define un color RGBA --- // --- Estructura Color: define un color RGBA ---
struct Color { struct Color {
private: private:
static constexpr int DEFAULT_LIGHTEN_AMOUNT = 50; static constexpr int DEFAULT_LIGHTEN_AMOUNT = 50;
static constexpr int DEFAULT_DARKEN_AMOUNT = 50; static constexpr int DEFAULT_DARKEN_AMOUNT = 50;
static constexpr int DEFAULT_APPROACH_STEP = 1; static constexpr int DEFAULT_APPROACH_STEP = 1;
static constexpr size_t HEX_RGB_LENGTH = 6; static constexpr size_t HEX_RGB_LENGTH = 6;
static constexpr size_t HEX_RGBA_LENGTH = 8; static constexpr size_t HEX_RGBA_LENGTH = 8;
static constexpr int HEX_BASE = 16; static constexpr int HEX_BASE = 16;
static constexpr size_t HEX_COMPONENT_LENGTH = 2; static constexpr size_t HEX_COMPONENT_LENGTH = 2;
public: public:
static constexpr Uint8 MAX_COLOR_VALUE = 255; static constexpr Uint8 MAX_COLOR_VALUE = 255;
static constexpr Uint8 MIN_COLOR_VALUE = 0; static constexpr Uint8 MIN_COLOR_VALUE = 0;
static constexpr Uint8 DEFAULT_ALPHA = 255; static constexpr Uint8 DEFAULT_ALPHA = 255;
static constexpr Uint8 MAX_ALPHA_VALUE = 255; static constexpr Uint8 MAX_ALPHA_VALUE = 255;
static constexpr Uint8 MIN_ALPHA_VALUE = 0; static constexpr Uint8 MIN_ALPHA_VALUE = 0;
Uint8 r, g, b, a; Uint8 r, g, b, a;
constexpr Color() constexpr Color()
: r(MIN_COLOR_VALUE), : r(MIN_COLOR_VALUE),
g(MIN_COLOR_VALUE), g(MIN_COLOR_VALUE),
b(MIN_COLOR_VALUE), b(MIN_COLOR_VALUE),
a(DEFAULT_ALPHA) {} a(DEFAULT_ALPHA) {}
explicit constexpr Color(Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha = DEFAULT_ALPHA) explicit constexpr Color(Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha = DEFAULT_ALPHA)
: r(red), : r(red),
g(green), g(green),
b(blue), b(blue),
a(alpha) {} a(alpha) {}
[[nodiscard]] constexpr auto INVERSE() const -> Color { [[nodiscard]] constexpr auto INVERSE() const -> Color {
return Color(MAX_COLOR_VALUE - r, MAX_COLOR_VALUE - g, MAX_COLOR_VALUE - b, a); return Color(MAX_COLOR_VALUE - r, MAX_COLOR_VALUE - g, MAX_COLOR_VALUE - b, a);
} }
[[nodiscard]] constexpr auto LIGHTEN(int amount = DEFAULT_LIGHTEN_AMOUNT) const -> Color { [[nodiscard]] constexpr auto LIGHTEN(int amount = DEFAULT_LIGHTEN_AMOUNT) const -> Color {
return Color( return Color(
std::min(static_cast<int>(MAX_COLOR_VALUE), r + amount), std::min(static_cast<int>(MAX_COLOR_VALUE), r + amount),
std::min(static_cast<int>(MAX_COLOR_VALUE), g + amount), std::min(static_cast<int>(MAX_COLOR_VALUE), g + amount),
std::min(static_cast<int>(MAX_COLOR_VALUE), b + amount), std::min(static_cast<int>(MAX_COLOR_VALUE), b + amount),
a); a);
} }
[[nodiscard]] constexpr auto DARKEN(int amount = DEFAULT_DARKEN_AMOUNT) const -> Color { [[nodiscard]] constexpr auto DARKEN(int amount = DEFAULT_DARKEN_AMOUNT) const -> Color {
return Color( return Color(
std::max(static_cast<int>(MIN_COLOR_VALUE), r - amount), std::max(static_cast<int>(MIN_COLOR_VALUE), r - amount),
std::max(static_cast<int>(MIN_COLOR_VALUE), g - amount), std::max(static_cast<int>(MIN_COLOR_VALUE), g - amount),
std::max(static_cast<int>(MIN_COLOR_VALUE), b - amount), std::max(static_cast<int>(MIN_COLOR_VALUE), b - amount),
a); a);
} }
// Método estático para crear Color desde string hexadecimal // Método estático para crear Color desde string hexadecimal
static auto fromHex(const std::string& hex_str) -> Color; static auto fromHex(const std::string& hex_str) -> Color;
// Conversiones de formato de color // Conversiones de formato de color
[[nodiscard]] constexpr static auto RGB_TO_HSV(Color color) -> HSV; [[nodiscard]] constexpr static auto RGB_TO_HSV(Color color) -> HSV;
[[nodiscard]] constexpr static auto HSV_TO_RGB(HSV hsv) -> Color; [[nodiscard]] constexpr static auto HSV_TO_RGB(HSV hsv) -> Color;
[[nodiscard]] constexpr auto IS_EQUAL_TO(const Color& other) const -> bool { [[nodiscard]] constexpr auto IS_EQUAL_TO(const Color& other) const -> bool {
return r == other.r && g == other.g && b == other.b && a == other.a; return r == other.r && g == other.g && b == other.b && a == other.a;
} }
[[nodiscard]] constexpr auto APPROACH_TO(const Color& target, int step = DEFAULT_APPROACH_STEP) const -> Color { [[nodiscard]] constexpr auto APPROACH_TO(const Color& target, int step = DEFAULT_APPROACH_STEP) const -> Color {
auto approach_component = [step](Uint8 current, Uint8 target_val) -> Uint8 { auto approach_component = [step](Uint8 current, Uint8 target_val) -> Uint8 {
if (std::abs(current - target_val) <= step) { if (std::abs(current - target_val) <= step) {
return target_val; return target_val;
} }
return (current < target_val) ? current + step : current - step; return (current < target_val) ? current + step : current - step;
}; };
Uint8 new_r = approach_component(r, target.r); Uint8 new_r = approach_component(r, target.r);
Uint8 new_g = approach_component(g, target.g); Uint8 new_g = approach_component(g, target.g);
Uint8 new_b = approach_component(b, target.b); Uint8 new_b = approach_component(b, target.b);
Uint8 new_a = approach_component(a, target.a); Uint8 new_a = approach_component(a, target.a);
return Color(new_r, new_g, new_b, new_a); return Color(new_r, new_g, new_b, new_a);
} }
// Interpolación lineal hacia otro color (t=0.0: this, t=1.0: target) // Interpolación lineal hacia otro color (t=0.0: this, t=1.0: target)
[[nodiscard]] constexpr auto LERP(const Color& target, float t) const -> Color { [[nodiscard]] constexpr auto LERP(const Color& target, float t) const -> Color {
// Asegurar que t esté en el rango [0.0, 1.0] // Asegurar que t esté en el rango [0.0, 1.0]
t = std::clamp(t, 0.0F, 1.0F); t = std::clamp(t, 0.0F, 1.0F);
// Interpolación lineal para cada componente // Interpolación lineal para cada componente
auto lerp_component = [t](Uint8 start, Uint8 end) -> Uint8 { auto lerp_component = [t](Uint8 start, Uint8 end) -> Uint8 {
return static_cast<Uint8>(start + ((end - start) * t)); return static_cast<Uint8>(start + ((end - start) * t));
}; };
return Color( return Color(
lerp_component(r, target.r), lerp_component(r, target.r),
lerp_component(g, target.g), lerp_component(g, target.g),
lerp_component(b, target.b), lerp_component(b, target.b),
lerp_component(a, target.a)); lerp_component(a, target.a));
} }
// Sobrecarga para aceptar componentes RGBA directamente // Sobrecarga para aceptar componentes RGBA directamente
[[nodiscard]] constexpr auto LERP(Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha, float t) const -> Color { [[nodiscard]] constexpr auto LERP(Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha, float t) const -> Color {
return LERP(Color(red, green, blue, alpha), t); return LERP(Color(red, green, blue, alpha), t);
} }
// Convierte el color a un entero de 32 bits en formato RGBA // Convierte el color a un entero de 32 bits en formato RGBA
[[nodiscard]] constexpr auto TO_UINT32() const -> Uint32 { [[nodiscard]] constexpr auto TO_UINT32() const -> Uint32 {
return (static_cast<Uint32>(r) << 24) | return (static_cast<Uint32>(r) << 24) |
(static_cast<Uint32>(g) << 16) | (static_cast<Uint32>(g) << 16) |
(static_cast<Uint32>(b) << 8) | (static_cast<Uint32>(b) << 8) |
static_cast<Uint32>(a); static_cast<Uint32>(a);
} }
}; };
// --- Enum ColorCycleStyle: define estilos de ciclo de color --- // --- Enum ColorCycleStyle: define estilos de ciclo de color ---
@@ -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
+4 -3
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};
+198 -198
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
+53 -53
View File
@@ -12,69 +12,69 @@
#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 ---
class DefineButtons { class DefineButtons {
public: public:
// --- Estructuras --- // --- Estructuras ---
struct Button { struct Button {
std::string label; std::string label;
Input::Action action; Input::Action action;
int button; int button;
Button(std::string label, Input::Action action, int button) Button(std::string label, Input::Action action, int button)
: label(std::move(label)), : label(std::move(label)),
action(action), action(action),
button(button) {} button(button) {}
}; };
// --- Constructor y destructor --- // --- Constructor y destructor ---
DefineButtons(); DefineButtons();
~DefineButtons() = default; ~DefineButtons() = default;
// --- Métodos principales --- // --- Métodos principales ---
void render(); void render();
void update(float delta_time); void update(float delta_time);
void handleEvents(const SDL_Event& event); void handleEvents(const SDL_Event& event);
auto enable(Options::Gamepad* options_gamepad) -> bool; auto enable(Options::Gamepad* options_gamepad) -> bool;
void disable(); void disable();
// --- Getters --- // --- Getters ---
[[nodiscard]] auto isReadyToClose() const -> bool; [[nodiscard]] auto isReadyToClose() const -> bool;
[[nodiscard]] auto isEnabled() const -> bool { return enabled_; } [[nodiscard]] auto isEnabled() const -> bool { return enabled_; }
[[nodiscard]] auto isFinished() const -> bool { return finished_; } [[nodiscard]] auto isFinished() const -> bool { return finished_; }
private: private:
// --- Constantes --- // --- Constantes ---
static constexpr float MESSAGE_DISPLAY_DURATION_S = 2.0F; // Cuánto tiempo mostrar el mensaje en segundos static constexpr float MESSAGE_DISPLAY_DURATION_S = 2.0F; // Cuánto tiempo mostrar el mensaje en segundos
// --- Objetos y punteros --- // --- Objetos y punteros ---
Input* input_ = nullptr; // Entrada del usuario Input* input_ = nullptr; // Entrada del usuario
Options::Gamepad* options_gamepad_ = nullptr; // Opciones del gamepad Options::Gamepad* options_gamepad_ = nullptr; // Opciones del gamepad
std::unique_ptr<WindowMessage> window_message_; // Mensaje de ventana std::unique_ptr<WindowMessage> window_message_; // Mensaje de ventana
// --- Variables de estado --- // --- Variables de estado ---
std::vector<Button> buttons_; // Lista de botones std::vector<Button> buttons_; // Lista de botones
std::vector<std::string> controller_names_; // Nombres de los controladores std::vector<std::string> controller_names_; // Nombres de los controladores
size_t index_button_ = 0; // Índice del botón seleccionado size_t index_button_ = 0; // Índice del botón seleccionado
float message_timer_ = 0.0F; // Timer en segundos para el mensaje float message_timer_ = 0.0F; // Timer en segundos para el mensaje
bool enabled_ = false; // Flag para indicar si está activo bool enabled_ = false; // Flag para indicar si está activo
bool finished_ = false; // Flag para indicar si ha terminado bool finished_ = false; // Flag para indicar si ha terminado
bool closing_ = false; // Flag para indicar que está cerrando bool closing_ = false; // Flag para indicar que está cerrando
bool message_shown_ = false; // Flag para indicar que ya mostró el mensaje bool message_shown_ = false; // Flag para indicar que ya mostró el mensaje
bool l2_was_pressed_ = false; // Estado anterior del trigger L2 bool l2_was_pressed_ = false; // Estado anterior del trigger L2
bool r2_was_pressed_ = false; // Estado anterior del trigger R2 bool r2_was_pressed_ = false; // Estado anterior del trigger R2
// --- Métodos internos --- // --- Métodos internos ---
void incIndexButton(); void incIndexButton();
void doControllerButtonDown(const SDL_GamepadButtonEvent& event); void doControllerButtonDown(const SDL_GamepadButtonEvent& event);
void doControllerAxisMotion(const SDL_GamepadAxisEvent& event); void doControllerAxisMotion(const SDL_GamepadAxisEvent& event);
void bindButtons(Options::Gamepad* options_gamepad); void bindButtons(Options::Gamepad* options_gamepad);
auto checkButtonNotInUse(SDL_GamepadButton button) -> bool; auto checkButtonNotInUse(SDL_GamepadButton button) -> bool;
auto checkTriggerNotInUse(int trigger_button) -> bool; auto checkTriggerNotInUse(int trigger_button) -> bool;
void clearButtons(); void clearButtons();
void checkEnd(); void checkEnd();
void updateWindowMessage(); void updateWindowMessage();
}; };
+26 -26
View File
@@ -10,41 +10,41 @@ constexpr int TOTAL_DEMO_DATA = 2000;
// --- Estructuras --- // --- Estructuras ---
struct DemoKeys { struct DemoKeys {
Uint8 left; Uint8 left;
Uint8 right; Uint8 right;
Uint8 no_input; Uint8 no_input;
Uint8 fire; Uint8 fire;
Uint8 fire_left; Uint8 fire_left;
Uint8 fire_right; Uint8 fire_right;
explicit DemoKeys(Uint8 l = 0, Uint8 r = 0, Uint8 ni = 0, Uint8 f = 0, Uint8 fl = 0, Uint8 fr = 0) explicit DemoKeys(Uint8 l = 0, Uint8 r = 0, Uint8 ni = 0, Uint8 f = 0, Uint8 fl = 0, Uint8 fr = 0)
: left(l), : left(l),
right(r), right(r),
no_input(ni), no_input(ni),
fire(f), fire(f),
fire_left(fl), fire_left(fl),
fire_right(fr) {} fire_right(fr) {}
}; };
// --- Tipos --- // --- Tipos ---
using DemoData = std::vector<DemoKeys>; using DemoData = std::vector<DemoKeys>;
struct Demo { struct Demo {
bool enabled = false; // Indica si está activo el modo demo bool enabled = false; // Indica si está activo el modo demo
bool recording = false; // Indica si está activado el modo para grabar la demo bool recording = false; // Indica si está activado el modo para grabar la demo
float elapsed_s = 0.0F; // Segundos transcurridos de demo float elapsed_s = 0.0F; // Segundos transcurridos de demo
int index = 0; // Contador para el modo demo int index = 0; // Contador para el modo demo
DemoKeys keys; // Variable con las pulsaciones de teclas del modo demo DemoKeys keys; // Variable con las pulsaciones de teclas del modo demo
std::vector<DemoData> data; // Vector con diferentes sets de datos con los movimientos para la demo std::vector<DemoData> data; // Vector con diferentes sets de datos con los movimientos para la demo
Demo() = default; Demo() = default;
Demo(bool e, bool r, int c, const DemoKeys& k, const std::vector<DemoData>& d) Demo(bool e, bool r, int c, const DemoKeys& k, const std::vector<DemoData>& d)
: enabled(e), : enabled(e),
recording(r), recording(r),
index(c), index(c),
keys(k), keys(k),
data(d) {} data(d) {}
}; };
// --- Funciones --- // --- Funciones ---
+26 -26
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>& {
return difficulties_list;
}
auto getNameFromCode(Code code) -> std::string {
for (const auto& difficulty : difficulties_list) {
if (difficulty.code == code) {
return difficulty.name;
}
} }
return !difficulties_list.empty() ? difficulties_list.front().name : "Unknown";
}
auto getCodeFromName(const std::string& name) -> Code { auto getDifficulties() -> std::vector<Info>& {
for (const auto& difficulty : difficulties_list) { return difficulties_list;
if (difficulty.name == name) { }
return difficulty.code;
} auto getNameFromCode(Code code) -> std::string {
for (const auto& difficulty : difficulties_list) {
if (difficulty.code == code) {
return difficulty.name;
}
}
return !difficulties_list.empty() ? difficulties_list.front().name : "Unknown";
}
auto getCodeFromName(const std::string& name) -> Code {
for (const auto& difficulty : difficulties_list) {
if (difficulty.name == name) {
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
+14 -14
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
+35 -35
View File
@@ -4,51 +4,51 @@
#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 ---
class Director { class Director {
public: public:
// --- Constructor y destructor --- // --- Constructor y destructor ---
Director(int argc, std::span<char*> argv); Director(int argc, std::span<char*> argv);
~Director(); ~Director();
// --- Bucle principal --- // --- Bucle principal ---
static auto run() -> int; static auto run() -> int;
private: private:
// --- Variables internas --- // --- Variables internas ---
std::string executable_path_; // Ruta del ejecutable std::string executable_path_; // Ruta del ejecutable
std::string system_folder_; // Carpeta del sistema para almacenar datos std::string system_folder_; // Carpeta del sistema para almacenar datos
// --- Inicialización y cierre del sistema --- // --- Inicialización y cierre del sistema ---
void init(); // Inicializa la aplicación void init(); // Inicializa la aplicación
static void close(); // Cierra y libera recursos static void close(); // Cierra y libera recursos
// --- Configuración inicial --- // --- Configuración inicial ---
static void loadParams(); // Carga los parámetros del programa static void loadParams(); // Carga los parámetros del programa
static void loadScoreFile(); // Carga el fichero de puntuaciones static void loadScoreFile(); // Carga el fichero de puntuaciones
void createSystemFolder(const std::string& folder); // Crea la carpeta del sistema void createSystemFolder(const std::string& folder); // Crea la carpeta del sistema
// --- Gestión de entrada y archivos --- // --- Gestión de entrada y archivos ---
void loadAssets(); // Crea el índice de archivos disponibles void loadAssets(); // Crea el índice de archivos disponibles
void checkProgramArguments(int argc, std::span<char*> argv); // Verifica los parámetros del programa // NOLINT(modernize-avoid-c-arrays) void checkProgramArguments(int argc, std::span<char*> argv); // Verifica los parámetros del programa // NOLINT(modernize-avoid-c-arrays)
// --- Secciones del programa --- // --- Secciones del programa ---
static void runLogo(); // Ejecuta la pantalla con el logo static void runLogo(); // Ejecuta la pantalla con el logo
static void runIntro(); // Ejecuta la introducción del juego static void runIntro(); // Ejecuta la introducción del juego
static void runTitle(); // Ejecuta la pantalla de título static void runTitle(); // Ejecuta la pantalla de título
static void runGame(); // Inicia el juego static void runGame(); // Inicia el juego
static void runInstructions(); // Muestra las instrucciones static void runInstructions(); // Muestra las instrucciones
static void runCredits(); // Muestra los créditos del juego static void runCredits(); // Muestra los créditos del juego
static void runHiScoreTable(); // Muestra la tabla de puntuaciones static void runHiScoreTable(); // Muestra la tabla de puntuaciones
static void runDemoGame(); // Ejecuta el modo demo static void runDemoGame(); // Ejecuta el modo demo
static void reset(); // Reinicia objetos y vuelve a la sección inicial static void reset(); // Reinicia objetos y vuelve a la sección inicial
// --- Gestión de archivos de idioma --- // --- Gestión de archivos de idioma ---
auto getLangFile(Lang::Code code) -> std::string; // Obtiene un fichero de idioma según el código auto getLangFile(Lang::Code code) -> std::string; // Obtiene un fichero de idioma según el código
// --- Apagado del sistema --- // --- Apagado del sistema ---
static void shutdownSystem(bool should_shutdown); // Apaga el sistema static void shutdownSystem(bool should_shutdown); // Apaga el sistema
}; };
+27 -27
View File
@@ -5,38 +5,38 @@
// --- Clase EnterName: gestor de entrada de nombre del jugador --- // --- Clase EnterName: gestor de entrada de nombre del jugador ---
class EnterName { class EnterName {
public: public:
// --- Constantes --- // --- Constantes ---
static constexpr size_t MAX_NAME_SIZE = 6; // Tamaño máximo del nombre static constexpr size_t MAX_NAME_SIZE = 6; // Tamaño máximo del nombre
EnterName(); EnterName();
~EnterName() = default; ~EnterName() = default;
void init(const std::string& name = ""); // Inicializa con nombre opcional (vacío por defecto) void init(const std::string& name = ""); // Inicializa con nombre opcional (vacío por defecto)
void incIndex(); // Incrementa el índice del carácter seleccionado en la lista void incIndex(); // Incrementa el índice del carácter seleccionado en la lista
void decIndex(); // Decrementa el índice del carácter seleccionado en la lista void decIndex(); // Decrementa el índice del carácter seleccionado en la lista
void addCharacter(); // Añade el carácter seleccionado al nombre void addCharacter(); // Añade el carácter seleccionado al nombre
void removeLastCharacter(); // Elimina el último carácter del nombre void removeLastCharacter(); // Elimina el último carácter del nombre
auto getFinalName() -> std::string; // Obtiene el nombre final (o aleatorio si vacío) auto getFinalName() -> std::string; // Obtiene el nombre final (o aleatorio si vacío)
[[nodiscard]] auto getCurrentName() const -> std::string { return name_; } // Obtiene el nombre actual en proceso [[nodiscard]] auto getCurrentName() const -> std::string { return name_; } // Obtiene el nombre actual en proceso
[[nodiscard]] auto getSelectedCharacter(int offset = 0) const -> std::string; // Devuelve el carácter seleccionado con offset relativo [[nodiscard]] auto getSelectedCharacter(int offset = 0) const -> std::string; // Devuelve el carácter seleccionado con offset relativo
[[nodiscard]] auto getCarousel(int size) const -> std::string; // Devuelve el carrusel de caracteres (size debe ser impar) [[nodiscard]] auto getCarousel(int size) const -> std::string; // Devuelve el carrusel de caracteres (size debe ser impar)
[[nodiscard]] auto getSelectedIndex() const -> int { return selected_index_; } // Obtiene el índice del carácter seleccionado [[nodiscard]] auto getSelectedIndex() const -> int { return selected_index_; } // Obtiene el índice del carácter seleccionado
[[nodiscard]] auto getCharacterList() const -> const std::string& { return character_list_; } // Obtiene la lista completa de caracteres [[nodiscard]] auto getCharacterList() const -> const std::string& { return character_list_; } // Obtiene la lista completa de caracteres
[[nodiscard]] auto nameIsFull() const -> bool { return name_.size() == MAX_NAME_SIZE; } // Informa de si el nombre ha alcanzado su limite [[nodiscard]] auto nameIsFull() const -> bool { return name_.size() == MAX_NAME_SIZE; } // Informa de si el nombre ha alcanzado su limite
[[nodiscard]] auto nameIsEmpty() const -> bool { return name_.empty(); } // Informa de si el nombre está vacío [[nodiscard]] auto nameIsEmpty() const -> bool { return name_.empty(); } // Informa de si el nombre está vacío
[[nodiscard]] auto endCharSelected() const -> bool { return selected_index_ == character_list_.size() - 1; } // Informa de si está seleccionado el caracter de terminar [[nodiscard]] auto endCharSelected() const -> bool { return selected_index_ == character_list_.size() - 1; } // Informa de si está seleccionado el caracter de terminar
private: private:
// --- Variables de estado --- // --- Variables de estado ---
std::string character_list_; // Lista de caracteres permitidos std::string character_list_; // Lista de caracteres permitidos
std::string name_; // Nombre en proceso std::string name_; // Nombre en proceso
size_t selected_index_ = 0; // Índice del carácter seleccionado en "character_list_" size_t selected_index_ = 0; // Índice del carácter seleccionado en "character_list_"
[[nodiscard]] auto sanitizeName(const std::string& name) const -> std::string; // Valida y limpia el nombre [[nodiscard]] auto sanitizeName(const std::string& name) const -> std::string; // Valida y limpia el nombre
static auto getRandomName() -> std::string; // Devuelve un nombre al azar static auto getRandomName() -> std::string; // Devuelve un nombre al azar
void forceEndCharSelected() { selected_index_ = character_list_.size() - 1; } // Establece como seleccionado el caracter de terminar void forceEndCharSelected() { selected_index_ = character_list_.size() - 1; } // Establece como seleccionado el caracter de terminar
}; };
+24 -24
View File
@@ -11,37 +11,37 @@ class Texture;
// --- Estructura ExplosionTexture: almacena información de una textura de explosión --- // --- Estructura ExplosionTexture: almacena información de una textura de explosión ---
struct ExplosionTexture { struct ExplosionTexture {
int size; // Tamaño de la explosión int size; // Tamaño de la explosión
std::shared_ptr<Texture> texture; // Textura para la explosión std::shared_ptr<Texture> texture; // Textura para la explosión
std::vector<std::string> animation; // Animación para la textura std::vector<std::string> animation; // Animación para la textura
ExplosionTexture(int sz, std::shared_ptr<Texture> tex, const std::vector<std::string>& anim) ExplosionTexture(int sz, std::shared_ptr<Texture> tex, const std::vector<std::string>& anim)
: size(sz), : size(sz),
texture(std::move(tex)), texture(std::move(tex)),
animation(anim) {} animation(anim) {}
}; };
// --- Clase Explosions: gestor de explosiones --- // --- Clase Explosions: gestor de explosiones ---
class Explosions { class Explosions {
public: public:
// --- Constructor y destructor --- // --- Constructor y destructor ---
Explosions() = default; // Constructor por defecto Explosions() = default; // Constructor por defecto
~Explosions() = default; // Destructor por defecto ~Explosions() = default; // Destructor por defecto
// --- Métodos principales --- // --- Métodos principales ---
void update(float delta_time); // Actualiza la lógica de la clase (time-based) void update(float delta_time); // Actualiza la lógica de la clase (time-based)
void render(); // Dibuja el objeto en pantalla void render(); // Dibuja el objeto en pantalla
// --- Configuración --- // --- Configuración ---
void addTexture(int size, const std::shared_ptr<Texture>& texture, const std::vector<std::string>& animation); // Añade texturas al objeto void addTexture(int size, const std::shared_ptr<Texture>& texture, const std::vector<std::string>& animation); // Añade texturas al objeto
void add(int x, int y, int size); // Añade una explosión void add(int x, int y, int size); // Añade una explosión
private: private:
// --- Variables de estado --- // --- Variables de estado ---
std::vector<ExplosionTexture> textures_; // Vector con las texturas a utilizar std::vector<ExplosionTexture> textures_; // Vector con las texturas a utilizar
std::vector<std::unique_ptr<AnimatedSprite>> explosions_; // Lista con todas las explosiones std::vector<std::unique_ptr<AnimatedSprite>> explosions_; // Lista con todas las explosiones
// --- Métodos internos --- // --- Métodos internos ---
void freeExplosions(); // Vacía el vector de elementos finalizados void freeExplosions(); // Vacía el vector de elementos finalizados
auto getIndexBySize(int size) -> int; // Busca una textura a partir del tamaño auto getIndexBySize(int size) -> int; // Busca una textura a partir del tamaño
}; };
+9 -10
View File
@@ -180,7 +180,7 @@ void Fade::updateCenterFade() {
void Fade::drawCenterFadeRectangles() { void Fade::drawCenterFadeRectangles() {
auto* temp = SDL_GetRenderTarget(renderer_); auto* temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer_, backbuffer_); SDL_SetRenderTarget(renderer_, backbuffer_);
cleanBackbuffer(r_, g_, b_, 0); // Limpiar para modo IN cleanBackbuffer(r_, g_, b_, 0); // Limpiar para modo IN
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, 255); SDL_SetRenderDrawColor(renderer_, r_, g_, b_, 255);
SDL_RenderFillRect(renderer_, &rect1_); SDL_RenderFillRect(renderer_, &rect1_);
@@ -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; }
} }
} }
@@ -331,7 +331,7 @@ void Fade::drawDiagonal() {
void Fade::drawRandomSquares(int active_count) { void Fade::drawRandomSquares(int active_count) {
auto* temp = SDL_GetRenderTarget(renderer_); auto* temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer_, backbuffer_); SDL_SetRenderTarget(renderer_, backbuffer_);
// El fondo se prepara en activate() // El fondo se prepara en activate()
SDL_BlendMode blend_mode; SDL_BlendMode blend_mode;
SDL_GetRenderDrawBlendMode(renderer_, &blend_mode); SDL_GetRenderDrawBlendMode(renderer_, &blend_mode);
@@ -410,7 +410,7 @@ void Fade::drawVenetianBlinds() {
SDL_BlendMode blend_mode; SDL_BlendMode blend_mode;
SDL_GetRenderDrawBlendMode(renderer_, &blend_mode); SDL_GetRenderDrawBlendMode(renderer_, &blend_mode);
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_NONE); SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_NONE);
// Dibuja las persianas con el color opuesto al fondo // Dibuja las persianas con el color opuesto al fondo
Uint8 draw_alpha = (mode_ == Mode::OUT) ? 255 : 0; Uint8 draw_alpha = (mode_ == Mode::OUT) ? 255 : 0;
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, draw_alpha); SDL_SetRenderDrawColor(renderer_, r_, g_, b_, draw_alpha);
@@ -434,10 +434,10 @@ void Fade::activate() {
// Preparación inicial de cada tipo // Preparación inicial de cada tipo
switch (type_) { switch (type_) {
/*case Type::FULLSCREEN: /*case Type::FULLSCREEN:
cleanBackbuffer(r_, g_, b_, (mode_ == Mode::OUT) ? 0 : 255); cleanBackbuffer(r_, g_, b_, (mode_ == Mode::OUT) ? 0 : 255);
SDL_SetTextureAlphaMod(backbuffer_, (mode_ == Mode::OUT) ? 255 : 0); SDL_SetTextureAlphaMod(backbuffer_, (mode_ == Mode::OUT) ? 255 : 0);
break;*/ break;*/
case Type::FULLSCREEN: { case Type::FULLSCREEN: {
// La textura en sí siempre debe ser de un color sólido y opaco. // La textura en sí siempre debe ser de un color sólido y opaco.
@@ -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;
+87 -87
View File
@@ -8,104 +8,104 @@ struct Color;
// --- Clase Fade: gestor de transiciones de fundido --- // --- Clase Fade: gestor de transiciones de fundido ---
class Fade { class Fade {
public: public:
// --- Enums --- // --- Enums ---
enum class Type : Uint8 { enum class Type : Uint8 {
FULLSCREEN = 0, // Fundido de pantalla completa FULLSCREEN = 0, // Fundido de pantalla completa
CENTER = 1, // Fundido desde el centro CENTER = 1, // Fundido desde el centro
RANDOM_SQUARE = 2, // Fundido con cuadrados aleatorios RANDOM_SQUARE = 2, // Fundido con cuadrados aleatorios
RANDOM_SQUARE2 = 3, // Fundido con cuadrados aleatorios (variante 2) RANDOM_SQUARE2 = 3, // Fundido con cuadrados aleatorios (variante 2)
DIAGONAL = 4, // Fundido diagonal desde esquina superior izquierda DIAGONAL = 4, // Fundido diagonal desde esquina superior izquierda
VENETIAN = 5, // Fundido tipo persiana veneciana VENETIAN = 5, // Fundido tipo persiana veneciana
}; };
enum class Mode : Uint8 { enum class Mode : Uint8 {
IN = 0, // Fundido de entrada IN = 0, // Fundido de entrada
OUT = 1, // Fundido de salida OUT = 1, // Fundido de salida
}; };
enum class State : Uint8 { enum class State : Uint8 {
NOT_ENABLED = 0, // No activado NOT_ENABLED = 0, // No activado
PRE = 1, // Estado previo PRE = 1, // Estado previo
FADING = 2, // Fundiendo FADING = 2, // Fundiendo
POST = 3, // Estado posterior POST = 3, // Estado posterior
FINISHED = 4, // Finalizado FINISHED = 4, // Finalizado
}; };
// --- Constructores y destructor --- // --- Constructores y destructor ---
Fade(); Fade();
~Fade(); ~Fade();
// --- Métodos principales --- // --- Métodos principales ---
void reset(); // Resetea variables para reutilizar el fade void reset(); // Resetea variables para reutilizar el fade
void render(); // Dibuja la transición en pantalla void render(); // Dibuja la transición en pantalla
void update(float delta_time = 0.0F); // Actualiza el estado interno void update(float delta_time = 0.0F); // Actualiza el estado interno
void activate(); // Activa el fade void activate(); // Activa el fade
// --- Configuración --- // --- Configuración ---
void setColor(Uint8 r, Uint8 g, Uint8 b); // Establece el color RGB del fade void setColor(Uint8 r, Uint8 g, Uint8 b); // Establece el color RGB del fade
void setColor(Color color); // Establece el color del fade void setColor(Color color); // Establece el color del fade
void setType(Type type) { type_ = type; } // Establece el tipo de fade void setType(Type type) { type_ = type; } // Establece el tipo de fade
void setMode(Mode mode) { mode_ = mode; } // Establece el modo de fade void setMode(Mode mode) { mode_ = mode; } // Establece el modo de fade
void setDuration(int milliseconds) { fading_duration_ = milliseconds; } // Duración del estado FADING en milisegundos void setDuration(int milliseconds) { fading_duration_ = milliseconds; } // Duración del estado FADING en milisegundos
void setPostDuration(int milliseconds) { post_duration_ = milliseconds; } // Duración posterior al fade en milisegundos void setPostDuration(int milliseconds) { post_duration_ = milliseconds; } // Duración posterior al fade en milisegundos
void setPreDuration(int milliseconds) { pre_duration_ = milliseconds; } // Duración previa al fade en milisegundos void setPreDuration(int milliseconds) { pre_duration_ = milliseconds; } // Duración previa al fade en milisegundos
// --- Getters --- // --- Getters ---
[[nodiscard]] auto getValue() const -> int { return value_; } [[nodiscard]] auto getValue() const -> int { return value_; }
[[nodiscard]] auto isEnabled() const -> bool { return state_ != State::NOT_ENABLED; } [[nodiscard]] auto isEnabled() const -> bool { return state_ != State::NOT_ENABLED; }
[[nodiscard]] auto hasEnded() const -> bool { return state_ == State::FINISHED; } [[nodiscard]] auto hasEnded() const -> bool { return state_ == State::FINISHED; }
private: private:
// --- Objetos y punteros --- // --- Objetos y punteros ---
SDL_Renderer* renderer_; // Renderizador de la ventana SDL_Renderer* renderer_; // Renderizador de la ventana
SDL_Texture* backbuffer_; // Backbuffer para efectos SDL_Texture* backbuffer_; // Backbuffer para efectos
// --- Variables de estado --- // --- Variables de estado ---
std::vector<SDL_FRect> square_; // Vector de cuadrados std::vector<SDL_FRect> square_; // Vector de cuadrados
std::vector<int> square_age_; // Edad de cada cuadrado (para RANDOM_SQUARE2 y DIAGONAL) std::vector<int> square_age_; // Edad de cada cuadrado (para RANDOM_SQUARE2 y DIAGONAL)
SDL_FRect rect1_, rect2_; // Rectángulos para efectos SDL_FRect rect1_, rect2_; // Rectángulos para efectos
Type type_; // Tipo de fade Type type_; // Tipo de fade
Mode mode_; // Modo de fade Mode mode_; // Modo de fade
State state_ = State::NOT_ENABLED; // Estado actual State state_ = State::NOT_ENABLED; // Estado actual
Uint8 r_, g_, b_, a_; // Color del fade (RGBA) Uint8 r_, g_, b_, a_; // Color del fade (RGBA)
int num_squares_width_; // Cuadrados en horizontal int num_squares_width_; // Cuadrados en horizontal
int num_squares_height_; // Cuadrados en vertical int num_squares_height_; // Cuadrados en vertical
int square_transition_duration_; // Duración de transición de cada cuadrado en ms int square_transition_duration_; // Duración de transición de cada cuadrado en ms
int fading_duration_; // Duración del estado FADING en milisegundos int fading_duration_; // Duración del estado FADING en milisegundos
Uint32 fading_start_time_ = 0; // Tiempo de inicio del estado FADING Uint32 fading_start_time_ = 0; // Tiempo de inicio del estado FADING
int post_duration_ = 0; // Duración posterior en milisegundos int post_duration_ = 0; // Duración posterior en milisegundos
Uint32 post_start_time_ = 0; // Tiempo de inicio del estado POST Uint32 post_start_time_ = 0; // Tiempo de inicio del estado POST
int pre_duration_ = 0; // Duración previa en milisegundos int pre_duration_ = 0; // Duración previa en milisegundos
Uint32 pre_start_time_ = 0; // Tiempo de inicio del estado PRE Uint32 pre_start_time_ = 0; // Tiempo de inicio del estado PRE
int value_ = 0; // Estado del fade (0-100) int value_ = 0; // Estado del fade (0-100)
// --- Inicialización y limpieza --- // --- Inicialización y limpieza ---
void init(); // Inicializa variables void init(); // Inicializa variables
void cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a); // Limpia el backbuffer con un color RGBA void cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a); // Limpia el backbuffer con un color RGBA
// --- Utilidades generales --- // --- Utilidades generales ---
static auto calculateValue(int min, int max, int current) -> int; // Calcula el valor del fade entre dos límites static auto calculateValue(int min, int max, int current) -> int; // Calcula el valor del fade entre dos límites
// --- Lógica de estado --- // --- Lógica de estado ---
void updatePreState(); // Actualiza el estado previo al fade void updatePreState(); // Actualiza el estado previo al fade
void updateFadingState(); // Actualiza el estado durante el fade void updateFadingState(); // Actualiza el estado durante el fade
void updatePostState(); // Actualiza el estado posterior al fade void updatePostState(); // Actualiza el estado posterior al fade
void changeToPostState(); // Cambia al estado POST e inicializa el tiempo void changeToPostState(); // Cambia al estado POST e inicializa el tiempo
// --- Efectos de fundido (fade) --- // --- Efectos de fundido (fade) ---
void updateFullscreenFade(); // Actualiza el fundido de pantalla completa void updateFullscreenFade(); // Actualiza el fundido de pantalla completa
void updateCenterFade(); // Actualiza el fundido desde el centro void updateCenterFade(); // Actualiza el fundido desde el centro
void updateRandomSquareFade(); // Actualiza el fundido con cuadrados aleatorios void updateRandomSquareFade(); // Actualiza el fundido con cuadrados aleatorios
void updateRandomSquare2Fade(); // Actualiza el fundido con cuadrados aleatorios (variante 2) void updateRandomSquare2Fade(); // Actualiza el fundido con cuadrados aleatorios (variante 2)
void updateDiagonalFade(); // Actualiza el fundido diagonal void updateDiagonalFade(); // Actualiza el fundido diagonal
void updateVenetianFade(); // Actualiza el fundido tipo persiana veneciana void updateVenetianFade(); // Actualiza el fundido tipo persiana veneciana
// --- Dibujo de efectos visuales --- // --- Dibujo de efectos visuales ---
void drawCenterFadeRectangles(); // Dibuja los rectángulos del fundido central void drawCenterFadeRectangles(); // Dibuja los rectángulos del fundido central
void drawRandomSquares(int active_count); // Dibuja los cuadrados aleatorios del fundido void drawRandomSquares(int active_count); // Dibuja los cuadrados aleatorios del fundido
void drawRandomSquares2(); // Dibuja los cuadrados con transición de color (RANDOM_SQUARE2) void drawRandomSquares2(); // Dibuja los cuadrados con transición de color (RANDOM_SQUARE2)
void drawDiagonal(); // Dibuja los cuadrados con patrón diagonal void drawDiagonal(); // Dibuja los cuadrados con patrón diagonal
void activateDiagonal(int diagonal_index, Uint32 current_time); // Activa una diagonal específica void activateDiagonal(int diagonal_index, Uint32 current_time); // Activa una diagonal específica
void drawVenetianBlinds(); // Dibuja las persianas venecianas del fundido void drawVenetianBlinds(); // Dibuja las persianas venecianas del fundido
}; };
+97 -97
View File
@@ -10,116 +10,116 @@ class Texture;
// --- Clase GameLogo: gestor del logo del juego --- // --- Clase GameLogo: gestor del logo del juego ---
class GameLogo { class GameLogo {
public: public:
// --- Constantes --- // --- Constantes ---
static constexpr float COFFEE_VEL_Y = 0.15F * 1000.0F; // Velocidad Y de coffee sprite (pixels/s) - 0.15F * 1000 = 150 pixels/s static constexpr float COFFEE_VEL_Y = 0.15F * 1000.0F; // Velocidad Y de coffee sprite (pixels/s) - 0.15F * 1000 = 150 pixels/s
static constexpr float COFFEE_ACCEL_Y = 0.00036F * 1000000.0F; // Aceleración Y de coffee sprite (pixels/s²) - 0.00036F * 1000000 = 360 pixels/s² static constexpr float COFFEE_ACCEL_Y = 0.00036F * 1000000.0F; // Aceleración Y de coffee sprite (pixels/s²) - 0.00036F * 1000000 = 360 pixels/s²
static constexpr float CRISIS_VEL_Y = -0.15F * 1000.0F; // Velocidad Y de crisis sprite (pixels/s) - -0.15F * 1000 = -150 pixels/s static constexpr float CRISIS_VEL_Y = -0.15F * 1000.0F; // Velocidad Y de crisis sprite (pixels/s) - -0.15F * 1000 = -150 pixels/s
static constexpr float CRISIS_ACCEL_Y = -0.00036F * 1000000.0F; // Aceleración Y de crisis sprite (pixels/s²) - -0.00036F * 1000000 = -360 pixels/s² static constexpr float CRISIS_ACCEL_Y = -0.00036F * 1000000.0F; // Aceleración Y de crisis sprite (pixels/s²) - -0.00036F * 1000000 = -360 pixels/s²
static constexpr int CRISIS_OFFSET_X = 15; // Desplazamiento X de crisis sprite static constexpr int CRISIS_OFFSET_X = 15; // Desplazamiento X de crisis sprite
static constexpr int DUST_SIZE = 16; // Tamaño de dust sprites static constexpr int DUST_SIZE = 16; // Tamaño de dust sprites
static constexpr float ZOOM_DECREMENT_PER_S = 0.006F * 1000.0F; // Decremento de zoom por segundo (0.006F * 1000 = 6.0F per second) static constexpr float ZOOM_DECREMENT_PER_S = 0.006F * 1000.0F; // Decremento de zoom por segundo (0.006F * 1000 = 6.0F per second)
static constexpr float SHAKE_DELAY_S = 33.34F / 1000.0F; // Delay de shake en segundos (33.34ms / 1000 = 0.03334s) static constexpr float SHAKE_DELAY_S = 33.34F / 1000.0F; // Delay de shake en segundos (33.34ms / 1000 = 0.03334s)
static constexpr float POST_FINISHED_FRAME_TIME_S = 16.67F / 1000.0F; // Tiempo entre decrementos del counter (16.67ms / 1000 = 0.01667s) static constexpr float POST_FINISHED_FRAME_TIME_S = 16.67F / 1000.0F; // Tiempo entre decrementos del counter (16.67ms / 1000 = 0.01667s)
// --- Constructores y destructor --- // --- Constructores y destructor ---
GameLogo(int x, int y); GameLogo(int x, int y);
~GameLogo() = default; ~GameLogo() = default;
// --- Métodos principales --- // --- Métodos principales ---
void render(); // Pinta la clase en pantalla void render(); // Pinta la clase en pantalla
void update(float delta_time); // Actualiza la lógica de la clase (time-based) void update(float delta_time); // Actualiza la lógica de la clase (time-based)
void enable(); // Activa la clase void enable(); // Activa la clase
// --- Getters --- // --- Getters ---
[[nodiscard]] auto hasFinished() const -> bool; // Indica si ha terminado la animación [[nodiscard]] auto hasFinished() const -> bool; // Indica si ha terminado la animación
private: private:
// --- Enums --- // --- Enums ---
enum class Status { enum class Status {
DISABLED, // Deshabilitado DISABLED, // Deshabilitado
MOVING, // En movimiento MOVING, // En movimiento
SHAKING, // Temblando SHAKING, // Temblando
FINISHED, // Terminado FINISHED, // Terminado
}; };
// --- Estructuras privadas --- // --- Estructuras privadas ---
struct Shake { struct Shake {
int desp = 1; // Pixels de desplazamiento para agitar la pantalla en el eje x int desp = 1; // Pixels de desplazamiento para agitar la pantalla en el eje x
int delay = 2; // Retraso entre cada desplazamiento de la pantalla al agitarse (frame-based) int delay = 2; // Retraso entre cada desplazamiento de la pantalla al agitarse (frame-based)
int length = 8; // Cantidad de desplazamientos a realizar int length = 8; // Cantidad de desplazamientos a realizar
int remaining = length; // Cantidad de desplazamientos pendientes a realizar int remaining = length; // Cantidad de desplazamientos pendientes a realizar
int counter = delay; // Contador para el retraso (frame-based) int counter = delay; // Contador para el retraso (frame-based)
float time_accumulator = 0.0F; // Acumulador de tiempo para deltaTime float time_accumulator = 0.0F; // Acumulador de tiempo para deltaTime
int origin = 0; // Valor inicial de la pantalla para dejarla igual tras el desplazamiento int origin = 0; // Valor inicial de la pantalla para dejarla igual tras el desplazamiento
Shake() = default; Shake() = default;
Shake(int d, int de, int l, int o) Shake(int d, int de, int l, int o)
: desp(d), : desp(d),
delay(de), delay(de),
length(l), length(l),
remaining(l), remaining(l),
counter(de), counter(de),
origin(o) {} origin(o) {}
void init(int d, int de, int l, int o) { void init(int d, int de, int l, int o) {
desp = d; desp = d;
delay = de; delay = de;
length = l; length = l;
remaining = l; remaining = l;
counter = de; counter = de;
time_accumulator = 0.0F; time_accumulator = 0.0F;
origin = o; origin = o;
} }
}; };
// --- Objetos y punteros --- // --- Objetos y punteros ---
std::shared_ptr<Texture> dust_texture_; // Textura con los graficos del polvo std::shared_ptr<Texture> dust_texture_; // Textura con los graficos del polvo
std::shared_ptr<Texture> coffee_texture_; // Textura con los graficos de la palabra "COFFEE" std::shared_ptr<Texture> coffee_texture_; // Textura con los graficos de la palabra "COFFEE"
std::shared_ptr<Texture> crisis_texture_; // Textura con los graficos de la palabra "CRISIS" std::shared_ptr<Texture> crisis_texture_; // Textura con los graficos de la palabra "CRISIS"
std::shared_ptr<Texture> arcade_edition_texture_; // Textura con los graficos de "Arcade Edition" std::shared_ptr<Texture> arcade_edition_texture_; // Textura con los graficos de "Arcade Edition"
std::unique_ptr<AnimatedSprite> dust_left_sprite_; // Sprite del polvo (izquierda) std::unique_ptr<AnimatedSprite> dust_left_sprite_; // Sprite del polvo (izquierda)
std::unique_ptr<AnimatedSprite> dust_right_sprite_; // Sprite del polvo (derecha) std::unique_ptr<AnimatedSprite> dust_right_sprite_; // Sprite del polvo (derecha)
std::unique_ptr<SmartSprite> coffee_sprite_; // Sprite de "COFFEE" std::unique_ptr<SmartSprite> coffee_sprite_; // Sprite de "COFFEE"
std::unique_ptr<SmartSprite> crisis_sprite_; // Sprite de "CRISIS" std::unique_ptr<SmartSprite> crisis_sprite_; // Sprite de "CRISIS"
std::unique_ptr<Sprite> arcade_edition_sprite_; // Sprite de "Arcade Edition" std::unique_ptr<Sprite> arcade_edition_sprite_; // Sprite de "Arcade Edition"
// --- Variables de estado --- // --- Variables de estado ---
Shake shake_; // Efecto de agitación Shake shake_; // Efecto de agitación
Status coffee_crisis_status_ = Status::DISABLED; // Estado de "COFFEE CRISIS" Status coffee_crisis_status_ = Status::DISABLED; // Estado de "COFFEE CRISIS"
Status arcade_edition_status_ = Status::DISABLED; // Estado de "ARCADE EDITION" Status arcade_edition_status_ = Status::DISABLED; // Estado de "ARCADE EDITION"
float x_; // Posición X del logo float x_; // Posición X del logo
float y_; // Posición Y del logo float y_; // Posición Y del logo
float zoom_ = 1.0F; // Zoom aplicado al texto "ARCADE EDITION" float zoom_ = 1.0F; // Zoom aplicado al texto "ARCADE EDITION"
float post_finished_delay_s_ = POST_FINISHED_FRAME_TIME_S; // Retraso final tras animaciones (s) float post_finished_delay_s_ = POST_FINISHED_FRAME_TIME_S; // Retraso final tras animaciones (s)
float post_finished_timer_ = 0.0F; // Timer acumulado para retraso final (s) float post_finished_timer_ = 0.0F; // Timer acumulado para retraso final (s)
// --- Inicialización --- // --- Inicialización ---
void init(); // Inicializa las variables void init(); // Inicializa las variables
[[nodiscard]] auto getInitialVerticalDesp() const -> int; // Calcula el desplazamiento vertical inicial [[nodiscard]] auto getInitialVerticalDesp() const -> int; // Calcula el desplazamiento vertical inicial
// --- Actualización de estados específicos --- // --- Actualización de estados específicos ---
void updateCoffeeCrisis(float delta_time); // Actualiza el estado de "Coffee Crisis" (time-based) void updateCoffeeCrisis(float delta_time); // Actualiza el estado de "Coffee Crisis" (time-based)
void updateArcadeEdition(float delta_time); // Actualiza el estado de "Arcade Edition" (time-based) void updateArcadeEdition(float delta_time); // Actualiza el estado de "Arcade Edition" (time-based)
void updatePostFinishedCounter(float delta_time); // Actualiza el contador tras finalizar una animación (time-based) void updatePostFinishedCounter(float delta_time); // Actualiza el contador tras finalizar una animación (time-based)
// --- Efectos visuales: movimiento y sacudidas --- // --- Efectos visuales: movimiento y sacudidas ---
void handleCoffeeCrisisMoving(float delta_time); // Maneja el movimiento de "Coffee Crisis" (time-based) void handleCoffeeCrisisMoving(float delta_time); // Maneja el movimiento de "Coffee Crisis" (time-based)
void handleCoffeeCrisisShaking(float delta_time); // Maneja la sacudida de "Coffee Crisis" (time-based) void handleCoffeeCrisisShaking(float delta_time); // Maneja la sacudida de "Coffee Crisis" (time-based)
void handleArcadeEditionMoving(float delta_time); // Maneja el movimiento de "Arcade Edition" (time-based) void handleArcadeEditionMoving(float delta_time); // Maneja el movimiento de "Arcade Edition" (time-based)
void handleArcadeEditionShaking(float delta_time); // Maneja la sacudida de "Arcade Edition" (time-based) void handleArcadeEditionShaking(float delta_time); // Maneja la sacudida de "Arcade Edition" (time-based)
void processShakeEffect(SmartSprite* primary_sprite, SmartSprite* secondary_sprite = nullptr); // Procesa el efecto de sacudida en sprites (frame-based) void processShakeEffect(SmartSprite* primary_sprite, SmartSprite* secondary_sprite = nullptr); // Procesa el efecto de sacudida en sprites (frame-based)
void processShakeEffect(SmartSprite* primary_sprite, SmartSprite* secondary_sprite, float delta_time); // Procesa el efecto de sacudida en sprites (time-based) void processShakeEffect(SmartSprite* primary_sprite, SmartSprite* secondary_sprite, float delta_time); // Procesa el efecto de sacudida en sprites (time-based)
void processArcadeEditionShake(float delta_time); // Procesa la sacudida específica de "Arcade Edition" (time-based) void processArcadeEditionShake(float delta_time); // Procesa la sacudida específica de "Arcade Edition" (time-based)
[[nodiscard]] auto calculateShakeDisplacement() const -> int; // Calcula el desplazamiento de la sacudida [[nodiscard]] auto calculateShakeDisplacement() const -> int; // Calcula el desplazamiento de la sacudida
// --- Gestión de finalización de efectos --- // --- Gestión de finalización de efectos ---
void handleCoffeeCrisisFinished(float delta_time); // Maneja el final de la animación "Coffee Crisis" (time-based) void handleCoffeeCrisisFinished(float delta_time); // Maneja el final de la animación "Coffee Crisis" (time-based)
void finishCoffeeCrisisShaking(); // Finaliza la sacudida de "Coffee Crisis" void finishCoffeeCrisisShaking(); // Finaliza la sacudida de "Coffee Crisis"
void finishArcadeEditionMoving(); // Finaliza el movimiento de "Arcade Edition" void finishArcadeEditionMoving(); // Finaliza el movimiento de "Arcade Edition"
// --- Utilidades --- // --- Utilidades ---
static void playTitleEffects(); // Reproduce efectos visuales/sonoros del título static void playTitleEffects(); // Reproduce efectos visuales/sonoros del título
void updateDustSprites(float delta_time); // Actualiza los sprites de polvo (time-based) void updateDustSprites(float delta_time); // Actualiza los sprites de polvo (time-based)
}; };
+101 -101
View File
@@ -10,24 +10,24 @@
// --- Estructuras --- // --- Estructuras ---
struct GamepadConfig { struct GamepadConfig {
std::string name; // Nombre del dispositivo std::string name; // Nombre del dispositivo
std::string path; // Ruta física del dispositivo std::string path; // Ruta física del dispositivo
std::unordered_map<InputAction, SDL_GamepadButton> bindings; // Asociación acción-botón std::unordered_map<InputAction, SDL_GamepadButton> bindings; // Asociación acción-botón
GamepadConfig(std::string name, std::string path) GamepadConfig(std::string name, std::string path)
: name(std::move(name)), : name(std::move(name)),
path(std::move(path)), path(std::move(path)),
bindings{ bindings{
{InputAction::FIRE_LEFT, SDL_GAMEPAD_BUTTON_WEST}, {InputAction::FIRE_LEFT, SDL_GAMEPAD_BUTTON_WEST},
{InputAction::FIRE_CENTER, SDL_GAMEPAD_BUTTON_NORTH}, {InputAction::FIRE_CENTER, SDL_GAMEPAD_BUTTON_NORTH},
{InputAction::FIRE_RIGHT, SDL_GAMEPAD_BUTTON_EAST}, {InputAction::FIRE_RIGHT, SDL_GAMEPAD_BUTTON_EAST},
{InputAction::START, SDL_GAMEPAD_BUTTON_START}, {InputAction::START, SDL_GAMEPAD_BUTTON_START},
{InputAction::SERVICE, SDL_GAMEPAD_BUTTON_BACK}} {} {InputAction::SERVICE, SDL_GAMEPAD_BUTTON_BACK}} {}
// Reasigna un botón a una acción // Reasigna un botón a una acción
void rebindAction(InputAction action, SDL_GamepadButton new_button) { void rebindAction(InputAction action, SDL_GamepadButton new_button) {
bindings[action] = new_button; bindings[action] = new_button;
} }
}; };
// --- Tipos --- // --- Tipos ---
@@ -35,102 +35,102 @@ using GamepadConfigs = std::vector<GamepadConfig>; // Vector de configuraciones
// --- Clase GamepadConfigManager: gestor de configuraciones de gamepad --- // --- Clase GamepadConfigManager: gestor de configuraciones de gamepad ---
class GamepadConfigManager { class GamepadConfigManager {
public: public:
// --- Métodos estáticos --- // --- Métodos estáticos ---
static auto writeToJson(const GamepadConfigs& configs, const std::string& filename) -> bool { // Escribir configuraciones a JSON static auto writeToJson(const GamepadConfigs& configs, const std::string& filename) -> bool { // Escribir configuraciones a JSON
try { try {
nlohmann::json j; nlohmann::json j;
j["gamepads"] = nlohmann::json::array(); j["gamepads"] = nlohmann::json::array();
for (const auto& config : configs) { for (const auto& config : configs) {
nlohmann::json gamepad_json; nlohmann::json gamepad_json;
gamepad_json["name"] = config.name; gamepad_json["name"] = config.name;
gamepad_json["path"] = config.path; gamepad_json["path"] = config.path;
gamepad_json["bindings"] = nlohmann::json::object(); gamepad_json["bindings"] = nlohmann::json::object();
// Convertir bindings a JSON // Convertir bindings a JSON
for (const auto& [action, button] : config.bindings) { for (const auto& [action, button] : config.bindings) {
auto action_it = ACTION_TO_STRING.find(action); auto action_it = ACTION_TO_STRING.find(action);
auto button_it = BUTTON_TO_STRING.find(button); auto button_it = BUTTON_TO_STRING.find(button);
if (action_it != ACTION_TO_STRING.end() && button_it != BUTTON_TO_STRING.end()) { if (action_it != ACTION_TO_STRING.end() && button_it != BUTTON_TO_STRING.end()) {
gamepad_json["bindings"][action_it->second] = button_it->second; gamepad_json["bindings"][action_it->second] = button_it->second;
}
} }
j["gamepads"].push_back(gamepad_json);
} }
// Escribir al archivo j["gamepads"].push_back(gamepad_json);
std::ofstream file(filename); }
if (!file.is_open()) {
return false;
}
file << j.dump(4); // Formato con indentación de 4 espacios // Escribir al archivo
file.close(); std::ofstream file(filename);
return true; if (!file.is_open()) {
} catch (const std::exception& e) {
// Log del error si tienes sistema de logging
return false; return false;
} }
file << j.dump(4); // Formato con indentación de 4 espacios
file.close();
return true;
} catch (const std::exception& e) {
// Log del error si tienes sistema de logging
return false;
} }
}
// Leer vector de GamepadConfig desde archivo JSON // Leer vector de GamepadConfig desde archivo JSON
static auto readFromJson(GamepadConfigs& configs, const std::string& filename) -> bool { static auto readFromJson(GamepadConfigs& configs, const std::string& filename) -> bool {
try { try {
std::ifstream file(filename);
if (!file.is_open()) {
return false;
}
nlohmann::json j;
file >> j;
file.close();
configs.clear();
if (!j.contains("gamepads") || !j["gamepads"].is_array()) {
return false;
}
for (const auto& gamepad_json : j["gamepads"]) {
if (!gamepad_json.contains("name") || !gamepad_json.contains("bindings")) {
continue; // Saltar configuraciones malformadas
}
// Leer el campo path si existe, si no dejarlo vacío
std::string path = gamepad_json.contains("path") ? gamepad_json["path"].get<std::string>() : "";
GamepadConfig config(gamepad_json["name"], path);
// Limpiar bindings por defecto para cargar los del archivo
config.bindings.clear();
// Cargar bindings desde JSON
for (const auto& [actionStr, buttonStr] : gamepad_json["bindings"].items()) {
auto action_it = STRING_TO_ACTION.find(actionStr);
auto button_it = STRING_TO_BUTTON.find(buttonStr);
if (action_it != STRING_TO_ACTION.end() && button_it != STRING_TO_BUTTON.end()) {
config.bindings[action_it->second] = button_it->second;
}
}
configs.push_back(config);
}
return true;
} catch (const std::exception& e) {
// Log del error si tienes sistema de logging
return false;
}
}
// Método auxiliar para verificar si un archivo existe
static auto fileExists(const std::string& filename) -> bool {
std::ifstream file(filename); std::ifstream file(filename);
return file.good(); if (!file.is_open()) {
return false;
}
nlohmann::json j;
file >> j;
file.close();
configs.clear();
if (!j.contains("gamepads") || !j["gamepads"].is_array()) {
return false;
}
for (const auto& gamepad_json : j["gamepads"]) {
if (!gamepad_json.contains("name") || !gamepad_json.contains("bindings")) {
continue; // Saltar configuraciones malformadas
}
// Leer el campo path si existe, si no dejarlo vacío
std::string path = gamepad_json.contains("path") ? gamepad_json["path"].get<std::string>() : "";
GamepadConfig config(gamepad_json["name"], path);
// Limpiar bindings por defecto para cargar los del archivo
config.bindings.clear();
// Cargar bindings desde JSON
for (const auto& [actionStr, buttonStr] : gamepad_json["bindings"].items()) {
auto action_it = STRING_TO_ACTION.find(actionStr);
auto button_it = STRING_TO_BUTTON.find(buttonStr);
if (action_it != STRING_TO_ACTION.end() && button_it != STRING_TO_BUTTON.end()) {
config.bindings[action_it->second] = button_it->second;
}
}
configs.push_back(config);
}
return true;
} catch (const std::exception& e) {
// Log del error si tienes sistema de logging
return false;
} }
}
// Método auxiliar para verificar si un archivo existe
static auto fileExists(const std::string& filename) -> bool {
std::ifstream file(filename);
return file.good();
}
}; };
+43 -43
View File
@@ -16,53 +16,53 @@
#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);
if (message.empty()) { if (message.empty()) {
return;
}
// Reemplazo de palabras clave por texto localizado
size_t pos;
while ((pos = message.find(" CONNECTED")) != std::string::npos) {
message.replace(pos, std::string(" CONNECTED").length(), " " + Lang::getText("[NOTIFICATIONS] CONNECTED"));
}
while ((pos = message.find(" DISCONNECTED")) != std::string::npos) {
message.replace(pos, std::string(" DISCONNECTED").length(), " " + Lang::getText("[NOTIFICATIONS] DISCONNECTED"));
}
Options::gamepad_manager.assignAndLinkGamepads();
Options::gamepad_manager.resyncGamepadsWithPlayers();
Notifier::get()->show({message});
ServiceMenu::get()->refresh();
}
// Comprueba los eventos que se pueden producir en cualquier sección del juego
void handle(const SDL_Event& event) {
switch (event.type) {
case SDL_EVENT_QUIT: // Evento de salida de la aplicación
Section::name = Section::Name::QUIT;
Section::options = Section::Options::NONE;
return; return;
}
case SDL_EVENT_RENDER_DEVICE_RESET: // Reemplazo de palabras clave por texto localizado
case SDL_EVENT_RENDER_TARGETS_RESET: size_t pos;
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SDL_RENDER_TARGETS_RESET"); while ((pos = message.find(" CONNECTED")) != std::string::npos) {
break; message.replace(pos, std::string(" CONNECTED").length(), " " + Lang::getText("[NOTIFICATIONS] CONNECTED"));
}
while ((pos = message.find(" DISCONNECTED")) != std::string::npos) {
message.replace(pos, std::string(" DISCONNECTED").length(), " " + Lang::getText("[NOTIFICATIONS] DISCONNECTED"));
}
case SDL_EVENT_WINDOW_RESIZED: Options::gamepad_manager.assignAndLinkGamepads();
Screen::get()->initShaders(); Options::gamepad_manager.resyncGamepadsWithPlayers();
break; Notifier::get()->show({message});
ServiceMenu::get()->refresh();
default:
break;
} }
ServiceMenu::get()->handleEvent(event); // Comprueba los eventos que se pueden producir en cualquier sección del juego
Mouse::handleEvent(event); void handle(const SDL_Event& event) {
handleInputEvents(event); switch (event.type) {
} case SDL_EVENT_QUIT: // Evento de salida de la aplicación
Section::name = Section::Name::QUIT;
Section::options = Section::Options::NONE;
return;
case SDL_EVENT_RENDER_DEVICE_RESET:
case SDL_EVENT_RENDER_TARGETS_RESET:
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SDL_RENDER_TARGETS_RESET");
break;
case SDL_EVENT_WINDOW_RESIZED:
Screen::get()->initShaders();
break;
default:
break;
}
ServiceMenu::get()->handleEvent(event);
Mouse::handleEvent(event);
handleInputEvents(event);
}
} // namespace GlobalEvents } // namespace GlobalEvents
+2 -2
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
+181 -181
View File
@@ -19,202 +19,202 @@
#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
Section::name = Section::Name::QUIT; Section::name = Section::Name::QUIT;
Section::options = Section::Options::NONE; Section::options = Section::Options::NONE;
} else { } else {
// 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
void reset() {
const std::string CODE = "RESET";
if (Notifier::get()->checkCode(CODE)) {
Section::name = Section::Name::RESET;
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 15")});
} else {
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 03"), std::string()}, -1, CODE);
}
}
// Activa o desactiva el audio
void toggleAudio() {
Options::audio.enabled = !Options::audio.enabled;
Audio::get()->enable(Options::audio.enabled);
Notifier::get()->show({"Audio " + boolToOnOff(Options::audio.enabled)});
}
// Cambia el modo de escalado entero
void toggleIntegerScale() {
Screen::get()->toggleIntegerScale();
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 12") + " " + boolToOnOff(Options::video.integer_scale)});
}
// Activa / desactiva el vsync
void toggleVSync() {
Screen::get()->toggleVSync();
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 14") + " " + boolToOnOff(Options::video.vsync)});
}
// Activa o desactiva los shaders
void toggleShaders() {
Screen::get()->toggleShaders();
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 13") + " " + boolToOnOff(Options::video.shaders)});
}
// Cambia al siguiente idioma
void setNextLang() {
const std::string CODE = "LANG";
const auto NEXT_LANG_CODE = Lang::getNextLangCode(Options::settings.language);
const auto NEXT_LANG_NAME = Lang::getLangName(NEXT_LANG_CODE);
if (Notifier::get()->checkCode(CODE)) {
// Si la notificación de cambiar idioma está activa, cambia de de idioma
Options::settings.language = NEXT_LANG_CODE;
Lang::loadFromFile(Lang::getLangFile(NEXT_LANG_CODE));
Section::name = Section::Name::RESET;
Section::options = Section::Options::RELOAD;
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 05") + NEXT_LANG_NAME});
} else {
// 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);
}
}
// Cambia el modo de disparo
void toggleFireMode() {
Options::settings.autofire = !Options::settings.autofire;
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 08") + " " + boolToOnOff(Options::settings.autofire)});
}
// Salta una sección del juego
void skipSection() {
switch (Section::name) {
case Section::Name::INTRO:
Audio::get()->stopMusic();
/* Continua en el case de abajo */
case Section::Name::LOGO:
case Section::Name::HI_SCORE_TABLE:
case Section::Name::INSTRUCTIONS: {
Section::name = Section::Name::TITLE;
Section::options = Section::Options::TITLE_1;
Section::attract_mode = Section::AttractMode::TITLE_TO_DEMO;
break;
} }
default:
break;
}
}
// Activa el menu de servicio
void toggleServiceMenu() {
ServiceMenu::get()->toggle();
}
// Cambia el modo de pantalla completa
void toggleFullscreen() {
Screen::get()->toggleFullscreen();
const std::string MODE = Options::video.fullscreen ? Lang::getText("[NOTIFICATIONS] 11") : Lang::getText("[NOTIFICATIONS] 10");
Notifier::get()->show({MODE});
}
// Reduce el tamaño de la ventana
void decWindowSize() {
if (Screen::get()->decWindowSize()) {
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 09") + " x" + std::to_string(Options::window.zoom)});
}
}
// Aumenta el tamaño de la ventana
void incWindowSize() {
if (Screen::get()->incWindowSize()) {
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 09") + " x" + std::to_string(Options::window.zoom)});
}
}
// Comprueba el boton de servicio
auto checkServiceButton() -> bool {
// Teclado
if (Input::get()->checkAction(Input::Action::SERVICE, Input::DO_NOT_ALLOW_REPEAT, Input::CHECK_KEYBOARD)) {
toggleServiceMenu();
return true;
} }
// Mandos // Reinicia
if (std::ranges::any_of(Input::get()->getGamepads(), [](const auto& gamepad) { void reset() {
return Input::get()->checkAction(Input::Action::SERVICE, Input::DO_NOT_ALLOW_REPEAT, Input::DO_NOT_CHECK_KEYBOARD, gamepad); const std::string CODE = "RESET";
})) { if (Notifier::get()->checkCode(CODE)) {
toggleServiceMenu(); Section::name = Section::Name::RESET;
return true; Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 15")});
} else {
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 03"), std::string()}, -1, CODE);
}
} }
return false; // Activa o desactiva el audio
} void toggleAudio() {
Options::audio.enabled = !Options::audio.enabled;
Audio::get()->enable(Options::audio.enabled);
Notifier::get()->show({"Audio " + boolToOnOff(Options::audio.enabled)});
}
// Comprueba las entradas para elementos del sistema // Cambia el modo de escalado entero
auto checkSystemInputs() -> bool { void toggleIntegerScale() {
using Action = Input::Action; Screen::get()->toggleIntegerScale();
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 12") + " " + boolToOnOff(Options::video.integer_scale)});
}
static const std::vector<std::pair<Action, std::function<void()>>> ACTIONS = { // Activa / desactiva el vsync
{Action::WINDOW_FULLSCREEN, toggleFullscreen}, void toggleVSync() {
{Action::WINDOW_DEC_SIZE, decWindowSize}, Screen::get()->toggleVSync();
{Action::WINDOW_INC_SIZE, incWindowSize}, Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 14") + " " + boolToOnOff(Options::video.vsync)});
{Action::EXIT, quit}, }
{Action::RESET, reset},
{Action::TOGGLE_AUDIO, toggleAudio}, // Activa o desactiva los shaders
{Action::TOGGLE_AUTO_FIRE, toggleFireMode}, void toggleShaders() {
{Action::CHANGE_LANG, setNextLang}, Screen::get()->toggleShaders();
{Action::TOGGLE_VIDEO_SHADERS, toggleShaders}, Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 13") + " " + boolToOnOff(Options::video.shaders)});
{Action::TOGGLE_VIDEO_INTEGER_SCALE, toggleIntegerScale}, }
{Action::TOGGLE_VIDEO_VSYNC, toggleVSync},
// Cambia al siguiente idioma
void setNextLang() {
const std::string CODE = "LANG";
const auto NEXT_LANG_CODE = Lang::getNextLangCode(Options::settings.language);
const auto NEXT_LANG_NAME = Lang::getLangName(NEXT_LANG_CODE);
if (Notifier::get()->checkCode(CODE)) {
// Si la notificación de cambiar idioma está activa, cambia de de idioma
Options::settings.language = NEXT_LANG_CODE;
Lang::loadFromFile(Lang::getLangFile(NEXT_LANG_CODE));
Section::name = Section::Name::RESET;
Section::options = Section::Options::RELOAD;
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 05") + NEXT_LANG_NAME});
} else {
// 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);
}
}
// Cambia el modo de disparo
void toggleFireMode() {
Options::settings.autofire = !Options::settings.autofire;
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 08") + " " + boolToOnOff(Options::settings.autofire)});
}
// Salta una sección del juego
void skipSection() {
switch (Section::name) {
case Section::Name::INTRO:
Audio::get()->stopMusic();
/* Continua en el case de abajo */
case Section::Name::LOGO:
case Section::Name::HI_SCORE_TABLE:
case Section::Name::INSTRUCTIONS: {
Section::name = Section::Name::TITLE;
Section::options = Section::Options::TITLE_1;
Section::attract_mode = Section::AttractMode::TITLE_TO_DEMO;
break;
}
default:
break;
}
}
// Activa el menu de servicio
void toggleServiceMenu() {
ServiceMenu::get()->toggle();
}
// Cambia el modo de pantalla completa
void toggleFullscreen() {
Screen::get()->toggleFullscreen();
const std::string MODE = Options::video.fullscreen ? Lang::getText("[NOTIFICATIONS] 11") : Lang::getText("[NOTIFICATIONS] 10");
Notifier::get()->show({MODE});
}
// Reduce el tamaño de la ventana
void decWindowSize() {
if (Screen::get()->decWindowSize()) {
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 09") + " x" + std::to_string(Options::window.zoom)});
}
}
// Aumenta el tamaño de la ventana
void incWindowSize() {
if (Screen::get()->incWindowSize()) {
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 09") + " x" + std::to_string(Options::window.zoom)});
}
}
// Comprueba el boton de servicio
auto checkServiceButton() -> bool {
// Teclado
if (Input::get()->checkAction(Input::Action::SERVICE, Input::DO_NOT_ALLOW_REPEAT, Input::CHECK_KEYBOARD)) {
toggleServiceMenu();
return true;
}
// Mandos
if (std::ranges::any_of(Input::get()->getGamepads(), [](const auto& gamepad) {
return Input::get()->checkAction(Input::Action::SERVICE, Input::DO_NOT_ALLOW_REPEAT, Input::DO_NOT_CHECK_KEYBOARD, gamepad);
})) {
toggleServiceMenu();
return true;
}
return false;
}
// Comprueba las entradas para elementos del sistema
auto checkSystemInputs() -> bool {
using Action = Input::Action;
static const std::vector<std::pair<Action, std::function<void()>>> ACTIONS = {
{Action::WINDOW_FULLSCREEN, toggleFullscreen},
{Action::WINDOW_DEC_SIZE, decWindowSize},
{Action::WINDOW_INC_SIZE, incWindowSize},
{Action::EXIT, quit},
{Action::RESET, reset},
{Action::TOGGLE_AUDIO, toggleAudio},
{Action::TOGGLE_AUTO_FIRE, toggleFireMode},
{Action::CHANGE_LANG, setNextLang},
{Action::TOGGLE_VIDEO_SHADERS, toggleShaders},
{Action::TOGGLE_VIDEO_INTEGER_SCALE, toggleIntegerScale},
{Action::TOGGLE_VIDEO_VSYNC, toggleVSync},
#ifdef _DEBUG #ifdef _DEBUG
{Action::SHOW_INFO, [] { Screen::get()->toggleDebugInfo(); }}, {Action::SHOW_INFO, [] { Screen::get()->toggleDebugInfo(); }},
#endif #endif
}; };
return std::ranges::any_of(ACTIONS, [](const auto& pair) { return std::ranges::any_of(ACTIONS, [](const auto& pair) {
if (Input::get()->checkAction(pair.first, Input::DO_NOT_ALLOW_REPEAT, Input::CHECK_KEYBOARD)) { if (Input::get()->checkAction(pair.first, Input::DO_NOT_ALLOW_REPEAT, Input::CHECK_KEYBOARD)) {
pair.second(); pair.second();
return true;
}
return false;
});
}
// Comprueba el resto de entradas
auto checkOtherInputs() -> bool {
// Saltar sección
if ((Input::get()->checkAnyButton()) && !ServiceMenu::get()->isEnabled()) {
skipSection();
return true; return true;
} }
return false; return false;
}); }
}
// Comprueba el resto de entradas // Comprueba las entradas del Menu de Servicio
auto checkOtherInputs() -> bool { inline auto checkServiceMenuInputs() -> bool {
// Saltar sección return ServiceMenu::get()->checkInput();
if ((Input::get()->checkAnyButton()) && !ServiceMenu::get()->isEnabled()) {
skipSection();
return true;
} }
return false;
}
// Comprueba las entradas del Menu de Servicio // Comprueba los inputs que se pueden introducir en cualquier sección del juego
inline auto checkServiceMenuInputs() -> bool { auto check() -> bool {
return ServiceMenu::get()->checkInput(); if (checkServiceButton()) {
} return true;
}
// Comprueba los inputs que se pueden introducir en cualquier sección del juego if (checkServiceMenuInputs()) {
auto check() -> bool { return true;
if (checkServiceButton()) { }
return true; if (checkSystemInputs()) {
return true;
}
if (checkOtherInputs()) {
return true;
}
return false;
} }
if (checkServiceMenuInputs()) {
return true;
}
if (checkSystemInputs()) {
return true;
}
if (checkOtherInputs()) {
return true;
}
return false;
}
} // namespace GlobalInputs } // namespace GlobalInputs
+2 -2
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
+171 -171
View File
@@ -14,213 +14,213 @@
// --- Clase Input: gestiona la entrada de teclado y mandos (singleton) --- // --- Clase Input: gestiona la entrada de teclado y mandos (singleton) ---
class Input { class Input {
public: public:
// --- Constantes --- // --- Constantes ---
static constexpr bool ALLOW_REPEAT = true; // Permite repetición static constexpr bool ALLOW_REPEAT = true; // Permite repetición
static constexpr bool DO_NOT_ALLOW_REPEAT = false; // No permite repetición static constexpr bool DO_NOT_ALLOW_REPEAT = false; // No permite repetición
static constexpr bool CHECK_KEYBOARD = true; // Comprueba teclado static constexpr bool CHECK_KEYBOARD = true; // Comprueba teclado
static constexpr bool DO_NOT_CHECK_KEYBOARD = false; // No comprueba teclado static constexpr bool DO_NOT_CHECK_KEYBOARD = false; // No comprueba teclado
static constexpr int TRIGGER_L2_AS_BUTTON = 100; // L2 como botón static constexpr int TRIGGER_L2_AS_BUTTON = 100; // L2 como botón
static constexpr int TRIGGER_R2_AS_BUTTON = 101; // R2 como botón static constexpr int TRIGGER_R2_AS_BUTTON = 101; // R2 como botón
// --- Tipos --- // --- Tipos ---
using Action = InputAction; // Alias para mantener compatibilidad using Action = InputAction; // Alias para mantener compatibilidad
// --- Estructuras --- // --- Estructuras ---
struct KeyState { struct KeyState {
Uint8 scancode; // Scancode asociado Uint8 scancode; // Scancode asociado
bool is_held; // Está pulsada ahora mismo bool is_held; // Está pulsada ahora mismo
bool just_pressed; // Se acaba de pulsar en este fotograma bool just_pressed; // Se acaba de pulsar en este fotograma
KeyState(Uint8 scancode = 0, bool is_held = false, bool just_pressed = false) KeyState(Uint8 scancode = 0, bool is_held = false, bool just_pressed = false)
: scancode(scancode), : scancode(scancode),
is_held(is_held), is_held(is_held),
just_pressed(just_pressed) {} just_pressed(just_pressed) {}
}; };
struct ButtonState { struct ButtonState {
int button; // GameControllerButton asociado int button; // GameControllerButton asociado
bool is_held; // Está pulsada ahora mismo bool is_held; // Está pulsada ahora mismo
bool just_pressed; // Se acaba de pulsar en este fotograma bool just_pressed; // Se acaba de pulsar en este fotograma
bool axis_active; // Estado del eje bool axis_active; // Estado del eje
bool trigger_active{false}; // Estado del trigger como botón digital bool trigger_active{false}; // Estado del trigger como botón digital
ButtonState(int btn = static_cast<int>(SDL_GAMEPAD_BUTTON_INVALID), bool is_held = false, bool just_pressed = false, bool axis_act = false) ButtonState(int btn = static_cast<int>(SDL_GAMEPAD_BUTTON_INVALID), bool is_held = false, bool just_pressed = false, bool axis_act = false)
: button(btn), : button(btn),
is_held(is_held), is_held(is_held),
just_pressed(just_pressed), just_pressed(just_pressed),
axis_active(axis_act) {} axis_active(axis_act) {}
}; };
struct Keyboard { struct Keyboard {
std::unordered_map<Action, KeyState> bindings; std::unordered_map<Action, KeyState> bindings;
Keyboard() Keyboard()
: bindings{ : bindings{
// Movimiento del jugador // Movimiento del jugador
{Action::UP, KeyState(SDL_SCANCODE_UP)}, {Action::UP, KeyState(SDL_SCANCODE_UP)},
{Action::DOWN, KeyState(SDL_SCANCODE_DOWN)}, {Action::DOWN, KeyState(SDL_SCANCODE_DOWN)},
{Action::LEFT, KeyState(SDL_SCANCODE_LEFT)}, {Action::LEFT, KeyState(SDL_SCANCODE_LEFT)},
{Action::RIGHT, KeyState(SDL_SCANCODE_RIGHT)}, {Action::RIGHT, KeyState(SDL_SCANCODE_RIGHT)},
// Disparo del jugador // Disparo del jugador
{Action::FIRE_LEFT, KeyState(SDL_SCANCODE_Q)}, {Action::FIRE_LEFT, KeyState(SDL_SCANCODE_Q)},
{Action::FIRE_CENTER, KeyState(SDL_SCANCODE_W)}, {Action::FIRE_CENTER, KeyState(SDL_SCANCODE_W)},
{Action::FIRE_RIGHT, KeyState(SDL_SCANCODE_E)}, {Action::FIRE_RIGHT, KeyState(SDL_SCANCODE_E)},
// Interfaz // Interfaz
{Action::START, KeyState(SDL_SCANCODE_RETURN)}, {Action::START, KeyState(SDL_SCANCODE_RETURN)},
// Menu de servicio // Menu de servicio
{Action::SERVICE, KeyState(SDL_SCANCODE_F12)}, {Action::SERVICE, KeyState(SDL_SCANCODE_F12)},
{Action::SM_SELECT, KeyState(SDL_SCANCODE_RETURN)}, {Action::SM_SELECT, KeyState(SDL_SCANCODE_RETURN)},
{Action::SM_BACK, KeyState(SDL_SCANCODE_BACKSPACE)}, {Action::SM_BACK, KeyState(SDL_SCANCODE_BACKSPACE)},
// Control del programa // Control del programa
{Action::EXIT, KeyState(SDL_SCANCODE_ESCAPE)}, {Action::EXIT, KeyState(SDL_SCANCODE_ESCAPE)},
{Action::PAUSE, KeyState(SDL_SCANCODE_P)}, {Action::PAUSE, KeyState(SDL_SCANCODE_P)},
{Action::BACK, KeyState(SDL_SCANCODE_BACKSPACE)}, {Action::BACK, KeyState(SDL_SCANCODE_BACKSPACE)},
{Action::WINDOW_DEC_SIZE, KeyState(SDL_SCANCODE_F1)}, {Action::WINDOW_DEC_SIZE, KeyState(SDL_SCANCODE_F1)},
{Action::WINDOW_INC_SIZE, KeyState(SDL_SCANCODE_F2)}, {Action::WINDOW_INC_SIZE, KeyState(SDL_SCANCODE_F2)},
{Action::WINDOW_FULLSCREEN, KeyState(SDL_SCANCODE_F3)}, {Action::WINDOW_FULLSCREEN, KeyState(SDL_SCANCODE_F3)},
{Action::TOGGLE_VIDEO_SHADERS, KeyState(SDL_SCANCODE_F4)}, {Action::TOGGLE_VIDEO_SHADERS, KeyState(SDL_SCANCODE_F4)},
{Action::TOGGLE_VIDEO_INTEGER_SCALE, KeyState(SDL_SCANCODE_F5)}, {Action::TOGGLE_VIDEO_INTEGER_SCALE, KeyState(SDL_SCANCODE_F5)},
{Action::TOGGLE_VIDEO_VSYNC, KeyState(SDL_SCANCODE_F6)}, {Action::TOGGLE_VIDEO_VSYNC, KeyState(SDL_SCANCODE_F6)},
{Action::TOGGLE_AUDIO, KeyState(SDL_SCANCODE_F7)}, {Action::TOGGLE_AUDIO, KeyState(SDL_SCANCODE_F7)},
{Action::TOGGLE_AUTO_FIRE, KeyState(SDL_SCANCODE_F8)}, {Action::TOGGLE_AUTO_FIRE, KeyState(SDL_SCANCODE_F8)},
{Action::CHANGE_LANG, KeyState(SDL_SCANCODE_F9)}, {Action::CHANGE_LANG, KeyState(SDL_SCANCODE_F9)},
{Action::RESET, KeyState(SDL_SCANCODE_F10)}, {Action::RESET, KeyState(SDL_SCANCODE_F10)},
{Action::SHOW_INFO, KeyState(SDL_SCANCODE_F11)}} {} {Action::SHOW_INFO, KeyState(SDL_SCANCODE_F11)}} {}
}; };
struct Gamepad { struct Gamepad {
SDL_Gamepad* pad; SDL_Gamepad* pad;
SDL_JoystickID instance_id; SDL_JoystickID instance_id;
std::string name; std::string name;
std::string path; std::string path;
std::unordered_map<Action, ButtonState> bindings; std::unordered_map<Action, ButtonState> bindings;
Gamepad(SDL_Gamepad* gamepad) Gamepad(SDL_Gamepad* gamepad)
: pad(gamepad), : pad(gamepad),
instance_id(SDL_GetJoystickID(SDL_GetGamepadJoystick(gamepad))), instance_id(SDL_GetJoystickID(SDL_GetGamepadJoystick(gamepad))),
name(std::string(SDL_GetGamepadName(gamepad))), name(std::string(SDL_GetGamepadName(gamepad))),
path(std::string(SDL_GetGamepadPath(pad))), path(std::string(SDL_GetGamepadPath(pad))),
bindings{ bindings{
// Movimiento del jugador // Movimiento del jugador
{Action::UP, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_DPAD_UP))}, {Action::UP, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_DPAD_UP))},
{Action::DOWN, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_DPAD_DOWN))}, {Action::DOWN, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_DPAD_DOWN))},
{Action::LEFT, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_DPAD_LEFT))}, {Action::LEFT, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_DPAD_LEFT))},
{Action::RIGHT, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_DPAD_RIGHT))}, {Action::RIGHT, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_DPAD_RIGHT))},
// Disparo del jugador // Disparo del jugador
{Action::FIRE_LEFT, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_WEST))}, {Action::FIRE_LEFT, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_WEST))},
{Action::FIRE_CENTER, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_NORTH))}, {Action::FIRE_CENTER, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_NORTH))},
{Action::FIRE_RIGHT, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_EAST))}, {Action::FIRE_RIGHT, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_EAST))},
// Interfaz // Interfaz
{Action::START, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_START))}, {Action::START, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_START))},
{Action::SERVICE, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_BACK))}, {Action::SERVICE, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_BACK))},
// Menu de servicio // Menu de servicio
{Action::SM_SELECT, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_WEST))}, {Action::SM_SELECT, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_WEST))},
{Action::SM_BACK, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_NORTH))}} {} {Action::SM_BACK, ButtonState(static_cast<int>(SDL_GAMEPAD_BUTTON_NORTH))}} {}
~Gamepad() { ~Gamepad() {
if (pad != nullptr) { if (pad != nullptr) {
SDL_CloseGamepad(pad); SDL_CloseGamepad(pad);
} }
} }
// Reasigna un botón a una acción // Reasigna un botón a una acción
void rebindAction(Action action, SDL_GamepadButton new_button) { void rebindAction(Action action, SDL_GamepadButton new_button) {
bindings[action] = static_cast<int>(new_button); bindings[action] = static_cast<int>(new_button);
} }
}; };
// --- Tipos --- // --- Tipos ---
using Gamepads = std::vector<std::shared_ptr<Gamepad>>; // Vector de gamepads using Gamepads = std::vector<std::shared_ptr<Gamepad>>; // Vector de gamepads
// --- Métodos de singleton --- // --- Métodos de singleton ---
static void init(const std::string& game_controller_db_path, const std::string& gamepad_configs_file); static void init(const std::string& game_controller_db_path, const std::string& gamepad_configs_file);
static void destroy(); static void destroy();
static auto get() -> Input*; static auto get() -> Input*;
// --- Métodos de configuración de controles --- // --- Métodos de configuración de controles ---
void bindKey(Action action, SDL_Scancode code); void bindKey(Action action, SDL_Scancode code);
static void bindGameControllerButton(const std::shared_ptr<Gamepad>& gamepad, Action action, SDL_GamepadButton button); static void bindGameControllerButton(const std::shared_ptr<Gamepad>& gamepad, Action action, SDL_GamepadButton button);
static void bindGameControllerButton(const std::shared_ptr<Gamepad>& gamepad, Action action_target, Action action_source); static void bindGameControllerButton(const std::shared_ptr<Gamepad>& gamepad, Action action_target, Action action_source);
// --- Métodos de consulta de entrada --- // --- Métodos de consulta de entrada ---
void update(); void update();
auto checkAction(Action action, bool repeat = true, bool check_keyboard = true, const std::shared_ptr<Gamepad>& gamepad = nullptr) -> bool; auto checkAction(Action action, bool repeat = true, bool check_keyboard = true, const std::shared_ptr<Gamepad>& gamepad = nullptr) -> bool;
auto checkAnyInput(bool check_keyboard = true, const std::shared_ptr<Gamepad>& gamepad = nullptr) -> bool; auto checkAnyInput(bool check_keyboard = true, const std::shared_ptr<Gamepad>& gamepad = nullptr) -> bool;
auto checkAnyButton(bool repeat = DO_NOT_ALLOW_REPEAT) -> bool; auto checkAnyButton(bool repeat = DO_NOT_ALLOW_REPEAT) -> bool;
// --- Métodos de gestión de mandos --- // --- Métodos de gestión de mandos ---
[[nodiscard]] auto gameControllerFound() const -> bool; [[nodiscard]] auto gameControllerFound() const -> bool;
static auto getControllerName(const std::shared_ptr<Gamepad>& gamepad) -> std::string; static auto getControllerName(const std::shared_ptr<Gamepad>& gamepad) -> std::string;
auto getControllerNames() const -> std::vector<std::string>; auto getControllerNames() const -> std::vector<std::string>;
[[nodiscard]] auto getNumGamepads() const -> int; [[nodiscard]] auto getNumGamepads() const -> int;
auto getGamepad(SDL_JoystickID id) const -> std::shared_ptr<Gamepad>; auto getGamepad(SDL_JoystickID id) const -> std::shared_ptr<Gamepad>;
auto getGamepadByName(const std::string& name) const -> std::shared_ptr<Input::Gamepad>; auto getGamepadByName(const std::string& name) const -> std::shared_ptr<Input::Gamepad>;
auto getGamepads() const -> const Gamepads& { return gamepads_; } auto getGamepads() const -> const Gamepads& { return gamepads_; }
// --- Métodos de consulta y utilidades --- // --- Métodos de consulta y utilidades ---
[[nodiscard]] static auto getControllerBinding(const std::shared_ptr<Gamepad>& gamepad, Action action) -> SDL_GamepadButton; [[nodiscard]] static auto getControllerBinding(const std::shared_ptr<Gamepad>& gamepad, Action action) -> SDL_GamepadButton;
[[nodiscard]] static auto inputToString(Action action) -> std::string; [[nodiscard]] static auto inputToString(Action action) -> std::string;
[[nodiscard]] static auto stringToInput(const std::string& name) -> Action; [[nodiscard]] static auto stringToInput(const std::string& name) -> Action;
// --- Métodos de reseteo de estado de entrada --- // --- Métodos de reseteo de estado de entrada ---
void resetInputStates(); void resetInputStates();
void resetJustPressed(); void resetJustPressed();
// --- Eventos --- // --- Eventos ---
auto handleEvent(const SDL_Event& event) -> std::string; auto handleEvent(const SDL_Event& event) -> std::string;
void printConnectedGamepads() const; void printConnectedGamepads() const;
auto findAvailableGamepadByName(const std::string& gamepad_name) -> std::shared_ptr<Gamepad>; auto findAvailableGamepadByName(const std::string& gamepad_name) -> std::shared_ptr<Gamepad>;
void saveGamepadConfigFromGamepad(std::shared_ptr<Gamepad> gamepad); void saveGamepadConfigFromGamepad(std::shared_ptr<Gamepad> gamepad);
private: private:
// --- Constantes --- // --- Constantes ---
static constexpr Sint16 AXIS_THRESHOLD = 30000; static constexpr Sint16 AXIS_THRESHOLD = 30000;
static constexpr Sint16 TRIGGER_THRESHOLD = 16384; // Umbral para triggers (aproximadamente 50% del rango) static constexpr Sint16 TRIGGER_THRESHOLD = 16384; // Umbral para triggers (aproximadamente 50% del rango)
static constexpr std::array<Action, 4> BUTTON_INPUTS = {Action::FIRE_LEFT, Action::FIRE_CENTER, Action::FIRE_RIGHT, Action::START}; // Listado de los inputs para jugar que utilizan botones, ni palancas ni crucetas static constexpr std::array<Action, 4> BUTTON_INPUTS = {Action::FIRE_LEFT, Action::FIRE_CENTER, Action::FIRE_RIGHT, Action::START}; // Listado de los inputs para jugar que utilizan botones, ni palancas ni crucetas
// --- Variables internas --- // --- Variables internas ---
Gamepads gamepads_; Gamepads gamepads_;
Keyboard keyboard_; Keyboard keyboard_;
std::string gamepad_mappings_file_; std::string gamepad_mappings_file_;
std::string gamepad_configs_file_; std::string gamepad_configs_file_;
GamepadConfigs gamepad_configs_; GamepadConfigs gamepad_configs_;
// --- Métodos internos --- // --- Métodos internos ---
void initSDLGamePad(); void initSDLGamePad();
static auto checkAxisInput(Action action, const std::shared_ptr<Gamepad>& gamepad, bool repeat) -> bool; static auto checkAxisInput(Action action, const std::shared_ptr<Gamepad>& gamepad, bool repeat) -> bool;
static auto checkTriggerInput(Action action, const std::shared_ptr<Gamepad>& gamepad, bool repeat) -> bool; static auto checkTriggerInput(Action action, const std::shared_ptr<Gamepad>& gamepad, bool repeat) -> bool;
auto addGamepad(int device_index) -> std::string; auto addGamepad(int device_index) -> std::string;
auto removeGamepad(SDL_JoystickID id) -> std::string; auto removeGamepad(SDL_JoystickID id) -> std::string;
void addGamepadMappingsFromFile(); void addGamepadMappingsFromFile();
void discoverGamepads(); void discoverGamepads();
// --- Métodos para integración con GamepadConfigManager --- // --- Métodos para integración con GamepadConfigManager ---
void loadGamepadConfigs(); void loadGamepadConfigs();
void saveGamepadConfigs(); void saveGamepadConfigs();
void applyGamepadConfig(std::shared_ptr<Gamepad> gamepad); void applyGamepadConfig(std::shared_ptr<Gamepad> gamepad);
// Métodos auxiliares opcionales // Métodos auxiliares opcionales
void setGamepadConfigsFile(const std::string& filename); void setGamepadConfigsFile(const std::string& filename);
auto getGamepadConfig(const std::string& gamepad_name) -> GamepadConfig*; auto getGamepadConfig(const std::string& gamepad_name) -> GamepadConfig*;
auto removeGamepadConfig(const std::string& gamepad_name) -> bool; auto removeGamepadConfig(const std::string& gamepad_name) -> bool;
// --- Constructor y destructor --- // --- Constructor y destructor ---
explicit Input(std::string game_controller_db_path, std::string gamepad_configs_file); explicit Input(std::string game_controller_db_path, std::string gamepad_configs_file);
~Input() = default; ~Input() = default;
// --- Singleton --- // --- Singleton ---
static Input* instance; static Input* instance;
}; };
+63 -63
View File
@@ -25,76 +25,76 @@ enum class ItemType : int {
// --- Clase Item: representa un objeto en el juego --- // --- Clase Item: representa un objeto en el juego ---
class Item { class Item {
public: public:
// --- Constantes --- // --- Constantes ---
static constexpr float WIDTH = 20.0F; // Anchura del item static constexpr float WIDTH = 20.0F; // Anchura del item
static constexpr float HEIGHT = 20.0F; // ALtura del item static constexpr float HEIGHT = 20.0F; // ALtura del item
static constexpr int COFFEE_MACHINE_WIDTH = 30; // Anchura de la máquina de café static constexpr int COFFEE_MACHINE_WIDTH = 30; // Anchura de la máquina de café
static constexpr int COFFEE_MACHINE_HEIGHT = 39; // Altura de la máquina de café static constexpr int COFFEE_MACHINE_HEIGHT = 39; // Altura de la máquina de café
static constexpr float LIFETIME_DURATION_S = 10.0F; // Duración de vida del ítem en segundos static constexpr float LIFETIME_DURATION_S = 10.0F; // Duración de vida del ítem en segundos
// Velocidades base (pixels/segundo) - Coffee Machine // Velocidades base (pixels/segundo) - Coffee Machine
static constexpr float COFFEE_MACHINE_VEL_X_FACTOR = 30.0F; // Factor para velocidad X de máquina de café (0.5*60fps) static constexpr float COFFEE_MACHINE_VEL_X_FACTOR = 30.0F; // Factor para velocidad X de máquina de café (0.5*60fps)
static constexpr float COFFEE_MACHINE_VEL_Y = -6.0F; // Velocidad Y inicial de máquina de café (-0.1*60fps) static constexpr float COFFEE_MACHINE_VEL_Y = -6.0F; // Velocidad Y inicial de máquina de café (-0.1*60fps)
static constexpr float COFFEE_MACHINE_ACCEL_Y = 360.0F; // Aceleración Y de máquina de café (0.1*60²fps = 360 pixels/segundo²) static constexpr float COFFEE_MACHINE_ACCEL_Y = 360.0F; // Aceleración Y de máquina de café (0.1*60²fps = 360 pixels/segundo²)
// Velocidades base (pixels/segundo) - Items normales // Velocidades base (pixels/segundo) - Items normales
static constexpr float ITEM_VEL_X_BASE = 60.0F; // Velocidad X base para items (1.0F*60fps) static constexpr float ITEM_VEL_X_BASE = 60.0F; // Velocidad X base para items (1.0F*60fps)
static constexpr float ITEM_VEL_X_STEP = 20.0F; // Incremento de velocidad X (0.33F*60fps) static constexpr float ITEM_VEL_X_STEP = 20.0F; // Incremento de velocidad X (0.33F*60fps)
static constexpr float ITEM_VEL_Y = -240.0F; // Velocidad Y inicial de items (-4.0F*60fps) static constexpr float ITEM_VEL_Y = -240.0F; // Velocidad Y inicial de items (-4.0F*60fps)
static constexpr float ITEM_ACCEL_Y = 720.0F; // Aceleración Y de items (0.2*60²fps = 720 pixels/segundo²) static constexpr float ITEM_ACCEL_Y = 720.0F; // Aceleración Y de items (0.2*60²fps = 720 pixels/segundo²)
// Constantes de física de rebote // Constantes de física de rebote
static constexpr float BOUNCE_VEL_THRESHOLD = 60.0F; // Umbral de velocidad para parar (1.0F*60fps) static constexpr float BOUNCE_VEL_THRESHOLD = 60.0F; // Umbral de velocidad para parar (1.0F*60fps)
static constexpr float COFFEE_BOUNCE_DAMPING = -0.20F; // Factor de rebote Y para máquina de café static constexpr float COFFEE_BOUNCE_DAMPING = -0.20F; // Factor de rebote Y para máquina de café
static constexpr float ITEM_BOUNCE_DAMPING = -0.5F; // Factor de rebote Y para items normales static constexpr float ITEM_BOUNCE_DAMPING = -0.5F; // Factor de rebote Y para items normales
static constexpr float HORIZONTAL_DAMPING = 0.75F; // Factor de amortiguación horizontal static constexpr float HORIZONTAL_DAMPING = 0.75F; // Factor de amortiguación horizontal
// --- Constructor y destructor --- // --- Constructor y destructor ---
Item(ItemType type, float x, float y, SDL_FRect& play_area, const std::shared_ptr<Texture>& texture, const std::vector<std::string>& animation); // Constructor principal Item(ItemType type, float x, float y, SDL_FRect& play_area, const std::shared_ptr<Texture>& texture, const std::vector<std::string>& animation); // Constructor principal
~Item() = default; // Destructor ~Item() = default; // Destructor
// --- Métodos principales --- // --- Métodos principales ---
void alignTo(int x); // Centra el objeto en la posición X indicada void alignTo(int x); // Centra el objeto en la posición X indicada
void render(); // Renderiza el objeto en pantalla void render(); // Renderiza el objeto en pantalla
void disable(); // Desactiva el objeto void disable(); // Desactiva el objeto
void update(float delta_time); // Actualiza la posición, animación y contadores (time-based) void update(float delta_time); // Actualiza la posición, animación y contadores (time-based)
// --- Getters --- // --- Getters ---
[[nodiscard]] auto getPosX() const -> float { return pos_x_; } // Obtiene la posición X [[nodiscard]] auto getPosX() const -> float { return pos_x_; } // Obtiene la posición X
[[nodiscard]] auto getPosY() const -> float { return pos_y_; } // Obtiene la posición Y [[nodiscard]] auto getPosY() const -> float { return pos_y_; } // Obtiene la posición Y
[[nodiscard]] auto getWidth() const -> int { return width_; } // Obtiene la anchura [[nodiscard]] auto getWidth() const -> int { return width_; } // Obtiene la anchura
[[nodiscard]] auto getHeight() const -> int { return height_; } // Obtiene la altura [[nodiscard]] auto getHeight() const -> int { return height_; } // Obtiene la altura
[[nodiscard]] auto getType() const -> ItemType { return type_; } // Obtiene el tipo [[nodiscard]] auto getType() const -> ItemType { return type_; } // Obtiene el tipo
[[nodiscard]] auto isEnabled() const -> bool { return enabled_; } // Verifica si está habilitado [[nodiscard]] auto isEnabled() const -> bool { return enabled_; } // Verifica si está habilitado
[[nodiscard]] auto isOnFloor() const -> bool { return floor_collision_; } // Verifica si está en el suelo [[nodiscard]] auto isOnFloor() const -> bool { return floor_collision_; } // Verifica si está en el suelo
auto getCollider() -> Circle& { return collider_; } // Obtiene el colisionador auto getCollider() -> Circle& { return collider_; } // Obtiene el colisionador
private: private:
// --- Objetos y punteros --- // --- Objetos y punteros ---
std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los gráficos del objeto std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los gráficos del objeto
// --- Variables de estado --- // --- Variables de estado ---
SDL_FRect play_area_; // Rectángulo con la zona de juego SDL_FRect play_area_; // Rectángulo con la zona de juego
Circle collider_; // Círculo de colisión del objeto Circle collider_; // Círculo de colisión del objeto
ItemType type_; // Tipo de objeto ItemType type_; // Tipo de objeto
float pos_x_ = 0.0F; // Posición X del objeto float pos_x_ = 0.0F; // Posición X del objeto
float pos_y_ = 0.0F; // Posición Y del objeto float pos_y_ = 0.0F; // Posición Y del objeto
float vel_x_ = 0.0F; // Velocidad en el eje X float vel_x_ = 0.0F; // Velocidad en el eje X
float vel_y_ = 0.0F; // Velocidad en el eje Y float vel_y_ = 0.0F; // Velocidad en el eje Y
float accel_x_ = 0.0F; // Aceleración en el eje X float accel_x_ = 0.0F; // Aceleración en el eje X
float accel_y_ = 0.0F; // Aceleración en el eje Y float accel_y_ = 0.0F; // Aceleración en el eje Y
float width_ = WIDTH; // Ancho del objeto float width_ = WIDTH; // Ancho del objeto
float height_ = HEIGHT; // Alto del objeto float height_ = HEIGHT; // Alto del objeto
float rotate_speed_ = 0.0F; // Velocidad de rotacion float rotate_speed_ = 0.0F; // Velocidad de rotacion
float lifetime_timer_ = 0.0F; // Acumulador de tiempo de vida del ítem (segundos) float lifetime_timer_ = 0.0F; // Acumulador de tiempo de vida del ítem (segundos)
bool floor_collision_ = false; // Indica si el objeto colisiona con el suelo bool floor_collision_ = false; // Indica si el objeto colisiona con el suelo
bool enabled_ = true; // Indica si el objeto está habilitado bool enabled_ = true; // Indica si el objeto está habilitado
// --- Métodos internos --- // --- Métodos internos ---
void shiftColliders(); // Alinea el círculo de colisión con la posición del objeto void shiftColliders(); // Alinea el círculo de colisión con la posición del objeto
void shiftSprite(); // Coloca el sprite en la posición del objeto void shiftSprite(); // Coloca el sprite en la posición del objeto
void move(float delta_time); // Actualiza la posición y estados del objeto (time-based) void move(float delta_time); // Actualiza la posición y estados del objeto (time-based)
void updateTimeToLive(float delta_time); // Actualiza el contador de tiempo de vida (time-based) void updateTimeToLive(float delta_time); // Actualiza el contador de tiempo de vida (time-based)
static auto getCoffeeMachineSpawn(int player_x, int item_width, int area_width, int margin = 2) -> int; // Calcula la zona de aparición de la máquina de café static auto getCoffeeMachineSpawn(int player_x, int item_width, int area_width, int margin = 2) -> int; // Calcula la zona de aparición de la máquina de café
}; };
+148 -148
View File
@@ -16,189 +16,189 @@
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
auto resource_data = ResourceHelper::loadFile(file_path); auto resource_data = ResourceHelper::loadFile(file_path);
try { try {
json j; json j;
if (!resource_data.empty()) { if (!resource_data.empty()) {
// Cargar desde datos del pack // Cargar desde datos del pack
std::string content(resource_data.begin(), resource_data.end()); std::string content(resource_data.begin(), resource_data.end());
j = json::parse(content); j = json::parse(content);
} else { } else {
// Fallback a filesystem directo // Fallback a filesystem directo
std::ifstream rfile(file_path); std::ifstream rfile(file_path);
if (!rfile.is_open()) { if (!rfile.is_open()) {
return false; return false;
}
rfile >> j;
} }
rfile >> j;
for (const auto& el : j.items()) {
texts[el.key()] = el.value();
}
} catch (const std::exception& e) {
// Puedes loguear el error si quieres
return false;
} }
for (const auto& el : j.items()) { return true;
texts[el.key()] = el.value(); }
// Obtiene el texto por clave
auto getText(const std::string& key) -> std::string {
auto it = texts.find(key);
if (it != texts.end()) {
return it->second;
} }
} catch (const std::exception& e) { return "[missing text: " + key + "]";
// Puedes loguear el error si quieres
return false;
} }
return true; // Obtiene el código del siguiente idioma disponible
} auto getNextLangCode(Code lang) -> Code {
for (size_t i = 0; i < languages.size(); ++i) {
// Obtiene el texto por clave if (languages[i].code == lang) {
auto getText(const std::string& key) -> std::string { return languages[(i + 1) % languages.size()].code;
auto it = texts.find(key); }
if (it != texts.end()) { }
return it->second; // Si no se encuentra, devuelve el primero por defecto
return languages[0].code;
} }
return "[missing text: " + key + "]";
}
// Obtiene el código del siguiente idioma disponible // Obtiene un idioma del vector de idiomas a partir de un código
auto getNextLangCode(Code lang) -> Code { auto getLanguage(Code code) -> Language {
for (size_t i = 0; i < languages.size(); ++i) { for (const auto& lang : languages) {
if (languages[i].code == lang) { if (lang.code == code) {
return languages[(i + 1) % languages.size()].code; return lang;
}
}
// Si no se encuentra, devuelve el primero por defecto
return languages[0];
}
// Devuelve el código de un idioma a partir de un nombre
auto getCodeFromName(const std::string& name) -> Code {
for (const auto& lang : languages) {
if (lang.name == name) {
return lang.code;
}
}
// Si no se encuentra, devuelve el primero por defecto
return languages[0].code;
}
// Devuelve el nombre de un idioma a partir de un código
auto getNameFromCode(Code code) -> std::string {
for (const auto& lang : languages) {
if (lang.code == code) {
return lang.name;
}
}
// Si no se encuentra, devuelve el nombre del primer idioma por defecto
return languages[0].name;
}
// Actualiza los nombres de los idiomas
void updateLanguageNames() {
for (auto& lang : languages) {
switch (lang.code) {
case Code::SPANISH:
lang.name = Lang::getText("[SERVICE_MENU] LANG_ES");
break;
case Code::VALENCIAN:
lang.name = Lang::getText("[SERVICE_MENU] LANG_BA");
break;
case Code::ENGLISH:
lang.name = Lang::getText("[SERVICE_MENU] LANG_EN");
break;
default:
lang.name = "Unknown";
break;
}
} }
} }
// Si no se encuentra, devuelve el primero por defecto
return languages[0].code;
}
// Obtiene un idioma del vector de idiomas a partir de un código // Actualiza los nombres de las dificultades
auto getLanguage(Code code) -> Language { void updateDifficultyNames() {
for (const auto& lang : languages) { // 1. Pide una referencia MODIFICABLE a la lista de dificultades
if (lang.code == code) { auto& difficulties = Difficulty::getDifficulties();
return lang;
// 2. Recorre la lista
for (auto& difficulty_info : difficulties) {
// 3. Para cada dificultad, usa su código para obtener el texto traducido y actualizar su nombre
switch (difficulty_info.code) {
case Difficulty::Code::EASY:
difficulty_info.name = Lang::getText("[SERVICE_MENU] EASY");
break;
case Difficulty::Code::NORMAL:
difficulty_info.name = Lang::getText("[SERVICE_MENU] NORMAL");
break;
case Difficulty::Code::HARD:
difficulty_info.name = Lang::getText("[SERVICE_MENU] HARD");
break;
}
} }
} }
// Si no se encuentra, devuelve el primero por defecto
return languages[0];
}
// Devuelve el código de un idioma a partir de un nombre // Obtiene una fichero a partir de un lang::Code
auto getCodeFromName(const std::string& name) -> Code { auto getLanguageFileName(Lang::Code code) -> std::string {
for (const auto& lang : languages) { for (const auto& lang : languages) {
if (lang.name == name) { if (lang.code == code) {
return lang.code; return Asset::get()->get(lang.file_name);
}
} }
// Si no se encuentra, devuelve el fichero del primer idioma por defecto
return Asset::get()->get(languages[0].file_name);
} }
// Si no se encuentra, devuelve el primero por defecto
return languages[0].code;
}
// Devuelve el nombre de un idioma a partir de un código // Establece el idioma
auto getNameFromCode(Code code) -> std::string { void setLanguage(Code code) {
for (const auto& lang : languages) { Options::settings.language = code;
if (lang.code == code) { loadFromFile(Asset::get()->get(getLanguage(code).file_name));
return lang.name; updateLanguageNames();
} updateDifficultyNames();
} }
// Si no se encuentra, devuelve el nombre del primer idioma por defecto
return languages[0].name;
}
// Actualiza los nombres de los idiomas // Obtiene una fichero a partir de un Code
void updateLanguageNames() { auto getLangFile(Code code) -> std::string {
for (auto& lang : languages) { switch (code) {
switch (lang.code) {
case Code::SPANISH:
lang.name = Lang::getText("[SERVICE_MENU] LANG_ES");
break;
case Code::VALENCIAN: case Code::VALENCIAN:
lang.name = Lang::getText("[SERVICE_MENU] LANG_BA"); return Asset::get()->get("ba_BA.json");
break; break;
case Code::ENGLISH: case Code::SPANISH:
lang.name = Lang::getText("[SERVICE_MENU] LANG_EN"); return Asset::get()->get("es_ES.json");
break; break;
default: default:
lang.name = "Unknown"; return Asset::get()->get("en_UK.json");
break; break;
} }
} }
}
// Actualiza los nombres de las dificultades // Obtiene una cadena a partir de un Code
void updateDifficultyNames() { auto getLangName(Code code) -> std::string {
// 1. Pide una referencia MODIFICABLE a la lista de dificultades switch (code) {
auto& difficulties = Difficulty::getDifficulties(); case Code::VALENCIAN:
return " \"ba_BA\"";
// 2. Recorre la lista
for (auto& difficulty_info : difficulties) {
// 3. Para cada dificultad, usa su código para obtener el texto traducido y actualizar su nombre
switch (difficulty_info.code) {
case Difficulty::Code::EASY:
difficulty_info.name = Lang::getText("[SERVICE_MENU] EASY");
break; break;
case Difficulty::Code::NORMAL: case Code::SPANISH:
difficulty_info.name = Lang::getText("[SERVICE_MENU] NORMAL"); return " \"es_ES\"";
break; break;
case Difficulty::Code::HARD: default:
difficulty_info.name = Lang::getText("[SERVICE_MENU] HARD"); return " \"en_UK\"";
break; break;
} }
} }
}
// Obtiene una fichero a partir de un lang::Code
auto getLanguageFileName(Lang::Code code) -> std::string {
for (const auto& lang : languages) {
if (lang.code == code) {
return Asset::get()->get(lang.file_name);
}
}
// Si no se encuentra, devuelve el fichero del primer idioma por defecto
return Asset::get()->get(languages[0].file_name);
}
// Establece el idioma
void setLanguage(Code code) {
Options::settings.language = code;
loadFromFile(Asset::get()->get(getLanguage(code).file_name));
updateLanguageNames();
updateDifficultyNames();
}
// Obtiene una fichero a partir de un Code
auto getLangFile(Code code) -> std::string {
switch (code) {
case Code::VALENCIAN:
return Asset::get()->get("ba_BA.json");
break;
case Code::SPANISH:
return Asset::get()->get("es_ES.json");
break;
default:
return Asset::get()->get("en_UK.json");
break;
}
}
// Obtiene una cadena a partir de un Code
auto getLangName(Code code) -> std::string {
switch (code) {
case Code::VALENCIAN:
return " \"ba_BA\"";
break;
case Code::SPANISH:
return " \"es_ES\"";
break;
default:
return " \"en_UK\"";
break;
}
}
} // namespace Lang } // namespace Lang
+21 -21
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
+2 -3
View File
@@ -94,7 +94,7 @@ auto ManageHiScoreTable::add(const HiScoreEntry& entry) -> int {
void ManageHiScoreTable::sort() { void ManageHiScoreTable::sort() {
struct struct
{ {
auto operator()(const HiScoreEntry& a, const HiScoreEntry& b) const -> bool { return a.score > b.score; } auto operator()(const HiScoreEntry& a, const HiScoreEntry& b) const -> bool { return a.score > b.score; }
} score_descending_comparator; } score_descending_comparator;
std::ranges::sort(table_, score_descending_comparator); std::ranges::sort(table_, score_descending_comparator);
@@ -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;
+36 -36
View File
@@ -7,15 +7,15 @@
// --- Estructuras --- // --- Estructuras ---
struct HiScoreEntry { struct HiScoreEntry {
std::string name; // Nombre std::string name; // Nombre
int score; // Puntuación int score; // Puntuación
bool one_credit_complete; // Indica si se ha conseguido 1CC bool one_credit_complete; // Indica si se ha conseguido 1CC
// Constructor // Constructor
explicit HiScoreEntry(const std::string& name = "", int score = 0, bool one_credit_complete = false) explicit HiScoreEntry(const std::string& name = "", int score = 0, bool one_credit_complete = false)
: name(name.substr(0, 6)), : name(name.substr(0, 6)),
score(score), score(score),
one_credit_complete(one_credit_complete) {} one_credit_complete(one_credit_complete) {}
}; };
// --- Tipos --- // --- Tipos ---
@@ -23,37 +23,37 @@ using Table = std::vector<HiScoreEntry>; // Tabla de puntuaciones
// --- Clase ManageHiScoreTable --- // --- Clase ManageHiScoreTable ---
class ManageHiScoreTable { class ManageHiScoreTable {
public: public:
// --- Constantes --- // --- Constantes ---
static constexpr int NO_ENTRY = -1; static constexpr int NO_ENTRY = -1;
static constexpr int FILE_VERSION = 1; static constexpr int FILE_VERSION = 1;
static constexpr int MAX_TABLE_SIZE = 100; static constexpr int MAX_TABLE_SIZE = 100;
static constexpr int MAX_NAME_SIZE = 50; static constexpr int MAX_NAME_SIZE = 50;
static constexpr int MAX_SCORE = 999999999; static constexpr int MAX_SCORE = 999999999;
// --- Constructor y destructor --- // --- Constructor y destructor ---
explicit ManageHiScoreTable(Table& table) // Constructor con referencia a tabla explicit ManageHiScoreTable(Table& table) // Constructor con referencia a tabla
: table_(table) {} : table_(table) {}
~ManageHiScoreTable() = default; // Destructor ~ManageHiScoreTable() = default; // Destructor
// --- Métodos públicos --- // --- Métodos públicos ---
void clear(); // Resetea la tabla a los valores por defecto void clear(); // Resetea la tabla a los valores por defecto
auto add(const HiScoreEntry& entry) -> int; // Añade un elemento a la tabla (devuelve la posición en la que se inserta) auto add(const HiScoreEntry& entry) -> int; // Añade un elemento a la tabla (devuelve la posición en la que se inserta)
auto loadFromFile(const std::string& file_path) -> bool; // Carga la tabla con los datos de un fichero auto loadFromFile(const std::string& file_path) -> bool; // Carga la tabla con los datos de un fichero
auto saveToFile(const std::string& file_path) -> bool; // Guarda la tabla en un fichero auto saveToFile(const std::string& file_path) -> bool; // Guarda la tabla en un fichero
private: private:
// --- Variables privadas --- // --- Variables privadas ---
Table& table_; // Referencia a la tabla con los records Table& table_; // Referencia a la tabla con los records
// --- Métodos privados --- // --- Métodos privados ---
void sort(); // Ordena la tabla void sort(); // Ordena la tabla
static auto calculateChecksum(const Table& table) -> unsigned int; // Calcula checksum de la tabla static auto calculateChecksum(const Table& table) -> unsigned int; // Calcula checksum de la tabla
// Métodos auxiliares para loadFromFile // Métodos auxiliares para loadFromFile
static auto validateMagicNumber(SDL_IOStream* file, const std::string& file_path) -> bool; static auto validateMagicNumber(SDL_IOStream* file, const std::string& file_path) -> bool;
static auto validateVersion(SDL_IOStream* file, const std::string& file_path) -> bool; static auto validateVersion(SDL_IOStream* file, const std::string& file_path) -> bool;
static auto readTableSize(SDL_IOStream* file, const std::string& file_path, int& table_size) -> bool; static auto readTableSize(SDL_IOStream* file, const std::string& file_path, int& table_size) -> bool;
static auto readEntry(SDL_IOStream* file, const std::string& file_path, int index, HiScoreEntry& entry) -> bool; static auto readEntry(SDL_IOStream* file, const std::string& file_path, int index, HiScoreEntry& entry) -> bool;
static auto verifyChecksum(SDL_IOStream* file, const std::string& file_path, const Table& temp_table) -> bool; static auto verifyChecksum(SDL_IOStream* file, const std::string& file_path, const Table& temp_table) -> bool;
}; };
+16 -16
View File
@@ -3,25 +3,25 @@
#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) {
SDL_ShowCursor(); SDL_ShowCursor();
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
+7 -7
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
+64 -64
View File
@@ -10,74 +10,74 @@ class Texture;
// --- Clase MovingSprite: añade movimiento y efectos de rotación, zoom y flip al sprite --- // --- Clase MovingSprite: añade movimiento y efectos de rotación, zoom y flip al sprite ---
class MovingSprite : public Sprite { class MovingSprite : public Sprite {
public: public:
// --- Estructuras --- // --- Estructuras ---
struct Rotate { struct Rotate {
bool enabled{false}; // Indica si ha de rotar bool enabled{false}; // Indica si ha de rotar
double angle{0.0}; // Ángulo para dibujarlo double angle{0.0}; // Ángulo para dibujarlo
float amount{0.0F}; // Cantidad de grados a girar en cada iteración float amount{0.0F}; // Cantidad de grados a girar en cada iteración
SDL_FPoint center{.x = 0.0F, .y = 0.0F}; // Centro de rotación SDL_FPoint center{.x = 0.0F, .y = 0.0F}; // Centro de rotación
}; };
// --- Constructores y destructor --- // --- Constructores y destructor ---
MovingSprite(std::shared_ptr<Texture> texture, SDL_FRect pos, MovingSprite::Rotate rotate, float horizontal_zoom, float vertical_zoom, SDL_FlipMode flip); MovingSprite(std::shared_ptr<Texture> texture, SDL_FRect pos, MovingSprite::Rotate rotate, float horizontal_zoom, float vertical_zoom, SDL_FlipMode flip);
MovingSprite(std::shared_ptr<Texture> texture, SDL_FRect pos); MovingSprite(std::shared_ptr<Texture> texture, SDL_FRect pos);
explicit MovingSprite(std::shared_ptr<Texture> texture); explicit MovingSprite(std::shared_ptr<Texture> texture);
~MovingSprite() override = default; ~MovingSprite() override = default;
// --- Métodos principales --- // --- Métodos principales ---
virtual void update(float delta_time); // Actualiza las variables internas del objeto (time-based) virtual void update(float delta_time); // Actualiza las variables internas del objeto (time-based)
void clear() override; // Reinicia todas las variables a cero void clear() override; // Reinicia todas las variables a cero
void stop(); // Elimina el movimiento del sprite void stop(); // Elimina el movimiento del sprite
void render() override; // Muestra el sprite por pantalla void render() override; // Muestra el sprite por pantalla
// --- Configuración --- // --- Configuración ---
void setPos(SDL_FRect rect); // Establece la posición y el tamaño del objeto void setPos(SDL_FRect rect); // Establece la posición y el tamaño del objeto
void setPos(float pos_x, float pos_y); // Establece la posición del objeto void setPos(float pos_x, float pos_y); // Establece la posición del objeto
void setPosX(float pos_x); // Establece la posición X void setPosX(float pos_x); // Establece la posición X
void setPosY(float pos_y); // Establece la posición Y void setPosY(float pos_y); // Establece la posición Y
void setVelX(float value) { vx_ = value; } // Establece la velocidad X void setVelX(float value) { vx_ = value; } // Establece la velocidad X
void setVelY(float value) { vy_ = value; } // Establece la velocidad Y void setVelY(float value) { vy_ = value; } // Establece la velocidad Y
void setAccelX(float value) { ax_ = value; } // Establece la aceleración X void setAccelX(float value) { ax_ = value; } // Establece la aceleración X
void setAccelY(float value) { ay_ = value; } // Establece la aceleración Y void setAccelY(float value) { ay_ = value; } // Establece la aceleración Y
void setHorizontalZoom(float value) { horizontal_zoom_ = value; } // Establece el zoom horizontal void setHorizontalZoom(float value) { horizontal_zoom_ = value; } // Establece el zoom horizontal
void setVerticalZoom(float value) { vertical_zoom_ = value; } // Establece el zoom vertical void setVerticalZoom(float value) { vertical_zoom_ = value; } // Establece el zoom vertical
void setAngle(double value) { rotate_.angle = value; } // Establece el ángulo void setAngle(double value) { rotate_.angle = value; } // Establece el ángulo
void setRotatingCenter(SDL_FPoint point) { rotate_.center = point; } // Establece el centro de rotación void setRotatingCenter(SDL_FPoint point) { rotate_.center = point; } // Establece el centro de rotación
void setRotate(bool enable); // Activa o desactiva el efecto de rotación void setRotate(bool enable); // Activa o desactiva el efecto de rotación
void startRotate(); // Habilita la rotación con centro automático void startRotate(); // Habilita la rotación con centro automático
void stopRotate(float threshold = 0.0F); // Detiene la rotación y resetea ángulo void stopRotate(float threshold = 0.0F); // Detiene la rotación y resetea ángulo
void setRotateAmount(double value) { rotate_.amount = value; } // Establece la velocidad de rotación void setRotateAmount(double value) { rotate_.amount = value; } // Establece la velocidad de rotación
void scaleRotateAmount(float value) { rotate_.amount *= value; } // Modifica la velocidad de rotacion void scaleRotateAmount(float value) { rotate_.amount *= value; } // Modifica la velocidad de rotacion
void switchRotate() { rotate_.amount *= -1; } // Cambia el sentido de la rotación void switchRotate() { rotate_.amount *= -1; } // Cambia el sentido de la rotación
void setFlip(SDL_FlipMode flip) { flip_ = flip; } // Establece el flip void setFlip(SDL_FlipMode flip) { flip_ = flip; } // Establece el flip
void flip() { flip_ = (flip_ == SDL_FLIP_HORIZONTAL) ? SDL_FLIP_NONE : SDL_FLIP_HORIZONTAL; } // Cambia el flip void flip() { flip_ = (flip_ == SDL_FLIP_HORIZONTAL) ? SDL_FLIP_NONE : SDL_FLIP_HORIZONTAL; } // Cambia el flip
// --- Getters --- // --- Getters ---
[[nodiscard]] auto getPosX() const -> float { return x_; } // Obtiene la posición X [[nodiscard]] auto getPosX() const -> float { return x_; } // Obtiene la posición X
[[nodiscard]] auto getPosY() const -> float { return y_; } // Obtiene la posición Y [[nodiscard]] auto getPosY() const -> float { return y_; } // Obtiene la posición Y
[[nodiscard]] auto getVelX() const -> float { return vx_; } // Obtiene la velocidad X [[nodiscard]] auto getVelX() const -> float { return vx_; } // Obtiene la velocidad X
[[nodiscard]] auto getVelY() const -> float { return vy_; } // Obtiene la velocidad Y [[nodiscard]] auto getVelY() const -> float { return vy_; } // Obtiene la velocidad Y
[[nodiscard]] auto getAccelX() const -> float { return ax_; } // Obtiene la aceleración X [[nodiscard]] auto getAccelX() const -> float { return ax_; } // Obtiene la aceleración X
[[nodiscard]] auto getAccelY() const -> float { return ay_; } // Obtiene la aceleración Y [[nodiscard]] auto getAccelY() const -> float { return ay_; } // Obtiene la aceleración Y
[[nodiscard]] auto isRotating() const -> bool { return rotate_.enabled; } // Verifica si está rotando [[nodiscard]] auto isRotating() const -> bool { return rotate_.enabled; } // Verifica si está rotando
auto getFlip() -> SDL_FlipMode { return flip_; } // Obtiene el flip auto getFlip() -> SDL_FlipMode { return flip_; } // Obtiene el flip
protected: protected:
// --- Variables de estado --- // --- Variables de estado ---
Rotate rotate_; // Variables usadas para controlar la rotación del sprite Rotate rotate_; // Variables usadas para controlar la rotación del sprite
SDL_FlipMode flip_; // Indica cómo se voltea el sprite SDL_FlipMode flip_; // Indica cómo se voltea el sprite
float x_ = 0.0F; // Posición en el eje X float x_ = 0.0F; // Posición en el eje X
float y_ = 0.0F; // Posición en el eje Y float y_ = 0.0F; // Posición en el eje Y
float vx_ = 0.0F; // Velocidad en el eje X float vx_ = 0.0F; // Velocidad en el eje X
float vy_ = 0.0F; // Velocidad en el eje Y float vy_ = 0.0F; // Velocidad en el eje Y
float ax_ = 0.0F; // Aceleración en el eje X float ax_ = 0.0F; // Aceleración en el eje X
float ay_ = 0.0F; // Aceleración en el eje Y float ay_ = 0.0F; // Aceleración en el eje Y
float horizontal_zoom_; // Zoom aplicado a la anchura float horizontal_zoom_; // Zoom aplicado a la anchura
float vertical_zoom_; // Zoom aplicado a la altura float vertical_zoom_; // Zoom aplicado a la altura
// --- Métodos internos --- // --- Métodos internos ---
void updateAngle() { rotate_.angle += rotate_.amount; } // Incrementa el valor del ángulo void updateAngle() { rotate_.angle += rotate_.amount; } // Incrementa el valor del ángulo
void move(float delta_time); // Mueve el sprite según velocidad y aceleración (time-based) void move(float delta_time); // Mueve el sprite según velocidad y aceleración (time-based)
void rotate(float delta_time); // Rota el sprite según los parámetros de rotación (time-based) void rotate(float delta_time); // Rota el sprite según los parámetros de rotación (time-based)
}; };
+374 -374
View File
@@ -20,431 +20,431 @@
#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();
// Opciones de control // Opciones de control
gamepad_manager.init(); gamepad_manager.init();
setKeyboardToPlayer(Player::Id::PLAYER1); setKeyboardToPlayer(Player::Id::PLAYER1);
// Opciones de cambios pendientes // Opciones de cambios pendientes
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();
std::ifstream file(settings.config_file); std::ifstream file(settings.config_file);
bool file_exists = file.is_open(); // Guardamos si el fichero existía al abrirlo bool file_exists = file.is_open(); // Guardamos si el fichero existía al abrirlo
// 2. Si el fichero existe, lo leemos para obtener los nombres de los mandos. // 2. Si el fichero existe, lo leemos para obtener los nombres de los mandos.
if (file_exists) { if (file_exists) {
// --- CASO: EL FICHERO EXISTE --- // --- CASO: EL FICHERO EXISTE ---
// SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\nReading file: %s", getFileName(settings.config_file).c_str()); // SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\nReading file: %s", getFileName(settings.config_file).c_str());
Logger::info("Reading file: " + getFileName(settings.config_file)); Logger::info("Reading file: " + getFileName(settings.config_file));
std::string line; std::string line;
std::string param_name; std::string param_name;
std::string param_value; std::string param_value;
while (std::getline(file, line)) { while (std::getline(file, line)) {
// Elimina comentarios // Elimina comentarios
auto comment_pos = line.find('#'); auto comment_pos = line.find('#');
if (comment_pos != std::string::npos) { if (comment_pos != std::string::npos) {
line.resize(comment_pos); line.resize(comment_pos);
} }
// Si la línea contiene '=', lo reemplazamos por un espacio para compatibilidad // Si la línea contiene '=', lo reemplazamos por un espacio para compatibilidad
auto equals_pos = line.find('='); auto equals_pos = line.find('=');
if (equals_pos != std::string::npos) { if (equals_pos != std::string::npos) {
line[equals_pos] = ' '; line[equals_pos] = ' ';
} }
// Usa un stream para separar palabras (elimina automáticamente espacios extra) // Usa un stream para separar palabras (elimina automáticamente espacios extra)
std::istringstream iss(line); std::istringstream iss(line);
if (iss >> param_name >> param_value) { if (iss >> param_name >> param_value) {
if (!set(param_name, param_value)) { if (!set(param_name, param_value)) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Unknown parameter: %s", param_name.c_str()); SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Unknown parameter: %s", param_name.c_str());
}
} }
} }
file.close();
} }
file.close();
}
// 3. Llamamos al asignador inteligente. // 3. Llamamos al asignador inteligente.
gamepad_manager.assignAndLinkGamepads(); gamepad_manager.assignAndLinkGamepads();
// 4. Si el fichero no existía, lo creamos ahora con la configuración por defecto. // 4. Si el fichero no existía, lo creamos ahora con la configuración por defecto.
if (!file_exists) { if (!file_exists) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Config file not found. Creating default settings."); SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Config file not found. Creating default settings.");
saveToFile(); saveToFile();
} }
return true;
}
// Guarda el fichero de configuración
auto saveToFile() -> bool {
std::ofstream file(settings.config_file);
if (!file.good()) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: %s can't be opened", getFileName(settings.config_file).c_str());
return false;
}
// SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Writing file: %s", getFileName(settings.config_file).c_str());
Logger::info("Writing file: " + getFileName(settings.config_file));
applyPendingChanges();
// Versión del archivo
file << "# Coffee Crisis Arcade Edition - Configuration File\n";
file << "# Format: key value\n";
file << "config.version " << settings.config_version << "\n";
// Opciones de ventana
file << "\n# WINDOW\n";
file << "window.zoom " << window.zoom << "\n";
// Opciones de video
file << "\n# VIDEO\n";
file << "# video.scale_mode [" << static_cast<int>(SDL_ScaleMode::SDL_SCALEMODE_NEAREST) << ": nearest, " << static_cast<int>(SDL_ScaleMode::SDL_SCALEMODE_LINEAR) << ": linear]\n";
file << "video.fullscreen " << boolToString(video.fullscreen) << "\n";
file << "video.scale_mode " << static_cast<int>(video.scale_mode) << "\n";
file << "video.vsync " << boolToString(video.vsync) << "\n";
file << "video.integer_scale " << boolToString(video.integer_scale) << "\n";
file << "video.shaders " << boolToString(video.shaders) << "\n";
// Opciones de audio
file << "\n# AUDIO\n";
file << "# volume range: [0 .. 100]\n";
file << "audio.enabled " << boolToString(audio.enabled) << "\n";
file << "audio.volume " << audio.volume << "\n";
file << "audio.music.enabled " << boolToString(audio.music.enabled) << "\n";
file << "audio.music.volume " << audio.music.volume << "\n";
file << "audio.sound.enabled " << boolToString(audio.sound.enabled) << "\n";
file << "audio.sound.volume " << audio.sound.volume << "\n";
// Opciones del juego
file << "\n# GAME\n";
file << "# game.language [0: spanish, 1: valencian, 2: english]\n";
file << "# game.difficulty [" << static_cast<int>(Difficulty::Code::EASY) << ": easy, " << static_cast<int>(Difficulty::Code::NORMAL) << ": normal, " << static_cast<int>(Difficulty::Code::HARD) << ": hard]\n";
file << "game.language " << static_cast<int>(settings.language) << "\n";
file << "game.difficulty " << static_cast<int>(settings.difficulty) << "\n";
file << "game.autofire " << boolToString(settings.autofire) << "\n";
file << "game.shutdown_enabled " << boolToString(settings.shutdown_enabled) << "\n";
file << "game.params_file " << settings.params_file << "\n";
// Opciones de mandos
file << "\n# CONTROLLERS\n";
gamepad_manager.saveToFile(file);
// Opciones de teclado
file << "\n# KEYBOARD\n";
file << "keyboard.player " << static_cast<int>(keyboard.player_id) << "\n";
// Cierra el fichero
file.close();
return true;
}
// Función auxiliar para analizar la configuración del mando y reducir duplicación
void parseAndSetController(const std::string& var, const std::string& value) {
size_t first_dot = var.find('.');
size_t second_dot = var.find('.', first_dot + 1);
if (first_dot == std::string::npos || second_dot == std::string::npos) {
return; // Formato inválido
}
try {
int controller_index = std::stoi(var.substr(first_dot + 1, second_dot - first_dot - 1));
std::string setting_key = var.substr(second_dot + 1);
gamepad_manager.setControllerProperty(controller_index, setting_key, value);
} catch (const std::exception&) {
// Error en parsing
}
}
auto set(const std::string& var, const std::string& value) -> bool {
// Clausula de protección: ignora líneas vacías o comentarios
if (var.empty() || var.starts_with("#")) {
return true; return true;
} }
// Un mapa estático asegura que se inicializa solo una vez // Guarda el fichero de configuración
static const std::map<std::string, std::function<void(const std::string&)>> SETTINGS_MAP = { auto saveToFile() -> bool {
// Configuración std::ofstream file(settings.config_file);
{"config.version", [](const auto& val) { settings.config_version = std::stoi(val); }},
// Ventana
{"window.zoom", [](const auto& val) { window.zoom = std::stoi(val); }},
// Vídeo
{"video.fullscreen", [](const auto& val) { video.fullscreen = stringToBool(val); }},
{"video.scale_mode", [](const auto& val) { video.scale_mode = static_cast<SDL_ScaleMode>(std::stoi(val)); }},
{"video.shaders", [](const auto& val) { video.shaders = stringToBool(val); }},
{"video.integer_scale", [](const auto& val) { video.integer_scale = stringToBool(val); }},
{"video.vsync", [](const auto& val) { video.vsync = stringToBool(val); }},
// Audio
{"audio.enabled", [](const auto& val) { audio.enabled = stringToBool(val); }},
{"audio.volume", [](const auto& val) { audio.volume = std::clamp(std::stoi(val), 0, 100); }},
{"audio.music.enabled", [](const auto& val) { audio.music.enabled = stringToBool(val); }},
{"audio.music.volume", [](const auto& val) { audio.music.volume = std::clamp(std::stoi(val), 0, 100); }},
{"audio.sound.enabled", [](const auto& val) { audio.sound.enabled = stringToBool(val); }},
{"audio.sound.volume", [](const auto& val) { audio.sound.volume = std::clamp(std::stoi(val), 0, 100); }},
// Juego
{"game.language", [](const auto& val) {
settings.language = static_cast<Lang::Code>(std::stoi(val));
if (settings.language != Lang::Code::ENGLISH && if (!file.good()) {
settings.language != Lang::Code::VALENCIAN && SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: %s can't be opened", getFileName(settings.config_file).c_str());
settings.language != Lang::Code::SPANISH) { return false;
settings.language = Lang::Code::ENGLISH; }
}
pending_changes.new_language = settings.language; // SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Writing file: %s", getFileName(settings.config_file).c_str());
}}, Logger::info("Writing file: " + getFileName(settings.config_file));
{"game.difficulty", [](const auto& val) {
settings.difficulty = static_cast<Difficulty::Code>(std::stoi(val)); applyPendingChanges();
pending_changes.new_difficulty = settings.difficulty;
}}, // Versión del archivo
{"game.autofire", [](const auto& val) { settings.autofire = stringToBool(val); }}, file << "# Coffee Crisis Arcade Edition - Configuration File\n";
{"game.shutdown_enabled", [](const auto& val) { settings.shutdown_enabled = stringToBool(val); }}, file << "# Format: key value\n";
{"game.params_file", [](const auto& val) { settings.params_file = val; }}, file << "config.version " << settings.config_version << "\n";
// Teclado
{"keyboard.player", [](const auto& val) { keyboard.player_id = static_cast<Player::Id>(stoi(val)); }}}; // Opciones de ventana
file << "\n# WINDOW\n";
file << "window.zoom " << window.zoom << "\n";
// Opciones de video
file << "\n# VIDEO\n";
file << "# video.scale_mode [" << static_cast<int>(SDL_ScaleMode::SDL_SCALEMODE_NEAREST) << ": nearest, " << static_cast<int>(SDL_ScaleMode::SDL_SCALEMODE_LINEAR) << ": linear]\n";
file << "video.fullscreen " << boolToString(video.fullscreen) << "\n";
file << "video.scale_mode " << static_cast<int>(video.scale_mode) << "\n";
file << "video.vsync " << boolToString(video.vsync) << "\n";
file << "video.integer_scale " << boolToString(video.integer_scale) << "\n";
file << "video.shaders " << boolToString(video.shaders) << "\n";
// Opciones de audio
file << "\n# AUDIO\n";
file << "# volume range: [0 .. 100]\n";
file << "audio.enabled " << boolToString(audio.enabled) << "\n";
file << "audio.volume " << audio.volume << "\n";
file << "audio.music.enabled " << boolToString(audio.music.enabled) << "\n";
file << "audio.music.volume " << audio.music.volume << "\n";
file << "audio.sound.enabled " << boolToString(audio.sound.enabled) << "\n";
file << "audio.sound.volume " << audio.sound.volume << "\n";
// Opciones del juego
file << "\n# GAME\n";
file << "# game.language [0: spanish, 1: valencian, 2: english]\n";
file << "# game.difficulty [" << static_cast<int>(Difficulty::Code::EASY) << ": easy, " << static_cast<int>(Difficulty::Code::NORMAL) << ": normal, " << static_cast<int>(Difficulty::Code::HARD) << ": hard]\n";
file << "game.language " << static_cast<int>(settings.language) << "\n";
file << "game.difficulty " << static_cast<int>(settings.difficulty) << "\n";
file << "game.autofire " << boolToString(settings.autofire) << "\n";
file << "game.shutdown_enabled " << boolToString(settings.shutdown_enabled) << "\n";
file << "game.params_file " << settings.params_file << "\n";
// Opciones de mandos
file << "\n# CONTROLLERS\n";
gamepad_manager.saveToFile(file);
// Opciones de teclado
file << "\n# KEYBOARD\n";
file << "keyboard.player " << static_cast<int>(keyboard.player_id) << "\n";
// Cierra el fichero
file.close();
return true;
}
// Función auxiliar para analizar la configuración del mando y reducir duplicación
void parseAndSetController(const std::string& var, const std::string& value) {
size_t first_dot = var.find('.');
size_t second_dot = var.find('.', first_dot + 1);
if (first_dot == std::string::npos || second_dot == std::string::npos) {
return; // Formato inválido
}
// Maneja por separado la configuración general de los mandos
if (var.starts_with("controller.")) {
try { try {
parseAndSetController(var, value); int controller_index = std::stoi(var.substr(first_dot + 1, second_dot - first_dot - 1));
return true; std::string setting_key = var.substr(second_dot + 1);
} catch (const std::out_of_range& e) {
// Error: por ejemplo, índice de mando fuera de rango gamepad_manager.setControllerProperty(controller_index, setting_key, value);
return false; } catch (const std::exception&) {
} catch (const std::invalid_argument& e) { // Error en parsing
// Error: por ejemplo, fallo en std::stoi
return false;
} }
} }
// Busca el nombre de la variable en el mapa auto set(const std::string& var, const std::string& value) -> bool {
if (auto it = SETTINGS_MAP.find(var); it != SETTINGS_MAP.end()) { // Clausula de protección: ignora líneas vacías o comentarios
if (var.empty() || var.starts_with("#")) {
return true;
}
// Un mapa estático asegura que se inicializa solo una vez
static const std::map<std::string, std::function<void(const std::string&)>> SETTINGS_MAP = {
// Configuración
{"config.version", [](const auto& val) { settings.config_version = std::stoi(val); }},
// Ventana
{"window.zoom", [](const auto& val) { window.zoom = std::stoi(val); }},
// Vídeo
{"video.fullscreen", [](const auto& val) { video.fullscreen = stringToBool(val); }},
{"video.scale_mode", [](const auto& val) { video.scale_mode = static_cast<SDL_ScaleMode>(std::stoi(val)); }},
{"video.shaders", [](const auto& val) { video.shaders = stringToBool(val); }},
{"video.integer_scale", [](const auto& val) { video.integer_scale = stringToBool(val); }},
{"video.vsync", [](const auto& val) { video.vsync = stringToBool(val); }},
// Audio
{"audio.enabled", [](const auto& val) { audio.enabled = stringToBool(val); }},
{"audio.volume", [](const auto& val) { audio.volume = std::clamp(std::stoi(val), 0, 100); }},
{"audio.music.enabled", [](const auto& val) { audio.music.enabled = stringToBool(val); }},
{"audio.music.volume", [](const auto& val) { audio.music.volume = std::clamp(std::stoi(val), 0, 100); }},
{"audio.sound.enabled", [](const auto& val) { audio.sound.enabled = stringToBool(val); }},
{"audio.sound.volume", [](const auto& val) { audio.sound.volume = std::clamp(std::stoi(val), 0, 100); }},
// Juego
{"game.language", [](const auto& val) {
settings.language = static_cast<Lang::Code>(std::stoi(val));
if (settings.language != Lang::Code::ENGLISH &&
settings.language != Lang::Code::VALENCIAN &&
settings.language != Lang::Code::SPANISH) {
settings.language = Lang::Code::ENGLISH;
}
pending_changes.new_language = settings.language;
}},
{"game.difficulty", [](const auto& val) {
settings.difficulty = static_cast<Difficulty::Code>(std::stoi(val));
pending_changes.new_difficulty = settings.difficulty;
}},
{"game.autofire", [](const auto& val) { settings.autofire = stringToBool(val); }},
{"game.shutdown_enabled", [](const auto& val) { settings.shutdown_enabled = stringToBool(val); }},
{"game.params_file", [](const auto& val) { settings.params_file = val; }},
// Teclado
{"keyboard.player", [](const auto& val) { keyboard.player_id = static_cast<Player::Id>(stoi(val)); }}};
// Maneja por separado la configuración general de los mandos
if (var.starts_with("controller.")) {
try {
parseAndSetController(var, value);
return true;
} catch (const std::out_of_range& e) {
// Error: por ejemplo, índice de mando fuera de rango
return false;
} catch (const std::invalid_argument& e) {
// Error: por ejemplo, fallo en std::stoi
return false;
}
}
// Busca el nombre de la variable en el mapa
if (auto it = SETTINGS_MAP.find(var); it != SETTINGS_MAP.end()) {
try {
// Ejecuta la función lambda asociada
it->second(value);
return true;
} catch (const std::invalid_argument& e) {
// Maneja casos donde std::stoi falla por entrada inválida
return false;
}
}
// Si la clave no se encontró en el mapa ni en la lógica de mandos
return false;
}
// Asigna el teclado al jugador
void setKeyboardToPlayer(Player::Id player_id) {
keyboard.player_id = player_id;
}
// Intercambia el teclado de jugador
void swapKeyboard() {
keyboard.player_id = keyboard.player_id == Player::Id::PLAYER1 ? Player::Id::PLAYER2 : Player::Id::PLAYER1;
}
// Intercambia los jugadores asignados a los dos primeros mandos
void swapControllers() {
gamepad_manager.swapPlayers();
}
// Averigua quien está usando el teclado
auto getPlayerWhoUsesKeyboard() -> Player::Id {
return keyboard.player_id;
}
// Aplica los cambios pendientes copiando los valores a sus variables
void applyPendingChanges() {
if (pending_changes.has_pending_changes) {
settings.language = pending_changes.new_language;
settings.difficulty = pending_changes.new_difficulty;
pending_changes.has_pending_changes = false;
}
}
void checkPendingChanges() {
pending_changes.has_pending_changes = settings.language != pending_changes.new_language ||
settings.difficulty != pending_changes.new_difficulty;
}
// Buscar y asignar un mando disponible por nombre
auto assignGamepadByName(const std::string& gamepad_name_to_find, Player::Id player_id) -> bool {
auto found_gamepad = Input::get()->findAvailableGamepadByName(gamepad_name_to_find);
if (found_gamepad) {
return gamepad_manager.assignGamepadToPlayer(player_id, found_gamepad, found_gamepad->name);
}
return false;
}
// Obtener información de un gamepad específico
auto getGamepadInfo(Player::Id player_id) -> std::string {
try { try {
// Ejecuta la función lambda asociada const auto& gamepad = gamepad_manager.getGamepad(player_id);
it->second(value); return "Player " + std::to_string(static_cast<int>(player_id)) +
return true; ": " + (gamepad.name.empty() ? "No gamepad" : gamepad.name);
} catch (const std::invalid_argument& e) { } catch (const std::exception&) {
// Maneja casos donde std::stoi falla por entrada inválida return "Invalid player";
return false;
} }
} }
// Si la clave no se encontró en el mapa ni en la lógica de mandos // Asigna los mandos físicos basándose en la configuración actual.
return false; void GamepadManager::assignAndLinkGamepads() {
} // 1. Obtenemos los mandos físicos conectados.
auto physical_gamepads = Input::get()->getGamepads();
// Asigna el teclado al jugador // 2. Reiniciamos las asignaciones actuales.
void setKeyboardToPlayer(Player::Id player_id) { std::array<std::string, MAX_PLAYERS> desired_paths;
keyboard.player_id = player_id; for (size_t i = 0; i < MAX_PLAYERS; ++i) {
} desired_paths[i] = gamepads_[i].path;
gamepads_[i].instance = nullptr;
// Intercambia el teclado de jugador
void swapKeyboard() {
keyboard.player_id = keyboard.player_id == Player::Id::PLAYER1 ? Player::Id::PLAYER2 : Player::Id::PLAYER1;
}
// Intercambia los jugadores asignados a los dos primeros mandos
void swapControllers() {
gamepad_manager.swapPlayers();
}
// Averigua quien está usando el teclado
auto getPlayerWhoUsesKeyboard() -> Player::Id {
return keyboard.player_id;
}
// Aplica los cambios pendientes copiando los valores a sus variables
void applyPendingChanges() {
if (pending_changes.has_pending_changes) {
settings.language = pending_changes.new_language;
settings.difficulty = pending_changes.new_difficulty;
pending_changes.has_pending_changes = false;
}
}
void checkPendingChanges() {
pending_changes.has_pending_changes = settings.language != pending_changes.new_language ||
settings.difficulty != pending_changes.new_difficulty;
}
// Buscar y asignar un mando disponible por nombre
auto assignGamepadByName(const std::string& gamepad_name_to_find, Player::Id player_id) -> bool {
auto found_gamepad = Input::get()->findAvailableGamepadByName(gamepad_name_to_find);
if (found_gamepad) {
return gamepad_manager.assignGamepadToPlayer(player_id, found_gamepad, found_gamepad->name);
}
return false;
}
// Obtener información de un gamepad específico
auto getGamepadInfo(Player::Id player_id) -> std::string {
try {
const auto& gamepad = gamepad_manager.getGamepad(player_id);
return "Player " + std::to_string(static_cast<int>(player_id)) +
": " + (gamepad.name.empty() ? "No gamepad" : gamepad.name);
} catch (const std::exception&) {
return "Invalid player";
}
}
// Asigna los mandos físicos basándose en la configuración actual.
void GamepadManager::assignAndLinkGamepads() {
// 1. Obtenemos los mandos físicos conectados.
auto physical_gamepads = Input::get()->getGamepads();
// 2. Reiniciamos las asignaciones actuales.
std::array<std::string, MAX_PLAYERS> desired_paths;
for (size_t i = 0; i < MAX_PLAYERS; ++i) {
desired_paths[i] = gamepads_[i].path;
gamepads_[i].instance = nullptr;
}
// 3. Vector para rastrear los mandos ya asignados.
std::vector<std::shared_ptr<Input::Gamepad>> assigned_instances;
// --- Ejecutamos las pasadas de asignación y limpieza ---
// Pasada 1: Intenta asignar por la ruta guardada.
assignGamepadsByPath(desired_paths, physical_gamepads, assigned_instances);
// Pasada 2: Asigna los mandos restantes a los jugadores libres.
assignRemainingGamepads(physical_gamepads, assigned_instances);
// Pasada 3: Limpia los datos de los slots que se quedaron sin mando.
clearUnassignedGamepadSlots();
}
// --- PRIMERA PASADA: Intenta asignar mandos basándose en la ruta guardada ---
void GamepadManager::assignGamepadsByPath(
const std::array<std::string, MAX_PLAYERS>& desired_paths,
const std::vector<std::shared_ptr<Input::Gamepad>>& physical_gamepads,
std::vector<std::shared_ptr<Input::Gamepad>>& assigned_instances) {
for (size_t i = 0; i < MAX_PLAYERS; ++i) {
const std::string& desired_path = desired_paths[i];
if (desired_path.empty()) {
continue; // No hay ruta guardada para este slot.
} }
// Buscamos un mando físico que coincida con la ruta y no esté ya asignado. // 3. Vector para rastrear los mandos ya asignados.
for (const auto& physical_gamepad : physical_gamepads) { std::vector<std::shared_ptr<Input::Gamepad>> assigned_instances;
if (physical_gamepad->path == desired_path && !isGamepadAssigned(physical_gamepad, assigned_instances)) {
// Asignamos y actualizamos TODOS los datos.
gamepads_[i].instance = physical_gamepad;
gamepads_[i].name = physical_gamepad->name; // <--- LA LÍNEA QUE FALTABA
// No es necesario actualizar la path aquí porque ya coincide.
assigned_instances.push_back(physical_gamepad); // --- Ejecutamos las pasadas de asignación y limpieza ---
break; // Mando encontrado para este jugador, pasamos al siguiente. // Pasada 1: Intenta asignar por la ruta guardada.
assignGamepadsByPath(desired_paths, physical_gamepads, assigned_instances);
// Pasada 2: Asigna los mandos restantes a los jugadores libres.
assignRemainingGamepads(physical_gamepads, assigned_instances);
// Pasada 3: Limpia los datos de los slots que se quedaron sin mando.
clearUnassignedGamepadSlots();
}
// --- PRIMERA PASADA: Intenta asignar mandos basándose en la ruta guardada ---
void GamepadManager::assignGamepadsByPath(
const std::array<std::string, MAX_PLAYERS>& desired_paths,
const std::vector<std::shared_ptr<Input::Gamepad>>& physical_gamepads,
std::vector<std::shared_ptr<Input::Gamepad>>& assigned_instances) {
for (size_t i = 0; i < MAX_PLAYERS; ++i) {
const std::string& desired_path = desired_paths[i];
if (desired_path.empty()) {
continue; // No hay ruta guardada para este slot.
}
// Buscamos un mando físico que coincida con la ruta y no esté ya asignado.
for (const auto& physical_gamepad : physical_gamepads) {
if (physical_gamepad->path == desired_path && !isGamepadAssigned(physical_gamepad, assigned_instances)) {
// Asignamos y actualizamos TODOS los datos.
gamepads_[i].instance = physical_gamepad;
gamepads_[i].name = physical_gamepad->name; // <--- LA LÍNEA QUE FALTABA
// No es necesario actualizar la path aquí porque ya coincide.
assigned_instances.push_back(physical_gamepad);
break; // Mando encontrado para este jugador, pasamos al siguiente.
}
} }
} }
} }
}
// --- 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) {
if (gamepads_[i].instance != nullptr) { if (gamepads_[i].instance != nullptr) {
continue; // Este jugador ya tiene un mando. continue; // Este jugador ya tiene un mando.
} }
// Buscamos un mando físico que todavía esté libre. // Buscamos un mando físico que todavía esté libre.
for (const auto& physical_gamepad : physical_gamepads) { for (const auto& physical_gamepad : physical_gamepads) {
if (!isGamepadAssigned(physical_gamepad, assigned_instances)) { if (!isGamepadAssigned(physical_gamepad, assigned_instances)) {
gamepads_[i].instance = physical_gamepad; gamepads_[i].instance = physical_gamepad;
// MUY IMPORTANTE: Actualizamos la configuración para reflejar la realidad. // MUY IMPORTANTE: Actualizamos la configuración para reflejar la realidad.
gamepads_[i].name = physical_gamepad->name; gamepads_[i].name = physical_gamepad->name;
gamepads_[i].path = physical_gamepad->path; gamepads_[i].path = physical_gamepad->path;
assigned_instances.push_back(physical_gamepad); assigned_instances.push_back(physical_gamepad);
break; // Mando encontrado, pasamos al siguiente jugador. break; // Mando encontrado, pasamos al siguiente jugador.
}
} }
} }
} }
}
// --- 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),
// significa que no hay un mando para él. // significa que no hay un mando para él.
if (gamepad_config.instance == nullptr) { if (gamepad_config.instance == nullptr) {
// Limpiamos sus datos de configuración para no mostrar información // Limpiamos sus datos de configuración para no mostrar información
// de un mando que ya no está conectado. // de un mando que ya no está conectado.
gamepad_config.name = Lang::getText("[SERVICE_MENU] NO_CONTROLLER"); gamepad_config.name = Lang::getText("[SERVICE_MENU] NO_CONTROLLER");
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");
case Player::Id::PLAYER2: case Player::Id::PLAYER2:
return Lang::getText("[SERVICE_MENU] PLAYER2"); return Lang::getText("[SERVICE_MENU] PLAYER2");
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;
}
if (name == Lang::getText("[SERVICE_MENU] PLAYER2")) {
return Player::Id::PLAYER2;
}
return Player::Id::NO_PLAYER;
} }
if (name == Lang::getText("[SERVICE_MENU] PLAYER2")) {
return Player::Id::PLAYER2;
}
return Player::Id::NO_PLAYER;
}
} // namespace Options } // namespace Options
+47 -47
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,11 +83,11 @@ 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);
gamepads_[1] = Gamepad(Player::Id::PLAYER2); gamepads_[1] = Gamepad(Player::Id::PLAYER2);
@@ -222,7 +222,7 @@ class GamepadManager {
[[nodiscard]] static auto size() -> size_t { return MAX_PLAYERS; } [[nodiscard]] static auto size() -> size_t { return MAX_PLAYERS; }
private: private:
static constexpr std::string_view UNASSIGNED_TEXT = "---"; static constexpr std::string_view UNASSIGNED_TEXT = "---";
static constexpr size_t MAX_PLAYERS = 2; static constexpr size_t MAX_PLAYERS = 2;
std::array<Gamepad, MAX_PLAYERS> gamepads_; // Punteros a las estructuras de mandos de Options std::array<Gamepad, MAX_PLAYERS> gamepads_; // Punteros a las estructuras de mandos de Options
@@ -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
+176 -176
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,193 +85,193 @@ 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); }},
{"game.height", [](const std::string& v) { param.game.height = std::stoi(v); }}, {"game.height", [](const std::string& v) { param.game.height = std::stoi(v); }},
{"game.play_area.rect.x", [](const std::string& v) { param.game.play_area.rect.x = std::stoi(v); }}, {"game.play_area.rect.x", [](const std::string& v) { param.game.play_area.rect.x = std::stoi(v); }},
{"game.play_area.rect.y", [](const std::string& v) { param.game.play_area.rect.y = std::stoi(v); }}, {"game.play_area.rect.y", [](const std::string& v) { param.game.play_area.rect.y = std::stoi(v); }},
{"game.play_area.rect.w", [](const std::string& v) { param.game.play_area.rect.w = std::stoi(v); }}, {"game.play_area.rect.w", [](const std::string& v) { param.game.play_area.rect.w = std::stoi(v); }},
{"game.play_area.rect.h", [](const std::string& v) { param.game.play_area.rect.h = std::stoi(v); }}, {"game.play_area.rect.h", [](const std::string& v) { param.game.play_area.rect.h = std::stoi(v); }},
{"game.name_entry_idle_time", [](const std::string& v) { param.game.name_entry_idle_time = std::stoi(v); }}, {"game.name_entry_idle_time", [](const std::string& v) { param.game.name_entry_idle_time = std::stoi(v); }},
{"game.name_entry_total_time", [](const std::string& v) { param.game.name_entry_total_time = std::stoi(v); }}, {"game.name_entry_total_time", [](const std::string& v) { param.game.name_entry_total_time = std::stoi(v); }},
{"fade.num_squares_width", [](const std::string& v) { param.fade.num_squares_width = std::stoi(v); }}, {"fade.num_squares_width", [](const std::string& v) { param.fade.num_squares_width = std::stoi(v); }},
{"fade.num_squares_height", [](const std::string& v) { param.fade.num_squares_height = std::stoi(v); }}, {"fade.num_squares_height", [](const std::string& v) { param.fade.num_squares_height = std::stoi(v); }},
{"fade.random_squares_duration_ms", [](const std::string& v) { param.fade.random_squares_duration_ms = std::stoi(v); }}, {"fade.random_squares_duration_ms", [](const std::string& v) { param.fade.random_squares_duration_ms = std::stoi(v); }},
{"fade.post_duration_ms", [](const std::string& v) { param.fade.post_duration_ms = std::stoi(v); }}, {"fade.post_duration_ms", [](const std::string& v) { param.fade.post_duration_ms = std::stoi(v); }},
{"fade.venetian_size", [](const std::string& v) { param.fade.venetian_size = std::stoi(v); }}, {"fade.venetian_size", [](const std::string& v) { param.fade.venetian_size = std::stoi(v); }},
{"scoreboard.rect.x", [](const std::string& v) { param.scoreboard.rect.x = std::stoi(v); }}, {"scoreboard.rect.x", [](const std::string& v) { param.scoreboard.rect.x = std::stoi(v); }},
{"scoreboard.rect.y", [](const std::string& v) { param.scoreboard.rect.y = std::stoi(v); }}, {"scoreboard.rect.y", [](const std::string& v) { param.scoreboard.rect.y = std::stoi(v); }},
{"scoreboard.rect.w", [](const std::string& v) { param.scoreboard.rect.w = std::stoi(v); }}, {"scoreboard.rect.w", [](const std::string& v) { param.scoreboard.rect.w = std::stoi(v); }},
{"scoreboard.rect.h", [](const std::string& v) { param.scoreboard.rect.h = std::stoi(v); }}, {"scoreboard.rect.h", [](const std::string& v) { param.scoreboard.rect.h = std::stoi(v); }},
{"scoreboard.skip_countdown_value", [](const std::string& v) { param.scoreboard.skip_countdown_value = std::stoi(v); }}, {"scoreboard.skip_countdown_value", [](const std::string& v) { param.scoreboard.skip_countdown_value = std::stoi(v); }},
{"title.press_start_position", [](const std::string& v) { param.title.press_start_position = std::stoi(v); }}, {"title.press_start_position", [](const std::string& v) { param.title.press_start_position = std::stoi(v); }},
{"title.arcade_edition_position", [](const std::string& v) { param.title.arcade_edition_position = std::stoi(v); }}, {"title.arcade_edition_position", [](const std::string& v) { param.title.arcade_edition_position = std::stoi(v); }},
{"title.title_c_c_position", [](const std::string& v) { param.title.title_c_c_position = std::stoi(v); }}, {"title.title_c_c_position", [](const std::string& v) { param.title.title_c_c_position = std::stoi(v); }},
{"intro.text_distance_from_bottom", [](const std::string& v) { param.intro.text_distance_from_bottom = std::stoi(v); }}}; {"intro.text_distance_from_bottom", [](const std::string& v) { param.intro.text_distance_from_bottom = std::stoi(v); }}};
static const std::unordered_map<std::string, std::function<void(const std::string&)>> COLOR_PARAMS = { static const std::unordered_map<std::string, std::function<void(const std::string&)>> COLOR_PARAMS = {
{"fade.color", [](const std::string& v) { param.fade.color = Color::fromHex(v); }}, {"fade.color", [](const std::string& v) { param.fade.color = Color::fromHex(v); }},
{"scoreboard.separator_color", [](const std::string& v) { param.scoreboard.separator_color = Color::fromHex(v); }}, {"scoreboard.separator_color", [](const std::string& v) { param.scoreboard.separator_color = Color::fromHex(v); }},
{"scoreboard.easy_color", [](const std::string& v) { param.scoreboard.easy_color = Color::fromHex(v); }}, {"scoreboard.easy_color", [](const std::string& v) { param.scoreboard.easy_color = Color::fromHex(v); }},
{"scoreboard.normal_color", [](const std::string& v) { param.scoreboard.normal_color = Color::fromHex(v); }}, {"scoreboard.normal_color", [](const std::string& v) { param.scoreboard.normal_color = Color::fromHex(v); }},
{"scoreboard.hard_color", [](const std::string& v) { param.scoreboard.hard_color = Color::fromHex(v); }}, {"scoreboard.hard_color", [](const std::string& v) { param.scoreboard.hard_color = Color::fromHex(v); }},
{"scoreboard.text_color1", [](const std::string& v) { param.scoreboard.text_color1 = Color::fromHex(v); }}, {"scoreboard.text_color1", [](const std::string& v) { param.scoreboard.text_color1 = Color::fromHex(v); }},
{"scoreboard.text_color2", [](const std::string& v) { param.scoreboard.text_color2 = Color::fromHex(v); }}, {"scoreboard.text_color2", [](const std::string& v) { param.scoreboard.text_color2 = Color::fromHex(v); }},
{"title.bg_color", [](const std::string& v) { param.title.bg_color = Color::fromHex(v); }}, {"title.bg_color", [](const std::string& v) { param.title.bg_color = Color::fromHex(v); }},
{"background.attenuate_color", [](const std::string& v) { param.background.attenuate_color = Color::fromHex(v); }}, {"background.attenuate_color", [](const std::string& v) { param.background.attenuate_color = Color::fromHex(v); }},
{"notification.color", [](const std::string& v) { param.notification.color = Color::fromHex(v); }}, {"notification.color", [](const std::string& v) { param.notification.color = Color::fromHex(v); }},
{"service_menu.title_color", [](const std::string& v) { param.service_menu.title_color = Color::fromHex(v); }}, {"service_menu.title_color", [](const std::string& v) { param.service_menu.title_color = Color::fromHex(v); }},
{"service_menu.text_color", [](const std::string& v) { param.service_menu.text_color = Color::fromHex(v); }}, {"service_menu.text_color", [](const std::string& v) { param.service_menu.text_color = Color::fromHex(v); }},
{"service_menu.selected_color", [](const std::string& v) { param.service_menu.selected_color = Color::fromHex(v); }}, {"service_menu.selected_color", [](const std::string& v) { param.service_menu.selected_color = Color::fromHex(v); }},
{"service_menu.bg_color", [](const std::string& v) { param.service_menu.bg_color = Color::fromHex(v); }}, {"service_menu.bg_color", [](const std::string& v) { param.service_menu.bg_color = Color::fromHex(v); }},
{"service_menu.window_message.bg_color", [](const std::string& v) { param.service_menu.window_message.bg_color = Color::fromHex(v); }}, {"service_menu.window_message.bg_color", [](const std::string& v) { param.service_menu.window_message.bg_color = Color::fromHex(v); }},
{"service_menu.window_message.border_color", [](const std::string& v) { param.service_menu.window_message.border_color = Color::fromHex(v); }}, {"service_menu.window_message.border_color", [](const std::string& v) { param.service_menu.window_message.border_color = Color::fromHex(v); }},
{"service_menu.window_message.title_color", [](const std::string& v) { param.service_menu.window_message.title_color = Color::fromHex(v); }}, {"service_menu.window_message.title_color", [](const std::string& v) { param.service_menu.window_message.title_color = Color::fromHex(v); }},
{"service_menu.window_message.text_color", [](const std::string& v) { param.service_menu.window_message.text_color = Color::fromHex(v); }}, {"service_menu.window_message.text_color", [](const std::string& v) { param.service_menu.window_message.text_color = Color::fromHex(v); }},
{"intro.bg_color", [](const std::string& v) { param.intro.bg_color = Color::fromHex(v); }}, {"intro.bg_color", [](const std::string& v) { param.intro.bg_color = Color::fromHex(v); }},
{"intro.card_color", [](const std::string& v) { param.intro.card_color = Color::fromHex(v); }}, {"intro.card_color", [](const std::string& v) { param.intro.card_color = Color::fromHex(v); }},
{"intro.shadow_color", [](const std::string& v) { param.intro.shadow_color = Color::fromHex(v); }}, {"intro.shadow_color", [](const std::string& v) { param.intro.shadow_color = Color::fromHex(v); }},
{"debug.color", [](const std::string& v) { param.debug.color = Color::fromHex(v); }}, {"debug.color", [](const std::string& v) { param.debug.color = Color::fromHex(v); }},
{"resource.color", [](const std::string& v) { param.resource.color = Color::fromHex(v); }}, {"resource.color", [](const std::string& v) { param.resource.color = Color::fromHex(v); }},
{"game.item_text_outline_color", [](const std::string& v) { param.game.item_text_outline_color = Color::fromHex(v); }}, {"game.item_text_outline_color", [](const std::string& v) { param.game.item_text_outline_color = Color::fromHex(v); }},
{"player.default_shirt[0].darkest", [](const std::string& v) { param.player.default_shirt[0].darkest = Color::fromHex(v); }}, {"player.default_shirt[0].darkest", [](const std::string& v) { param.player.default_shirt[0].darkest = Color::fromHex(v); }},
{"player.default_shirt[0].dark", [](const std::string& v) { param.player.default_shirt[0].dark = Color::fromHex(v); }}, {"player.default_shirt[0].dark", [](const std::string& v) { param.player.default_shirt[0].dark = Color::fromHex(v); }},
{"player.default_shirt[0].base", [](const std::string& v) { param.player.default_shirt[0].base = Color::fromHex(v); }}, {"player.default_shirt[0].base", [](const std::string& v) { param.player.default_shirt[0].base = Color::fromHex(v); }},
{"player.default_shirt[0].light", [](const std::string& v) { param.player.default_shirt[0].light = Color::fromHex(v); }}, {"player.default_shirt[0].light", [](const std::string& v) { param.player.default_shirt[0].light = Color::fromHex(v); }},
{"player.default_shirt[1].darkest", [](const std::string& v) { param.player.default_shirt[1].darkest = Color::fromHex(v); }}, {"player.default_shirt[1].darkest", [](const std::string& v) { param.player.default_shirt[1].darkest = Color::fromHex(v); }},
{"player.default_shirt[1].dark", [](const std::string& v) { param.player.default_shirt[1].dark = Color::fromHex(v); }}, {"player.default_shirt[1].dark", [](const std::string& v) { param.player.default_shirt[1].dark = Color::fromHex(v); }},
{"player.default_shirt[1].base", [](const std::string& v) { param.player.default_shirt[1].base = Color::fromHex(v); }}, {"player.default_shirt[1].base", [](const std::string& v) { param.player.default_shirt[1].base = Color::fromHex(v); }},
{"player.default_shirt[1].light", [](const std::string& v) { param.player.default_shirt[1].light = Color::fromHex(v); }}, {"player.default_shirt[1].light", [](const std::string& v) { param.player.default_shirt[1].light = Color::fromHex(v); }},
{"player.one_coffee_shirt[0].darkest", [](const std::string& v) { param.player.one_coffee_shirt[0].darkest = Color::fromHex(v); }}, {"player.one_coffee_shirt[0].darkest", [](const std::string& v) { param.player.one_coffee_shirt[0].darkest = Color::fromHex(v); }},
{"player.one_coffee_shirt[0].dark", [](const std::string& v) { param.player.one_coffee_shirt[0].dark = Color::fromHex(v); }}, {"player.one_coffee_shirt[0].dark", [](const std::string& v) { param.player.one_coffee_shirt[0].dark = Color::fromHex(v); }},
{"player.one_coffee_shirt[0].base", [](const std::string& v) { param.player.one_coffee_shirt[0].base = Color::fromHex(v); }}, {"player.one_coffee_shirt[0].base", [](const std::string& v) { param.player.one_coffee_shirt[0].base = Color::fromHex(v); }},
{"player.one_coffee_shirt[0].light", [](const std::string& v) { param.player.one_coffee_shirt[0].light = Color::fromHex(v); }}, {"player.one_coffee_shirt[0].light", [](const std::string& v) { param.player.one_coffee_shirt[0].light = Color::fromHex(v); }},
{"player.one_coffee_shirt[1].darkest", [](const std::string& v) { param.player.one_coffee_shirt[1].darkest = Color::fromHex(v); }}, {"player.one_coffee_shirt[1].darkest", [](const std::string& v) { param.player.one_coffee_shirt[1].darkest = Color::fromHex(v); }},
{"player.one_coffee_shirt[1].dark", [](const std::string& v) { param.player.one_coffee_shirt[1].dark = Color::fromHex(v); }}, {"player.one_coffee_shirt[1].dark", [](const std::string& v) { param.player.one_coffee_shirt[1].dark = Color::fromHex(v); }},
{"player.one_coffee_shirt[1].base", [](const std::string& v) { param.player.one_coffee_shirt[1].base = Color::fromHex(v); }}, {"player.one_coffee_shirt[1].base", [](const std::string& v) { param.player.one_coffee_shirt[1].base = Color::fromHex(v); }},
{"player.one_coffee_shirt[1].light", [](const std::string& v) { param.player.one_coffee_shirt[1].light = Color::fromHex(v); }}, {"player.one_coffee_shirt[1].light", [](const std::string& v) { param.player.one_coffee_shirt[1].light = Color::fromHex(v); }},
{"player.two_coffee_shirt[0].darkest", [](const std::string& v) { param.player.two_coffee_shirt[0].darkest = Color::fromHex(v); }}, {"player.two_coffee_shirt[0].darkest", [](const std::string& v) { param.player.two_coffee_shirt[0].darkest = Color::fromHex(v); }},
{"player.two_coffee_shirt[0].dark", [](const std::string& v) { param.player.two_coffee_shirt[0].dark = Color::fromHex(v); }}, {"player.two_coffee_shirt[0].dark", [](const std::string& v) { param.player.two_coffee_shirt[0].dark = Color::fromHex(v); }},
{"player.two_coffee_shirt[0].base", [](const std::string& v) { param.player.two_coffee_shirt[0].base = Color::fromHex(v); }}, {"player.two_coffee_shirt[0].base", [](const std::string& v) { param.player.two_coffee_shirt[0].base = Color::fromHex(v); }},
{"player.two_coffee_shirt[0].light", [](const std::string& v) { param.player.two_coffee_shirt[0].light = Color::fromHex(v); }}, {"player.two_coffee_shirt[0].light", [](const std::string& v) { param.player.two_coffee_shirt[0].light = Color::fromHex(v); }},
{"player.two_coffee_shirt[1].darkest", [](const std::string& v) { param.player.two_coffee_shirt[1].darkest = Color::fromHex(v); }}, {"player.two_coffee_shirt[1].darkest", [](const std::string& v) { param.player.two_coffee_shirt[1].darkest = Color::fromHex(v); }},
{"player.two_coffee_shirt[1].dark", [](const std::string& v) { param.player.two_coffee_shirt[1].dark = Color::fromHex(v); }}, {"player.two_coffee_shirt[1].dark", [](const std::string& v) { param.player.two_coffee_shirt[1].dark = Color::fromHex(v); }},
{"player.two_coffee_shirt[1].base", [](const std::string& v) { param.player.two_coffee_shirt[1].base = Color::fromHex(v); }}, {"player.two_coffee_shirt[1].base", [](const std::string& v) { param.player.two_coffee_shirt[1].base = Color::fromHex(v); }},
{"player.two_coffee_shirt[1].light", [](const std::string& v) { param.player.two_coffee_shirt[1].light = Color::fromHex(v); }}, {"player.two_coffee_shirt[1].light", [](const std::string& v) { param.player.two_coffee_shirt[1].light = Color::fromHex(v); }},
{"player.outline_color[0]", [](const std::string& v) { param.player.outline_color[0] = Color::fromHex(v); }}, {"player.outline_color[0]", [](const std::string& v) { param.player.outline_color[0] = Color::fromHex(v); }},
{"player.outline_color[1]", [](const std::string& v) { param.player.outline_color[1] = Color::fromHex(v); }}}; {"player.outline_color[1]", [](const std::string& v) { param.player.outline_color[1] = Color::fromHex(v); }}};
static const std::unordered_map<std::string, std::function<void(const std::string&)>> BOOL_PARAMS = { static const std::unordered_map<std::string, std::function<void(const std::string&)>> BOOL_PARAMS = {
{"scoreboard.separator_autocolor", [](const std::string& v) { param.scoreboard.separator_autocolor = stringToBool(v); }}, {"scoreboard.separator_autocolor", [](const std::string& v) { param.scoreboard.separator_autocolor = stringToBool(v); }},
{"scoreboard.text_autocolor", [](const std::string& v) { param.scoreboard.text_autocolor = stringToBool(v); }}, {"scoreboard.text_autocolor", [](const std::string& v) { param.scoreboard.text_autocolor = stringToBool(v); }},
{"balloon.bouncing_sound", [](const std::string& v) { param.balloon.bouncing_sound = stringToBool(v); }}, {"balloon.bouncing_sound", [](const std::string& v) { param.balloon.bouncing_sound = stringToBool(v); }},
{"notification.sound", [](const std::string& v) { param.notification.sound = stringToBool(v); }}, {"notification.sound", [](const std::string& v) { param.notification.sound = stringToBool(v); }},
{"service_menu.drop_shadow", [](const std::string& v) { param.service_menu.drop_shadow = stringToBool(v); }}}; {"service_menu.drop_shadow", [](const std::string& v) { param.service_menu.drop_shadow = stringToBool(v); }}};
static const std::unordered_map<std::string, std::function<void(const std::string&)>> FLOAT_PARAMS = { static const std::unordered_map<std::string, std::function<void(const std::string&)>> FLOAT_PARAMS = {
{"balloon.settings[0].vel", [](const std::string& v) { param.balloon.settings.at(0).vel = std::stof(v); }}, {"balloon.settings[0].vel", [](const std::string& v) { param.balloon.settings.at(0).vel = std::stof(v); }},
{"balloon.settings[0].grav", [](const std::string& v) { param.balloon.settings.at(0).grav = std::stof(v); }}, {"balloon.settings[0].grav", [](const std::string& v) { param.balloon.settings.at(0).grav = std::stof(v); }},
{"balloon.settings[1].vel", [](const std::string& v) { param.balloon.settings.at(1).vel = std::stof(v); }}, {"balloon.settings[1].vel", [](const std::string& v) { param.balloon.settings.at(1).vel = std::stof(v); }},
{"balloon.settings[1].grav", [](const std::string& v) { param.balloon.settings.at(1).grav = std::stof(v); }}, {"balloon.settings[1].grav", [](const std::string& v) { param.balloon.settings.at(1).grav = std::stof(v); }},
{"balloon.settings[2].vel", [](const std::string& v) { param.balloon.settings.at(2).vel = std::stof(v); }}, {"balloon.settings[2].vel", [](const std::string& v) { param.balloon.settings.at(2).vel = std::stof(v); }},
{"balloon.settings[2].grav", [](const std::string& v) { param.balloon.settings.at(2).grav = std::stof(v); }}, {"balloon.settings[2].grav", [](const std::string& v) { param.balloon.settings.at(2).grav = std::stof(v); }},
{"balloon.settings[3].vel", [](const std::string& v) { param.balloon.settings.at(3).vel = std::stof(v); }}, {"balloon.settings[3].vel", [](const std::string& v) { param.balloon.settings.at(3).vel = std::stof(v); }},
{"balloon.settings[3].grav", [](const std::string& v) { param.balloon.settings.at(3).grav = std::stof(v); }}, {"balloon.settings[3].grav", [](const std::string& v) { param.balloon.settings.at(3).grav = std::stof(v); }},
{"tabe.min_spawn_time", [](const std::string& v) { param.tabe.min_spawn_time = std::stof(v); }}, {"tabe.min_spawn_time", [](const std::string& v) { param.tabe.min_spawn_time = std::stof(v); }},
{"tabe.max_spawn_time", [](const std::string& v) { param.tabe.max_spawn_time = std::stof(v); }}, {"tabe.max_spawn_time", [](const std::string& v) { param.tabe.max_spawn_time = std::stof(v); }},
{"title.title_duration", [](const std::string& v) { param.title.title_duration = std::stof(v); }}, {"title.title_duration", [](const std::string& v) { param.title.title_duration = std::stof(v); }},
{"service_menu.window_message.padding", [](const std::string& v) { param.service_menu.window_message.padding = std::stof(v); }}, {"service_menu.window_message.padding", [](const std::string& v) { param.service_menu.window_message.padding = std::stof(v); }},
{"service_menu.window_message.line_spacing", [](const std::string& v) { param.service_menu.window_message.line_spacing = std::stof(v); }}, {"service_menu.window_message.line_spacing", [](const std::string& v) { param.service_menu.window_message.line_spacing = std::stof(v); }},
{"service_menu.window_message.title_separator_spacing", [](const std::string& v) { param.service_menu.window_message.title_separator_spacing = std::stof(v); }}, {"service_menu.window_message.title_separator_spacing", [](const std::string& v) { param.service_menu.window_message.title_separator_spacing = std::stof(v); }},
{"service_menu.window_message.min_width", [](const std::string& v) { param.service_menu.window_message.min_width = std::stof(v); }}, {"service_menu.window_message.min_width", [](const std::string& v) { param.service_menu.window_message.min_width = std::stof(v); }},
{"service_menu.window_message.min_height", [](const std::string& v) { param.service_menu.window_message.min_height = std::stof(v); }}, {"service_menu.window_message.min_height", [](const std::string& v) { param.service_menu.window_message.min_height = std::stof(v); }},
{"service_menu.window_message.max_width_ratio", [](const std::string& v) { param.service_menu.window_message.max_width_ratio = std::stof(v); }}, {"service_menu.window_message.max_width_ratio", [](const std::string& v) { param.service_menu.window_message.max_width_ratio = std::stof(v); }},
{"service_menu.window_message.max_height_ratio", [](const std::string& v) { param.service_menu.window_message.max_height_ratio = std::stof(v); }}, {"service_menu.window_message.max_height_ratio", [](const std::string& v) { param.service_menu.window_message.max_height_ratio = std::stof(v); }},
{"service_menu.window_message.text_safety_margin", [](const std::string& v) { param.service_menu.window_message.text_safety_margin = std::stof(v); }}, {"service_menu.window_message.text_safety_margin", [](const std::string& v) { param.service_menu.window_message.text_safety_margin = std::stof(v); }},
{"service_menu.window_message.animation_duration", [](const std::string& v) { param.service_menu.window_message.animation_duration = std::stof(v); }}}; {"service_menu.window_message.animation_duration", [](const std::string& v) { param.service_menu.window_message.animation_duration = std::stof(v); }}};
static const std::unordered_map<std::string, std::function<void(const std::string&)>> INT_PARAMS_EXTRA = {}; static const std::unordered_map<std::string, std::function<void(const std::string&)>> INT_PARAMS_EXTRA = {};
// Colores válidos para globos // Colores válidos para globos
static const std::unordered_map<std::string, bool> VALID_BALLOON_COLORS = { static const std::unordered_map<std::string, bool> VALID_BALLOON_COLORS = {
{"blue", true}, {"blue", true},
{"orange", true}, {"orange", true},
{"red", true}, {"red", true},
{"green", true}}; {"green", true}};
auto validate_balloon_color = [](const std::string& color) -> bool { auto validate_balloon_color = [](const std::string& color) -> bool {
return VALID_BALLOON_COLORS.find(color) != VALID_BALLOON_COLORS.end(); return VALID_BALLOON_COLORS.find(color) != VALID_BALLOON_COLORS.end();
}; };
static const std::unordered_map<std::string, std::function<void(const std::string&)>> STRING_PARAMS = { static const std::unordered_map<std::string, std::function<void(const std::string&)>> STRING_PARAMS = {
{"balloon.color[0]", [validate_balloon_color](const std::string& v) { {"balloon.color[0]", [validate_balloon_color](const std::string& v) {
if (!validate_balloon_color(v)) { if (!validate_balloon_color(v)) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Color de globo inválido '%s'. Usando 'blue' por defecto.", v.c_str()); SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Color de globo inválido '%s'. Usando 'blue' por defecto.", v.c_str());
param.balloon.color.at(0) = "blue"; param.balloon.color.at(0) = "blue";
} else { } else {
param.balloon.color.at(0) = v; param.balloon.color.at(0) = v;
} }
}}, }},
{"balloon.color[1]", [validate_balloon_color](const std::string& v) { {"balloon.color[1]", [validate_balloon_color](const std::string& v) {
if (!validate_balloon_color(v)) { if (!validate_balloon_color(v)) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Color de globo inválido '%s'. Usando 'orange' por defecto.", v.c_str()); SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Color de globo inválido '%s'. Usando 'orange' por defecto.", v.c_str());
param.balloon.color.at(1) = "orange"; param.balloon.color.at(1) = "orange";
} else { } else {
param.balloon.color.at(1) = v; param.balloon.color.at(1) = v;
} }
}}, }},
{"balloon.color[2]", [validate_balloon_color](const std::string& v) { {"balloon.color[2]", [validate_balloon_color](const std::string& v) {
if (!validate_balloon_color(v)) { if (!validate_balloon_color(v)) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Color de globo inválido '%s'. Usando 'red' por defecto.", v.c_str()); SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Color de globo inválido '%s'. Usando 'red' por defecto.", v.c_str());
param.balloon.color.at(2) = "red"; param.balloon.color.at(2) = "red";
} else { } else {
param.balloon.color.at(2) = v; param.balloon.color.at(2) = v;
} }
}}, }},
{"balloon.color[3]", [validate_balloon_color](const std::string& v) { {"balloon.color[3]", [validate_balloon_color](const std::string& v) {
if (!validate_balloon_color(v)) { if (!validate_balloon_color(v)) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Color de globo inválido '%s'. Usando 'green' por defecto.", v.c_str()); SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Color de globo inválido '%s'. Usando 'green' por defecto.", v.c_str());
param.balloon.color.at(3) = "green"; param.balloon.color.at(3) = "green";
} else { } else {
param.balloon.color.at(3) = v; param.balloon.color.at(3) = v;
} }
}}}; }}};
// Lambda para intentar cada mapa de parámetros // Lambda para intentar cada mapa de parámetros
auto try_map = [&](const auto& param_map) -> bool { auto try_map = [&](const auto& param_map) -> bool {
auto it = param_map.find(var); auto it = param_map.find(var);
if (it != param_map.end()) { if (it != param_map.end()) {
it->second(value); it->second(value);
return true;
}
return false;
};
// Intentar con todos los mapas
if (try_map(INT_PARAMS) || try_map(COLOR_PARAMS) || try_map(BOOL_PARAMS) ||
try_map(FLOAT_PARAMS) || try_map(STRING_PARAMS)) {
return true; return true;
} }
return false;
};
// Intentar con todos los mapas // Casos especiales que necesitan lógica personalizada
if (try_map(INT_PARAMS) || try_map(COLOR_PARAMS) || try_map(BOOL_PARAMS) || if (var == "notification.pos_h") {
try_map(FLOAT_PARAMS) || try_map(STRING_PARAMS)) { if (value == "LEFT") {
return true; param.notification.pos_h = Notifier::Position::LEFT;
} } else if (value == "MIDDLE") {
param.notification.pos_h = Notifier::Position::MIDDLE;
// Casos especiales que necesitan lógica personalizada } else {
if (var == "notification.pos_h") { param.notification.pos_h = Notifier::Position::RIGHT;
if (value == "LEFT") { }
param.notification.pos_h = Notifier::Position::LEFT; return true;
} else if (value == "MIDDLE") {
param.notification.pos_h = Notifier::Position::MIDDLE;
} else {
param.notification.pos_h = Notifier::Position::RIGHT;
} }
return true;
}
if (var == "notification.pos_v") { if (var == "notification.pos_v") {
param.notification.pos_v = value == "TOP" ? Notifier::Position::TOP : Notifier::Position::BOTTOM; param.notification.pos_v = value == "TOP" ? Notifier::Position::TOP : Notifier::Position::BOTTOM;
return true; return true;
} }
return false; // Parámetro no encontrado return false; // Parámetro no encontrado
} }
} // namespace } // namespace
+162 -162
View File
@@ -12,240 +12,240 @@
// --- Parámetros del juego --- // --- Parámetros del juego ---
struct ParamGame { struct ParamGame {
float width = GameDefaults::Game::WIDTH; float width = GameDefaults::Game::WIDTH;
float height = GameDefaults::Game::HEIGHT; float height = GameDefaults::Game::HEIGHT;
Zone play_area{}; // Se inicializa en el constructor de Param Zone play_area{}; // Se inicializa en el constructor de Param
Zone game_area{}; // Se inicializa en el constructor de Param Zone game_area{}; // Se inicializa en el constructor de Param
int name_entry_idle_time = GameDefaults::Game::NAME_ENTRY_IDLE_TIME; int name_entry_idle_time = GameDefaults::Game::NAME_ENTRY_IDLE_TIME;
int name_entry_total_time = GameDefaults::Game::NAME_ENTRY_TOTAL_TIME; int name_entry_total_time = GameDefaults::Game::NAME_ENTRY_TOTAL_TIME;
Color item_text_outline_color; Color item_text_outline_color;
}; };
// --- Parámetros del fade --- // --- Parámetros del fade ---
struct ParamFade { struct ParamFade {
Color color = Color::fromHex(GameDefaults::Fade::COLOR); Color color = Color::fromHex(GameDefaults::Fade::COLOR);
float num_squares_width = GameDefaults::Fade::NUM_SQUARES_WIDTH; float num_squares_width = GameDefaults::Fade::NUM_SQUARES_WIDTH;
float num_squares_height = GameDefaults::Fade::NUM_SQUARES_HEIGHT; float num_squares_height = GameDefaults::Fade::NUM_SQUARES_HEIGHT;
int random_squares_duration_ms = GameDefaults::Fade::RANDOM_SQUARES_DURATION_MS; int random_squares_duration_ms = GameDefaults::Fade::RANDOM_SQUARES_DURATION_MS;
int post_duration_ms = GameDefaults::Fade::POST_DURATION_MS; int post_duration_ms = GameDefaults::Fade::POST_DURATION_MS;
float venetian_size = GameDefaults::Fade::VENETIAN_SIZE; float venetian_size = GameDefaults::Fade::VENETIAN_SIZE;
}; };
// --- Parámetros de la pantalla de título --- // --- Parámetros de la pantalla de título ---
struct ParamTitle { struct ParamTitle {
int press_start_position = GameDefaults::Title::PRESS_START_POSITION; int press_start_position = GameDefaults::Title::PRESS_START_POSITION;
float title_duration = GameDefaults::Title::DURATION_S; float title_duration = GameDefaults::Title::DURATION_S;
int arcade_edition_position = GameDefaults::Title::ARCADE_EDITION_POSITION; int arcade_edition_position = GameDefaults::Title::ARCADE_EDITION_POSITION;
int title_c_c_position = GameDefaults::Title::TITLE_C_C_POSITION; int title_c_c_position = GameDefaults::Title::TITLE_C_C_POSITION;
Color bg_color = Color::fromHex(GameDefaults::Title::BG_COLOR); Color bg_color = Color::fromHex(GameDefaults::Title::BG_COLOR);
}; };
// --- Parámetros del fondo --- // --- Parámetros del fondo ---
struct ParamBackground { struct ParamBackground {
Color attenuate_color = Color::fromHex(GameDefaults::Background::ATTENUATE_COLOR); Color attenuate_color = Color::fromHex(GameDefaults::Background::ATTENUATE_COLOR);
}; };
// --- Parámetros de los globos --- // --- Parámetros de los globos ---
struct ParamBalloon { struct ParamBalloon {
struct Settings { struct Settings {
float grav; float grav;
float vel; float vel;
// Constructor por defecto // Constructor por defecto
constexpr Settings(float grav_val = 0.0F, float vel_val = 0.0F) constexpr Settings(float grav_val = 0.0F, float vel_val = 0.0F)
: grav(grav_val), : grav(grav_val),
vel(vel_val) {} vel(vel_val) {}
}; };
// Inicialización con los valores por defecto desde GameDefaults // Inicialización con los valores por defecto desde GameDefaults
std::array<Settings, 4> settings = {{Settings(GameDefaults::Balloon::SETTINGS[0].grav, GameDefaults::Balloon::SETTINGS[0].vel), std::array<Settings, 4> settings = {{Settings(GameDefaults::Balloon::SETTINGS[0].grav, GameDefaults::Balloon::SETTINGS[0].vel),
Settings(GameDefaults::Balloon::SETTINGS[1].grav, GameDefaults::Balloon::SETTINGS[1].vel), Settings(GameDefaults::Balloon::SETTINGS[1].grav, GameDefaults::Balloon::SETTINGS[1].vel),
Settings(GameDefaults::Balloon::SETTINGS[2].grav, GameDefaults::Balloon::SETTINGS[2].vel), Settings(GameDefaults::Balloon::SETTINGS[2].grav, GameDefaults::Balloon::SETTINGS[2].vel),
Settings(GameDefaults::Balloon::SETTINGS[3].grav, GameDefaults::Balloon::SETTINGS[3].vel)}}; Settings(GameDefaults::Balloon::SETTINGS[3].grav, GameDefaults::Balloon::SETTINGS[3].vel)}};
std::array<std::string, 4> color = {{GameDefaults::Balloon::COLORS[0], std::array<std::string, 4> color = {{GameDefaults::Balloon::COLORS[0],
GameDefaults::Balloon::COLORS[1], GameDefaults::Balloon::COLORS[1],
GameDefaults::Balloon::COLORS[2], GameDefaults::Balloon::COLORS[2],
GameDefaults::Balloon::COLORS[3]}}; GameDefaults::Balloon::COLORS[3]}};
bool bouncing_sound = GameDefaults::Balloon::BOUNCING_SOUND; bool bouncing_sound = GameDefaults::Balloon::BOUNCING_SOUND;
}; };
// --- Parámetros de las notificaciones --- // --- Parámetros de las notificaciones ---
struct ParamNotification { struct ParamNotification {
Notifier::Position pos_h = GameDefaults::Notification::POS_H; Notifier::Position pos_h = GameDefaults::Notification::POS_H;
Notifier::Position pos_v = GameDefaults::Notification::POS_V; Notifier::Position pos_v = GameDefaults::Notification::POS_V;
bool sound = GameDefaults::Notification::SOUND; bool sound = GameDefaults::Notification::SOUND;
Color color = Color::fromHex(GameDefaults::Notification::COLOR); Color color = Color::fromHex(GameDefaults::Notification::COLOR);
}; };
// --- Parámetros del marcador --- // --- Parámetros del marcador ---
struct ParamScoreboard { struct ParamScoreboard {
SDL_FRect rect = { SDL_FRect rect = {
GameDefaults::Scoreboard::RECT_X, GameDefaults::Scoreboard::RECT_X,
GameDefaults::Scoreboard::RECT_Y, GameDefaults::Scoreboard::RECT_Y,
GameDefaults::Scoreboard::RECT_W, GameDefaults::Scoreboard::RECT_W,
GameDefaults::Scoreboard::RECT_H}; GameDefaults::Scoreboard::RECT_H};
bool separator_autocolor = GameDefaults::Scoreboard::SEPARATOR_AUTOCOLOR; bool separator_autocolor = GameDefaults::Scoreboard::SEPARATOR_AUTOCOLOR;
Color separator_color = Color::fromHex(GameDefaults::Scoreboard::SEPARATOR_COLOR); Color separator_color = Color::fromHex(GameDefaults::Scoreboard::SEPARATOR_COLOR);
Color easy_color = Color::fromHex(GameDefaults::Scoreboard::EASY_COLOR); Color easy_color = Color::fromHex(GameDefaults::Scoreboard::EASY_COLOR);
Color normal_color = Color::fromHex(GameDefaults::Scoreboard::NORMAL_COLOR); Color normal_color = Color::fromHex(GameDefaults::Scoreboard::NORMAL_COLOR);
Color hard_color = Color::fromHex(GameDefaults::Scoreboard::HARD_COLOR); Color hard_color = Color::fromHex(GameDefaults::Scoreboard::HARD_COLOR);
bool text_autocolor = GameDefaults::Scoreboard::TEXT_AUTOCOLOR; bool text_autocolor = GameDefaults::Scoreboard::TEXT_AUTOCOLOR;
Color text_color1 = Color::fromHex(GameDefaults::Scoreboard::TEXT_COLOR1); Color text_color1 = Color::fromHex(GameDefaults::Scoreboard::TEXT_COLOR1);
Color text_color2 = Color::fromHex(GameDefaults::Scoreboard::TEXT_COLOR2); Color text_color2 = Color::fromHex(GameDefaults::Scoreboard::TEXT_COLOR2);
int skip_countdown_value = GameDefaults::Scoreboard::SKIP_COUNTDOWN_VALUE; int skip_countdown_value = GameDefaults::Scoreboard::SKIP_COUNTDOWN_VALUE;
}; };
// --- Parámetros del menú de servicio --- // --- Parámetros del menú de servicio ---
struct ParamServiceMenu { struct ParamServiceMenu {
Color title_color = Color::fromHex(GameDefaults::ServiceMenu::TITLE_COLOR); Color title_color = Color::fromHex(GameDefaults::ServiceMenu::TITLE_COLOR);
Color text_color = Color::fromHex(GameDefaults::ServiceMenu::TEXT_COLOR); Color text_color = Color::fromHex(GameDefaults::ServiceMenu::TEXT_COLOR);
Color selected_color = Color::fromHex(GameDefaults::ServiceMenu::SELECTED_COLOR); Color selected_color = Color::fromHex(GameDefaults::ServiceMenu::SELECTED_COLOR);
Color bg_color = Color::fromHex(GameDefaults::ServiceMenu::BG_COLOR); Color bg_color = Color::fromHex(GameDefaults::ServiceMenu::BG_COLOR);
bool drop_shadow = GameDefaults::ServiceMenu::DROP_SHADOW; bool drop_shadow = GameDefaults::ServiceMenu::DROP_SHADOW;
// Configuración para ventanas de mensaje // Configuración para ventanas de mensaje
struct WindowMessage { struct WindowMessage {
Color bg_color = Color::fromHex(GameDefaults::ServiceMenu::WindowMessage::BG_COLOR); Color bg_color = Color::fromHex(GameDefaults::ServiceMenu::WindowMessage::BG_COLOR);
Color border_color = Color::fromHex(GameDefaults::ServiceMenu::WindowMessage::BORDER_COLOR); Color border_color = Color::fromHex(GameDefaults::ServiceMenu::WindowMessage::BORDER_COLOR);
Color title_color = Color::fromHex(GameDefaults::ServiceMenu::WindowMessage::TITLE_COLOR); Color title_color = Color::fromHex(GameDefaults::ServiceMenu::WindowMessage::TITLE_COLOR);
Color text_color = Color::fromHex(GameDefaults::ServiceMenu::WindowMessage::TEXT_COLOR); Color text_color = Color::fromHex(GameDefaults::ServiceMenu::WindowMessage::TEXT_COLOR);
float padding = GameDefaults::ServiceMenu::WindowMessage::PADDING; float padding = GameDefaults::ServiceMenu::WindowMessage::PADDING;
float line_spacing = GameDefaults::ServiceMenu::WindowMessage::LINE_SPACING; float line_spacing = GameDefaults::ServiceMenu::WindowMessage::LINE_SPACING;
float title_separator_spacing = GameDefaults::ServiceMenu::WindowMessage::TITLE_SEPARATOR_SPACING; float title_separator_spacing = GameDefaults::ServiceMenu::WindowMessage::TITLE_SEPARATOR_SPACING;
float min_width = GameDefaults::ServiceMenu::WindowMessage::MIN_WIDTH; float min_width = GameDefaults::ServiceMenu::WindowMessage::MIN_WIDTH;
float min_height = GameDefaults::ServiceMenu::WindowMessage::MIN_HEIGHT; float min_height = GameDefaults::ServiceMenu::WindowMessage::MIN_HEIGHT;
float max_width_ratio = GameDefaults::ServiceMenu::WindowMessage::MAX_WIDTH_RATIO; float max_width_ratio = GameDefaults::ServiceMenu::WindowMessage::MAX_WIDTH_RATIO;
float max_height_ratio = GameDefaults::ServiceMenu::WindowMessage::MAX_HEIGHT_RATIO; float max_height_ratio = GameDefaults::ServiceMenu::WindowMessage::MAX_HEIGHT_RATIO;
float text_safety_margin = GameDefaults::ServiceMenu::WindowMessage::TEXT_SAFETY_MARGIN; float text_safety_margin = GameDefaults::ServiceMenu::WindowMessage::TEXT_SAFETY_MARGIN;
float animation_duration = GameDefaults::ServiceMenu::WindowMessage::ANIMATION_DURATION; float animation_duration = GameDefaults::ServiceMenu::WindowMessage::ANIMATION_DURATION;
} window_message; } window_message;
}; };
// --- Parámetros de la intro --- // --- Parámetros de la intro ---
struct ParamIntro { struct ParamIntro {
Color bg_color = Color::fromHex(GameDefaults::Intro::BG_COLOR); Color bg_color = Color::fromHex(GameDefaults::Intro::BG_COLOR);
Color card_color = Color::fromHex(GameDefaults::Intro::CARD_COLOR); Color card_color = Color::fromHex(GameDefaults::Intro::CARD_COLOR);
Color shadow_color = Color::fromHex(GameDefaults::Intro::SHADOW_COLOR); Color shadow_color = Color::fromHex(GameDefaults::Intro::SHADOW_COLOR);
int text_distance_from_bottom = GameDefaults::Intro::TEXT_DISTANCE_FROM_BOTTOM; int text_distance_from_bottom = GameDefaults::Intro::TEXT_DISTANCE_FROM_BOTTOM;
}; };
// --- Parámetros para Debug --- // --- Parámetros para Debug ---
struct ParamDebug { struct ParamDebug {
Color color = Color::fromHex(GameDefaults::Debug::COLOR); Color color = Color::fromHex(GameDefaults::Debug::COLOR);
}; };
// --- Parámetros para Resource --- // --- Parámetros para Resource ---
struct ParamResource { struct ParamResource {
Color color = Color::fromHex(GameDefaults::Resource::COLOR); Color color = Color::fromHex(GameDefaults::Resource::COLOR);
}; };
// --- Parámetros para Tabe --- // --- Parámetros para Tabe ---
struct ParamTabe { struct ParamTabe {
float min_spawn_time = GameDefaults::Tabe::MIN_SPAWN_TIME; float min_spawn_time = GameDefaults::Tabe::MIN_SPAWN_TIME;
float max_spawn_time = GameDefaults::Tabe::MAX_SPAWN_TIME; float max_spawn_time = GameDefaults::Tabe::MAX_SPAWN_TIME;
}; };
// --- Parámetros del Jugador --- // --- Parámetros del Jugador ---
struct ParamPlayer { struct ParamPlayer {
// Configuración de camisetas del jugador // Configuración de camisetas del jugador
struct Shirt { struct Shirt {
Color darkest; // Tono más oscuro - bordes y contornos Color darkest; // Tono más oscuro - bordes y contornos
Color dark; // Tono oscuro - sombras Color dark; // Tono oscuro - sombras
Color base; // Tono principal - color base de la camiseta Color base; // Tono principal - color base de la camiseta
Color light; // Tono claro - zonas iluminadas/highlights Color light; // Tono claro - zonas iluminadas/highlights
// Constructor por defecto // Constructor por defecto
Shirt() = default; Shirt() = default;
// Constructor con tonalidades específicas // Constructor con tonalidades específicas
Shirt(const Color& darkest_tone, const Color& dark_tone, const Color& base_tone, const Color& light_tone) Shirt(const Color& darkest_tone, const Color& dark_tone, const Color& base_tone, const Color& light_tone)
: darkest(darkest_tone), : darkest(darkest_tone),
dark(dark_tone), dark(dark_tone),
base(base_tone), base(base_tone),
light(light_tone) {} light(light_tone) {}
}; };
// Inicialización con valores por defecto // Inicialización con valores por defecto
const Shirt default_player0_shirt = Shirt( const Shirt default_player0_shirt = Shirt(
Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER0_DARKEST), Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER0_DARKEST),
Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER0_DARK), Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER0_DARK),
Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER0_BASE), Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER0_BASE),
Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER0_LIGHT)); Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER0_LIGHT));
const Shirt default_player1_shirt = Shirt( const Shirt default_player1_shirt = Shirt(
Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER1_DARKEST), Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER1_DARKEST),
Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER1_DARK), Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER1_DARK),
Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER1_BASE), Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER1_BASE),
Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER1_LIGHT)); Color::fromHex(GameDefaults::Player::DefaultShirt::PLAYER1_LIGHT));
std::array<Shirt, 2> default_shirt = {default_player0_shirt, default_player1_shirt}; std::array<Shirt, 2> default_shirt = {default_player0_shirt, default_player1_shirt};
const Shirt one_coffee_player0_shirt = Shirt( const Shirt one_coffee_player0_shirt = Shirt(
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER0_DARKEST), Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER0_DARKEST),
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER0_DARK), Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER0_DARK),
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER0_BASE), Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER0_BASE),
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER0_LIGHT)); Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER0_LIGHT));
const Shirt one_coffee_player1_shirt = Shirt( const Shirt one_coffee_player1_shirt = Shirt(
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER1_DARKEST), Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER1_DARKEST),
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER1_DARK), Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER1_DARK),
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER1_BASE), Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER1_BASE),
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER1_LIGHT)); Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER1_LIGHT));
std::array<Shirt, 2> one_coffee_shirt = {one_coffee_player0_shirt, one_coffee_player1_shirt}; std::array<Shirt, 2> one_coffee_shirt = {one_coffee_player0_shirt, one_coffee_player1_shirt};
const Shirt two_coffee_player0_shirt = Shirt( const Shirt two_coffee_player0_shirt = Shirt(
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER0_DARKEST), Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER0_DARKEST),
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER0_DARK), Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER0_DARK),
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER0_BASE), Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER0_BASE),
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER0_LIGHT)); Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER0_LIGHT));
const Shirt two_coffee_player1_shirt = Shirt( const Shirt two_coffee_player1_shirt = Shirt(
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER1_DARKEST), Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER1_DARKEST),
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER1_DARK), Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER1_DARK),
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER1_BASE), Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER1_BASE),
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER1_LIGHT)); Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER1_LIGHT));
std::array<Shirt, 2> two_coffee_shirt = {two_coffee_player0_shirt, two_coffee_player1_shirt}; std::array<Shirt, 2> two_coffee_shirt = {two_coffee_player0_shirt, two_coffee_player1_shirt};
const Color outline_player0_color = Color::fromHex(GameDefaults::Player::OutlineColor::PLAYER0); const Color outline_player0_color = Color::fromHex(GameDefaults::Player::OutlineColor::PLAYER0);
const Color outline_player1_color = Color::fromHex(GameDefaults::Player::OutlineColor::PLAYER1); const Color outline_player1_color = Color::fromHex(GameDefaults::Player::OutlineColor::PLAYER1);
std::array<Color, 2> outline_color = {outline_player0_color, outline_player1_color}; std::array<Color, 2> outline_color = {outline_player0_color, outline_player1_color};
}; };
// --- Estructura Param: almacena todos los parámetros del juego --- // --- Estructura Param: almacena todos los parámetros del juego ---
struct Param { struct Param {
ParamGame game; ParamGame game;
ParamFade fade; ParamFade fade;
ParamScoreboard scoreboard; ParamScoreboard scoreboard;
ParamTitle title; ParamTitle title;
ParamBackground background; ParamBackground background;
ParamBalloon balloon; ParamBalloon balloon;
ParamNotification notification; ParamNotification notification;
ParamServiceMenu service_menu; ParamServiceMenu service_menu;
ParamIntro intro; ParamIntro intro;
ParamDebug debug; ParamDebug debug;
ParamResource resource; ParamResource resource;
ParamTabe tabe; ParamTabe tabe;
ParamPlayer player; ParamPlayer player;
// Constructor que inicializa las zonas que dependen de otros valores // Constructor que inicializa las zonas que dependen de otros valores
Param() { Param() {
// Inicializar play_area usando los valores por defecto // Inicializar play_area usando los valores por defecto
game.play_area.rect = { game.play_area.rect = {
.x = GameDefaults::Game::PLAY_AREA_X, .x = GameDefaults::Game::PLAY_AREA_X,
.y = GameDefaults::Game::PLAY_AREA_Y, .y = GameDefaults::Game::PLAY_AREA_Y,
.w = GameDefaults::Game::PLAY_AREA_W, .w = GameDefaults::Game::PLAY_AREA_W,
.h = GameDefaults::Game::PLAY_AREA_H}; .h = GameDefaults::Game::PLAY_AREA_H};
// Las zonas calculadas se inicializarán en precalculateZones() // Las zonas calculadas se inicializarán en precalculateZones()
precalculateZones(); precalculateZones();
} }
// Función pública para recalcular zonas (necesaria después de cambiar parámetros) // Función pública para recalcular zonas (necesaria después de cambiar parámetros)
void precalculateZones(); void precalculateZones();
}; };
// --- Variables --- // --- Variables ---
+57 -57
View File
@@ -24,36 +24,36 @@ enum class PathCentered { // Centrado del recorrido
}; };
// --- Estructuras --- // --- Estructuras ---
struct Path { // Define un recorrido para el sprite struct Path { // Define un recorrido para el sprite
float start_pos; // Posición inicial float start_pos; // Posición inicial
float end_pos; // Posición final float end_pos; // Posición final
PathType type; // Tipo de movimiento (horizontal/vertical) PathType type; // Tipo de movimiento (horizontal/vertical)
float fixed_pos; // Posición fija en el eje contrario float fixed_pos; // Posición fija en el eje contrario
float duration_s; // Duración de la animación en segundos float duration_s; // Duración de la animación en segundos
float waiting_time_s; // Tiempo de espera una vez en el destino float waiting_time_s; // Tiempo de espera una vez en el destino
std::function<double(double)> easing_function; // Función de easing std::function<double(double)> easing_function; // Función de easing
float elapsed_time = 0.0F; // Tiempo transcurrido float elapsed_time = 0.0F; // Tiempo transcurrido
float waiting_elapsed = 0.0F; // Tiempo de espera transcurrido float waiting_elapsed = 0.0F; // Tiempo de espera transcurrido
bool on_destination = false; // Indica si ha llegado al destino bool on_destination = false; // Indica si ha llegado al destino
bool finished = false; // Indica si ha terminado de esperarse bool finished = false; // Indica si ha terminado de esperarse
// Constructor para paths generados // Constructor para paths generados
Path(float start, float end, PathType path_type, float fixed, float duration, float waiting, std::function<double(double)> easing) Path(float start, float end, PathType path_type, float fixed, float duration, float waiting, std::function<double(double)> easing)
: start_pos(start), : start_pos(start),
end_pos(end), end_pos(end),
type(path_type), type(path_type),
fixed_pos(fixed), fixed_pos(fixed),
duration_s(duration), duration_s(duration),
waiting_time_s(waiting), waiting_time_s(waiting),
easing_function(std::move(easing)) {} easing_function(std::move(easing)) {}
// Constructor para paths por puntos (convertido a segundos) // Constructor para paths por puntos (convertido a segundos)
Path(const std::vector<SDL_FPoint>& spots_init, float waiting_time_s_init); Path(const std::vector<SDL_FPoint>& spots_init, float waiting_time_s_init);
// Variables para paths por puntos // Variables para paths por puntos
std::vector<SDL_FPoint> spots; // Solo para paths por puntos std::vector<SDL_FPoint> spots; // Solo para paths por puntos
int counter = 0; // Solo para paths por puntos int counter = 0; // Solo para paths por puntos
bool is_point_path = false; // Indica si es un path por puntos bool is_point_path = false; // Indica si es un path por puntos
}; };
// --- Funciones --- // --- Funciones ---
@@ -61,41 +61,41 @@ auto createPath(float start, float end, PathType type, float fixed_pos, int step
// --- Clase PathSprite: Sprite que sigue uno o varios recorridos --- // --- Clase PathSprite: Sprite que sigue uno o varios recorridos ---
class PathSprite : public Sprite { class PathSprite : public Sprite {
public: public:
// --- Constructor y destructor --- // --- Constructor y destructor ---
explicit PathSprite(std::shared_ptr<Texture> texture) explicit PathSprite(std::shared_ptr<Texture> texture)
: Sprite(std::move(texture)) {} : Sprite(std::move(texture)) {}
~PathSprite() override = default; ~PathSprite() override = default;
// --- Métodos principales --- // --- Métodos principales ---
void update(float delta_time); // Actualiza la posición del sprite según el recorrido (delta_time en segundos) void update(float delta_time); // Actualiza la posición del sprite según el recorrido (delta_time en segundos)
void render() override; // Muestra el sprite por pantalla void render() override; // Muestra el sprite por pantalla
// --- Gestión de recorridos --- // --- Gestión de recorridos ---
void addPath(Path path, bool centered = false); // Añade un recorrido (Path) void addPath(Path path, bool centered = false); // Añade un recorrido (Path)
void addPath(const std::vector<SDL_FPoint>& spots, float waiting_time_s = 0.0F); // Añade un recorrido a partir de puntos void addPath(const std::vector<SDL_FPoint>& spots, float waiting_time_s = 0.0F); // Añade un recorrido a partir de puntos
void addPath(float start, float end, PathType type, float fixed_pos, float duration_s, const std::function<double(double)>& easing_function, float waiting_time_s = 0.0F); // Añade un recorrido generado void addPath(float start, float end, PathType type, float fixed_pos, float duration_s, const std::function<double(double)>& easing_function, float waiting_time_s = 0.0F); // Añade un recorrido generado
// --- Estado y control --- // --- Estado y control ---
void enable(); // Habilita el objeto void enable(); // Habilita el objeto
[[nodiscard]] auto hasFinished() const -> bool; // Indica si ha terminado todos los recorridos [[nodiscard]] auto hasFinished() const -> bool; // Indica si ha terminado todos los recorridos
// --- Getters --- // --- Getters ---
[[nodiscard]] auto getCurrentPath() const -> int { return current_path_; } // Devuelve el índice del recorrido actual [[nodiscard]] auto getCurrentPath() const -> int { return current_path_; } // Devuelve el índice del recorrido actual
private: private:
// --- Variables internas --- // --- Variables internas ---
bool enabled_ = false; // Indica si el objeto está habilitado bool enabled_ = false; // Indica si el objeto está habilitado
bool has_finished_ = false; // Indica si el objeto ha finalizado el recorrido bool has_finished_ = false; // Indica si el objeto ha finalizado el recorrido
int current_path_ = 0; // Recorrido que se está recorriendo actualmente int current_path_ = 0; // Recorrido que se está recorriendo actualmente
std::vector<Path> paths_; // Caminos a recorrer por el sprite std::vector<Path> paths_; // Caminos a recorrer por el sprite
// --- Métodos internos --- // --- Métodos internos ---
void moveThroughCurrentPath(float delta_time); // Coloca el sprite en los diferentes puntos del recorrido void moveThroughCurrentPath(float delta_time); // Coloca el sprite en los diferentes puntos del recorrido
void goToNextPathOrDie(); // Cambia de recorrido o finaliza void goToNextPathOrDie(); // Cambia de recorrido o finaliza
// --- Métodos auxiliares para addPath --- // --- Métodos auxiliares para addPath ---
[[nodiscard]] static auto determineCenteringType(const Path& path, bool centered) -> PathCentered; // Determina el tipo de centrado [[nodiscard]] static auto determineCenteringType(const Path& path, bool centered) -> PathCentered; // Determina el tipo de centrado
static void centerPathOnX(Path& path, float offset); // Aplica centrado en el eje X static void centerPathOnX(Path& path, float offset); // Aplica centrado en el eje X
static void centerPathOnY(Path& path, float offset); // Aplica centrado en el eje Y static void centerPathOnY(Path& path, float offset); // Aplica centrado en el eje Y
}; };
+112 -112
View File
@@ -7,129 +7,129 @@
// --- Clase PauseManager: maneja el sistema de pausa del juego --- // --- Clase PauseManager: maneja el sistema de pausa del juego ---
class PauseManager { class PauseManager {
public: public:
// --- Enums --- // --- Enums ---
enum class Source : uint8_t { // Fuentes de pausa enum class Source : uint8_t { // Fuentes de pausa
NONE = 0, NONE = 0,
PLAYER = 1 << 0, // 0001 PLAYER = 1 << 0, // 0001
SERVICE_MENU = 1 << 1, // 0010 SERVICE_MENU = 1 << 1, // 0010
FOCUS_LOST = 1 << 2 // 0100 FOCUS_LOST = 1 << 2 // 0100
}; };
// --- Operadores friend --- // --- Operadores friend ---
friend auto operator|(Source a, Source b) -> Source { friend auto operator|(Source a, Source b) -> Source {
return static_cast<Source>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b)); return static_cast<Source>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
}
friend auto operator&(Source a, Source b) -> Source {
return static_cast<Source>(static_cast<uint8_t>(a) & static_cast<uint8_t>(b));
}
friend auto operator~(Source a) -> uint8_t {
return ~static_cast<uint8_t>(a);
}
friend auto operator&=(Source& a, uint8_t b) -> Source& {
a = static_cast<Source>(static_cast<uint8_t>(a) & b);
return a;
}
friend auto operator|=(Source& a, Source b) -> Source& {
return a = a | b;
}
friend auto operator&=(Source& a, Source b) -> Source& {
return a = a & b;
}
// --- Constructor y destructor ---
explicit PauseManager(std::function<void(bool)> callback = nullptr) // Constructor con callback opcional
: on_pause_changed_callback_(std::move(callback)) {}
// --- Métodos principales ---
void setFlag(Source source, bool enable) { // Establece/quita una fuente de pausa específica
bool was_paused = isPaused();
if (enable) {
flags_ |= source;
} else {
flags_ &= ~source; // Ahora funciona: Source &= uint8_t
} }
friend auto operator&(Source a, Source b) -> Source { if (was_paused != isPaused()) {
return static_cast<Source>(static_cast<uint8_t>(a) & static_cast<uint8_t>(b)); notifyPauseChanged();
}
}
// --- Métodos específicos para cada fuente ---
void setPlayerPause(bool enable) { setFlag(Source::PLAYER, enable); }
void setServiceMenuPause(bool enable) { setFlag(Source::SERVICE_MENU, enable); }
void setFocusLossPause(bool enable) { setFlag(Source::FOCUS_LOST, enable); }
void togglePlayerPause() { setPlayerPause(!isPlayerPaused()); } // Toggle para el jugador (más común)
// --- Getters ---
[[nodiscard]] auto isPaused() const -> bool { return flags_ != Source::NONE; }
[[nodiscard]] auto isPlayerPaused() const -> bool { return hasFlag(Source::PLAYER); }
[[nodiscard]] auto isServiceMenuPaused() const -> bool { return hasFlag(Source::SERVICE_MENU); }
[[nodiscard]] auto isFocusLossPaused() const -> bool { return hasFlag(Source::FOCUS_LOST); }
[[nodiscard]] auto getFlags() const -> Source { return flags_; } // Obtiene las banderas actuales
// --- Métodos de utilidad ---
void clearAll() { // Limpia todas las pausas (útil para reset)
if (isPaused()) {
flags_ = Source::NONE;
notifyPauseChanged();
}
}
[[nodiscard]] auto getStatusString() const -> std::string { // Método para debug
if (flags_ == Source::NONE) {
return "Active";
} }
friend auto operator~(Source a) -> uint8_t { std::string result = "Paused by: ";
return ~static_cast<uint8_t>(a); bool first = true;
}
friend auto operator&=(Source& a, uint8_t b) -> Source& { if (hasFlag(Source::PLAYER)) {
a = static_cast<Source>(static_cast<uint8_t>(a) & b); if (!first) {
return a; result += ", ";
}
friend auto operator|=(Source& a, Source b) -> Source& {
return a = a | b;
}
friend auto operator&=(Source& a, Source b) -> Source& {
return a = a & b;
}
// --- Constructor y destructor ---
explicit PauseManager(std::function<void(bool)> callback = nullptr) // Constructor con callback opcional
: on_pause_changed_callback_(std::move(callback)) {}
// --- Métodos principales ---
void setFlag(Source source, bool enable) { // Establece/quita una fuente de pausa específica
bool was_paused = isPaused();
if (enable) {
flags_ |= source;
} else {
flags_ &= ~source; // Ahora funciona: Source &= uint8_t
} }
result += "Player";
if (was_paused != isPaused()) { first = false;
notifyPauseChanged(); }
if (hasFlag(Source::SERVICE_MENU)) {
if (!first) {
result += ", ";
} }
result += "ServiceMenu";
first = false;
}
if (hasFlag(Source::FOCUS_LOST)) {
if (!first) {
result += ", ";
}
result += "FocusLoss";
} }
// --- Métodos específicos para cada fuente --- return result;
void setPlayerPause(bool enable) { setFlag(Source::PLAYER, enable); } }
void setServiceMenuPause(bool enable) { setFlag(Source::SERVICE_MENU, enable); } void setCallback(std::function<void(bool)> callback) { // Permite cambiar el callback en runtime
void setFocusLossPause(bool enable) { setFlag(Source::FOCUS_LOST, enable); } on_pause_changed_callback_ = std::move(callback);
}
void togglePlayerPause() { setPlayerPause(!isPlayerPaused()); } // Toggle para el jugador (más común) private:
// --- Variables ---
Source flags_ = Source::NONE;
std::function<void(bool)> on_pause_changed_callback_;
// --- Getters --- // --- Métodos internos ---
[[nodiscard]] auto isPaused() const -> bool { return flags_ != Source::NONE; } [[nodiscard]] auto hasFlag(Source flag) const -> bool {
[[nodiscard]] auto isPlayerPaused() const -> bool { return hasFlag(Source::PLAYER); } return (flags_ & flag) != Source::NONE;
[[nodiscard]] auto isServiceMenuPaused() const -> bool { return hasFlag(Source::SERVICE_MENU); } }
[[nodiscard]] auto isFocusLossPaused() const -> bool { return hasFlag(Source::FOCUS_LOST); } void notifyPauseChanged() {
if (on_pause_changed_callback_) {
[[nodiscard]] auto getFlags() const -> Source { return flags_; } // Obtiene las banderas actuales on_pause_changed_callback_(isPaused());
// --- Métodos de utilidad ---
void clearAll() { // Limpia todas las pausas (útil para reset)
if (isPaused()) {
flags_ = Source::NONE;
notifyPauseChanged();
}
}
[[nodiscard]] auto getStatusString() const -> std::string { // Método para debug
if (flags_ == Source::NONE) {
return "Active";
}
std::string result = "Paused by: ";
bool first = true;
if (hasFlag(Source::PLAYER)) {
if (!first) {
result += ", ";
}
result += "Player";
first = false;
}
if (hasFlag(Source::SERVICE_MENU)) {
if (!first) {
result += ", ";
}
result += "ServiceMenu";
first = false;
}
if (hasFlag(Source::FOCUS_LOST)) {
if (!first) {
result += ", ";
}
result += "FocusLoss";
}
return result;
}
void setCallback(std::function<void(bool)> callback) { // Permite cambiar el callback en runtime
on_pause_changed_callback_ = std::move(callback);
}
private:
// --- Variables ---
Source flags_ = Source::NONE;
std::function<void(bool)> on_pause_changed_callback_;
// --- Métodos internos ---
[[nodiscard]] auto hasFlag(Source flag) const -> bool {
return (flags_ & flag) != Source::NONE;
}
void notifyPauseChanged() {
if (on_pause_changed_callback_) {
on_pause_changed_callback_(isPaused());
}
} }
}
}; };
+318 -318
View File
@@ -37,369 +37,369 @@ class Texture;
// El sistema de disparo utiliza duraciones configurables mediante constantes // El sistema de disparo utiliza duraciones configurables mediante constantes
// para facilitar el ajuste del gameplay y la sensación de disparo. // para facilitar el ajuste del gameplay y la sensación de disparo.
class Player { class Player {
public: public:
// --- Constantes --- // --- Constantes ---
static constexpr int WIDTH = 32; // Anchura static constexpr int WIDTH = 32; // Anchura
static constexpr int HEIGHT = 32; // Altura static constexpr int HEIGHT = 32; // Altura
// --- Estructuras --- // --- Estructuras ---
struct BulletColorPair { struct BulletColorPair {
Bullet::Color normal_color; // Color de bala sin power-up Bullet::Color normal_color; // Color de bala sin power-up
Bullet::Color powered_color; // Color de bala con power-up Bullet::Color powered_color; // Color de bala con power-up
}; };
// --- Enums --- // --- Enums ---
enum class Id : int { enum class Id : int {
NO_PLAYER = -1, // Sin jugador NO_PLAYER = -1, // Sin jugador
BOTH_PLAYERS = 0, // Ambos jugadores BOTH_PLAYERS = 0, // Ambos jugadores
PLAYER1 = 1, // Jugador 1 PLAYER1 = 1, // Jugador 1
PLAYER2 = 2 // Jugador 2 PLAYER2 = 2 // Jugador 2
}; };
enum class State { enum class State {
// Estados de movimiento // Estados de movimiento
WALKING_LEFT, // Caminando hacia la izquierda WALKING_LEFT, // Caminando hacia la izquierda
WALKING_RIGHT, // Caminando hacia la derecha WALKING_RIGHT, // Caminando hacia la derecha
WALKING_STOP, // Parado, sin moverse WALKING_STOP, // Parado, sin moverse
// Estados de disparo // Estados de disparo
FIRING_UP, // Disparando hacia arriba FIRING_UP, // Disparando hacia arriba
FIRING_LEFT, // Disparando hacia la izquierda FIRING_LEFT, // Disparando hacia la izquierda
FIRING_RIGHT, // Disparando hacia la derecha FIRING_RIGHT, // Disparando hacia la derecha
FIRING_NONE, // No está disparando FIRING_NONE, // No está disparando
// Estados de retroceso tras disparar // Estados de retroceso tras disparar
RECOILING_UP, // Retroceso tras disparar hacia arriba RECOILING_UP, // Retroceso tras disparar hacia arriba
RECOILING_LEFT, // Retroceso tras disparar hacia la izquierda RECOILING_LEFT, // Retroceso tras disparar hacia la izquierda
RECOILING_RIGHT, // Retroceso tras disparar hacia la derecha RECOILING_RIGHT, // Retroceso tras disparar hacia la derecha
// Estados de enfriamiento tras disparar // Estados de enfriamiento tras disparar
COOLING_UP, // Enfriando tras disparar hacia arriba COOLING_UP, // Enfriando tras disparar hacia arriba
COOLING_LEFT, // Enfriando tras disparar hacia la izquierda COOLING_LEFT, // Enfriando tras disparar hacia la izquierda
COOLING_RIGHT, // Enfriando tras disparar hacia la derecha COOLING_RIGHT, // Enfriando tras disparar hacia la derecha
// Estados generales del jugador // Estados generales del jugador
PLAYING, // Está jugando activamente PLAYING, // Está jugando activamente
CONTINUE, // Cuenta atrás para continuar tras perder CONTINUE, // Cuenta atrás para continuar tras perder
CONTINUE_TIME_OUT, // Se ha terminado la cuenta atras para continuar y se retira al jugador de la zona de juego CONTINUE_TIME_OUT, // Se ha terminado la cuenta atras para continuar y se retira al jugador de la zona de juego
WAITING, // Esperando para entrar a jugar WAITING, // Esperando para entrar a jugar
ENTERING_NAME, // Introduciendo nombre para la tabla de puntuaciones ENTERING_NAME, // Introduciendo nombre para la tabla de puntuaciones
SHOWING_NAME, // Mostrando el nombre introducido SHOWING_NAME, // Mostrando el nombre introducido
ROLLING, // El jugador está dando vueltas y rebotando ROLLING, // El jugador está dando vueltas y rebotando
LYING_ON_THE_FLOOR_FOREVER, // El jugador está inconsciente para siempre en el suelo (demo) LYING_ON_THE_FLOOR_FOREVER, // El jugador está inconsciente para siempre en el suelo (demo)
GAME_OVER, // Fin de la partida, no puede jugar GAME_OVER, // Fin de la partida, no puede jugar
CELEBRATING, // Celebrando victoria (pose de victoria) CELEBRATING, // Celebrando victoria (pose de victoria)
ENTERING_NAME_GAME_COMPLETED, // Introduciendo nombre tras completar el juego ENTERING_NAME_GAME_COMPLETED, // Introduciendo nombre tras completar el juego
LEAVING_SCREEN, // Saliendo de la pantalla (animación) LEAVING_SCREEN, // Saliendo de la pantalla (animación)
ENTERING_SCREEN, // Entrando a la pantalla (animación) ENTERING_SCREEN, // Entrando a la pantalla (animación)
CREDITS, // Estado para mostrar los créditos del juego CREDITS, // Estado para mostrar los créditos del juego
TITLE_ANIMATION, // Animacion para el titulo TITLE_ANIMATION, // Animacion para el titulo
TITLE_HIDDEN, // Animacion para el titulo TITLE_HIDDEN, // Animacion para el titulo
RECOVER, // Al aceptar continuar RECOVER, // Al aceptar continuar
RESPAWNING, // Tras continuar y dar las gracias, otorga inmunidad y vuelve al juego RESPAWNING, // Tras continuar y dar las gracias, otorga inmunidad y vuelve al juego
}; };
// --- Estructuras --- // --- Estructuras ---
struct Config { struct Config {
Id id; // Identificador del jugador Id id; // Identificador del jugador
float x; // Posición X inicial float x; // Posición X inicial
int y; // Posición Y inicial int y; // Posición Y inicial
bool demo; // Modo demo bool demo; // Modo demo
SDL_FRect* play_area; // Área de juego (puntero para mantener referencia) SDL_FRect* play_area; // Área de juego (puntero para mantener referencia)
std::vector<std::shared_ptr<Texture>> texture; // Texturas del jugador std::vector<std::shared_ptr<Texture>> texture; // Texturas del jugador
std::vector<std::vector<std::string>> animations; // Animaciones del jugador std::vector<std::vector<std::string>> animations; // Animaciones del jugador
Table* hi_score_table; // Tabla de puntuaciones (puntero para referencia) Table* hi_score_table; // Tabla de puntuaciones (puntero para referencia)
int* glowing_entry; // Entrada brillante (puntero para mantener referencia) int* glowing_entry; // Entrada brillante (puntero para mantener referencia)
IStageInfo* stage_info; // Gestor de pantallas (puntero) IStageInfo* stage_info; // Gestor de pantallas (puntero)
}; };
// --- Constructor y destructor --- // --- Constructor y destructor ---
Player(const Config& config); Player(const Config& config);
~Player() = default; ~Player() = default;
// --- Inicialización y ciclo de vida --- // --- Inicialización y ciclo de vida ---
void init(); // Inicializa el jugador void init(); // Inicializa el jugador
void update(float delta_time); // Actualiza estado, animación y contadores (time-based) void update(float delta_time); // Actualiza estado, animación y contadores (time-based)
void render(); // Dibuja el jugador en pantalla void render(); // Dibuja el jugador en pantalla
// --- Entrada y control --- // --- Entrada y control ---
void setInput(Input::Action action); // Procesa entrada general void setInput(Input::Action action); // Procesa entrada general
void setInputPlaying(Input::Action action); // Procesa entrada en modo jugando void setInputPlaying(Input::Action action); // Procesa entrada en modo jugando
void setInputEnteringName(Input::Action action); // Procesa entrada al introducir nombre void setInputEnteringName(Input::Action action); // Procesa entrada al introducir nombre
// --- Movimiento y animación --- // --- Movimiento y animación ---
void move(float delta_time); // Mueve el jugador (time-based) void move(float delta_time); // Mueve el jugador (time-based)
void setAnimation(float delta_time); // Establece la animación según el estado (time-based) void setAnimation(float delta_time); // Establece la animación según el estado (time-based)
// --- Texturas y animaciones --- // --- Texturas y animaciones ---
void setPlayerTextures(const std::vector<std::shared_ptr<Texture>>& texture); // Cambia las texturas del jugador void setPlayerTextures(const std::vector<std::shared_ptr<Texture>>& texture); // Cambia las texturas del jugador
// --- Gameplay: Puntuación y power-ups --- // --- Gameplay: Puntuación y power-ups ---
void addScore(int score, int lowest_hi_score_entry); // Añade puntos void addScore(int score, int lowest_hi_score_entry); // Añade puntos
void incScoreMultiplier(); // Incrementa el multiplicador void incScoreMultiplier(); // Incrementa el multiplicador
void decScoreMultiplier(); // Decrementa el multiplicador void decScoreMultiplier(); // Decrementa el multiplicador
// --- Estados de juego --- // --- Estados de juego ---
void setPlayingState(State state); // Cambia el estado de juego void setPlayingState(State state); // Cambia el estado de juego
void setInvulnerable(bool value); // Establece el valor del estado de invulnerabilidad void setInvulnerable(bool value); // Establece el valor del estado de invulnerabilidad
void setPowerUp(); // Activa el modo PowerUp void setPowerUp(); // Activa el modo PowerUp
void updatePowerUp(float delta_time); // Actualiza el valor de PowerUp void updatePowerUp(float delta_time); // Actualiza el valor de PowerUp
void giveExtraHit(); // Concede un toque extra al jugador void giveExtraHit(); // Concede un toque extra al jugador
void removeExtraHit(); // Quita el toque extra al jugador void removeExtraHit(); // Quita el toque extra al jugador
void decContinueCounter(); // Decrementa el contador de continuar void decContinueCounter(); // Decrementa el contador de continuar
void setWalkingState(State state) { walking_state_ = state; } // Establece el estado de caminar void setWalkingState(State state) { walking_state_ = state; } // Establece el estado de caminar
void startFiringSystem(int cooldown_frames); // Inicia el sistema de disparo void startFiringSystem(int cooldown_frames); // Inicia el sistema de disparo
void setScoreBoardPanel(Scoreboard::Id panel) { scoreboard_panel_ = panel; } // Establece el panel del marcador void setScoreBoardPanel(Scoreboard::Id panel) { scoreboard_panel_ = panel; } // Establece el panel del marcador
void addCredit(); void addCredit();
void passShowingName(); void passShowingName();
// --- Estado del juego: Consultas (is* methods) --- // --- Estado del juego: Consultas (is* methods) ---
[[nodiscard]] auto isLyingOnTheFloorForever() const -> bool { return playing_state_ == State::LYING_ON_THE_FLOOR_FOREVER; } [[nodiscard]] auto isLyingOnTheFloorForever() const -> bool { return playing_state_ == State::LYING_ON_THE_FLOOR_FOREVER; }
[[nodiscard]] auto isCelebrating() const -> bool { return playing_state_ == State::CELEBRATING; } [[nodiscard]] auto isCelebrating() const -> bool { return playing_state_ == State::CELEBRATING; }
[[nodiscard]] auto isContinue() const -> bool { return playing_state_ == State::CONTINUE; } [[nodiscard]] auto isContinue() const -> bool { return playing_state_ == State::CONTINUE; }
[[nodiscard]] auto isDying() const -> bool { return playing_state_ == State::ROLLING; } [[nodiscard]] auto isDying() const -> bool { return playing_state_ == State::ROLLING; }
[[nodiscard]] auto isEnteringName() const -> bool { return playing_state_ == State::ENTERING_NAME; } [[nodiscard]] auto isEnteringName() const -> bool { return playing_state_ == State::ENTERING_NAME; }
[[nodiscard]] auto isShowingName() const -> bool { return playing_state_ == State::SHOWING_NAME; } [[nodiscard]] auto isShowingName() const -> bool { return playing_state_ == State::SHOWING_NAME; }
[[nodiscard]] auto isEnteringNameGameCompleted() const -> bool { return playing_state_ == State::ENTERING_NAME_GAME_COMPLETED; } [[nodiscard]] auto isEnteringNameGameCompleted() const -> bool { return playing_state_ == State::ENTERING_NAME_GAME_COMPLETED; }
[[nodiscard]] auto isLeavingScreen() const -> bool { return playing_state_ == State::LEAVING_SCREEN; } [[nodiscard]] auto isLeavingScreen() const -> bool { return playing_state_ == State::LEAVING_SCREEN; }
[[nodiscard]] auto isGameOver() const -> bool { return playing_state_ == State::GAME_OVER; } [[nodiscard]] auto isGameOver() const -> bool { return playing_state_ == State::GAME_OVER; }
[[nodiscard]] auto isPlaying() const -> bool { return playing_state_ == State::PLAYING; } [[nodiscard]] auto isPlaying() const -> bool { return playing_state_ == State::PLAYING; }
[[nodiscard]] auto isWaiting() const -> bool { return playing_state_ == State::WAITING; } [[nodiscard]] auto isWaiting() const -> bool { return playing_state_ == State::WAITING; }
[[nodiscard]] auto isTitleHidden() const -> bool { return playing_state_ == State::TITLE_HIDDEN; } [[nodiscard]] auto isTitleHidden() const -> bool { return playing_state_ == State::TITLE_HIDDEN; }
// --- Estados específicos: Consultas adicionales --- // --- Estados específicos: Consultas adicionales ---
[[nodiscard]] auto canFire() const -> bool { return can_fire_new_system_; } // Usa nuevo sistema [[nodiscard]] auto canFire() const -> bool { return can_fire_new_system_; } // Usa nuevo sistema
[[nodiscard]] auto hasExtraHit() const -> bool { return extra_hit_; } [[nodiscard]] auto hasExtraHit() const -> bool { return extra_hit_; }
[[nodiscard]] auto isCooling() const -> bool { return firing_state_ == State::COOLING_LEFT || firing_state_ == State::COOLING_UP || firing_state_ == State::COOLING_RIGHT; } [[nodiscard]] auto isCooling() const -> bool { return firing_state_ == State::COOLING_LEFT || firing_state_ == State::COOLING_UP || firing_state_ == State::COOLING_RIGHT; }
[[nodiscard]] auto isRecoiling() const -> bool { return firing_state_ == State::RECOILING_LEFT || firing_state_ == State::RECOILING_UP || firing_state_ == State::RECOILING_RIGHT; } [[nodiscard]] auto isRecoiling() const -> bool { return firing_state_ == State::RECOILING_LEFT || firing_state_ == State::RECOILING_UP || firing_state_ == State::RECOILING_RIGHT; }
[[nodiscard]] auto qualifiesForHighScore() const -> bool { return qualifies_for_high_score_; } [[nodiscard]] auto qualifiesForHighScore() const -> bool { return qualifies_for_high_score_; }
[[nodiscard]] auto isInvulnerable() const -> bool { return invulnerable_; } [[nodiscard]] auto isInvulnerable() const -> bool { return invulnerable_; }
[[nodiscard]] auto isPowerUp() const -> bool { return power_up_; } [[nodiscard]] auto isPowerUp() const -> bool { return power_up_; }
[[nodiscard]] auto isInBulletColorToggleMode() const -> bool { return in_power_up_ending_phase_; } [[nodiscard]] auto isInBulletColorToggleMode() const -> bool { return in_power_up_ending_phase_; }
// --- Getters: Propiedades y valores --- // --- Getters: Propiedades y valores ---
// Posición y dimensiones // Posición y dimensiones
[[nodiscard]] auto getPosX() const -> int { return static_cast<int>(pos_x_); } [[nodiscard]] auto getPosX() const -> int { return static_cast<int>(pos_x_); }
[[nodiscard]] auto getPosY() const -> int { return pos_y_; } [[nodiscard]] auto getPosY() const -> int { return pos_y_; }
[[nodiscard]] static auto getWidth() -> int { return WIDTH; } [[nodiscard]] static auto getWidth() -> int { return WIDTH; }
[[nodiscard]] static auto getHeight() -> int { return HEIGHT; } [[nodiscard]] static auto getHeight() -> int { return HEIGHT; }
// Jugador y identificación // Jugador y identificación
[[nodiscard]] auto getId() const -> Player::Id { return id_; } [[nodiscard]] auto getId() const -> Player::Id { return id_; }
[[nodiscard]] auto getName() const -> const std::string& { return name_; } [[nodiscard]] auto getName() const -> const std::string& { return name_; }
[[nodiscard]] auto getPlayingState() const -> State { return playing_state_; } [[nodiscard]] auto getPlayingState() const -> State { return playing_state_; }
auto getCollider() -> Circle& { return collider_; } auto getCollider() -> Circle& { return collider_; }
[[nodiscard]] auto getZOrder() const -> size_t { return z_order_; } [[nodiscard]] auto getZOrder() const -> size_t { return z_order_; }
void setZOrder(size_t z_order) { z_order_ = z_order; } void setZOrder(size_t z_order) { z_order_ = z_order; }
// Puntuación y juego // Puntuación y juego
[[nodiscard]] auto getScore() const -> int { return score_; } [[nodiscard]] auto getScore() const -> int { return score_; }
[[nodiscard]] auto getScoreMultiplier() const -> float { return score_multiplier_; } [[nodiscard]] auto getScoreMultiplier() const -> float { return score_multiplier_; }
[[nodiscard]] auto get1CC() const -> bool { return game_completed_ && credits_used_ <= 1; } [[nodiscard]] auto get1CC() const -> bool { return game_completed_ && credits_used_ <= 1; }
[[nodiscard]] auto getScoreBoardPanel() const -> Scoreboard::Id { return scoreboard_panel_; } [[nodiscard]] auto getScoreBoardPanel() const -> Scoreboard::Id { return scoreboard_panel_; }
// Power-ups y estado especial // Power-ups y estado especial
[[nodiscard]] auto getCoffees() const -> int { return coffees_; } [[nodiscard]] auto getCoffees() const -> int { return coffees_; }
[[nodiscard]] auto getPowerUpCounter() const -> int { return power_up_counter_; } [[nodiscard]] auto getPowerUpCounter() const -> int { return power_up_counter_; }
[[nodiscard]] auto getInvulnerableCounter() const -> int { return invulnerable_counter_; } [[nodiscard]] auto getInvulnerableCounter() const -> int { return invulnerable_counter_; }
[[nodiscard]] auto getBulletColor() const -> Bullet::Color; // Devuelve el color actual de bala según el estado [[nodiscard]] auto getBulletColor() const -> Bullet::Color; // Devuelve el color actual de bala según el estado
auto getNextBulletColor() -> Bullet::Color; // Devuelve el color para la próxima bala (alterna si está en modo toggle) auto getNextBulletColor() -> Bullet::Color; // Devuelve el color para la próxima bala (alterna si está en modo toggle)
void setBulletColors(Bullet::Color normal, Bullet::Color powered); // Establece los colores de bala para este jugador void setBulletColors(Bullet::Color normal, Bullet::Color powered); // Establece los colores de bala para este jugador
[[nodiscard]] auto getBulletSoundFile() const -> std::string { return bullet_sound_file_; } // Devuelve el archivo de sonido de bala [[nodiscard]] auto getBulletSoundFile() const -> std::string { return bullet_sound_file_; } // Devuelve el archivo de sonido de bala
void setBulletSoundFile(const std::string& filename); // Establece el archivo de sonido de bala para este jugador void setBulletSoundFile(const std::string& filename); // Establece el archivo de sonido de bala para este jugador
// Contadores y timers // Contadores y timers
[[nodiscard]] auto getContinueCounter() const -> int { return continue_counter_; } [[nodiscard]] auto getContinueCounter() const -> int { return continue_counter_; }
[[nodiscard]] auto getRecordName() const -> std::string { return enter_name_ ? enter_name_->getFinalName() : "xxx"; } [[nodiscard]] auto getRecordName() const -> std::string { return enter_name_ ? enter_name_->getFinalName() : "xxx"; }
[[nodiscard]] auto getLastEnterName() const -> std::string { return last_enter_name_; } [[nodiscard]] auto getLastEnterName() const -> std::string { return last_enter_name_; }
// --- Configuración e interfaz externa --- // --- Configuración e interfaz externa ---
void setName(const std::string& name) { name_ = name; } void setName(const std::string& name) { name_ = name; }
void setGamepad(std::shared_ptr<Input::Gamepad> gamepad) { gamepad_ = std::move(gamepad); } void setGamepad(std::shared_ptr<Input::Gamepad> gamepad) { gamepad_ = std::move(gamepad); }
[[nodiscard]] auto getGamepad() const -> std::shared_ptr<Input::Gamepad> { return gamepad_; } [[nodiscard]] auto getGamepad() const -> std::shared_ptr<Input::Gamepad> { return gamepad_; }
void setUsesKeyboard(bool value) { uses_keyboard_ = value; } void setUsesKeyboard(bool value) { uses_keyboard_ = value; }
[[nodiscard]] auto getUsesKeyboard() const -> bool { return uses_keyboard_; } [[nodiscard]] auto getUsesKeyboard() const -> bool { return uses_keyboard_; }
[[nodiscard]] auto getController() const -> int { return controller_index_; } [[nodiscard]] auto getController() const -> int { return controller_index_; }
// Demo file management // Demo file management
[[nodiscard]] auto getDemoFile() const -> size_t { return demo_file_; } [[nodiscard]] auto getDemoFile() const -> size_t { return demo_file_; }
void setDemoFile(size_t demo_file) { demo_file_ = demo_file; } void setDemoFile(size_t demo_file) { demo_file_ = demo_file; }
private: private:
// --- Constantes de física y movimiento --- // --- Constantes de física y movimiento ---
static constexpr float BASE_SPEED = 90.0F; // Velocidad base del jugador (pixels/segundo) static constexpr float BASE_SPEED = 90.0F; // Velocidad base del jugador (pixels/segundo)
// --- Constantes de power-ups y estados especiales --- // --- Constantes de power-ups y estados especiales ---
static constexpr int POWERUP_COUNTER = 1500; // Duración del estado PowerUp (frames) static constexpr int POWERUP_COUNTER = 1500; // Duración del estado PowerUp (frames)
static constexpr int INVULNERABLE_COUNTER = 200; // Duración del estado invulnerable (frames) static constexpr int INVULNERABLE_COUNTER = 200; // Duración del estado invulnerable (frames)
static constexpr size_t INVULNERABLE_TEXTURE = 3; // Textura usada durante invulnerabilidad static constexpr size_t INVULNERABLE_TEXTURE = 3; // Textura usada durante invulnerabilidad
// --- Constantes del sistema de disparo (obsoletas - usar nuevo sistema) --- // --- Constantes del sistema de disparo (obsoletas - usar nuevo sistema) ---
static constexpr int COOLING_DURATION = 50; // Duración del enfriamiento tras disparar static constexpr int COOLING_DURATION = 50; // Duración del enfriamiento tras disparar
static constexpr int COOLING_COMPLETE = 0; // Valor que indica enfriamiento completado static constexpr int COOLING_COMPLETE = 0; // Valor que indica enfriamiento completado
// --- Constantes de estados de espera --- // --- Constantes de estados de espera ---
static constexpr int WAITING_COUNTER = 1000; // Tiempo de espera en estado de espera static constexpr int WAITING_COUNTER = 1000; // Tiempo de espera en estado de espera
// --- Constantes del nuevo sistema de disparo de dos líneas --- // --- Constantes del nuevo sistema de disparo de dos líneas ---
static constexpr float AIMING_DURATION_FACTOR = 0.5F; // 50% del cooldown funcional static constexpr float AIMING_DURATION_FACTOR = 0.5F; // 50% del cooldown funcional
static constexpr float RECOILING_DURATION_MULTIPLIER = 4.0F; // 4 veces la duración de aiming static constexpr float RECOILING_DURATION_MULTIPLIER = 4.0F; // 4 veces la duración de aiming
static constexpr float THREAT_POSE_DURATION = 50.0F / 60.0F; // 50 frames = ~0.833s (duración base) static constexpr float THREAT_POSE_DURATION = 50.0F / 60.0F; // 50 frames = ~0.833s (duración base)
static constexpr float MIN_THREAT_POSE_DURATION = 6.0F / 60.0F; // 6 frames = ~0.1s (duración mínima) static constexpr float MIN_THREAT_POSE_DURATION = 6.0F / 60.0F; // 6 frames = ~0.1s (duración mínima)
// --- Objetos y punteros --- // --- Objetos y punteros ---
std::unique_ptr<AnimatedSprite> player_sprite_; // Sprite para dibujar el jugador std::unique_ptr<AnimatedSprite> player_sprite_; // Sprite para dibujar el jugador
std::unique_ptr<AnimatedSprite> power_sprite_; // Sprite para dibujar el aura del jugador con el poder a tope std::unique_ptr<AnimatedSprite> power_sprite_; // Sprite para dibujar el aura del jugador con el poder a tope
std::unique_ptr<EnterName> enter_name_; // Clase utilizada para introducir el nombre std::unique_ptr<EnterName> enter_name_; // Clase utilizada para introducir el nombre
std::unique_ptr<Cooldown> cooldown_ = nullptr; // Objeto para gestionar cooldowns de teclado std::unique_ptr<Cooldown> cooldown_ = nullptr; // Objeto para gestionar cooldowns de teclado
std::shared_ptr<Input::Gamepad> gamepad_ = nullptr; // Dispositivo asociado std::shared_ptr<Input::Gamepad> gamepad_ = nullptr; // Dispositivo asociado
Table* hi_score_table_ = nullptr; // Tabla de máximas puntuaciones Table* hi_score_table_ = nullptr; // Tabla de máximas puntuaciones
int* glowing_entry_ = nullptr; // Entrada de la tabla de puntuaciones para hacerla brillar int* glowing_entry_ = nullptr; // Entrada de la tabla de puntuaciones para hacerla brillar
IStageInfo* stage_info_; // Informacion de la pantalla actual IStageInfo* stage_info_; // Informacion de la pantalla actual
// --- Variables de estado --- // --- Variables de estado ---
SDL_FRect play_area_; // Rectángulo con la zona de juego SDL_FRect play_area_; // Rectángulo con la zona de juego
Circle collider_ = Circle(0, 0, 9); // Círculo de colisión del jugador Circle collider_ = Circle(0, 0, 9); // Círculo de colisión del jugador
std::string name_; // Nombre del jugador std::string name_; // Nombre del jugador
std::string last_enter_name_; // Último nombre introducido en la tabla de puntuaciones std::string last_enter_name_; // Último nombre introducido en la tabla de puntuaciones
Scoreboard::Id scoreboard_panel_ = Scoreboard::Id::LEFT; // Panel del marcador asociado al jugador Scoreboard::Id scoreboard_panel_ = Scoreboard::Id::LEFT; // Panel del marcador asociado al jugador
Id id_; // Identificador para el jugador Id id_; // Identificador para el jugador
State walking_state_ = State::WALKING_STOP; // Estado del jugador al moverse State walking_state_ = State::WALKING_STOP; // Estado del jugador al moverse
State firing_state_ = State::FIRING_NONE; // Estado del jugador al disparar State firing_state_ = State::FIRING_NONE; // Estado del jugador al disparar
State playing_state_ = State::WAITING; // Estado del jugador en el juego State playing_state_ = State::WAITING; // Estado del jugador en el juego
BulletColorPair bullet_colors_ = {.normal_color = Bullet::Color::YELLOW, .powered_color = Bullet::Color::GREEN}; // Par de colores de balas para este jugador BulletColorPair bullet_colors_ = {.normal_color = Bullet::Color::YELLOW, .powered_color = Bullet::Color::GREEN}; // Par de colores de balas para este jugador
std::string bullet_sound_file_ = "bullet1p.wav"; // Archivo de sonido de bala para este jugador std::string bullet_sound_file_ = "bullet1p.wav"; // Archivo de sonido de bala para este jugador
float pos_x_ = 0.0F; // Posición en el eje X float pos_x_ = 0.0F; // Posición en el eje X
float default_pos_x_; // Posición inicial para el jugador float default_pos_x_; // Posición inicial para el jugador
float vel_x_ = 0.0F; // Cantidad de píxeles a desplazarse en el eje X float vel_x_ = 0.0F; // Cantidad de píxeles a desplazarse en el eje X
float score_multiplier_ = 1.0F; // Multiplicador de puntos float score_multiplier_ = 1.0F; // Multiplicador de puntos
int pos_y_ = 0; // Posición en el eje Y int pos_y_ = 0; // Posición en el eje Y
int default_pos_y_; // Posición inicial para el jugador int default_pos_y_; // Posición inicial para el jugador
int vel_y_ = 0; // Cantidad de píxeles a desplazarse en el eje Y int vel_y_ = 0; // Cantidad de píxeles a desplazarse en el eje Y
float invulnerable_time_accumulator_ = 0.0F; // Acumulador de tiempo para invulnerabilidad (time-based) float invulnerable_time_accumulator_ = 0.0F; // Acumulador de tiempo para invulnerabilidad (time-based)
float power_up_time_accumulator_ = 0.0F; // Acumulador de tiempo para power-up (time-based) float power_up_time_accumulator_ = 0.0F; // Acumulador de tiempo para power-up (time-based)
float continue_time_accumulator_ = 0.0F; // Acumulador de tiempo para continue counter (time-based) float continue_time_accumulator_ = 0.0F; // Acumulador de tiempo para continue counter (time-based)
float name_entry_time_accumulator_ = 0.0F; // Acumulador de tiempo para name entry counter (time-based) float name_entry_time_accumulator_ = 0.0F; // Acumulador de tiempo para name entry counter (time-based)
float showing_name_time_accumulator_ = 0.0F; // Acumulador de tiempo para showing name (time-based) float showing_name_time_accumulator_ = 0.0F; // Acumulador de tiempo para showing name (time-based)
float waiting_time_accumulator_ = 0.0F; // Acumulador de tiempo para waiting movement (time-based) float waiting_time_accumulator_ = 0.0F; // Acumulador de tiempo para waiting movement (time-based)
float step_time_accumulator_ = 0.0F; // Acumulador de tiempo para step counter (time-based) float step_time_accumulator_ = 0.0F; // Acumulador de tiempo para step counter (time-based)
// ======================================== // ========================================
// NUEVO SISTEMA DE DISPARO DE DOS LÍNEAS // NUEVO SISTEMA DE DISPARO DE DOS LÍNEAS
// ======================================== // ========================================
// LÍNEA 1: SISTEMA FUNCIONAL (CanFire) // LÍNEA 1: SISTEMA FUNCIONAL (CanFire)
float fire_cooldown_timer_ = 0.0F; // Tiempo restante hasta poder disparar otra vez float fire_cooldown_timer_ = 0.0F; // Tiempo restante hasta poder disparar otra vez
bool can_fire_new_system_ = true; // true si puede disparar ahora mismo bool can_fire_new_system_ = true; // true si puede disparar ahora mismo
// LÍNEA 2: SISTEMA VISUAL (Animaciones) // LÍNEA 2: SISTEMA VISUAL (Animaciones)
enum class VisualFireState { enum class VisualFireState {
NORMAL, // Brazo en posición neutral NORMAL, // Brazo en posición neutral
AIMING, // Brazo alzado (disparando) AIMING, // Brazo alzado (disparando)
RECOILING, // Brazo en retroceso RECOILING, // Brazo en retroceso
THREAT_POSE // Posición amenazante THREAT_POSE // Posición amenazante
}; };
VisualFireState visual_fire_state_ = VisualFireState::NORMAL; VisualFireState visual_fire_state_ = VisualFireState::NORMAL;
float visual_state_timer_ = 0.0F; // Tiempo en el estado visual actual float visual_state_timer_ = 0.0F; // Tiempo en el estado visual actual
float aiming_duration_ = 0.0F; // Duración del estado AIMING float aiming_duration_ = 0.0F; // Duración del estado AIMING
float recoiling_duration_ = 0.0F; // Duración del estado RECOILING float recoiling_duration_ = 0.0F; // Duración del estado RECOILING
int invulnerable_counter_ = INVULNERABLE_COUNTER; // Contador para la invulnerabilidad int invulnerable_counter_ = INVULNERABLE_COUNTER; // Contador para la invulnerabilidad
int score_ = 0; // Puntos del jugador int score_ = 0; // Puntos del jugador
int coffees_ = 0; // Indica cuántos cafés lleva acumulados int coffees_ = 0; // Indica cuántos cafés lleva acumulados
int power_up_counter_ = POWERUP_COUNTER; // Temporizador para el modo PowerUp int power_up_counter_ = POWERUP_COUNTER; // Temporizador para el modo PowerUp
int power_up_x_offset_ = 0; // Desplazamiento del sprite de PowerUp respecto al sprite del jugador int power_up_x_offset_ = 0; // Desplazamiento del sprite de PowerUp respecto al sprite del jugador
int continue_counter_ = 10; // Contador para poder continuar int continue_counter_ = 10; // Contador para poder continuar
int controller_index_ = 0; // Índice del array de mandos que utilizará para moverse int controller_index_ = 0; // Índice del array de mandos que utilizará para moverse
size_t demo_file_ = 0; // Indice del fichero de datos para el modo demo size_t demo_file_ = 0; // Indice del fichero de datos para el modo demo
size_t z_order_ = 0; // Orden de dibujado en la pantalla size_t z_order_ = 0; // Orden de dibujado en la pantalla
float name_entry_idle_time_accumulator_ = 0.0F; // Tiempo idle acumulado para poner nombre (milisegundos) float name_entry_idle_time_accumulator_ = 0.0F; // Tiempo idle acumulado para poner nombre (milisegundos)
float name_entry_total_time_accumulator_ = 0.0F; // Tiempo total acumulado poniendo nombre (milisegundos) float name_entry_total_time_accumulator_ = 0.0F; // Tiempo total acumulado poniendo nombre (milisegundos)
int step_counter_ = 0; // Cuenta los pasos para los estados en los que camina automáticamente int step_counter_ = 0; // Cuenta los pasos para los estados en los que camina automáticamente
int credits_used_ = 0; // Indica el número de veces que ha continuado int credits_used_ = 0; // Indica el número de veces que ha continuado
int waiting_counter_ = 0; // Contador para el estado de espera int waiting_counter_ = 0; // Contador para el estado de espera
bool qualifies_for_high_score_ = false; // Indica si tiene una puntuación que le permite entrar en la tabla de records bool qualifies_for_high_score_ = false; // Indica si tiene una puntuación que le permite entrar en la tabla de records
bool invulnerable_ = true; // Indica si el jugador es invulnerable bool invulnerable_ = true; // Indica si el jugador es invulnerable
bool extra_hit_ = false; // Indica si el jugador tiene un toque extra bool extra_hit_ = false; // Indica si el jugador tiene un toque extra
bool power_up_ = false; // Indica si el jugador tiene activo el modo PowerUp bool power_up_ = false; // Indica si el jugador tiene activo el modo PowerUp
bool power_sprite_visible_ = false; // Indica si el sprite de power-up debe ser visible bool power_sprite_visible_ = false; // Indica si el sprite de power-up debe ser visible
bool in_power_up_ending_phase_ = false; // Indica si está en la fase final del power-up (alternando colores) bool in_power_up_ending_phase_ = false; // Indica si está en la fase final del power-up (alternando colores)
bool bullet_color_toggle_ = false; // Para alternar entre verde y amarillo en fase final bool bullet_color_toggle_ = false; // Para alternar entre verde y amarillo en fase final
bool demo_ = false; // Para que el jugador sepa si está en el modo demostración bool demo_ = false; // Para que el jugador sepa si está en el modo demostración
bool game_completed_ = false; // Indica si ha completado el juego bool game_completed_ = false; // Indica si ha completado el juego
bool uses_keyboard_ = false; // Indica si usa el teclado como dispositivo de control bool uses_keyboard_ = false; // Indica si usa el teclado como dispositivo de control
bool recover_sound_triggered_ = false; // Indica si ya ha sonado el sonido en el estado RECOVER bool recover_sound_triggered_ = false; // Indica si ya ha sonado el sonido en el estado RECOVER
// --- Métodos internos --- // --- Métodos internos ---
void shiftColliders(); // Actualiza el círculo de colisión a la posición del jugador void shiftColliders(); // Actualiza el círculo de colisión a la posición del jugador
void shiftSprite(); // Recoloca el sprite void shiftSprite(); // Recoloca el sprite
// --- Setters internos --- // --- Setters internos ---
void setController(int index) { controller_index_ = index; } void setController(int index) { controller_index_ = index; }
void setFiringState(State state) { firing_state_ = state; } void setFiringState(State state) { firing_state_ = state; }
void setInvulnerableCounter(int value) { invulnerable_counter_ = value; } void setInvulnerableCounter(int value) { invulnerable_counter_ = value; }
void setPowerUpCounter(int value) { power_up_counter_ = value; } void setPowerUpCounter(int value) { power_up_counter_ = value; }
void setScore(int score) { score_ = score; } void setScore(int score) { score_ = score; }
void setScoreMultiplier(float value) { score_multiplier_ = value; } void setScoreMultiplier(float value) { score_multiplier_ = value; }
// --- Actualizadores de estado (time-based) --- // --- Actualizadores de estado (time-based) ---
void updateInvulnerable(float delta_time); // Monitoriza el estado de invulnerabilidad void updateInvulnerable(float delta_time); // Monitoriza el estado de invulnerabilidad
void updateContinueCounter(float delta_time); // Actualiza el contador de continue void updateContinueCounter(float delta_time); // Actualiza el contador de continue
void updateEnterNameCounter(float delta_time); // Actualiza el contador de entrar nombre void updateEnterNameCounter(float delta_time); // Actualiza el contador de entrar nombre
void updateShowingName(float delta_time); // Actualiza el estado SHOWING_NAME void updateShowingName(float delta_time); // Actualiza el estado SHOWING_NAME
void decNameEntryCounter(); // Decrementa el contador de entrar nombre void decNameEntryCounter(); // Decrementa el contador de entrar nombre
// --- Utilidades generales --- // --- Utilidades generales ---
void updateScoreboard(); // Actualiza el panel del marcador void updateScoreboard(); // Actualiza el panel del marcador
void setScoreboardMode(Scoreboard::Mode mode) const; // Cambia el modo del marcador void setScoreboardMode(Scoreboard::Mode mode) const; // Cambia el modo del marcador
void playSound(const std::string& name) const; // Hace sonar un sonido void playSound(const std::string& name) const; // Hace sonar un sonido
[[nodiscard]] auto isRenderable() const -> bool; // Indica si se puede dibujar el objeto [[nodiscard]] auto isRenderable() const -> bool; // Indica si se puede dibujar el objeto
void addScoreToScoreBoard() const; // Añade una puntuación a la tabla de records void addScoreToScoreBoard() const; // Añade una puntuación a la tabla de records
// --- Sistema de disparo (nuevo - dos líneas) --- // --- Sistema de disparo (nuevo - dos líneas) ---
void updateFireSystem(float delta_time); // Método principal del nuevo sistema de disparo void updateFireSystem(float delta_time); // Método principal del nuevo sistema de disparo
void updateFunctionalLine(float delta_time); // Actualiza la línea funcional (CanFire) void updateFunctionalLine(float delta_time); // Actualiza la línea funcional (CanFire)
void updateVisualLine(float delta_time); // Actualiza la línea visual (Animaciones) void updateVisualLine(float delta_time); // Actualiza la línea visual (Animaciones)
void updateFiringStateFromVisual(); // Sincroniza firing_state_ con visual_fire_state_ void updateFiringStateFromVisual(); // Sincroniza firing_state_ con visual_fire_state_
void transitionToRecoilingNew(); // Transición AIMING → RECOILING void transitionToRecoilingNew(); // Transición AIMING → RECOILING
void transitionToThreatPose(); // Transición RECOILING → THREAT_POSE void transitionToThreatPose(); // Transición RECOILING → THREAT_POSE
void transitionToNormalNew(); // Transición THREAT_POSE → NORMAL void transitionToNormalNew(); // Transición THREAT_POSE → NORMAL
// --- Manejadores de movimiento --- // --- Manejadores de movimiento ---
void handlePlayingMovement(float delta_time); // Gestiona el movimiento durante el juego void handlePlayingMovement(float delta_time); // Gestiona el movimiento durante el juego
void handleRecoverMovement(); // Comprueba si ha acabado la animación de recuperación void handleRecoverMovement(); // Comprueba si ha acabado la animación de recuperación
void updateStepCounter(float delta_time); // Incrementa o ajusta el contador de pasos void updateStepCounter(float delta_time); // Incrementa o ajusta el contador de pasos
void setInputBasedOnPlayerId(); // Asocia las entradas de control según el jugador void setInputBasedOnPlayerId(); // Asocia las entradas de control según el jugador
// --- Manejadores de estados especiales --- // --- Manejadores de estados especiales ---
void handleRollingMovement(); // Actualiza la lógica de movimiento de "rodar" void handleRollingMovement(); // Actualiza la lógica de movimiento de "rodar"
void handleRollingBoundaryCollision(); // Detecta colisiones con límites durante rodamiento void handleRollingBoundaryCollision(); // Detecta colisiones con límites durante rodamiento
void handleRollingGroundCollision(); // Gestiona interacción con el suelo durante rodamiento void handleRollingGroundCollision(); // Gestiona interacción con el suelo durante rodamiento
void handleRollingStop(); // Detiene el movimiento del objeto rodante void handleRollingStop(); // Detiene el movimiento del objeto rodante
void handleRollingBounce(); // Aplica lógica de rebote durante rodamiento void handleRollingBounce(); // Aplica lógica de rebote durante rodamiento
void handleContinueTimeOut(); // Gestiona tiempo de espera en pantalla "Continuar" void handleContinueTimeOut(); // Gestiona tiempo de espera en pantalla "Continuar"
// --- Manejadores de transiciones de pantalla --- // --- Manejadores de transiciones de pantalla ---
void handleTitleAnimation(float delta_time); // Ejecuta animación del título void handleTitleAnimation(float delta_time); // Ejecuta animación del título
void handleLeavingScreen(float delta_time); // Lógica para salir de pantalla void handleLeavingScreen(float delta_time); // Lógica para salir de pantalla
void handleEnteringScreen(float delta_time); // Lógica para entrar en pantalla void handleEnteringScreen(float delta_time); // Lógica para entrar en pantalla
void handlePlayer1Entering(float delta_time); // Entrada del Jugador 1 void handlePlayer1Entering(float delta_time); // Entrada del Jugador 1
void handlePlayer2Entering(float delta_time); // Entrada del Jugador 2 void handlePlayer2Entering(float delta_time); // Entrada del Jugador 2
// --- Manejadores de pantallas especiales --- // --- Manejadores de pantallas especiales ---
void handleCreditsMovement(float delta_time); // Movimiento en pantalla de créditos void handleCreditsMovement(float delta_time); // Movimiento en pantalla de créditos
void handleCreditsRightMovement(); // Movimiento hacia la derecha en créditos void handleCreditsRightMovement(); // Movimiento hacia la derecha en créditos
void handleCreditsLeftMovement(); // Movimiento hacia la izquierda en créditos void handleCreditsLeftMovement(); // Movimiento hacia la izquierda en créditos
void handleWaitingMovement(float delta_time); // Animación del jugador saludando void handleWaitingMovement(float delta_time); // Animación del jugador saludando
void updateWalkingStateForCredits(); // Actualiza estado de caminata en créditos void updateWalkingStateForCredits(); // Actualiza estado de caminata en créditos
// --- Introducción de nombre --- // --- Introducción de nombre ---
void handleNameCharacterAddition(); void handleNameCharacterAddition();
void handleNameCharacterRemoval(); void handleNameCharacterRemoval();
void handleNameSelectionMove(Input::Action action); void handleNameSelectionMove(Input::Action action);
void confirmNameEntry(); void confirmNameEntry();
// --- Utilidades de animación --- // --- Utilidades de animación ---
[[nodiscard]] auto computeAnimation() const -> std::pair<std::string, SDL_FlipMode>; // Calcula animación de movimiento y disparo [[nodiscard]] auto computeAnimation() const -> std::pair<std::string, SDL_FlipMode>; // Calcula animación de movimiento y disparo
}; };
+460 -460
View File
@@ -11,512 +11,512 @@
namespace Rendering { namespace Rendering {
OpenGLShader::~OpenGLShader() { OpenGLShader::~OpenGLShader() {
cleanup(); cleanup();
}
#ifndef __APPLE__
auto OpenGLShader::initGLExtensions() -> bool {
glCreateShader = (PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader");
glShaderSource = (PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource");
glCompileShader = (PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader");
glGetShaderiv = (PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv");
glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)SDL_GL_GetProcAddress("glGetShaderInfoLog");
glDeleteShader = (PFNGLDELETESHADERPROC)SDL_GL_GetProcAddress("glDeleteShader");
glAttachShader = (PFNGLATTACHSHADERPROC)SDL_GL_GetProcAddress("glAttachShader");
glCreateProgram = (PFNGLCREATEPROGRAMPROC)SDL_GL_GetProcAddress("glCreateProgram");
glLinkProgram = (PFNGLLINKPROGRAMPROC)SDL_GL_GetProcAddress("glLinkProgram");
glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)SDL_GL_GetProcAddress("glValidateProgram");
glGetProgramiv = (PFNGLGETPROGRAMIVPROC)SDL_GL_GetProcAddress("glGetProgramiv");
glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)SDL_GL_GetProcAddress("glGetProgramInfoLog");
glUseProgram = (PFNGLUSEPROGRAMPROC)SDL_GL_GetProcAddress("glUseProgram");
glDeleteProgram = (PFNGLDELETEPROGRAMPROC)SDL_GL_GetProcAddress("glDeleteProgram");
glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)SDL_GL_GetProcAddress("glGetUniformLocation");
glUniform2f = (PFNGLUNIFORM2FPROC)SDL_GL_GetProcAddress("glUniform2f");
glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)SDL_GL_GetProcAddress("glGenVertexArrays");
glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)SDL_GL_GetProcAddress("glBindVertexArray");
glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)SDL_GL_GetProcAddress("glDeleteVertexArrays");
glGenBuffers = (PFNGLGENBUFFERSPROC)SDL_GL_GetProcAddress("glGenBuffers");
glBindBuffer = (PFNGLBINDBUFFERPROC)SDL_GL_GetProcAddress("glBindBuffer");
glBufferData = (PFNGLBUFFERDATAPROC)SDL_GL_GetProcAddress("glBufferData");
glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)SDL_GL_GetProcAddress("glDeleteBuffers");
glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)SDL_GL_GetProcAddress("glVertexAttribPointer");
glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)SDL_GL_GetProcAddress("glEnableVertexAttribArray");
return (glCreateShader != nullptr) && (glShaderSource != nullptr) && (glCompileShader != nullptr) && (glGetShaderiv != nullptr) &&
(glGetShaderInfoLog != nullptr) && (glDeleteShader != nullptr) && (glAttachShader != nullptr) && (glCreateProgram != nullptr) &&
(glLinkProgram != nullptr) && (glValidateProgram != nullptr) && (glGetProgramiv != nullptr) && (glGetProgramInfoLog != nullptr) &&
(glUseProgram != nullptr) && (glDeleteProgram != nullptr) && (glGetUniformLocation != nullptr) && (glUniform2f != nullptr) &&
(glGenVertexArrays != nullptr) && (glBindVertexArray != nullptr) && (glDeleteVertexArrays != nullptr) &&
(glGenBuffers != nullptr) && (glBindBuffer != nullptr) && (glBufferData != nullptr) && (glDeleteBuffers != nullptr) &&
(glVertexAttribPointer != nullptr) && (glEnableVertexAttribArray != nullptr);
}
#endif
void OpenGLShader::checkGLError(const char* operation) {
GLenum error = glGetError();
if (error != GL_NO_ERROR) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error OpenGL en %s: 0x%x",
operation,
error);
}
}
auto OpenGLShader::compileShader(const std::string& source, GLenum shader_type) -> GLuint {
if (source.empty()) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"ERROR: El código fuente del shader está vacío");
return 0;
}
GLuint shader_id = glCreateShader(shader_type);
if (shader_id == 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error al crear shader");
checkGLError("glCreateShader");
return 0;
}
std::array<const char*, 1> sources = {source.c_str()};
glShaderSource(shader_id, 1, sources.data(), nullptr);
checkGLError("glShaderSource");
glCompileShader(shader_id);
checkGLError("glCompileShader");
// Verificar compilación
GLint compiled = GL_FALSE;
glGetShaderiv(shader_id, GL_COMPILE_STATUS, &compiled);
if (compiled != GL_TRUE) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error en compilación del shader");
GLint log_length;
glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &log_length);
if (log_length > 0) {
std::vector<char> log(log_length);
glGetShaderInfoLog(shader_id, log_length, &log_length, log.data());
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Log de compilación: %s",
log.data());
}
glDeleteShader(shader_id);
return 0;
}
return shader_id;
}
auto OpenGLShader::linkProgram(GLuint vertex_shader, GLuint fragment_shader) -> GLuint {
GLuint program = glCreateProgram();
if (program == 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error al crear programa de shaders");
return 0;
}
glAttachShader(program, vertex_shader);
checkGLError("glAttachShader(vertex)");
glAttachShader(program, fragment_shader);
checkGLError("glAttachShader(fragment)");
glLinkProgram(program);
checkGLError("glLinkProgram");
// Verificar enlace
GLint linked = GL_FALSE;
glGetProgramiv(program, GL_LINK_STATUS, &linked);
if (linked != GL_TRUE) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error al enlazar programa");
GLint log_length;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
if (log_length > 0) {
std::vector<char> log(log_length);
glGetProgramInfoLog(program, log_length, &log_length, log.data());
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Log de enlace: %s",
log.data());
}
glDeleteProgram(program);
return 0;
}
glValidateProgram(program);
checkGLError("glValidateProgram");
return program;
}
void OpenGLShader::createQuadGeometry() {
// Datos del quad: posición (x, y) + coordenadas de textura (u, v)
// Formato: x, y, u, v
std::array<float, 16> vertices = {
// Posición // TexCoords
-1.0F,
-1.0F,
0.0F,
0.0F, // Inferior izquierda
1.0F,
-1.0F,
1.0F,
0.0F, // Inferior derecha
1.0F,
1.0F,
1.0F,
1.0F, // Superior derecha
-1.0F,
1.0F,
0.0F,
1.0F // Superior izquierda
};
// Índices para dibujar el quad con dos triángulos
std::array<unsigned int, 6> indices = {
0,
1,
2, // Primer triángulo
2,
3,
0 // Segundo triángulo
};
// Generar y configurar VAO
glGenVertexArrays(1, &vao_);
glBindVertexArray(vao_);
checkGLError("glBindVertexArray");
// Generar y configurar VBO
glGenBuffers(1, &vbo_);
glBindBuffer(GL_ARRAY_BUFFER, vbo_);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices.data(), GL_STATIC_DRAW);
checkGLError("glBufferData(VBO)");
// Generar y configurar EBO
glGenBuffers(1, &ebo_);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices.data(), GL_STATIC_DRAW);
checkGLError("glBufferData(EBO)");
// Atributo 0: Posición (2 floats)
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), nullptr);
glEnableVertexAttribArray(0);
checkGLError("glVertexAttribPointer(position)");
// Atributo 1: Coordenadas de textura (2 floats)
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), static_cast<const void*>(static_cast<const char*>(nullptr) + 2 * sizeof(float)));
glEnableVertexAttribArray(1);
checkGLError("glVertexAttribPointer(texcoord)");
// Desvincular
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
auto OpenGLShader::getTextureID(SDL_Texture* texture) -> GLuint {
if (texture == nullptr) {
return 1;
}
SDL_PropertiesID props = SDL_GetTextureProperties(texture);
GLuint texture_id = 0;
// Intentar obtener ID de textura OpenGL
texture_id = (GLuint)(uintptr_t)SDL_GetPointerProperty(props, "SDL.texture.opengl.texture", nullptr);
if (texture_id == 0) {
texture_id = (GLuint)(uintptr_t)SDL_GetPointerProperty(props, "texture.opengl.texture", nullptr);
}
if (texture_id == 0) {
texture_id = (GLuint)SDL_GetNumberProperty(props, "SDL.texture.opengl.texture", 1);
}
if (texture_id == 0) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"No se pudo obtener ID de textura OpenGL, usando 1 por defecto");
texture_id = 1;
}
return texture_id;
}
auto OpenGLShader::init(SDL_Window* window,
SDL_Texture* texture,
const std::string& vertex_source,
const std::string& fragment_source) -> bool {
window_ = window;
back_buffer_ = texture;
renderer_ = SDL_GetRenderer(window);
if (renderer_ == nullptr) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error: No se pudo obtener el renderer");
return false;
}
// Obtener tamaños
SDL_GetWindowSize(window_, &window_width_, &window_height_);
SDL_GetTextureSize(back_buffer_, &texture_width_, &texture_height_);
/*
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Inicializando shaders: ventana=%dx%d, textura=%.0fx%.0f",
window_width_,
window_height_,
texture_width_,
texture_height_);
*/
Logger::info(
"Inicializando shaders: ventana=" +
std::to_string(window_width_) +
"x" +
std::to_string(window_height_) +
", textura=" +
std::to_string(static_cast<int>(texture_width_)) +
"x" +
std::to_string(static_cast<int>(texture_height_)));
// Verificar que es OpenGL
const char* renderer_name = SDL_GetRendererName(renderer_);
if ((renderer_name == nullptr) || strncmp(renderer_name, "opengl", 6) != 0) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"Renderer no es OpenGL: %s",
(renderer_name != nullptr) ? renderer_name : "unknown");
return false;
} }
#ifndef __APPLE__ #ifndef __APPLE__
// Inicializar extensiones OpenGL en Windows/Linux auto OpenGLShader::initGLExtensions() -> bool {
if (!initGLExtensions()) { glCreateShader = (PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader");
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, glShaderSource = (PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource");
"Error al inicializar extensiones OpenGL"); glCompileShader = (PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader");
return false; glGetShaderiv = (PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv");
glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)SDL_GL_GetProcAddress("glGetShaderInfoLog");
glDeleteShader = (PFNGLDELETESHADERPROC)SDL_GL_GetProcAddress("glDeleteShader");
glAttachShader = (PFNGLATTACHSHADERPROC)SDL_GL_GetProcAddress("glAttachShader");
glCreateProgram = (PFNGLCREATEPROGRAMPROC)SDL_GL_GetProcAddress("glCreateProgram");
glLinkProgram = (PFNGLLINKPROGRAMPROC)SDL_GL_GetProcAddress("glLinkProgram");
glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)SDL_GL_GetProcAddress("glValidateProgram");
glGetProgramiv = (PFNGLGETPROGRAMIVPROC)SDL_GL_GetProcAddress("glGetProgramiv");
glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)SDL_GL_GetProcAddress("glGetProgramInfoLog");
glUseProgram = (PFNGLUSEPROGRAMPROC)SDL_GL_GetProcAddress("glUseProgram");
glDeleteProgram = (PFNGLDELETEPROGRAMPROC)SDL_GL_GetProcAddress("glDeleteProgram");
glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)SDL_GL_GetProcAddress("glGetUniformLocation");
glUniform2f = (PFNGLUNIFORM2FPROC)SDL_GL_GetProcAddress("glUniform2f");
glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)SDL_GL_GetProcAddress("glGenVertexArrays");
glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)SDL_GL_GetProcAddress("glBindVertexArray");
glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)SDL_GL_GetProcAddress("glDeleteVertexArrays");
glGenBuffers = (PFNGLGENBUFFERSPROC)SDL_GL_GetProcAddress("glGenBuffers");
glBindBuffer = (PFNGLBINDBUFFERPROC)SDL_GL_GetProcAddress("glBindBuffer");
glBufferData = (PFNGLBUFFERDATAPROC)SDL_GL_GetProcAddress("glBufferData");
glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)SDL_GL_GetProcAddress("glDeleteBuffers");
glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)SDL_GL_GetProcAddress("glVertexAttribPointer");
glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)SDL_GL_GetProcAddress("glEnableVertexAttribArray");
return (glCreateShader != nullptr) && (glShaderSource != nullptr) && (glCompileShader != nullptr) && (glGetShaderiv != nullptr) &&
(glGetShaderInfoLog != nullptr) && (glDeleteShader != nullptr) && (glAttachShader != nullptr) && (glCreateProgram != nullptr) &&
(glLinkProgram != nullptr) && (glValidateProgram != nullptr) && (glGetProgramiv != nullptr) && (glGetProgramInfoLog != nullptr) &&
(glUseProgram != nullptr) && (glDeleteProgram != nullptr) && (glGetUniformLocation != nullptr) && (glUniform2f != nullptr) &&
(glGenVertexArrays != nullptr) && (glBindVertexArray != nullptr) && (glDeleteVertexArrays != nullptr) &&
(glGenBuffers != nullptr) && (glBindBuffer != nullptr) && (glBufferData != nullptr) && (glDeleteBuffers != nullptr) &&
(glVertexAttribPointer != nullptr) && (glEnableVertexAttribArray != nullptr);
} }
#endif #endif
// Limpiar shader anterior si existe void OpenGLShader::checkGLError(const char* operation) {
if (program_id_ != 0) { GLenum error = glGetError();
glDeleteProgram(program_id_); if (error != GL_NO_ERROR) {
program_id_ = 0; SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
} "Error OpenGL en %s: 0x%x",
operation,
// Compilar shaders error);
GLuint vertex_shader = compileShader(vertex_source, GL_VERTEX_SHADER);
GLuint fragment_shader = compileShader(fragment_source, GL_FRAGMENT_SHADER);
if (vertex_shader == 0 || fragment_shader == 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error al compilar shaders");
if (vertex_shader != 0) {
glDeleteShader(vertex_shader);
} }
if (fragment_shader != 0) { }
glDeleteShader(fragment_shader);
auto OpenGLShader::compileShader(const std::string& source, GLenum shader_type) -> GLuint {
if (source.empty()) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"ERROR: El código fuente del shader está vacío");
return 0;
} }
return false;
GLuint shader_id = glCreateShader(shader_type);
if (shader_id == 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error al crear shader");
checkGLError("glCreateShader");
return 0;
}
std::array<const char*, 1> sources = {source.c_str()};
glShaderSource(shader_id, 1, sources.data(), nullptr);
checkGLError("glShaderSource");
glCompileShader(shader_id);
checkGLError("glCompileShader");
// Verificar compilación
GLint compiled = GL_FALSE;
glGetShaderiv(shader_id, GL_COMPILE_STATUS, &compiled);
if (compiled != GL_TRUE) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error en compilación del shader");
GLint log_length;
glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &log_length);
if (log_length > 0) {
std::vector<char> log(log_length);
glGetShaderInfoLog(shader_id, log_length, &log_length, log.data());
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Log de compilación: %s",
log.data());
}
glDeleteShader(shader_id);
return 0;
}
return shader_id;
} }
// Enlazar programa auto OpenGLShader::linkProgram(GLuint vertex_shader, GLuint fragment_shader) -> GLuint {
program_id_ = linkProgram(vertex_shader, fragment_shader); GLuint program = glCreateProgram();
if (program == 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error al crear programa de shaders");
return 0;
}
// Limpiar shaders (ya no necesarios tras el enlace) glAttachShader(program, vertex_shader);
glDeleteShader(vertex_shader); checkGLError("glAttachShader(vertex)");
glDeleteShader(fragment_shader); glAttachShader(program, fragment_shader);
checkGLError("glAttachShader(fragment)");
if (program_id_ == 0) { glLinkProgram(program);
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, checkGLError("glLinkProgram");
"Error al crear programa de shaders");
return false; // Verificar enlace
GLint linked = GL_FALSE;
glGetProgramiv(program, GL_LINK_STATUS, &linked);
if (linked != GL_TRUE) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error al enlazar programa");
GLint log_length;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
if (log_length > 0) {
std::vector<char> log(log_length);
glGetProgramInfoLog(program, log_length, &log_length, log.data());
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Log de enlace: %s",
log.data());
}
glDeleteProgram(program);
return 0;
}
glValidateProgram(program);
checkGLError("glValidateProgram");
return program;
} }
// Crear geometría del quad void OpenGLShader::createQuadGeometry() {
createQuadGeometry(); // Datos del quad: posición (x, y) + coordenadas de textura (u, v)
// Formato: x, y, u, v
std::array<float, 16> vertices = {
// Posición // TexCoords
-1.0F,
-1.0F,
0.0F,
0.0F, // Inferior izquierda
1.0F,
-1.0F,
1.0F,
0.0F, // Inferior derecha
1.0F,
1.0F,
1.0F,
1.0F, // Superior derecha
-1.0F,
1.0F,
0.0F,
1.0F // Superior izquierda
};
// Índices para dibujar el quad con dos triángulos
std::array<unsigned int, 6> indices = {
0,
1,
2, // Primer triángulo
2,
3,
0 // Segundo triángulo
};
// Generar y configurar VAO
glGenVertexArrays(1, &vao_);
glBindVertexArray(vao_);
checkGLError("glBindVertexArray");
// Generar y configurar VBO
glGenBuffers(1, &vbo_);
glBindBuffer(GL_ARRAY_BUFFER, vbo_);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices.data(), GL_STATIC_DRAW);
checkGLError("glBufferData(VBO)");
// Generar y configurar EBO
glGenBuffers(1, &ebo_);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices.data(), GL_STATIC_DRAW);
checkGLError("glBufferData(EBO)");
// Atributo 0: Posición (2 floats)
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), nullptr);
glEnableVertexAttribArray(0);
checkGLError("glVertexAttribPointer(position)");
// Atributo 1: Coordenadas de textura (2 floats)
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), static_cast<const void*>(static_cast<const char*>(nullptr) + 2 * sizeof(float)));
glEnableVertexAttribArray(1);
checkGLError("glVertexAttribPointer(texcoord)");
// Desvincular
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
auto OpenGLShader::getTextureID(SDL_Texture* texture) -> GLuint {
if (texture == nullptr) {
return 1;
}
SDL_PropertiesID props = SDL_GetTextureProperties(texture);
GLuint texture_id = 0;
// Intentar obtener ID de textura OpenGL
texture_id = (GLuint)(uintptr_t)SDL_GetPointerProperty(props, "SDL.texture.opengl.texture", nullptr);
if (texture_id == 0) {
texture_id = (GLuint)(uintptr_t)SDL_GetPointerProperty(props, "texture.opengl.texture", nullptr);
}
if (texture_id == 0) {
texture_id = (GLuint)SDL_GetNumberProperty(props, "SDL.texture.opengl.texture", 1);
}
if (texture_id == 0) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"No se pudo obtener ID de textura OpenGL, usando 1 por defecto");
texture_id = 1;
}
return texture_id;
}
auto OpenGLShader::init(SDL_Window* window,
SDL_Texture* texture,
const std::string& vertex_source,
const std::string& fragment_source) -> bool {
window_ = window;
back_buffer_ = texture;
renderer_ = SDL_GetRenderer(window);
if (renderer_ == nullptr) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error: No se pudo obtener el renderer");
return false;
}
// Obtener tamaños
SDL_GetWindowSize(window_, &window_width_, &window_height_);
SDL_GetTextureSize(back_buffer_, &texture_width_, &texture_height_);
// Obtener ubicación del uniform TextureSize
glUseProgram(program_id_);
texture_size_location_ = glGetUniformLocation(program_id_, "TextureSize");
if (texture_size_location_ != -1) {
/* /*
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Configurando TextureSize uniform: %.0fx%.0f", "Inicializando shaders: ventana=%dx%d, textura=%.0fx%.0f",
window_width_,
window_height_,
texture_width_, texture_width_,
texture_height_); texture_height_);
*/ */
Logger::info( Logger::info(
"Configurando TextureSize uniform: " + "Inicializando shaders: ventana=" +
std::to_string(window_width_) +
"x" +
std::to_string(window_height_) +
", textura=" +
std::to_string(static_cast<int>(texture_width_)) + std::to_string(static_cast<int>(texture_width_)) +
"x" + "x" +
std::to_string(static_cast<int>(texture_height_))); std::to_string(static_cast<int>(texture_height_)));
glUniform2f(texture_size_location_, texture_width_, texture_height_);
checkGLError("glUniform2f(TextureSize)"); // Verificar que es OpenGL
} else { const char* renderer_name = SDL_GetRendererName(renderer_);
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, if ((renderer_name == nullptr) || strncmp(renderer_name, "opengl", 6) != 0) {
"Uniform 'TextureSize' no encontrado en shader"); SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"Renderer no es OpenGL: %s",
(renderer_name != nullptr) ? renderer_name : "unknown");
return false;
}
#ifndef __APPLE__
// Inicializar extensiones OpenGL en Windows/Linux
if (!initGLExtensions()) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error al inicializar extensiones OpenGL");
return false;
}
#endif
// Limpiar shader anterior si existe
if (program_id_ != 0) {
glDeleteProgram(program_id_);
program_id_ = 0;
}
// Compilar shaders
GLuint vertex_shader = compileShader(vertex_source, GL_VERTEX_SHADER);
GLuint fragment_shader = compileShader(fragment_source, GL_FRAGMENT_SHADER);
if (vertex_shader == 0 || fragment_shader == 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error al compilar shaders");
if (vertex_shader != 0) {
glDeleteShader(vertex_shader);
}
if (fragment_shader != 0) {
glDeleteShader(fragment_shader);
}
return false;
}
// Enlazar programa
program_id_ = linkProgram(vertex_shader, fragment_shader);
// Limpiar shaders (ya no necesarios tras el enlace)
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
if (program_id_ == 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Error al crear programa de shaders");
return false;
}
// Crear geometría del quad
createQuadGeometry();
// Obtener ubicación del uniform TextureSize
glUseProgram(program_id_);
texture_size_location_ = glGetUniformLocation(program_id_, "TextureSize");
if (texture_size_location_ != -1) {
/*
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Configurando TextureSize uniform: %.0fx%.0f",
texture_width_,
texture_height_);
*/
Logger::info(
"Configurando TextureSize uniform: " +
std::to_string(static_cast<int>(texture_width_)) +
"x" +
std::to_string(static_cast<int>(texture_height_)));
glUniform2f(texture_size_location_, texture_width_, texture_height_);
checkGLError("glUniform2f(TextureSize)");
} else {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"Uniform 'TextureSize' no encontrado en shader");
}
glUseProgram(0);
is_initialized_ = true;
/*
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"** OpenGL 3.3 Shader Backend inicializado correctamente");
*/
Logger::info("OpenGL 3.3 Shader Backend inicializado correctamente");
return true;
} }
glUseProgram(0);
is_initialized_ = true; void OpenGLShader::render() {
/* if (!is_initialized_ || program_id_ == 0) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, // Fallback: renderizado SDL normal
"** OpenGL 3.3 Shader Backend inicializado correctamente"); SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 255);
*/ SDL_SetRenderTarget(renderer_, nullptr);
Logger::info("OpenGL 3.3 Shader Backend inicializado correctamente"); SDL_RenderClear(renderer_);
return true; SDL_RenderTexture(renderer_, back_buffer_, nullptr, nullptr);
} SDL_RenderPresent(renderer_);
return;
}
void OpenGLShader::render() { // Obtener tamaño actual de ventana (puede haber cambiado)
if (!is_initialized_ || program_id_ == 0) { int current_width;
// Fallback: renderizado SDL normal int current_height;
SDL_GetWindowSize(window_, &current_width, &current_height);
// Guardar estados OpenGL
GLint old_program;
glGetIntegerv(GL_CURRENT_PROGRAM, &old_program);
std::array<GLint, 4> old_viewport{};
glGetIntegerv(GL_VIEWPORT, old_viewport.data());
GLboolean was_texture_enabled = glIsEnabled(GL_TEXTURE_2D);
GLint old_texture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_texture);
GLint old_vao;
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &old_vao);
// Preparar renderizado
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 255); SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 255);
SDL_SetRenderTarget(renderer_, nullptr); SDL_SetRenderTarget(renderer_, nullptr);
SDL_RenderClear(renderer_); SDL_RenderClear(renderer_);
SDL_RenderTexture(renderer_, back_buffer_, nullptr, nullptr);
SDL_RenderPresent(renderer_);
return;
}
// Obtener tamaño actual de ventana (puede haber cambiado) // Obtener y bindear textura
int current_width; GLuint texture_id = getTextureID(back_buffer_);
int current_height; glEnable(GL_TEXTURE_2D);
SDL_GetWindowSize(window_, &current_width, &current_height); glBindTexture(GL_TEXTURE_2D, texture_id);
checkGLError("glBindTexture");
// Guardar estados OpenGL // Usar nuestro programa
GLint old_program; glUseProgram(program_id_);
glGetIntegerv(GL_CURRENT_PROGRAM, &old_program); checkGLError("glUseProgram");
std::array<GLint, 4> old_viewport{}; // Configurar viewport (obtener tamaño lógico de SDL)
glGetIntegerv(GL_VIEWPORT, old_viewport.data()); int logical_w;
int logical_h;
SDL_RendererLogicalPresentation mode;
SDL_GetRenderLogicalPresentation(renderer_, &logical_w, &logical_h, &mode);
GLboolean was_texture_enabled = glIsEnabled(GL_TEXTURE_2D); if (logical_w == 0 || logical_h == 0) {
GLint old_texture; logical_w = current_width;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_texture); logical_h = current_height;
GLint old_vao;
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &old_vao);
// Preparar renderizado
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 255);
SDL_SetRenderTarget(renderer_, nullptr);
SDL_RenderClear(renderer_);
// Obtener y bindear textura
GLuint texture_id = getTextureID(back_buffer_);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture_id);
checkGLError("glBindTexture");
// Usar nuestro programa
glUseProgram(program_id_);
checkGLError("glUseProgram");
// Configurar viewport (obtener tamaño lógico de SDL)
int logical_w;
int logical_h;
SDL_RendererLogicalPresentation mode;
SDL_GetRenderLogicalPresentation(renderer_, &logical_w, &logical_h, &mode);
if (logical_w == 0 || logical_h == 0) {
logical_w = current_width;
logical_h = current_height;
}
// Calcular viewport considerando aspect ratio
int viewport_x = 0;
int viewport_y = 0;
int viewport_w = current_width;
int viewport_h = current_height;
if (mode == SDL_LOGICAL_PRESENTATION_INTEGER_SCALE) {
int scale_x = current_width / logical_w;
int scale_y = current_height / logical_h;
int scale = (scale_x < scale_y) ? scale_x : scale_y;
scale = std::max(scale, 1);
viewport_w = logical_w * scale;
viewport_h = logical_h * scale;
viewport_x = (current_width - viewport_w) / 2;
viewport_y = (current_height - viewport_h) / 2;
} else {
float window_aspect = static_cast<float>(current_width) / current_height;
float logical_aspect = static_cast<float>(logical_w) / logical_h;
if (window_aspect > logical_aspect) {
viewport_w = static_cast<int>(logical_aspect * current_height);
viewport_x = (current_width - viewport_w) / 2;
} else {
viewport_h = static_cast<int>(current_width / logical_aspect);
viewport_y = (current_height - viewport_h) / 2;
} }
// Calcular viewport considerando aspect ratio
int viewport_x = 0;
int viewport_y = 0;
int viewport_w = current_width;
int viewport_h = current_height;
if (mode == SDL_LOGICAL_PRESENTATION_INTEGER_SCALE) {
int scale_x = current_width / logical_w;
int scale_y = current_height / logical_h;
int scale = (scale_x < scale_y) ? scale_x : scale_y;
scale = std::max(scale, 1);
viewport_w = logical_w * scale;
viewport_h = logical_h * scale;
viewport_x = (current_width - viewport_w) / 2;
viewport_y = (current_height - viewport_h) / 2;
} else {
float window_aspect = static_cast<float>(current_width) / current_height;
float logical_aspect = static_cast<float>(logical_w) / logical_h;
if (window_aspect > logical_aspect) {
viewport_w = static_cast<int>(logical_aspect * current_height);
viewport_x = (current_width - viewport_w) / 2;
} else {
viewport_h = static_cast<int>(current_width / logical_aspect);
viewport_y = (current_height - viewport_h) / 2;
}
}
glViewport(viewport_x, viewport_y, viewport_w, viewport_h);
checkGLError("glViewport");
// Dibujar quad usando VAO
glBindVertexArray(vao_);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
checkGLError("glDrawElements");
// Presentar
SDL_GL_SwapWindow(window_);
// Restaurar estados OpenGL
glUseProgram(old_program);
glBindTexture(GL_TEXTURE_2D, old_texture);
if (was_texture_enabled == 0U) {
glDisable(GL_TEXTURE_2D);
}
glBindVertexArray(old_vao);
glViewport(old_viewport[0], old_viewport[1], old_viewport[2], old_viewport[3]);
} }
glViewport(viewport_x, viewport_y, viewport_w, viewport_h); void OpenGLShader::setTextureSize(float width, float height) {
checkGLError("glViewport"); if (!is_initialized_ || program_id_ == 0) {
return;
}
// Dibujar quad usando VAO texture_width_ = width;
glBindVertexArray(vao_); texture_height_ = height;
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
checkGLError("glDrawElements");
// Presentar GLint old_program;
SDL_GL_SwapWindow(window_); glGetIntegerv(GL_CURRENT_PROGRAM, &old_program);
// Restaurar estados OpenGL glUseProgram(program_id_);
glUseProgram(old_program);
glBindTexture(GL_TEXTURE_2D, old_texture);
if (was_texture_enabled == 0U) {
glDisable(GL_TEXTURE_2D);
}
glBindVertexArray(old_vao);
glViewport(old_viewport[0], old_viewport[1], old_viewport[2], old_viewport[3]);
}
void OpenGLShader::setTextureSize(float width, float height) { if (texture_size_location_ != -1) {
if (!is_initialized_ || program_id_ == 0) { glUniform2f(texture_size_location_, width, height);
return; checkGLError("glUniform2f(TextureSize)");
}
glUseProgram(old_program);
} }
texture_width_ = width; void OpenGLShader::cleanup() {
texture_height_ = height; if (vao_ != 0) {
glDeleteVertexArrays(1, &vao_);
vao_ = 0;
}
GLint old_program; if (vbo_ != 0) {
glGetIntegerv(GL_CURRENT_PROGRAM, &old_program); glDeleteBuffers(1, &vbo_);
vbo_ = 0;
}
glUseProgram(program_id_); if (ebo_ != 0) {
glDeleteBuffers(1, &ebo_);
ebo_ = 0;
}
if (texture_size_location_ != -1) { if (program_id_ != 0) {
glUniform2f(texture_size_location_, width, height); glDeleteProgram(program_id_);
checkGLError("glUniform2f(TextureSize)"); program_id_ = 0;
}
is_initialized_ = false;
window_ = nullptr;
renderer_ = nullptr;
back_buffer_ = nullptr;
} }
glUseProgram(old_program);
}
void OpenGLShader::cleanup() {
if (vao_ != 0) {
glDeleteVertexArrays(1, &vao_);
vao_ = 0;
}
if (vbo_ != 0) {
glDeleteBuffers(1, &vbo_);
vbo_ = 0;
}
if (ebo_ != 0) {
glDeleteBuffers(1, &ebo_);
ebo_ = 0;
}
if (program_id_ != 0) {
glDeleteProgram(program_id_);
program_id_ = 0;
}
is_initialized_ = false;
window_ = nullptr;
renderer_ = nullptr;
back_buffer_ = nullptr;
}
} // namespace Rendering } // namespace Rendering
+12 -12
View File
@@ -10,16 +10,16 @@
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:
* - VAO (Vertex Array Objects) * - VAO (Vertex Array Objects)
* - 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;
@@ -33,7 +33,7 @@ class OpenGLShader : public ShaderBackend {
void cleanup() final; void cleanup() final;
[[nodiscard]] auto isHardwareAccelerated() const -> bool override { return is_initialized_; } [[nodiscard]] auto isHardwareAccelerated() const -> bool override { return is_initialized_; }
private: private:
// Funciones auxiliares // Funciones auxiliares
auto initGLExtensions() -> bool; auto initGLExtensions() -> bool;
auto compileShader(const std::string& source, GLenum shader_type) -> GLuint; auto compileShader(const std::string& source, GLenum shader_type) -> GLuint;
@@ -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
+9 -9
View File
@@ -6,14 +6,14 @@
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
+26 -26
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
@@ -371,9 +371,9 @@ auto Resource::loadTextLazy(const std::string& name) -> std::shared_ptr<Text> {
// Mapeo de objetos de texto a sus recursos // Mapeo de objetos de texto a sus recursos
struct TextMapping { struct TextMapping {
std::string key; std::string key;
std::string texture_file; std::string texture_file;
std::string text_file; std::string text_file;
}; };
const std::vector<TextMapping> TEXT_MAPPINGS = { const std::vector<TextMapping> TEXT_MAPPINGS = {
@@ -573,9 +573,9 @@ void Resource::createPlayerTextures() {
// Configuración de jugadores y sus paletas // Configuración de jugadores y sus paletas
struct PlayerConfig { struct PlayerConfig {
std::string base_texture; std::string base_texture;
std::vector<std::string> palette_files; std::vector<std::string> palette_files;
std::string name_prefix; std::string name_prefix;
}; };
std::vector<PlayerConfig> players = { std::vector<PlayerConfig> players = {
@@ -649,12 +649,12 @@ void Resource::createPlayerTextures() {
// Crea texturas a partir de textos para mostrar puntuaciones y mensajes // Crea texturas a partir de textos para mostrar puntuaciones y mensajes
void Resource::createTextTextures() { void Resource::createTextTextures() {
struct NameAndText { struct NameAndText {
std::string name; std::string name;
std::string text; std::string text;
NameAndText(std::string name_init, std::string text_init) NameAndText(std::string name_init, std::string text_init)
: name(std::move(name_init)), : name(std::move(name_init)),
text(std::move(text_init)) {} text(std::move(text_init)) {}
}; };
Logger::cr(); Logger::cr();
@@ -695,16 +695,16 @@ void Resource::createTextTextures() {
// Crea los objetos de texto a partir de los archivos de textura y texto // Crea los objetos de texto a partir de los archivos de textura y texto
void Resource::createText() { void Resource::createText() {
struct ResourceInfo { struct ResourceInfo {
std::string key; std::string key;
std::string texture_file; std::string texture_file;
std::string text_file; std::string text_file;
std::string white_texture_file; // Textura blanca opcional std::string white_texture_file; // Textura blanca opcional
ResourceInfo(std::string k, std::string t_file, std::string txt_file, std::string w_file = "") ResourceInfo(std::string k, std::string t_file, std::string txt_file, std::string w_file = "")
: key(std::move(k)), : key(std::move(k)),
texture_file(std::move(t_file)), texture_file(std::move(t_file)),
text_file(std::move(txt_file)), text_file(std::move(txt_file)),
white_texture_file(std::move(w_file)) {} white_texture_file(std::move(w_file)) {}
}; };
Logger::cr(); Logger::cr();
+142 -142
View File
@@ -18,174 +18,174 @@ struct JA_Sound_t;
// --- Clase Resource: gestiona todos los recursos del juego (singleton) --- // --- Clase Resource: gestiona todos los recursos del juego (singleton) ---
class Resource { class Resource {
public: public:
// --- Enum para el modo de carga --- // --- Enum para el modo de carga ---
enum class LoadingMode { enum class LoadingMode {
PRELOAD, // Carga todos los recursos al inicio PRELOAD, // Carga todos los recursos al inicio
LAZY_LOAD // Carga los recursos bajo demanda LAZY_LOAD // Carga los recursos bajo demanda
}; };
// --- Métodos de singleton --- // --- Métodos de singleton ---
static void init(LoadingMode mode = LoadingMode::PRELOAD); // Inicializa el objeto Resource con modo de carga static void init(LoadingMode mode = LoadingMode::PRELOAD); // Inicializa el objeto Resource con modo de carga
static void destroy(); // Libera el objeto Resource static void destroy(); // Libera el objeto Resource
static auto get() -> Resource*; // Obtiene el puntero al objeto Resource static auto get() -> Resource*; // Obtiene el puntero al objeto Resource
// --- Métodos de acceso a recursos --- // --- Métodos de acceso a recursos ---
auto getSound(const std::string& name) -> JA_Sound_t*; // Obtiene el sonido por nombre auto getSound(const std::string& name) -> JA_Sound_t*; // Obtiene el sonido por nombre
auto getMusic(const std::string& name) -> JA_Music_t*; // Obtiene la música por nombre auto getMusic(const std::string& name) -> JA_Music_t*; // Obtiene la música por nombre
auto getTexture(const std::string& name) -> std::shared_ptr<Texture>; // Obtiene la textura por nombre auto getTexture(const std::string& name) -> std::shared_ptr<Texture>; // Obtiene la textura por nombre
auto getTextFile(const std::string& name) -> std::shared_ptr<Text::File>; // Obtiene el fichero de texto por nombre auto getTextFile(const std::string& name) -> std::shared_ptr<Text::File>; // Obtiene el fichero de texto por nombre
auto getText(const std::string& name) -> std::shared_ptr<Text>; // Obtiene el objeto de texto por nombre auto getText(const std::string& name) -> std::shared_ptr<Text>; // Obtiene el objeto de texto por nombre
auto getAnimation(const std::string& name) -> AnimationsFileBuffer&; // Obtiene la animación por nombre auto getAnimation(const std::string& name) -> AnimationsFileBuffer&; // Obtiene la animación por nombre
auto getDemoData(int index) -> DemoData&; // Obtiene los datos de demo por índice auto getDemoData(int index) -> DemoData&; // Obtiene los datos de demo por índice
// --- Métodos de recarga de recursos --- // --- Métodos de recarga de recursos ---
void reload(); // Recarga todos los recursos void reload(); // Recarga todos los recursos
// --- Método para obtener el modo de carga actual --- // --- Método para obtener el modo de carga actual ---
[[nodiscard]] auto getLoadingMode() const -> LoadingMode { return loading_mode_; } [[nodiscard]] auto getLoadingMode() const -> LoadingMode { return loading_mode_; }
private: private:
// --- Estructuras para recursos individuales --- // --- Estructuras para recursos individuales ---
struct ResourceSound { struct ResourceSound {
std::string name; // Nombre del sonido std::string name; // Nombre del sonido
JA_Sound_t* sound; // Objeto con el sonido JA_Sound_t* sound; // Objeto con el sonido
ResourceSound(std::string name, JA_Sound_t* sound = nullptr) ResourceSound(std::string name, JA_Sound_t* sound = nullptr)
: name(std::move(name)), : name(std::move(name)),
sound(sound) {} sound(sound) {}
}; };
struct ResourceMusic { struct ResourceMusic {
std::string name; // Nombre de la música std::string name; // Nombre de la música
JA_Music_t* music; // Objeto con la música JA_Music_t* music; // Objeto con la música
ResourceMusic(std::string name, JA_Music_t* music = nullptr) ResourceMusic(std::string name, JA_Music_t* music = nullptr)
: name(std::move(name)), : name(std::move(name)),
music(music) {} music(music) {}
}; };
struct ResourceTexture { struct ResourceTexture {
std::string name; // Nombre de la textura std::string name; // Nombre de la textura
std::shared_ptr<Texture> texture; // Objeto con la textura std::shared_ptr<Texture> texture; // Objeto con la textura
ResourceTexture(std::string name, std::shared_ptr<Texture> texture = nullptr) ResourceTexture(std::string name, std::shared_ptr<Texture> texture = nullptr)
: name(std::move(name)), : name(std::move(name)),
texture(std::move(texture)) {} texture(std::move(texture)) {}
}; };
struct ResourceTextFile { struct ResourceTextFile {
std::string name; // Nombre del fichero std::string name; // Nombre del fichero
std::shared_ptr<Text::File> text_file; // Objeto con los descriptores de la fuente de texto std::shared_ptr<Text::File> text_file; // Objeto con los descriptores de la fuente de texto
ResourceTextFile(std::string name, std::shared_ptr<Text::File> text_file = nullptr) ResourceTextFile(std::string name, std::shared_ptr<Text::File> text_file = nullptr)
: name(std::move(name)), : name(std::move(name)),
text_file(std::move(text_file)) {} text_file(std::move(text_file)) {}
}; };
struct ResourceText { struct ResourceText {
std::string name; // Nombre del objeto std::string name; // Nombre del objeto
std::shared_ptr<Text> text; // Objeto de texto std::shared_ptr<Text> text; // Objeto de texto
ResourceText(std::string name, std::shared_ptr<Text> text = nullptr) ResourceText(std::string name, std::shared_ptr<Text> text = nullptr)
: name(std::move(name)), : name(std::move(name)),
text(std::move(text)) {} text(std::move(text)) {}
}; };
struct ResourceAnimation { struct ResourceAnimation {
std::string name; // Nombre de la animación std::string name; // Nombre de la animación
AnimationsFileBuffer animation; // Objeto con las animaciones AnimationsFileBuffer animation; // Objeto con las animaciones
ResourceAnimation(std::string name, AnimationsFileBuffer animation = {}) ResourceAnimation(std::string name, AnimationsFileBuffer animation = {})
: name(std::move(name)), : name(std::move(name)),
animation(std::move(animation)) {} animation(std::move(animation)) {}
}; };
// --- Estructura para el progreso de carga --- // --- Estructura para el progreso de carga ---
struct ResourceCount { struct ResourceCount {
size_t total; // Número total de recursos size_t total; // Número total de recursos
size_t loaded; // Número de recursos cargados size_t loaded; // Número de recursos cargados
ResourceCount() ResourceCount()
: total(0), : total(0),
loaded(0) {} loaded(0) {}
ResourceCount(size_t total) ResourceCount(size_t total)
: total(total), : total(total),
loaded(0) {} loaded(0) {}
void add(size_t amount) { loaded += amount; } void add(size_t amount) { loaded += amount; }
void increase() { loaded++; } void increase() { loaded++; }
[[nodiscard]] auto getPercentage() const -> float { [[nodiscard]] auto getPercentage() const -> float {
return total > 0 ? static_cast<float>(loaded) / static_cast<float>(total) : 0.0F; return total > 0 ? static_cast<float>(loaded) / static_cast<float>(total) : 0.0F;
} }
}; };
// --- Constantes para la pantalla de carga --- // --- Constantes para la pantalla de carga ---
static constexpr float X_PADDING = 60.0F; static constexpr float X_PADDING = 60.0F;
static constexpr float Y_PADDING = 20.0F; static constexpr float Y_PADDING = 20.0F;
static constexpr float BAR_HEIGHT = 5.0F; static constexpr float BAR_HEIGHT = 5.0F;
static constexpr Color BAR_COLOR = Color(128, 128, 128); static constexpr Color BAR_COLOR = Color(128, 128, 128);
static constexpr Color TEXT_COLOR = Color(255, 255, 255); static constexpr Color TEXT_COLOR = Color(255, 255, 255);
// --- Modo de carga --- // --- Modo de carga ---
LoadingMode loading_mode_; LoadingMode loading_mode_;
// --- Vectores de recursos --- // --- Vectores de recursos ---
std::vector<ResourceSound> sounds_; // Vector con los sonidos std::vector<ResourceSound> sounds_; // Vector con los sonidos
std::vector<ResourceMusic> musics_; // Vector con las músicas std::vector<ResourceMusic> musics_; // Vector con las músicas
std::vector<ResourceTexture> textures_; // Vector con las texturas std::vector<ResourceTexture> textures_; // Vector con las texturas
std::vector<ResourceTextFile> text_files_; // Vector con los ficheros de texto std::vector<ResourceTextFile> text_files_; // Vector con los ficheros de texto
std::vector<ResourceText> texts_; // Vector con los objetos de texto std::vector<ResourceText> texts_; // Vector con los objetos de texto
std::vector<ResourceAnimation> animations_; // Vector con las animaciones std::vector<ResourceAnimation> animations_; // Vector con las animaciones
std::vector<DemoData> demos_; // Vector con los ficheros de datos para el modo demostración std::vector<DemoData> demos_; // Vector con los ficheros de datos para el modo demostración
// --- Progreso de carga --- // --- Progreso de carga ---
ResourceCount loading_count_; // Contador de recursos cargados ResourceCount loading_count_; // Contador de recursos cargados
std::shared_ptr<Text> loading_text_; // Texto para escribir en pantalla std::shared_ptr<Text> loading_text_; // Texto para escribir en pantalla
std::string loading_resource_name_; // Nombre del recurso que se está cargando std::string loading_resource_name_; // Nombre del recurso que se está cargando
SDL_FRect loading_wired_rect_; SDL_FRect loading_wired_rect_;
SDL_FRect loading_full_rect_; SDL_FRect loading_full_rect_;
// --- Métodos internos de carga y gestión --- // --- Métodos internos de carga y gestión ---
void loadSounds(); // Carga los sonidos void loadSounds(); // Carga los sonidos
void loadMusics(); // Carga las músicas void loadMusics(); // Carga las músicas
void loadTextures(); // Carga las texturas void loadTextures(); // Carga las texturas
void loadTextFiles(); // Carga los ficheros de texto void loadTextFiles(); // Carga los ficheros de texto
void loadAnimations(); // Carga las animaciones void loadAnimations(); // Carga las animaciones
void loadDemoData(); // Carga los datos para el modo demostración void loadDemoData(); // Carga los datos para el modo demostración
void loadDemoDataQuiet(); // Carga los datos de demo sin mostrar progreso (para modo lazy) void loadDemoDataQuiet(); // Carga los datos de demo sin mostrar progreso (para modo lazy)
void loadEssentialResources(); // Carga recursos esenciales en modo lazy void loadEssentialResources(); // Carga recursos esenciales en modo lazy
void loadEssentialTextures(); // Carga solo las texturas esenciales (fuentes) void loadEssentialTextures(); // Carga solo las texturas esenciales (fuentes)
void loadTextFilesQuiet(); // Carga ficheros de texto sin mostrar progreso (para modo lazy) void loadTextFilesQuiet(); // Carga ficheros de texto sin mostrar progreso (para modo lazy)
void createPlayerTextures(); // Crea las texturas de jugadores con todas sus variantes de paleta void createPlayerTextures(); // Crea las texturas de jugadores con todas sus variantes de paleta
void createTextTextures(); // Crea las texturas a partir de los datos cargados void createTextTextures(); // Crea las texturas a partir de los datos cargados
void createText(); // Crea los objetos de texto void createText(); // Crea los objetos de texto
void clear(); // Vacía todos los vectores de recursos void clear(); // Vacía todos los vectores de recursos
void load(); // Carga todos los recursos void load(); // Carga todos los recursos
void clearSounds(); // Vacía el vector de sonidos void clearSounds(); // Vacía el vector de sonidos
void clearMusics(); // Vacía el vector de músicas void clearMusics(); // Vacía el vector de músicas
// --- Métodos para carga perezosa --- // --- Métodos para carga perezosa ---
void initResourceLists(); // Inicializa las listas de recursos sin cargar el contenido void initResourceLists(); // Inicializa las listas de recursos sin cargar el contenido
static auto loadSoundLazy(const std::string& name) -> JA_Sound_t*; // Carga un sonido específico bajo demanda static auto loadSoundLazy(const std::string& name) -> JA_Sound_t*; // Carga un sonido específico bajo demanda
static auto loadMusicLazy(const std::string& name) -> JA_Music_t*; // Carga una música específica bajo demanda static auto loadMusicLazy(const std::string& name) -> JA_Music_t*; // Carga una música específica bajo demanda
static auto loadTextureLazy(const std::string& name) -> std::shared_ptr<Texture>; // Carga una textura específica bajo demanda static auto loadTextureLazy(const std::string& name) -> std::shared_ptr<Texture>; // Carga una textura específica bajo demanda
static auto loadTextFileLazy(const std::string& name) -> std::shared_ptr<Text::File>; // Carga un fichero de texto específico bajo demanda static auto loadTextFileLazy(const std::string& name) -> std::shared_ptr<Text::File>; // Carga un fichero de texto específico bajo demanda
auto loadTextLazy(const std::string& name) -> std::shared_ptr<Text>; // Carga un objeto de texto específico bajo demanda auto loadTextLazy(const std::string& name) -> std::shared_ptr<Text>; // Carga un objeto de texto específico bajo demanda
static auto loadAnimationLazy(const std::string& name) -> AnimationsFileBuffer; // Carga una animación específica bajo demanda static auto loadAnimationLazy(const std::string& name) -> AnimationsFileBuffer; // Carga una animación específica bajo demanda
// --- Métodos internos para gestionar el progreso --- // --- Métodos internos para gestionar el progreso ---
void calculateTotalResources(); // Calcula el número de recursos para cargar void calculateTotalResources(); // Calcula el número de recursos para cargar
void renderProgress(); // Muestra el progreso de carga void renderProgress(); // Muestra el progreso de carga
static void checkEvents(); // Comprueba los eventos durante la carga static void checkEvents(); // Comprueba los eventos durante la carga
void updateLoadingProgress(std::string name); // Actualiza el progreso de carga void updateLoadingProgress(std::string name); // Actualiza el progreso de carga
void initProgressBar(); // Inicializa los rectangulos que definen la barra de progreso void initProgressBar(); // Inicializa los rectangulos que definen la barra de progreso
void updateProgressBar(); // Actualiza la barra de estado void updateProgressBar(); // Actualiza la barra de estado
// --- Constructores y destructor privados (singleton) --- // --- Constructores y destructor privados (singleton) ---
explicit Resource(LoadingMode mode); // Constructor privado con modo de carga explicit Resource(LoadingMode mode); // Constructor privado con modo de carga
~Resource(); // Destructor privado ~Resource(); // Destructor privado
// --- Instancia singleton --- // --- Instancia singleton ---
static Resource* instance; // Instancia única de Resource static Resource* instance; // Instancia única de Resource
}; };
+72 -72
View File
@@ -8,91 +8,91 @@
#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();
resource_system_initialized = loader.initialize(pack_file, enable_fallback);
if (resource_system_initialized) {
std::cout << "Resource system initialized with pack: " << pack_file << '\n';
} else {
std::cout << "Resource system using fallback mode (filesystem only)" << '\n';
}
return true; // Always return true as fallback is acceptable
}
void shutdownResourceSystem() {
if (resource_system_initialized) {
ResourceLoader::getInstance().shutdown();
resource_system_initialized = false;
}
}
auto loadFile(const std::string& filepath) -> std::vector<uint8_t> {
if (resource_system_initialized && shouldUseResourcePack(filepath)) {
auto& loader = ResourceLoader::getInstance(); auto& loader = ResourceLoader::getInstance();
std::string pack_path = getPackPath(filepath); resource_system_initialized = loader.initialize(pack_file, enable_fallback);
auto data = loader.loadResource(pack_path); if (resource_system_initialized) {
if (!data.empty()) { std::cout << "Resource system initialized with pack: " << pack_file << '\n';
return data; } else {
std::cout << "Resource system using fallback mode (filesystem only)" << '\n';
}
return true; // Always return true as fallback is acceptable
}
void shutdownResourceSystem() {
if (resource_system_initialized) {
ResourceLoader::getInstance().shutdown();
resource_system_initialized = false;
} }
} }
// Fallback a filesystem auto loadFile(const std::string& filepath) -> std::vector<uint8_t> {
std::ifstream file(filepath, std::ios::binary | std::ios::ate); if (resource_system_initialized && shouldUseResourcePack(filepath)) {
if (!file) { auto& loader = ResourceLoader::getInstance();
return {}; std::string pack_path = getPackPath(filepath);
auto data = loader.loadResource(pack_path);
if (!data.empty()) {
return data;
}
}
// Fallback a filesystem
std::ifstream file(filepath, std::ios::binary | std::ios::ate);
if (!file) {
return {};
}
std::streamsize file_size = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<uint8_t> data(file_size);
if (!file.read(reinterpret_cast<char*>(data.data()), file_size)) {
return {};
}
return data;
} }
std::streamsize file_size = file.tellg(); auto shouldUseResourcePack(const std::string& filepath) -> bool {
file.seekg(0, std::ios::beg); // Archivos que NO van al pack:
// - config/ (ahora está fuera de data/)
// - archivos absolutos del sistema
std::vector<uint8_t> data(file_size); if (filepath.find("config/") != std::string::npos) {
if (!file.read(reinterpret_cast<char*>(data.data()), file_size)) { return false;
return {}; }
}
return data; // Si contiene "data/" es candidato para el pack
} if (filepath.find("data/") != std::string::npos) {
return true;
}
auto shouldUseResourcePack(const std::string& filepath) -> bool {
// Archivos que NO van al pack:
// - config/ (ahora está fuera de data/)
// - archivos absolutos del sistema
if (filepath.find("config/") != std::string::npos) {
return false; return false;
} }
// Si contiene "data/" es candidato para el pack auto getPackPath(const std::string& asset_path) -> std::string {
if (filepath.find("data/") != std::string::npos) { std::string pack_path = asset_path;
return true;
// Normalizar separadores de path a '/'
std::ranges::replace(pack_path, '\\', '/');
// Remover prefijo "data/" si existe
size_t data_pos = pack_path.find("data/");
if (data_pos != std::string::npos) {
pack_path = pack_path.substr(data_pos + 5); // +5 para saltar "data/"
}
// Remover cualquier prefijo de path absoluto
size_t last_data = pack_path.rfind("data/");
if (last_data != std::string::npos) {
pack_path = pack_path.substr(last_data + 5);
}
return pack_path;
} }
return false;
}
auto getPackPath(const std::string& asset_path) -> std::string {
std::string pack_path = asset_path;
// Normalizar separadores de path a '/'
std::ranges::replace(pack_path, '\\', '/');
// Remover prefijo "data/" si existe
size_t data_pos = pack_path.find("data/");
if (data_pos != std::string::npos) {
pack_path = pack_path.substr(data_pos + 5); // +5 para saltar "data/"
}
// Remover cualquier prefijo de path absoluto
size_t last_data = pack_path.rfind("data/");
if (last_data != std::string::npos) {
pack_path = pack_path.substr(last_data + 5);
}
return pack_path;
}
} // namespace ResourceHelper } // namespace ResourceHelper
+28 -28
View File
@@ -8,38 +8,38 @@
// 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());
}
// Crear archivo temporal para funciones que esperan path
std::string temp_path = "/tmp/ccae_" + std::to_string(std::hash<std::string>{}(asset_path));
std::ofstream temp_file(temp_path, std::ios::binary);
temp_file.write(reinterpret_cast<const char*>(data.data()), data.size());
temp_file.close();
T* result = loader_func(temp_path.c_str());
std::filesystem::remove(temp_path);
return result;
} }
// Crear archivo temporal para funciones que esperan path
std::string temp_path = "/tmp/ccae_" + std::to_string(std::hash<std::string>{}(asset_path));
std::ofstream temp_file(temp_path, std::ios::binary);
temp_file.write(reinterpret_cast<const char*>(data.data()), data.size());
temp_file.close();
T* result = loader_func(temp_path.c_str());
std::filesystem::remove(temp_path);
return result;
}
} // namespace ResourceHelper } // namespace ResourceHelper
+20 -20
View File
@@ -9,31 +9,31 @@
class ResourcePack; class ResourcePack;
class ResourceLoader { class ResourceLoader {
private: private:
static std::unique_ptr<ResourceLoader> instance; static std::unique_ptr<ResourceLoader> instance;
ResourcePack* resource_pack_; ResourcePack* resource_pack_;
std::string pack_path_; std::string pack_path_;
bool fallback_to_files_; bool fallback_to_files_;
ResourceLoader(); ResourceLoader();
public: public:
static auto getInstance() -> ResourceLoader&; static auto getInstance() -> ResourceLoader&;
~ResourceLoader(); ~ResourceLoader();
auto initialize(const std::string& pack_file, bool enable_fallback = true) -> bool; auto initialize(const std::string& pack_file, bool enable_fallback = true) -> bool;
void shutdown(); void shutdown();
auto loadResource(const std::string& filename) -> std::vector<uint8_t>; auto loadResource(const std::string& filename) -> std::vector<uint8_t>;
auto resourceExists(const std::string& filename) -> bool; auto resourceExists(const std::string& filename) -> bool;
void setFallbackToFiles(bool enable) { fallback_to_files_ = enable; } void setFallbackToFiles(bool enable) { fallback_to_files_ = enable; }
[[nodiscard]] auto getFallbackToFiles() const -> bool { return fallback_to_files_; } [[nodiscard]] auto getFallbackToFiles() const -> bool { return fallback_to_files_; }
[[nodiscard]] auto getLoadedResourceCount() const -> size_t; [[nodiscard]] auto getLoadedResourceCount() const -> size_t;
[[nodiscard]] auto getAvailableResources() const -> std::vector<std::string>; [[nodiscard]] auto getAvailableResources() const -> std::vector<std::string>;
private: private:
static auto loadFromFile(const std::string& filename) -> std::vector<uint8_t>; static auto loadFromFile(const std::string& filename) -> std::vector<uint8_t>;
static auto getDataPath(const std::string& filename) -> std::string; static auto getDataPath(const std::string& filename) -> std::string;
}; };
+24 -24
View File
@@ -7,38 +7,38 @@
#include <vector> // Para vector #include <vector> // Para vector
struct ResourceEntry { struct ResourceEntry {
std::string filename; std::string filename;
uint64_t offset; uint64_t offset;
uint64_t size; uint64_t size;
uint32_t checksum; uint32_t checksum;
}; };
class ResourcePack { class ResourcePack {
private: private:
std::unordered_map<std::string, ResourceEntry> resources_; std::unordered_map<std::string, ResourceEntry> resources_;
std::vector<uint8_t> data_; std::vector<uint8_t> data_;
bool loaded_; bool loaded_;
static auto calculateChecksum(const std::vector<uint8_t>& data) -> uint32_t; static auto calculateChecksum(const std::vector<uint8_t>& data) -> uint32_t;
static void encryptData(std::vector<uint8_t>& data, const std::string& key); static void encryptData(std::vector<uint8_t>& data, const std::string& key);
static void decryptData(std::vector<uint8_t>& data, const std::string& key); static void decryptData(std::vector<uint8_t>& data, const std::string& key);
public: public:
ResourcePack(); ResourcePack();
~ResourcePack(); ~ResourcePack();
auto loadPack(const std::string& pack_file) -> bool; auto loadPack(const std::string& pack_file) -> bool;
auto savePack(const std::string& pack_file) -> bool; auto savePack(const std::string& pack_file) -> bool;
auto addFile(const std::string& filename, const std::string& filepath) -> bool; auto addFile(const std::string& filename, const std::string& filepath) -> bool;
auto addDirectory(const std::string& directory) -> bool; auto addDirectory(const std::string& directory) -> bool;
auto getResource(const std::string& filename) -> std::vector<uint8_t>; auto getResource(const std::string& filename) -> std::vector<uint8_t>;
auto hasResource(const std::string& filename) const -> bool; auto hasResource(const std::string& filename) const -> bool;
void clear(); void clear();
auto getResourceCount() const -> size_t; auto getResourceCount() const -> size_t;
auto getResourceList() const -> std::vector<std::string>; auto getResourceList() const -> std::vector<std::string>;
static const std::string DEFAULT_ENCRYPT_KEY; static const std::string DEFAULT_ENCRYPT_KEY;
}; };
+133 -133
View File
@@ -19,151 +19,151 @@ class Texture;
// --- Clase Scoreboard --- // --- Clase Scoreboard ---
class Scoreboard { class Scoreboard {
public: public:
// --- Enums --- // --- Enums ---
enum class Id : size_t { enum class Id : size_t {
LEFT = 0, LEFT = 0,
CENTER = 1, CENTER = 1,
RIGHT = 2, RIGHT = 2,
SIZE = 3 SIZE = 3
}; };
enum class Mode : int { enum class Mode : int {
SCORE, SCORE,
STAGE_INFO, STAGE_INFO,
CONTINUE, CONTINUE,
WAITING, WAITING,
GAME_OVER, GAME_OVER,
DEMO, DEMO,
SCORE_TO_ENTER_NAME, // Transición animada: SCORE → ENTER_NAME SCORE_TO_ENTER_NAME, // Transición animada: SCORE → ENTER_NAME
ENTER_NAME, ENTER_NAME,
ENTER_TO_SHOW_NAME, // Transición animada: ENTER_NAME → SHOW_NAME ENTER_TO_SHOW_NAME, // Transición animada: ENTER_NAME → SHOW_NAME
SHOW_NAME, SHOW_NAME,
GAME_COMPLETED, GAME_COMPLETED,
NUM_MODES, NUM_MODES,
}; };
// --- Estructuras --- // --- Estructuras ---
struct Panel { struct Panel {
Mode mode; // Modo en el que se encuentra el panel Mode mode; // Modo en el que se encuentra el panel
SDL_FRect pos; // Posición donde dibujar el panel dentro del marcador SDL_FRect pos; // Posición donde dibujar el panel dentro del marcador
}; };
struct PanelPulse { struct PanelPulse {
bool active = false; // Si el pulso está activo bool active = false; // Si el pulso está activo
float elapsed_s = 0.0F; // Tiempo transcurrido desde el inicio float elapsed_s = 0.0F; // Tiempo transcurrido desde el inicio
float duration_s = 0.5F; // Duración total del pulso float duration_s = 0.5F; // Duración total del pulso
}; };
// --- Métodos de singleton --- // --- Métodos de singleton ---
static void init(); // Crea el objeto Scoreboard static void init(); // Crea el objeto Scoreboard
static void destroy(); // Libera el objeto Scoreboard static void destroy(); // Libera el objeto Scoreboard
static auto get() -> Scoreboard*; // Obtiene el puntero al objeto Scoreboard static auto get() -> Scoreboard*; // Obtiene el puntero al objeto Scoreboard
// --- Métodos principales --- // --- Métodos principales ---
void update(float delta_time); // Actualiza la lógica del marcador void update(float delta_time); // Actualiza la lógica del marcador
void render(); // Pinta el marcador void render(); // Pinta el marcador
// --- Setters --- // --- Setters ---
void setColor(Color color); // Establece el color del marcador void setColor(Color color); // Establece el color del marcador
void setPos(SDL_FRect rect); // Establece la posición y tamaño del marcador void setPos(SDL_FRect rect); // Establece la posición y tamaño del marcador
void setContinue(Id id, int continue_counter) { continue_counter_.at(static_cast<size_t>(id)) = continue_counter; } void setContinue(Id id, int continue_counter) { continue_counter_.at(static_cast<size_t>(id)) = continue_counter; }
void setHiScore(int hi_score) { hi_score_ = hi_score; } void setHiScore(int hi_score) { hi_score_ = hi_score; }
void setHiScoreName(const std::string& name) { hi_score_name_ = name; } void setHiScoreName(const std::string& name) { hi_score_name_ = name; }
void setMode(Id id, Mode mode); // Establece el modo del panel y gestiona transiciones void setMode(Id id, Mode mode); // Establece el modo del panel y gestiona transiciones
void setMult(Id id, float mult) { mult_.at(static_cast<size_t>(id)) = mult; } void setMult(Id id, float mult) { mult_.at(static_cast<size_t>(id)) = mult; }
void setName(Id id, const std::string& name) { name_.at(static_cast<size_t>(id)) = name; } void setName(Id id, const std::string& name) { name_.at(static_cast<size_t>(id)) = name; }
void setPower(float power) { power_ = power; } void setPower(float power) { power_ = power; }
void setEnterName(Id id, const std::string& enter_name) { enter_name_.at(static_cast<size_t>(id)) = enter_name; } void setEnterName(Id id, const std::string& enter_name) { enter_name_.at(static_cast<size_t>(id)) = enter_name; }
void setCharacterSelected(Id id, const std::string& character_selected) { character_selected_.at(static_cast<size_t>(id)) = character_selected; } void setCharacterSelected(Id id, const std::string& character_selected) { character_selected_.at(static_cast<size_t>(id)) = character_selected; }
void setCarouselAnimation(Id id, int selected_index, EnterName* enter_name_ptr); // Configura la animación del carrusel void setCarouselAnimation(Id id, int selected_index, EnterName* enter_name_ptr); // Configura la animación del carrusel
void setScore(Id id, int score) { score_.at(static_cast<size_t>(id)) = score; } void setScore(Id id, int score) { score_.at(static_cast<size_t>(id)) = score; }
void setSelectorPos(Id id, int pos) { selector_pos_.at(static_cast<size_t>(id)) = pos; } void setSelectorPos(Id id, int pos) { selector_pos_.at(static_cast<size_t>(id)) = pos; }
void setStage(int stage) { stage_ = stage; } void setStage(int stage) { stage_ = stage; }
void triggerPanelPulse(Id id, float duration_s = 0.5F); // Activa un pulso en el panel especificado void triggerPanelPulse(Id id, float duration_s = 0.5F); // Activa un pulso en el panel especificado
private: private:
// --- Objetos y punteros --- // --- Objetos y punteros ---
SDL_Renderer* renderer_; // El renderizador de la ventana SDL_Renderer* renderer_; // El renderizador de la ventana
std::shared_ptr<Texture> game_power_meter_texture_; // Textura con el marcador de poder de la fase std::shared_ptr<Texture> game_power_meter_texture_; // Textura con el marcador de poder de la fase
std::unique_ptr<Sprite> power_meter_sprite_; // Sprite para el medidor de poder de la fase std::unique_ptr<Sprite> power_meter_sprite_; // Sprite para el medidor de poder de la fase
std::shared_ptr<Text> text_; // Fuente para el marcador del juego std::shared_ptr<Text> text_; // Fuente para el marcador del juego
SDL_Texture* background_ = nullptr; // Textura para dibujar el marcador SDL_Texture* background_ = nullptr; // Textura para dibujar el marcador
std::vector<SDL_Texture*> panel_texture_; // Texturas para dibujar cada panel std::vector<SDL_Texture*> panel_texture_; // Texturas para dibujar cada panel
// --- Variables de estado --- // --- Variables de estado ---
std::array<std::string, static_cast<int>(Id::SIZE)> name_ = {}; // Nombre de cada jugador std::array<std::string, static_cast<int>(Id::SIZE)> name_ = {}; // Nombre de cada jugador
std::array<std::string, static_cast<int>(Id::SIZE)> enter_name_ = {}; // Nombre introducido para la tabla de records std::array<std::string, static_cast<int>(Id::SIZE)> enter_name_ = {}; // Nombre introducido para la tabla de records
std::array<std::string, static_cast<int>(Id::SIZE)> character_selected_ = {}; // Caracter seleccionado std::array<std::string, static_cast<int>(Id::SIZE)> character_selected_ = {}; // Caracter seleccionado
std::array<EnterName*, static_cast<int>(Id::SIZE)> enter_name_ref_ = {}; // Referencias a EnterName para obtener character_list_ std::array<EnterName*, static_cast<int>(Id::SIZE)> enter_name_ref_ = {}; // Referencias a EnterName para obtener character_list_
std::array<float, static_cast<int>(Id::SIZE)> carousel_position_ = {}; // Posición actual del carrusel (índice en character_list_) std::array<float, static_cast<int>(Id::SIZE)> carousel_position_ = {}; // Posición actual del carrusel (índice en character_list_)
std::array<float, static_cast<int>(Id::SIZE)> carousel_target_ = {}; // Posición objetivo del carrusel std::array<float, static_cast<int>(Id::SIZE)> carousel_target_ = {}; // Posición objetivo del carrusel
std::array<int, static_cast<int>(Id::SIZE)> carousel_prev_index_ = {}; // Índice previo para detectar cambios std::array<int, static_cast<int>(Id::SIZE)> carousel_prev_index_ = {}; // Índice previo para detectar cambios
std::array<float, static_cast<int>(Id::SIZE)> text_slide_offset_ = {}; // Progreso de animación de deslizamiento (0.0 a 1.0) std::array<float, static_cast<int>(Id::SIZE)> text_slide_offset_ = {}; // Progreso de animación de deslizamiento (0.0 a 1.0)
std::array<Panel, static_cast<int>(Id::SIZE)> panel_ = {}; // Lista con todos los paneles del marcador std::array<Panel, static_cast<int>(Id::SIZE)> panel_ = {}; // Lista con todos los paneles del marcador
std::array<PanelPulse, static_cast<int>(Id::SIZE)> panel_pulse_ = {}; // Estado de pulso para cada panel std::array<PanelPulse, static_cast<int>(Id::SIZE)> panel_pulse_ = {}; // Estado de pulso para cada panel
Colors::Cycle name_color_cycle_; // Ciclo de colores para destacar el nombre una vez introducido Colors::Cycle name_color_cycle_; // Ciclo de colores para destacar el nombre una vez introducido
Color animated_color_; // Color actual animado (ciclo automático cada 100ms) Color animated_color_; // Color actual animado (ciclo automático cada 100ms)
std::string hi_score_name_; // Nombre del jugador con la máxima puntuación std::string hi_score_name_; // Nombre del jugador con la máxima puntuación
SDL_FRect rect_ = {0, 0, 320, 40}; // Posición y dimensiones del marcador SDL_FRect rect_ = {0, 0, 320, 40}; // Posición y dimensiones del marcador
Color color_; // Color del marcador Color color_; // Color del marcador
std::array<size_t, static_cast<int>(Id::SIZE)> selector_pos_ = {}; // Posición del selector de letra para introducir el nombre std::array<size_t, static_cast<int>(Id::SIZE)> selector_pos_ = {}; // Posición del selector de letra para introducir el nombre
std::array<int, static_cast<int>(Id::SIZE)> score_ = {}; // Puntuación de los jugadores std::array<int, static_cast<int>(Id::SIZE)> score_ = {}; // Puntuación de los jugadores
std::array<int, static_cast<int>(Id::SIZE)> continue_counter_ = {}; // Tiempo para continuar de los jugadores std::array<int, static_cast<int>(Id::SIZE)> continue_counter_ = {}; // Tiempo para continuar de los jugadores
std::array<float, static_cast<int>(Id::SIZE)> mult_ = {}; // Multiplicador de los jugadores std::array<float, static_cast<int>(Id::SIZE)> mult_ = {}; // Multiplicador de los jugadores
Uint64 ticks_ = SDL_GetTicks(); // Variable donde almacenar el valor de SDL_GetTicks() Uint64 ticks_ = SDL_GetTicks(); // Variable donde almacenar el valor de SDL_GetTicks()
int stage_ = 1; // Número de fase actual int stage_ = 1; // Número de fase actual
int hi_score_ = 0; // Máxima puntuación int hi_score_ = 0; // Máxima puntuación
int time_counter_ = 0; // Contador de segundos int time_counter_ = 0; // Contador de segundos
Uint32 name_color_index_ = 0; // Índice actual del color en el ciclo de animación del nombre Uint32 name_color_index_ = 0; // Índice actual del color en el ciclo de animación del nombre
Uint64 name_color_last_update_ = 0; // Último tick de actualización del color del nombre Uint64 name_color_last_update_ = 0; // Último tick de actualización del color del nombre
float power_ = 0.0F; // Poder actual de la fase float power_ = 0.0F; // Poder actual de la fase
std::array<float, static_cast<size_t>(Id::SIZE)> carousel_speed_scale_ = {1.0F, 1.0F, 1.0F}; std::array<float, static_cast<size_t>(Id::SIZE)> carousel_speed_scale_ = {1.0F, 1.0F, 1.0F};
// --- Constantes --- // --- Constantes ---
static constexpr int CAROUSEL_VISIBLE_LETTERS = 9; static constexpr int CAROUSEL_VISIBLE_LETTERS = 9;
static constexpr float TEXT_SLIDE_DURATION = 0.3F; // Duración de la animación de deslizamiento en segundos static constexpr float TEXT_SLIDE_DURATION = 0.3F; // Duración de la animación de deslizamiento en segundos
static constexpr int PANEL_PULSE_LIGHTEN_AMOUNT = 40; // Cantidad de aclarado para el pulso del panel static constexpr int PANEL_PULSE_LIGHTEN_AMOUNT = 40; // Cantidad de aclarado para el pulso del panel
// --- Variables de aspecto --- // --- Variables de aspecto ---
Color text_color1_, text_color2_; // Colores para los marcadores del texto; Color text_color1_, text_color2_; // Colores para los marcadores del texto;
// --- Puntos predefinidos para colocar elementos en los paneles --- // --- Puntos predefinidos para colocar elementos en los paneles ---
SDL_FPoint slot4_1_, slot4_2_, slot4_3_, slot4_4_; SDL_FPoint slot4_1_, slot4_2_, slot4_3_, slot4_4_;
SDL_FPoint enter_name_pos_; SDL_FPoint enter_name_pos_;
// --- Métodos internos --- // --- Métodos internos ---
void recalculateAnchors(); // Recalcula las anclas de los elementos void recalculateAnchors(); // Recalcula las anclas de los elementos
static auto updateScoreText(int num) -> std::string; // Transforma un valor numérico en una cadena de 7 cifras static auto updateScoreText(int num) -> std::string; // Transforma un valor numérico en una cadena de 7 cifras
void createBackgroundTexture(); // Crea la textura de fondo void createBackgroundTexture(); // Crea la textura de fondo
void createPanelTextures(); // Crea las texturas de los paneles void createPanelTextures(); // Crea las texturas de los paneles
void fillPanelTextures(); // Rellena los diferentes paneles del marcador void fillPanelTextures(); // Rellena los diferentes paneles del marcador
void fillBackgroundTexture(); // Rellena la textura de fondo void fillBackgroundTexture(); // Rellena la textura de fondo
void updateTimeCounter(); // Actualiza el contador void updateTimeCounter(); // Actualiza el contador
void updateNameColorIndex(); // Actualiza el índice del color animado del nombre void updateNameColorIndex(); // Actualiza el índice del color animado del nombre
void updateCarouselAnimation(float delta_time); // Actualiza la animación del carrusel void updateCarouselAnimation(float delta_time); // Actualiza la animación del carrusel
void updateTextSlideAnimation(float delta_time); // Actualiza la animación de deslizamiento de texto void updateTextSlideAnimation(float delta_time); // Actualiza la animación de deslizamiento de texto
void updatePanelPulses(float delta_time); // Actualiza las animaciones de pulso de los paneles void updatePanelPulses(float delta_time); // Actualiza las animaciones de pulso de los paneles
void renderSeparator(); // Dibuja la línea que separa la zona de juego del marcador void renderSeparator(); // Dibuja la línea que separa la zona de juego del marcador
void renderPanelContent(size_t panel_index); void renderPanelContent(size_t panel_index);
void renderScoreMode(size_t panel_index); void renderScoreMode(size_t panel_index);
void renderDemoMode(); void renderDemoMode();
void renderWaitingMode(); void renderWaitingMode();
void renderGameOverMode(); void renderGameOverMode();
void renderStageInfoMode(); void renderStageInfoMode();
void renderContinueMode(size_t panel_index); void renderContinueMode(size_t panel_index);
void renderScoreToEnterNameMode(size_t panel_index); // Renderiza la transición SCORE → ENTER_NAME void renderScoreToEnterNameMode(size_t panel_index); // Renderiza la transición SCORE → ENTER_NAME
void renderEnterNameMode(size_t panel_index); void renderEnterNameMode(size_t panel_index);
void renderNameInputField(size_t panel_index); void renderNameInputField(size_t panel_index);
void renderEnterToShowNameMode(size_t panel_index); // Renderiza la transición ENTER_NAME → SHOW_NAME void renderEnterToShowNameMode(size_t panel_index); // Renderiza la transición ENTER_NAME → SHOW_NAME
void renderShowNameMode(size_t panel_index); void renderShowNameMode(size_t panel_index);
void renderGameCompletedMode(size_t panel_index); void renderGameCompletedMode(size_t panel_index);
void renderCarousel(size_t panel_index, int center_x, int y); // Pinta el carrusel de caracteres con colores LERP void renderCarousel(size_t panel_index, int center_x, int y); // Pinta el carrusel de caracteres con colores LERP
// --- Constructores y destructor privados (singleton) --- // --- Constructores y destructor privados (singleton) ---
Scoreboard(); // Constructor privado Scoreboard(); // Constructor privado
~Scoreboard(); // Destructor privado ~Scoreboard(); // Destructor privado
// --- Instancia singleton --- // --- Instancia singleton ---
static Scoreboard* instance; // Instancia única de Scoreboard static Scoreboard* instance; // Instancia única de Scoreboard
}; };
+197 -197
View File
@@ -14,239 +14,239 @@ 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) ---
class Screen { class Screen {
public: public:
// --- Métodos de singleton --- // --- Métodos de singleton ---
static void init(); // Inicializa el objeto Screen static void init(); // Inicializa el objeto Screen
static void destroy(); // Libera el objeto Screen static void destroy(); // Libera el objeto Screen
static auto get() -> Screen*; // Obtiene el puntero al objeto Screen static auto get() -> Screen*; // Obtiene el puntero al objeto Screen
// --- Métodos principales --- // --- Métodos principales ---
void update(float delta_time); // Recibe deltaTime de las secciones y actualiza la lógica void update(float delta_time); // Recibe deltaTime de las secciones y actualiza la lógica
void coreUpdate(); // Actualiza los elementos mínimos void coreUpdate(); // Actualiza los elementos mínimos
void clean(Color color = Color(0x00, 0x00, 0x00)); // Limpia la pantalla void clean(Color color = Color(0x00, 0x00, 0x00)); // Limpia la pantalla
void start(); // Prepara para empezar a dibujar en la textura de juego void start(); // Prepara para empezar a dibujar en la textura de juego
void render(); // Vuelca el contenido del renderizador en pantalla void render(); // Vuelca el contenido del renderizador en pantalla
void coreRender(); // Vuelca el contenido del renderizador en pantalla exceptuando ciertas partes void coreRender(); // Vuelca el contenido del renderizador en pantalla exceptuando ciertas partes
// --- Configuración de ventana y render --- // --- Configuración de ventana y render ---
void setFullscreenMode(); // Establece el modo de pantalla completa void setFullscreenMode(); // Establece el modo de pantalla completa
void toggleFullscreen(); // Cambia entre pantalla completa y ventana void toggleFullscreen(); // Cambia entre pantalla completa y ventana
void setWindowZoom(int zoom); // Cambia el tamaño de la ventana void setWindowZoom(int zoom); // Cambia el tamaño de la ventana
auto decWindowSize() -> bool; // Reduce el tamaño de la ventana auto decWindowSize() -> bool; // Reduce el tamaño de la ventana
auto incWindowSize() -> bool; // Aumenta el tamaño de la ventana auto incWindowSize() -> bool; // Aumenta el tamaño de la ventana
void applySettings(); // Aplica los valores de las opciones void applySettings(); // Aplica los valores de las opciones
void initShaders(); // Inicializa los shaders void initShaders(); // Inicializa los shaders
// --- Efectos visuales --- // --- Efectos visuales ---
void shake(int desp = 2, float delay_s = 0.05F, float duration_s = 0.133F) { shake_effect_.enable(src_rect_, dst_rect_, desp, delay_s, duration_s); } // Agita la pantalla (tiempo en segundos) void shake(int desp = 2, float delay_s = 0.05F, float duration_s = 0.133F) { shake_effect_.enable(src_rect_, dst_rect_, desp, delay_s, duration_s); } // Agita la pantalla (tiempo en segundos)
void flash(Color color, float duration_s = 0.167F, float delay_s = 0.0F) { flash_effect_ = FlashEffect(true, duration_s, delay_s, color); } // Pone la pantalla de color (tiempo en segundos) void flash(Color color, float duration_s = 0.167F, float delay_s = 0.0F) { flash_effect_ = FlashEffect(true, duration_s, delay_s, color); } // Pone la pantalla de color (tiempo en segundos)
void toggleShaders(); // Alterna entre activar y desactivar los shaders void toggleShaders(); // Alterna entre activar y desactivar los shaders
void toggleIntegerScale(); // Alterna entre activar y desactivar el escalado entero void toggleIntegerScale(); // Alterna entre activar y desactivar el escalado entero
void toggleVSync(); // Alterna entre activar y desactivar el V-Sync void toggleVSync(); // Alterna entre activar y desactivar el V-Sync
void setVSync(bool enabled); // Establece el estado del V-Sync void setVSync(bool enabled); // Establece el estado del V-Sync
void attenuate(bool value) { attenuate_effect_ = value; } // Atenúa la pantalla void attenuate(bool value) { attenuate_effect_ = value; } // Atenúa la pantalla
// --- Getters --- // --- Getters ---
auto getRenderer() -> SDL_Renderer* { return renderer_; } // Obtiene el renderizador auto getRenderer() -> SDL_Renderer* { return renderer_; } // Obtiene el renderizador
void show() { SDL_ShowWindow(window_); } // Muestra la ventana void show() { SDL_ShowWindow(window_); } // Muestra la ventana
void hide() { SDL_HideWindow(window_); } // Oculta la ventana void hide() { SDL_HideWindow(window_); } // Oculta la ventana
void getSingletons(); // Obtiene los punteros a los singletones void getSingletons(); // Obtiene los punteros a los singletones
[[nodiscard]] static auto getVSync() -> bool { return Options::video.vsync; } // Obtiene el valor de V-Sync [[nodiscard]] static auto getVSync() -> bool { return Options::video.vsync; } // Obtiene el valor de V-Sync
[[nodiscard]] auto getText() const -> std::shared_ptr<Text> { return text_; } // Obtiene el puntero al texto de Screen [[nodiscard]] auto getText() const -> std::shared_ptr<Text> { return text_; } // Obtiene el puntero al texto de Screen
// --- Display Monitor getters --- // --- Display Monitor getters ---
[[nodiscard]] auto getDisplayMonitorName() const -> std::string { return display_monitor_.name; } [[nodiscard]] auto getDisplayMonitorName() const -> std::string { return display_monitor_.name; }
[[nodiscard]] auto getDisplayMonitorWidth() const -> int { return display_monitor_.width; } [[nodiscard]] auto getDisplayMonitorWidth() const -> int { return display_monitor_.width; }
[[nodiscard]] auto getDisplayMonitorHeight() const -> int { return display_monitor_.height; } [[nodiscard]] auto getDisplayMonitorHeight() const -> int { return display_monitor_.height; }
[[nodiscard]] auto getDisplayMonitorRefreshRate() const -> int { return display_monitor_.refresh_rate; } [[nodiscard]] auto getDisplayMonitorRefreshRate() const -> int { return display_monitor_.refresh_rate; }
#ifdef _DEBUG #ifdef _DEBUG
// --- Debug --- // --- Debug ---
void toggleDebugInfo() { debug_info_.show = !debug_info_.show; } void toggleDebugInfo() { debug_info_.show = !debug_info_.show; }
void setDebugInfoEnabled(bool value) { debug_info_.show = value; } void setDebugInfoEnabled(bool value) { debug_info_.show = value; }
#endif #endif
private: private:
// --- Constantes --- // --- Constantes ---
static constexpr int WINDOWS_DECORATIONS = 35; // Decoraciones de la ventana static constexpr int WINDOWS_DECORATIONS = 35; // Decoraciones de la ventana
// --- Estructuras privadas --- // --- Estructuras privadas ---
struct DisplayMonitor { struct DisplayMonitor {
std::string name; std::string name;
int width; int width;
int height; int height;
int refresh_rate; int refresh_rate;
}; };
struct FPS { struct FPS {
Uint32 ticks{0}; // Tiempo en milisegundos desde que se comenzó a contar. Uint32 ticks{0}; // Tiempo en milisegundos desde que se comenzó a contar.
int frame_count{0}; // Número acumulado de frames en el intervalo. int frame_count{0}; // Número acumulado de frames en el intervalo.
int last_value{0}; // Número de frames calculado en el último segundo. int last_value{0}; // Número de frames calculado en el último segundo.
FPS() = default; FPS() = default;
void increment() { frame_count++; } void increment() { frame_count++; }
auto calculate(Uint32 current_ticks) -> int { auto calculate(Uint32 current_ticks) -> int {
if (current_ticks - ticks >= 1000) { if (current_ticks - ticks >= 1000) {
last_value = frame_count; last_value = frame_count;
frame_count = 0; frame_count = 0;
ticks = current_ticks; ticks = current_ticks;
} }
return last_value; return last_value;
}
};
// Efecto de flash en pantalla: pinta la pantalla de un color durante un tiempo
struct FlashEffect {
bool enabled; // Indica si el efecto está activo
float duration_s; // Duración total del efecto en segundos
float delay_s; // Retraso antes de mostrar el flash en segundos
float timer_s; // Timer en segundos (contador decreciente)
Color color; // Color del flash
explicit FlashEffect(bool enabled = false, float duration_s = 0.0F, float delay_s = 0.0F, Color color = Color(0xFF, 0xFF, 0xFF))
: enabled(enabled),
duration_s(duration_s),
delay_s(delay_s),
timer_s(duration_s),
color(color) {}
void update(float delta_time) {
if (enabled && timer_s > 0.0F) {
timer_s -= delta_time;
if (timer_s <= 0.0F) {
enabled = false;
} }
}; }
}
[[nodiscard]] auto isRendarable() const -> bool { return enabled && timer_s < duration_s - delay_s; }
};
// Efecto de flash en pantalla: pinta la pantalla de un color durante un tiempo // Efecto de sacudida/agitación de pantalla: mueve la imagen para simular un temblor
struct FlashEffect { struct ShakeEffect {
bool enabled; // Indica si el efecto está activo int desp; // Desplazamiento máximo de la sacudida (en píxeles)
float duration_s; // Duración total del efecto en segundos float delay_s; // Segundos entre cada movimiento de sacudida
float delay_s; // Retraso antes de mostrar el flash en segundos float counter_s; // Timer para el siguiente movimiento (decreciente)
float timer_s; // Timer en segundos (contador decreciente) float duration_s; // Duración total del efecto en segundos
Color color; // Color del flash float remaining_s; // Tiempo restante de sacudida
int original_pos; // Posición original de la imagen (x)
int original_width; // Ancho original de la imagen
bool enabled; // Indica si el efecto está activo
explicit FlashEffect(bool enabled = false, float duration_s = 0.0F, float delay_s = 0.0F, Color color = Color(0xFF, 0xFF, 0xFF)) explicit ShakeEffect(bool en = false, int dp = 2, float dl_s = 0.05F, float cnt_s = 0.0F, float len_s = 0.133F, float rem_s = 0.0F, int orig_pos = 0, int orig_width = 800)
: enabled(enabled), : desp(dp),
duration_s(duration_s), delay_s(dl_s),
delay_s(delay_s), counter_s(cnt_s),
timer_s(duration_s), duration_s(len_s),
color(color) {} remaining_s(rem_s),
original_pos(orig_pos),
original_width(orig_width),
enabled(en) {}
void update(float delta_time) { // Activa el efecto de sacudida y guarda la posición y tamaño originales
if (enabled && timer_s > 0.0F) { void enable(SDL_FRect& src_rect, SDL_FRect& dst_rect, int new_desp = -1, float new_delay_s = -1.0F, float new_duration_s = -1.0F) {
timer_s -= delta_time; if (!enabled) {
if (timer_s <= 0.0F) { enabled = true;
enabled = false; original_pos = src_rect.x;
} original_width = src_rect.w;
}
// Usar nuevos valores si se proporcionan, sino mantener los actuales
if (new_desp != -1) {
desp = new_desp;
}
if (new_delay_s >= 0.0F) {
delay_s = new_delay_s;
}
if (new_duration_s >= 0.0F) {
duration_s = new_duration_s;
} }
[[nodiscard]] auto isRendarable() const -> bool { return enabled && timer_s < duration_s - delay_s; }
};
// Efecto de sacudida/agitación de pantalla: mueve la imagen para simular un temblor src_rect.w -= desp;
struct ShakeEffect { dst_rect.w = src_rect.w;
int desp; // Desplazamiento máximo de la sacudida (en píxeles) }
float delay_s; // Segundos entre cada movimiento de sacudida remaining_s = duration_s;
float counter_s; // Timer para el siguiente movimiento (decreciente) counter_s = delay_s;
float duration_s; // Duración total del efecto en segundos }
float remaining_s; // Tiempo restante de sacudida
int original_pos; // Posición original de la imagen (x)
int original_width; // Ancho original de la imagen
bool enabled; // Indica si el efecto está activo
explicit ShakeEffect(bool en = false, int dp = 2, float dl_s = 0.05F, float cnt_s = 0.0F, float len_s = 0.133F, float rem_s = 0.0F, int orig_pos = 0, int orig_width = 800) // Actualiza el estado del efecto de sacudida
: desp(dp), void update(SDL_FRect& src_rect, SDL_FRect& dst_rect, float delta_time) {
delay_s(dl_s), if (enabled) {
counter_s(cnt_s), counter_s -= delta_time;
duration_s(len_s), if (counter_s <= 0.0F) {
remaining_s(rem_s),
original_pos(orig_pos),
original_width(orig_width),
enabled(en) {}
// Activa el efecto de sacudida y guarda la posición y tamaño originales
void enable(SDL_FRect& src_rect, SDL_FRect& dst_rect, int new_desp = -1, float new_delay_s = -1.0F, float new_duration_s = -1.0F) {
if (!enabled) {
enabled = true;
original_pos = src_rect.x;
original_width = src_rect.w;
// Usar nuevos valores si se proporcionan, sino mantener los actuales
if (new_desp != -1) {
desp = new_desp;
}
if (new_delay_s >= 0.0F) {
delay_s = new_delay_s;
}
if (new_duration_s >= 0.0F) {
duration_s = new_duration_s;
}
src_rect.w -= desp;
dst_rect.w = src_rect.w;
}
remaining_s = duration_s;
counter_s = delay_s; counter_s = delay_s;
} // Alternar desplazamiento basado en tiempo restante
const bool SHAKE_LEFT = static_cast<int>(remaining_s * 30.0F) % 2 == 0; // ~30 cambios por segundo
const auto SRC_DESP = SHAKE_LEFT ? 0 : desp;
const auto DST_DESP = SHAKE_LEFT ? desp : 0;
src_rect.x = original_pos + SRC_DESP;
dst_rect.x = original_pos + DST_DESP;
// Actualiza el estado del efecto de sacudida remaining_s -= delay_s;
void update(SDL_FRect& src_rect, SDL_FRect& dst_rect, float delta_time) { if (remaining_s <= 0.0F) {
if (enabled) { enabled = false;
counter_s -= delta_time; src_rect.x = original_pos;
if (counter_s <= 0.0F) { src_rect.w = original_width;
counter_s = delay_s; dst_rect.x = original_pos;
// Alternar desplazamiento basado en tiempo restante dst_rect.w = original_width;
const bool SHAKE_LEFT = static_cast<int>(remaining_s * 30.0F) % 2 == 0; // ~30 cambios por segundo
const auto SRC_DESP = SHAKE_LEFT ? 0 : desp;
const auto DST_DESP = SHAKE_LEFT ? desp : 0;
src_rect.x = original_pos + SRC_DESP;
dst_rect.x = original_pos + DST_DESP;
remaining_s -= delay_s;
if (remaining_s <= 0.0F) {
enabled = false;
src_rect.x = original_pos;
src_rect.w = original_width;
dst_rect.x = original_pos;
dst_rect.w = original_width;
}
}
} }
} }
}
}
[[nodiscard]] auto isEnabled() const -> bool { return enabled; } [[nodiscard]] auto isEnabled() const -> bool { return enabled; }
}; };
#ifdef _DEBUG #ifdef _DEBUG
struct Debug { struct Debug {
std::shared_ptr<Text> text; std::shared_ptr<Text> text;
bool show = false; bool show = false;
}; };
#endif #endif
// --- Objetos y punteros --- // --- Objetos y punteros ---
SDL_Window* window_; // Ventana de la aplicación SDL_Window* window_; // Ventana de la aplicación
SDL_Renderer* renderer_; // El renderizador de la ventana SDL_Renderer* renderer_; // El renderizador de la ventana
SDL_Texture* game_canvas_; // Textura donde se dibuja todo antes de volcarse al renderizador SDL_Texture* game_canvas_; // Textura donde se dibuja todo antes de volcarse al renderizador
ServiceMenu* service_menu_; // Objeto para mostrar el menú de servicio ServiceMenu* service_menu_; // Objeto para mostrar el menú de servicio
Notifier* notifier_; // Objeto para mostrar las notificaciones por pantalla Notifier* notifier_; // Objeto para mostrar las notificaciones por pantalla
std::shared_ptr<Text> text_; // Objeto para escribir texto en pantalla std::shared_ptr<Text> text_; // Objeto para escribir texto en pantalla
std::unique_ptr<Rendering::ShaderBackend> shader_backend_; // Backend de shaders (OpenGL/Metal/Vulkan) std::unique_ptr<Rendering::ShaderBackend> shader_backend_; // Backend de shaders (OpenGL/Metal/Vulkan)
// --- Variables de estado --- // --- Variables de estado ---
SDL_FRect src_rect_; // Coordenadas de origen para dibujar la textura del juego SDL_FRect src_rect_; // Coordenadas de origen para dibujar la textura del juego
SDL_FRect dst_rect_; // Coordenadas destino para dibujar la textura del juego SDL_FRect dst_rect_; // Coordenadas destino para dibujar la textura del juego
std::string vertex_shader_source_; // Almacena el vertex shader std::string vertex_shader_source_; // Almacena el vertex shader
std::string fragment_shader_source_; // Almacena el fragment shader std::string fragment_shader_source_; // Almacena el fragment shader
FPS fps_; // Gestión de frames por segundo FPS fps_; // Gestión de frames por segundo
FlashEffect flash_effect_; // Efecto de flash en pantalla FlashEffect flash_effect_; // Efecto de flash en pantalla
ShakeEffect shake_effect_; // Efecto de agitar la pantalla ShakeEffect shake_effect_; // Efecto de agitar la pantalla
bool attenuate_effect_ = false; // Indica si la pantalla ha de estar atenuada bool attenuate_effect_ = false; // Indica si la pantalla ha de estar atenuada
DisplayMonitor display_monitor_; // Información del monitor actual DisplayMonitor display_monitor_; // Información del monitor actual
#ifdef _DEBUG #ifdef _DEBUG
Debug debug_info_; // Información de debug Debug debug_info_; // Información de debug
#endif #endif
// --- Métodos internos --- // --- Métodos internos ---
auto initSDLVideo() -> bool; // Arranca SDL VIDEO y crea la ventana auto initSDLVideo() -> bool; // Arranca SDL VIDEO y crea la ventana
void renderFlash(); // Dibuja el efecto de flash en la pantalla void renderFlash(); // Dibuja el efecto de flash en la pantalla
void renderShake(); // Aplica el efecto de agitar la pantalla void renderShake(); // Aplica el efecto de agitar la pantalla
void renderInfo(); // Muestra información por pantalla void renderInfo(); // Muestra información por pantalla
void renderPresent(); // Selecciona y ejecuta el método de renderizado adecuado void renderPresent(); // Selecciona y ejecuta el método de renderizado adecuado
void loadShaders(); // Carga el contenido del archivo GLSL void loadShaders(); // Carga el contenido del archivo GLSL
void adjustWindowSize(); // Calcula el tamaño de la ventana void adjustWindowSize(); // Calcula el tamaño de la ventana
void getDisplayInfo(); // Obtiene información sobre la pantalla void getDisplayInfo(); // Obtiene información sobre la pantalla
void renderOverlays(); // Renderiza todos los overlays y efectos void renderOverlays(); // Renderiza todos los overlays y efectos
void renderAttenuate(); // Atenúa la pantalla void renderAttenuate(); // Atenúa la pantalla
void createText(); // Crea el objeto de texto void createText(); // Crea el objeto de texto
// --- Constructores y destructor privados (singleton) --- // --- Constructores y destructor privados (singleton) ---
Screen(); // Constructor privado Screen(); // Constructor privado
~Screen(); // Destructor privado ~Screen(); // Destructor privado
// --- Instancia singleton --- // --- Instancia singleton ---
static Screen* instance; // Instancia única de Screen static Screen* instance; // Instancia única de Screen
}; };
+35 -35
View File
@@ -7,42 +7,42 @@
*/ */
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
TITLE, // Pantalla de título/menú principal TITLE, // Pantalla de título/menú principal
GAME, // Juego principal GAME, // Juego principal
HI_SCORE_TABLE, // Tabla de récords HI_SCORE_TABLE, // Tabla de récords
GAME_DEMO, // Modo demo GAME_DEMO, // Modo demo
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
TITLE_TIME_OUT, // Timeout en el título TITLE_TIME_OUT, // Timeout en el título
TITLE_1, // Opción 1 en el título TITLE_1, // Opción 1 en el título
TITLE_2, // Opción 2 en el título TITLE_2, // Opción 2 en el título
RELOAD, // Recargar sección RELOAD, // Recargar sección
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
+126 -126
View File
@@ -17,151 +17,151 @@ class Player;
class TiledBG; class TiledBG;
class Credits { class Credits {
public: public:
// --- Constructor y destructor --- // --- Constructor y destructor ---
Credits(); Credits();
~Credits(); ~Credits();
// --- Bucle principal --- // --- Bucle principal ---
void run(); void run();
private: private:
// --- Métodos del bucle principal --- // --- Métodos del bucle principal ---
void update(float delta_time); // Actualización principal de la lógica (time-based) void update(float delta_time); // Actualización principal de la lógica (time-based)
auto calculateDeltaTime() -> float; // Calcula el deltatime auto calculateDeltaTime() -> float; // Calcula el deltatime
void initVars(); // Inicializa variables void initVars(); // Inicializa variables
void startCredits(); // Inicializa mas variables void startCredits(); // Inicializa mas variables
// --- Constantes de clase (time-based) --- // --- Constantes de clase (time-based) ---
static constexpr int PLAY_AREA_HEIGHT = 200; static constexpr int PLAY_AREA_HEIGHT = 200;
static constexpr float FAST_FORWARD_MULTIPLIER = 6.0F; static constexpr float FAST_FORWARD_MULTIPLIER = 6.0F;
static constexpr float BLACK_RECT_INTERVAL_S = 4.0F / 60.0F; // ~0.0667s (cada 4 frames a 60fps) static constexpr float BLACK_RECT_INTERVAL_S = 4.0F / 60.0F; // ~0.0667s (cada 4 frames a 60fps)
static constexpr int HORIZONTAL_SPEED = 2; static constexpr int HORIZONTAL_SPEED = 2;
static constexpr float MAX_TIME_AFTER_LOGO_S = 20.0F; static constexpr float MAX_TIME_AFTER_LOGO_S = 20.0F;
static constexpr float PRE_FADE_DELAY_S = 8.0F; static constexpr float PRE_FADE_DELAY_S = 8.0F;
// --- Objetos principales --- // --- Objetos principales ---
std::unique_ptr<BalloonManager> balloon_manager_; // Gestión de globos std::unique_ptr<BalloonManager> balloon_manager_; // Gestión de globos
std::unique_ptr<TiledBG> tiled_bg_; // Mosaico animado de fondo std::unique_ptr<TiledBG> tiled_bg_; // Mosaico animado de fondo
std::unique_ptr<Fade> fade_in_; // Fundido de entrada std::unique_ptr<Fade> fade_in_; // Fundido de entrada
std::unique_ptr<Fade> fade_out_; // Fundido de salida std::unique_ptr<Fade> fade_out_; // Fundido de salida
std::vector<std::shared_ptr<Player>> players_; // Vector de jugadores std::vector<std::shared_ptr<Player>> players_; // Vector de jugadores
// --- Gestión de texturas --- // --- Gestión de texturas ---
SDL_Texture* text_texture_; // Textura con el texto de créditos SDL_Texture* text_texture_; // Textura con el texto de créditos
SDL_Texture* canvas_; // Textura donde se dibuja todo SDL_Texture* canvas_; // Textura donde se dibuja todo
// --- Temporización (time-based puro) --- // --- Temporización (time-based puro) ---
Uint64 last_time_ = 0; // Último tiempo registrado para deltaTime Uint64 last_time_ = 0; // Último tiempo registrado para deltaTime
float elapsed_time_balloons_ = 0.0F; // Tiempo acumulado para lanzamiento de globos (segundos) float elapsed_time_balloons_ = 0.0F; // Tiempo acumulado para lanzamiento de globos (segundos)
float counter_pre_fade_ = 0.0F; // Tiempo antes de activar fundido final (segundos) float counter_pre_fade_ = 0.0F; // Tiempo antes de activar fundido final (segundos)
float time_since_logo_positioned_ = 0.0F; // Tiempo desde que el logo llegó a su posición (segundos) float time_since_logo_positioned_ = 0.0F; // Tiempo desde que el logo llegó a su posición (segundos)
float current_step_ = 0.0F; float current_step_ = 0.0F;
int total_steps_ = 1; int total_steps_ = 1;
bool initialized_ = false; bool initialized_ = false;
// --- Guardar estados iniciales para cálculo de pasos --- // --- Guardar estados iniciales para cálculo de pasos ---
int init_top_h_ = 0; int init_top_h_ = 0;
int init_bottom_y_ = 0; int init_bottom_y_ = 0;
int init_left_w_ = 0; int init_left_w_ = 0;
int init_right_x_ = 0; int init_right_x_ = 0;
// --- Variables de estado --- // --- Variables de estado ---
bool fading_ = false; // Estado del fade final bool fading_ = false; // Estado del fade final
bool want_to_pass_ = false; // Jugador quiere saltarse créditos bool want_to_pass_ = false; // Jugador quiere saltarse créditos
bool mini_logo_on_position_ = false; // Minilogo en posición final bool mini_logo_on_position_ = false; // Minilogo en posición final
bool vertical_done_ = false; bool vertical_done_ = false;
bool horizontal_done_ = false; bool horizontal_done_ = false;
// --- Diseño y posicionamiento --- // --- Diseño y posicionamiento ---
float black_bars_size_ = (param.game.game_area.rect.h - PLAY_AREA_HEIGHT) / 2; // Tamaño de las barras negras float black_bars_size_ = (param.game.game_area.rect.h - PLAY_AREA_HEIGHT) / 2; // Tamaño de las barras negras
int mini_logo_final_pos_ = 0; // Posición final del minilogo int mini_logo_final_pos_ = 0; // Posición final del minilogo
Color color_; // Color usado para los efectos Color color_; // Color usado para los efectos
// --- Control de audio --- // --- Control de audio ---
int initial_volume_ = Options::audio.music.volume; // Volumen inicial int initial_volume_ = Options::audio.music.volume; // Volumen inicial
int steps_ = 0; // Pasos para reducir audio int steps_ = 0; // Pasos para reducir audio
// --- Estado de acumuladores para animaciones --- // --- Estado de acumuladores para animaciones ---
struct CreditsState { struct CreditsState {
float texture_accumulator = 0.0F; float texture_accumulator = 0.0F;
float balloon_accumulator = 0.0F; float balloon_accumulator = 0.0F;
float powerball_accumulator = 0.0F; float powerball_accumulator = 0.0F;
float black_rect_accumulator = 0.0F; float black_rect_accumulator = 0.0F;
float r = 255.0F; // UPPER_LIMIT float r = 255.0F; // UPPER_LIMIT
float g = 0.0F; // LOWER_LIMIT float g = 0.0F; // LOWER_LIMIT
float b = 0.0F; // LOWER_LIMIT float b = 0.0F; // LOWER_LIMIT
float step_r = -0.5F; float step_r = -0.5F;
float step_g = 0.3F; float step_g = 0.3F;
float step_b = 0.1F; float step_b = 0.1F;
} credits_state_; } credits_state_;
// --- Rectángulos de renderizado --- // --- Rectángulos de renderizado ---
// Texto de créditos // Texto de créditos
SDL_FRect credits_rect_src_ = param.game.game_area.rect; SDL_FRect credits_rect_src_ = param.game.game_area.rect;
SDL_FRect credits_rect_dst_ = param.game.game_area.rect; SDL_FRect credits_rect_dst_ = param.game.game_area.rect;
// Mini logo // Mini logo
SDL_FRect mini_logo_rect_src_ = param.game.game_area.rect; SDL_FRect mini_logo_rect_src_ = param.game.game_area.rect;
SDL_FRect mini_logo_rect_dst_ = param.game.game_area.rect; SDL_FRect mini_logo_rect_dst_ = param.game.game_area.rect;
// Definición del área de juego // Definición del área de juego
SDL_FRect play_area_ = { SDL_FRect play_area_ = {
param.game.game_area.rect.x, param.game.game_area.rect.x,
param.game.game_area.rect.y + black_bars_size_, param.game.game_area.rect.y + black_bars_size_,
param.game.game_area.rect.w, param.game.game_area.rect.w,
PLAY_AREA_HEIGHT}; PLAY_AREA_HEIGHT};
// Barras negras para efecto letterbox // Barras negras para efecto letterbox
SDL_FRect top_black_rect_ = { SDL_FRect top_black_rect_ = {
play_area_.x, play_area_.x,
param.game.game_area.rect.y, param.game.game_area.rect.y,
play_area_.w, play_area_.w,
black_bars_size_}; black_bars_size_};
SDL_FRect bottom_black_rect_ = { SDL_FRect bottom_black_rect_ = {
play_area_.x, play_area_.x,
param.game.game_area.rect.h - black_bars_size_, param.game.game_area.rect.h - black_bars_size_,
play_area_.w, play_area_.w,
black_bars_size_}; black_bars_size_};
SDL_FRect left_black_rect_ = { SDL_FRect left_black_rect_ = {
play_area_.x, play_area_.x,
param.game.game_area.center_y - 1, param.game.game_area.center_y - 1,
0, 0,
2}; 2};
SDL_FRect right_black_rect_ = { SDL_FRect right_black_rect_ = {
play_area_.x + play_area_.w, play_area_.x + play_area_.w,
param.game.game_area.center_y - 1, param.game.game_area.center_y - 1,
0, 0,
2}; 2};
// Borde para la ventana // Borde para la ventana
SDL_FRect border_rect_ = play_area_; // Delimitador de ventana SDL_FRect border_rect_ = play_area_; // Delimitador de ventana
void render(); // Renderizado de la escena void render(); // Renderizado de la escena
static void checkEvents(); // Manejo de eventos static void checkEvents(); // Manejo de eventos
void checkInput(); // Procesamiento de entrada void checkInput(); // Procesamiento de entrada
// --- Métodos de renderizado --- // --- Métodos de renderizado ---
void fillTextTexture(); // Crear textura de texto de créditos void fillTextTexture(); // Crear textura de texto de créditos
void fillCanvas(); // Renderizar todos los sprites y fondos void fillCanvas(); // Renderizar todos los sprites y fondos
void renderPlayers(); // Renderiza los jugadores void renderPlayers(); // Renderiza los jugadores
void drawBorderRect(); // Renderiza el rectangulo del borde void drawBorderRect(); // Renderiza el rectangulo del borde
// --- Métodos de lógica del juego --- // --- Métodos de lógica del juego ---
void throwBalloons(float delta_time); // Lanzar globos al escenario (time-based) void throwBalloons(float delta_time); // Lanzar globos al escenario (time-based)
void initPlayers(); // Inicializar jugadores void initPlayers(); // Inicializar jugadores
void updateAllFades(float delta_time); // Actualizar estados de fade (time-based) void updateAllFades(float delta_time); // Actualizar estados de fade (time-based)
void cycleColors(float delta_time); // Cambiar colores de fondo void cycleColors(float delta_time); // Cambiar colores de fondo
void updatePlayers(float delta_time); // Actualza los jugadores (time-based) void updatePlayers(float delta_time); // Actualza los jugadores (time-based)
// --- Métodos de interfaz --- // --- Métodos de interfaz ---
void updateBlackRects(); // Actualizar rectángulos negros (letterbox) (frame-based) void updateBlackRects(); // Actualizar rectángulos negros (letterbox) (frame-based)
void updateBlackRects(float delta_time); // Actualizar rectángulos negros (letterbox) (time-based) void updateBlackRects(float delta_time); // Actualizar rectángulos negros (letterbox) (time-based)
void updateBorderRect(); // Actualizar rectángulo rojo (borde) void updateBorderRect(); // Actualizar rectángulo rojo (borde)
void updateTextureDstRects(); // Actualizar destinos de texturas (frame-based) void updateTextureDstRects(); // Actualizar destinos de texturas (frame-based)
void updateTextureDstRects(float delta_time); // Actualizar destinos de texturas (time-based) void updateTextureDstRects(float delta_time); // Actualizar destinos de texturas (time-based)
// --- Métodos de audio --- // --- Métodos de audio ---
static void setVolume(int amount); // Establecer volumen static void setVolume(int amount); // Establecer volumen
void resetVolume() const; // Restablecer volumen void resetVolume() const; // Restablecer volumen
}; };
+248 -248
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 ---
@@ -51,308 +51,308 @@ enum class Code;
// Utiliza un sistema de tiempo basado en milisegundos para garantizar // Utiliza un sistema de tiempo basado en milisegundos para garantizar
// comportamiento consistente independientemente del framerate. // comportamiento consistente independientemente del framerate.
class Game { class Game {
public: public:
// --- Constantes --- // --- Constantes ---
static constexpr bool DEMO_OFF = false; // Modo demo desactivado static constexpr bool DEMO_OFF = false; // Modo demo desactivado
static constexpr bool DEMO_ON = true; // Modo demo activado static constexpr bool DEMO_ON = true; // Modo demo activado
// --- Constructor y destructor --- // --- Constructor y destructor ---
Game(Player::Id player_id, int current_stage, bool demo_enabled); // Constructor principal Game(Player::Id player_id, int current_stage, bool demo_enabled); // Constructor principal
~Game(); // Destructor ~Game(); // Destructor
// --- Bucle principal --- // --- Bucle principal ---
void run(); // Ejecuta el bucle principal del juego void run(); // Ejecuta el bucle principal del juego
private: private:
using Players = std::vector<std::shared_ptr<Player>>; using Players = std::vector<std::shared_ptr<Player>>;
// --- Enums --- // --- Enums ---
enum class State { enum class State {
FADE_IN, // Transición de entrada FADE_IN, // Transición de entrada
ENTERING_PLAYER, // Jugador entrando ENTERING_PLAYER, // Jugador entrando
SHOWING_GET_READY_MESSAGE, // Mostrando mensaje de preparado SHOWING_GET_READY_MESSAGE, // Mostrando mensaje de preparado
PLAYING, // Jugando PLAYING, // Jugando
COMPLETED, // Juego completado COMPLETED, // Juego completado
GAME_OVER, // Fin del juego GAME_OVER, // Fin del juego
}; };
// --- Constantes de tiempo (en segundos) --- // --- Constantes de tiempo (en segundos) ---
static constexpr float HELP_COUNTER_S = 16.667F; // Contador de ayuda (1000 frames a 60fps → segundos) static constexpr float HELP_COUNTER_S = 16.667F; // Contador de ayuda (1000 frames a 60fps → segundos)
static constexpr float GAME_COMPLETED_START_FADE_S = 8.333F; // Inicio del fade al completar (500 frames → segundos) static constexpr float GAME_COMPLETED_START_FADE_S = 8.333F; // Inicio del fade al completar (500 frames → segundos)
static constexpr float GAME_COMPLETED_END_S = 11.667F; // Fin del juego completado (700 frames → segundos) static constexpr float GAME_COMPLETED_END_S = 11.667F; // Fin del juego completado (700 frames → segundos)
static constexpr float GAME_OVER_DURATION_S = 8.5F; static constexpr float GAME_OVER_DURATION_S = 8.5F;
static constexpr float TIME_STOPPED_DURATION_S = 6.0F; static constexpr float TIME_STOPPED_DURATION_S = 6.0F;
static constexpr float DEMO_FADE_PRE_DURATION_S = 0.5F; static constexpr float DEMO_FADE_PRE_DURATION_S = 0.5F;
static constexpr int ITEM_POINTS_1_DISK_ODDS = 10; static constexpr int ITEM_POINTS_1_DISK_ODDS = 10;
static constexpr int ITEM_POINTS_2_GAVINA_ODDS = 6; static constexpr int ITEM_POINTS_2_GAVINA_ODDS = 6;
static constexpr int ITEM_POINTS_3_PACMAR_ODDS = 3; static constexpr int ITEM_POINTS_3_PACMAR_ODDS = 3;
static constexpr int ITEM_CLOCK_ODDS = 5; static constexpr int ITEM_CLOCK_ODDS = 5;
static constexpr int ITEM_COFFEE_ODDS = 5; static constexpr int ITEM_COFFEE_ODDS = 5;
static constexpr int ITEM_POWER_BALL_ODDS = 0; static constexpr int ITEM_POWER_BALL_ODDS = 0;
static constexpr int ITEM_COFFEE_MACHINE_ODDS = 4; static constexpr int ITEM_COFFEE_MACHINE_ODDS = 4;
// --- Estructuras --- // --- Estructuras ---
struct Helper { struct Helper {
bool need_coffee{false}; // Indica si se necesitan cafes bool need_coffee{false}; // Indica si se necesitan cafes
bool need_coffee_machine{false}; // Indica si se necesita PowerUp bool need_coffee_machine{false}; // Indica si se necesita PowerUp
bool need_power_ball{false}; // Indica si se necesita una PowerBall bool need_power_ball{false}; // Indica si se necesita una PowerBall
float counter; // Contador para no dar ayudas consecutivas float counter; // Contador para no dar ayudas consecutivas
int item_disk_odds; // Probabilidad de aparición del objeto int item_disk_odds; // Probabilidad de aparición del objeto
int item_gavina_odds; // Probabilidad de aparición del objeto int item_gavina_odds; // Probabilidad de aparición del objeto
int item_pacmar_odds; // Probabilidad de aparición del objeto int item_pacmar_odds; // Probabilidad de aparición del objeto
int item_clock_odds; // Probabilidad de aparición del objeto int item_clock_odds; // Probabilidad de aparición del objeto
int item_coffee_odds; // Probabilidad de aparición del objeto int item_coffee_odds; // Probabilidad de aparición del objeto
int item_coffee_machine_odds; // Probabilidad de aparición del objeto int item_coffee_machine_odds; // Probabilidad de aparición del objeto
Helper() Helper()
: counter(HELP_COUNTER_S * 1000), // Convertir a milisegundos para compatibilidad : counter(HELP_COUNTER_S * 1000), // Convertir a milisegundos para compatibilidad
item_disk_odds(ITEM_POINTS_1_DISK_ODDS), item_disk_odds(ITEM_POINTS_1_DISK_ODDS),
item_gavina_odds(ITEM_POINTS_2_GAVINA_ODDS), item_gavina_odds(ITEM_POINTS_2_GAVINA_ODDS),
item_pacmar_odds(ITEM_POINTS_3_PACMAR_ODDS), item_pacmar_odds(ITEM_POINTS_3_PACMAR_ODDS),
item_clock_odds(ITEM_CLOCK_ODDS), item_clock_odds(ITEM_CLOCK_ODDS),
item_coffee_odds(ITEM_COFFEE_ODDS), item_coffee_odds(ITEM_COFFEE_ODDS),
item_coffee_machine_odds(ITEM_COFFEE_MACHINE_ODDS) {} item_coffee_machine_odds(ITEM_COFFEE_MACHINE_ODDS) {}
}; };
// --- Objetos y punteros --- // --- Objetos y punteros ---
SDL_Renderer* renderer_; // El renderizador de la ventana SDL_Renderer* renderer_; // El renderizador de la ventana
Screen* screen_; // Objeto encargado de dibujar en pantalla Screen* screen_; // Objeto encargado de dibujar en pantalla
Input* input_; // Manejador de entrada Input* input_; // Manejador de entrada
Scoreboard* scoreboard_; // Objeto para dibujar el marcador Scoreboard* scoreboard_; // Objeto para dibujar el marcador
SDL_Texture* canvas_; // Textura para dibujar la zona de juego SDL_Texture* canvas_; // Textura para dibujar la zona de juego
Players players_; // Vector con los jugadores Players players_; // Vector con los jugadores
Players players_draw_list_; // Vector con los jugadores ordenados para ser renderizados Players players_draw_list_; // Vector con los jugadores ordenados para ser renderizados
std::list<std::unique_ptr<Item>> items_; // Vector con los items std::list<std::unique_ptr<Item>> items_; // Vector con los items
std::list<std::unique_ptr<SmartSprite>> smart_sprites_; // Vector con los smartsprites std::list<std::unique_ptr<SmartSprite>> smart_sprites_; // Vector con los smartsprites
std::list<std::unique_ptr<PathSprite>> path_sprites_; // Vector con los pathsprites std::list<std::unique_ptr<PathSprite>> path_sprites_; // Vector con los pathsprites
std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items
std::vector<std::vector<std::shared_ptr<Texture>>> player_textures_; // Vector con todas las texturas de los jugadores std::vector<std::vector<std::shared_ptr<Texture>>> player_textures_; // Vector con todas las texturas de los jugadores
std::vector<std::shared_ptr<Texture>> game_text_textures_; // Vector con las texturas para los sprites con textos std::vector<std::shared_ptr<Texture>> game_text_textures_; // Vector con las texturas para los sprites con textos
std::vector<std::vector<std::string>> item_animations_; // Vector con las animaciones de los items std::vector<std::vector<std::string>> item_animations_; // Vector con las animaciones de los items
std::vector<std::vector<std::string>> player1_animations_; // Vector con las animaciones del jugador 1 std::vector<std::vector<std::string>> player1_animations_; // Vector con las animaciones del jugador 1
std::vector<std::vector<std::string>> player2_animations_; // Vector con las animaciones del jugador 2 std::vector<std::vector<std::string>> player2_animations_; // Vector con las animaciones del jugador 2
std::unique_ptr<PauseManager> pause_manager_; // Objeto para gestionar la pausa std::unique_ptr<PauseManager> pause_manager_; // Objeto para gestionar la pausa
std::unique_ptr<StageManager> stage_manager_; // Objeto para gestionar las fases std::unique_ptr<StageManager> stage_manager_; // Objeto para gestionar las fases
std::unique_ptr<BalloonManager> balloon_manager_; // Objeto para gestionar los globos std::unique_ptr<BalloonManager> balloon_manager_; // Objeto para gestionar los globos
std::unique_ptr<BulletManager> bullet_manager_; // Objeto para gestionar las balas std::unique_ptr<BulletManager> bullet_manager_; // Objeto para gestionar las balas
std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
std::unique_ptr<Fade> fade_in_; // Objeto para renderizar fades std::unique_ptr<Fade> fade_in_; // Objeto para renderizar fades
std::unique_ptr<Fade> fade_out_; // Objeto para renderizar fades std::unique_ptr<Fade> fade_out_; // Objeto para renderizar fades
std::unique_ptr<Tabe> tabe_; // Objeto para gestionar el Tabe Volaor std::unique_ptr<Tabe> tabe_; // Objeto para gestionar el Tabe Volaor
std::vector<Path> paths_; // Vector con los recorridos precalculados almacenados std::vector<Path> paths_; // Vector con los recorridos precalculados almacenados
// --- Variables de estado --- // --- Variables de estado ---
HiScoreEntry hi_score_ = HiScoreEntry( HiScoreEntry hi_score_ = HiScoreEntry(
Options::settings.hi_score_table[0].name, Options::settings.hi_score_table[0].name,
Options::settings.hi_score_table[0].score); // Máxima puntuación y nombre de quien la ostenta Options::settings.hi_score_table[0].score); // Máxima puntuación y nombre de quien la ostenta
Demo demo_; // Variable con todas las variables relacionadas con el modo demo Demo demo_; // Variable con todas las variables relacionadas con el modo demo
Difficulty::Code difficulty_ = Options::settings.difficulty; // Dificultad del juego Difficulty::Code difficulty_ = Options::settings.difficulty; // Dificultad del juego
Helper helper_; // Variable para gestionar las ayudas Helper helper_; // Variable para gestionar las ayudas
Uint64 last_time_ = 0; // Último tiempo registrado para deltaTime Uint64 last_time_ = 0; // Último tiempo registrado para deltaTime
bool coffee_machine_enabled_ = false; // Indica si hay una máquina de café en el terreno de juego bool coffee_machine_enabled_ = false; // Indica si hay una máquina de café en el terreno de juego
bool hi_score_achieved_ = false; // Indica si se ha superado la puntuación máxima bool hi_score_achieved_ = false; // Indica si se ha superado la puntuación máxima
float difficulty_score_multiplier_ = 1.0F; // Multiplicador de puntos en función de la dificultad float difficulty_score_multiplier_ = 1.0F; // Multiplicador de puntos en función de la dificultad
float counter_ = 0.0F; // Contador para el juego float counter_ = 0.0F; // Contador para el juego
float game_completed_timer_ = 0.0F; // Acumulador de tiempo para el tramo final (milisegundos) float game_completed_timer_ = 0.0F; // Acumulador de tiempo para el tramo final (milisegundos)
float game_over_timer_ = 0.0F; // Timer para el estado de fin de partida (milisegundos) float game_over_timer_ = 0.0F; // Timer para el estado de fin de partida (milisegundos)
float time_stopped_timer_ = 0.0F; // Temporizador para llevar la cuenta del tiempo detenido float time_stopped_timer_ = 0.0F; // Temporizador para llevar la cuenta del tiempo detenido
float time_stopped_sound_timer_ = 0.0F; // Temporizador para controlar el sonido del tiempo detenido float time_stopped_sound_timer_ = 0.0F; // Temporizador para controlar el sonido del tiempo detenido
int menace_ = 0; // Nivel de amenaza actual int menace_ = 0; // Nivel de amenaza actual
int menace_threshold_ = 0; // Umbral del nivel de amenaza. Si el nivel de amenaza cae por debajo del umbral, se generan más globos. Si el umbral aumenta, aumenta el número de globos int menace_threshold_ = 0; // Umbral del nivel de amenaza. Si el nivel de amenaza cae por debajo del umbral, se generan más globos. Si el umbral aumenta, aumenta el número de globos
State state_ = State::FADE_IN; // Estado State state_ = State::FADE_IN; // Estado
// Estructuras para gestionar flags de eventos basados en tiempo // Estructuras para gestionar flags de eventos basados en tiempo
struct GameOverFlags { struct GameOverFlags {
bool music_fade_triggered = false; bool music_fade_triggered = false;
bool message_triggered = false; bool message_triggered = false;
bool fade_out_triggered = false; bool fade_out_triggered = false;
void reset() { void reset() {
music_fade_triggered = false; music_fade_triggered = false;
message_triggered = false; message_triggered = false;
fade_out_triggered = false; fade_out_triggered = false;
} }
} game_over_flags_; } game_over_flags_;
struct GameCompletedFlags { struct GameCompletedFlags {
bool start_celebrations_triggered = false; bool start_celebrations_triggered = false;
bool end_celebrations_triggered = false; bool end_celebrations_triggered = false;
void reset() { void reset() {
start_celebrations_triggered = false; start_celebrations_triggered = false;
end_celebrations_triggered = false; end_celebrations_triggered = false;
} }
} game_completed_flags_; } game_completed_flags_;
struct TimeStoppedFlags { struct TimeStoppedFlags {
bool color_flash_sound_played = false; bool color_flash_sound_played = false;
bool warning_phase_started = false; bool warning_phase_started = false;
void reset() { void reset() {
color_flash_sound_played = false; color_flash_sound_played = false;
warning_phase_started = false; warning_phase_started = false;
} }
} time_stopped_flags_; } time_stopped_flags_;
#ifdef _DEBUG #ifdef _DEBUG
bool auto_pop_balloons_ = false; // Si es true, incrementa automaticamente los globos explotados bool auto_pop_balloons_ = false; // Si es true, incrementa automaticamente los globos explotados
#endif #endif
// --- Ciclo principal del juego --- // --- Ciclo principal del juego ---
void update(float delta_time); // Actualiza la lógica principal del juego void update(float delta_time); // Actualiza la lógica principal del juego
auto calculateDeltaTime() -> float; // Calcula el deltatime auto calculateDeltaTime() -> float; // Calcula el deltatime
void render(); // Renderiza todos los elementos del juego void render(); // Renderiza todos los elementos del juego
void handleEvents(); // Procesa los eventos del sistema en cola void handleEvents(); // Procesa los eventos del sistema en cola
void checkState(); // Verifica y actualiza el estado actual del juego void checkState(); // Verifica y actualiza el estado actual del juego
void setState(State state); // Cambia el estado del juego void setState(State state); // Cambia el estado del juego
void cleanLists(); // Limpia vectores de elementos deshabilitados void cleanLists(); // Limpia vectores de elementos deshabilitados
// --- Gestión de estados del juego --- // --- Gestión de estados del juego ---
void updateGameStates(float delta_time); // Actualiza todos los estados del juego void updateGameStates(float delta_time); // Actualiza todos los estados del juego
void updateGameStateFadeIn(float delta_time); // Gestiona el estado de transición de entrada (time-based) void updateGameStateFadeIn(float delta_time); // Gestiona el estado de transición de entrada (time-based)
void updateGameStateEnteringPlayer(float delta_time); // Gestiona el estado de entrada de jugador void updateGameStateEnteringPlayer(float delta_time); // Gestiona el estado de entrada de jugador
void updateGameStateShowingGetReadyMessage(float delta_time); // Gestiona el estado de mensaje "preparado" void updateGameStateShowingGetReadyMessage(float delta_time); // Gestiona el estado de mensaje "preparado"
void updateGameStatePlaying(float delta_time); // Gestiona el estado de juego activo void updateGameStatePlaying(float delta_time); // Gestiona el estado de juego activo
void updateGameStateCompleted(float delta_time); // Gestiona el estado de juego completado void updateGameStateCompleted(float delta_time); // Gestiona el estado de juego completado
void updateGameStateGameOver(float delta_time); // Gestiona las actualizaciones continuas del estado de fin de partida void updateGameStateGameOver(float delta_time); // Gestiona las actualizaciones continuas del estado de fin de partida
// --- Gestión de jugadores --- // --- Gestión de jugadores ---
void initPlayers(Player::Id player_id); // Inicializa los datos de los jugadores void initPlayers(Player::Id player_id); // Inicializa los datos de los jugadores
void updatePlayers(float delta_time); // Actualiza las variables y estados de los jugadores void updatePlayers(float delta_time); // Actualiza las variables y estados de los jugadores
void renderPlayers(); // Renderiza todos los jugadores en pantalla void renderPlayers(); // Renderiza todos los jugadores en pantalla
auto getPlayer(Player::Id id) -> std::shared_ptr<Player>; // Obtiene un jugador por su identificador auto getPlayer(Player::Id id) -> std::shared_ptr<Player>; // Obtiene un jugador por su identificador
static auto getController(Player::Id player_id) -> int; // Obtiene el controlador asignado a un jugador static auto getController(Player::Id player_id) -> int; // Obtiene el controlador asignado a un jugador
// --- Estado de jugadores --- // --- Estado de jugadores ---
void checkAndUpdatePlayerStatus(int active_player_index, int inactive_player_index); // Actualiza estado entre jugadores void checkAndUpdatePlayerStatus(int active_player_index, int inactive_player_index); // Actualiza estado entre jugadores
void checkPlayersStatusPlaying(); // Verifica el estado de juego de todos los jugadores void checkPlayersStatusPlaying(); // Verifica el estado de juego de todos los jugadores
auto allPlayersAreWaitingOrGameOver() -> bool; // Verifica si todos esperan o han perdido auto allPlayersAreWaitingOrGameOver() -> bool; // Verifica si todos esperan o han perdido
auto allPlayersAreGameOver() -> bool; // Verifica si todos los jugadores han perdido auto allPlayersAreGameOver() -> bool; // Verifica si todos los jugadores han perdido
auto allPlayersAreNotPlaying() -> bool; // Verifica si ningún jugador está activo auto allPlayersAreNotPlaying() -> bool; // Verifica si ningún jugador está activo
// --- Colisiones de jugadores --- // --- Colisiones de jugadores ---
void handlePlayerCollision(std::shared_ptr<Player>& player, std::shared_ptr<Balloon>& balloon); // Procesa colisión de jugador con globo void handlePlayerCollision(std::shared_ptr<Player>& player, std::shared_ptr<Balloon>& balloon); // Procesa colisión de jugador con globo
auto checkPlayerBalloonCollision(std::shared_ptr<Player>& player) -> std::shared_ptr<Balloon>; // Detecta colisión jugador-globo auto checkPlayerBalloonCollision(std::shared_ptr<Player>& player) -> std::shared_ptr<Balloon>; // Detecta colisión jugador-globo
void checkPlayerItemCollision(std::shared_ptr<Player>& player); // Detecta colisión jugador-ítem void checkPlayerItemCollision(std::shared_ptr<Player>& player); // Detecta colisión jugador-ítem
// --- Sistema de entrada (input) --- // --- Sistema de entrada (input) ---
void checkInput(); // Gestiona toda la entrada durante el juego void checkInput(); // Gestiona toda la entrada durante el juego
void checkPauseInput(); // Verifica solicitudes de pausa de controladores void checkPauseInput(); // Verifica solicitudes de pausa de controladores
// --- Entrada de jugadores normales --- // --- Entrada de jugadores normales ---
void handlePlayersInput(); // Gestiona entrada de todos los jugadores void handlePlayersInput(); // Gestiona entrada de todos los jugadores
void handleNormalPlayerInput(const std::shared_ptr<Player>& player); // Procesa entrada de un jugador específico void handleNormalPlayerInput(const std::shared_ptr<Player>& player); // Procesa entrada de un jugador específico
void handleFireInput(const std::shared_ptr<Player>& player, Bullet::Type type); // Gestiona disparo de jugador void handleFireInput(const std::shared_ptr<Player>& player, Bullet::Type type); // Gestiona disparo de jugador
void handleFireInputs(const std::shared_ptr<Player>& player, bool autofire); // Procesa disparos automáticos void handleFireInputs(const std::shared_ptr<Player>& player, bool autofire); // Procesa disparos automáticos
void handlePlayerContinueInput(const std::shared_ptr<Player>& player); // Permite continuar al jugador void handlePlayerContinueInput(const std::shared_ptr<Player>& player); // Permite continuar al jugador
void handlePlayerWaitingInput(const std::shared_ptr<Player>& player); // Permite (re)entrar al jugador void handlePlayerWaitingInput(const std::shared_ptr<Player>& player); // Permite (re)entrar al jugador
void handleNameInput(const std::shared_ptr<Player>& player); // Gestiona entrada de nombre del jugador void handleNameInput(const std::shared_ptr<Player>& player); // Gestiona entrada de nombre del jugador
// --- Entrada en modo demo --- // --- Entrada en modo demo ---
void demoHandleInput(); // Gestiona entrada durante el modo demostración void demoHandleInput(); // Gestiona entrada durante el modo demostración
void demoHandlePassInput(); // Permite saltar la demostración void demoHandlePassInput(); // Permite saltar la demostración
void demoHandlePlayerInput(const std::shared_ptr<Player>& player, int index); // Procesa entrada de jugador en demo void demoHandlePlayerInput(const std::shared_ptr<Player>& player, int index); // Procesa entrada de jugador en demo
// --- Colisiones específicas de balas --- // --- Colisiones específicas de balas ---
auto checkBulletTabeCollision(const std::shared_ptr<Bullet>& bullet) -> bool; // Detecta colisión bala-Tabe auto checkBulletTabeCollision(const std::shared_ptr<Bullet>& bullet) -> bool; // Detecta colisión bala-Tabe
auto checkBulletBalloonCollision(const std::shared_ptr<Bullet>& bullet) -> bool; // Detecta colisión bala-globo auto checkBulletBalloonCollision(const std::shared_ptr<Bullet>& bullet) -> bool; // Detecta colisión bala-globo
void processBalloonHit(const std::shared_ptr<Bullet>& bullet, const std::shared_ptr<Balloon>& balloon); // Procesa impacto en globo void processBalloonHit(const std::shared_ptr<Bullet>& bullet, const std::shared_ptr<Balloon>& balloon); // Procesa impacto en globo
// --- Sistema de ítems y power-ups --- // --- Sistema de ítems y power-ups ---
void updateItems(float delta_time); // Actualiza posición y estado de todos los ítems void updateItems(float delta_time); // Actualiza posición y estado de todos los ítems
void renderItems(); // Renderiza todos los ítems activos void renderItems(); // Renderiza todos los ítems activos
auto dropItem() -> ItemType; // Determina aleatoriamente qué ítem soltar auto dropItem() -> ItemType; // Determina aleatoriamente qué ítem soltar
void createItem(ItemType type, float x, float y); // Crea un nuevo ítem en posición específica void createItem(ItemType type, float x, float y); // Crea un nuevo ítem en posición específica
void freeItems(); // Libera memoria del vector de ítems void freeItems(); // Libera memoria del vector de ítems
void destroyAllItems(); // Elimina todos los ítems activos de la pantalla void destroyAllItems(); // Elimina todos los ítems activos de la pantalla
// --- ítems especiales --- // --- ítems especiales ---
void enableTimeStopItem(); // Activa el efecto de detener el tiempo void enableTimeStopItem(); // Activa el efecto de detener el tiempo
void disableTimeStopItem(); // Desactiva el efecto de detener el tiempo void disableTimeStopItem(); // Desactiva el efecto de detener el tiempo
void updateTimeStopped(float delta_time); // Actualiza el estado del tiempo detenido void updateTimeStopped(float delta_time); // Actualiza el estado del tiempo detenido
void handleGameCompletedEvents(); // Maneja eventos del juego completado void handleGameCompletedEvents(); // Maneja eventos del juego completado
void handleGameOverEvents(); // Maneja eventos discretos basados en tiempo durante game over void handleGameOverEvents(); // Maneja eventos discretos basados en tiempo durante game over
void throwCoffee(int x, int y); // Crea efecto de café arrojado al ser golpeado void throwCoffee(int x, int y); // Crea efecto de café arrojado al ser golpeado
// --- Gestión de caída de ítems --- // --- Gestión de caída de ítems ---
void handleItemDrop(const std::shared_ptr<Balloon>& balloon, const std::shared_ptr<Player>& player); // Gestiona caída de ítem desde globo void handleItemDrop(const std::shared_ptr<Balloon>& balloon, const std::shared_ptr<Player>& player); // Gestiona caída de ítem desde globo
// --- Sprites inteligentes (smartsprites) --- // --- Sprites inteligentes (smartsprites) ---
void updateSmartSprites(float delta_time); // Actualiza todos los sprites con lógica propia (time-based) void updateSmartSprites(float delta_time); // Actualiza todos los sprites con lógica propia (time-based)
void renderSmartSprites(); // Renderiza todos los sprites inteligentes void renderSmartSprites(); // Renderiza todos los sprites inteligentes
void freeSmartSprites(); // Libera memoria de sprites inteligentes void freeSmartSprites(); // Libera memoria de sprites inteligentes
// --- Sprites por ruta (pathsprites) --- // --- Sprites por ruta (pathsprites) ---
void updatePathSprites(float delta_time); // Actualiza sprites que siguen rutas predefinidas void updatePathSprites(float delta_time); // Actualiza sprites que siguen rutas predefinidas
void renderPathSprites(); // Renderiza sprites animados por ruta void renderPathSprites(); // Renderiza sprites animados por ruta
void freePathSprites(); // Libera memoria de sprites por ruta void freePathSprites(); // Libera memoria de sprites por ruta
void initPaths(); // Inicializa rutas predefinidas para animaciones void initPaths(); // Inicializa rutas predefinidas para animaciones
// --- Creación de sprites especiales --- // --- Creación de sprites especiales ---
void createItemText(int x, const std::shared_ptr<Texture>& texture); // Crea texto animado para ítems void createItemText(int x, const std::shared_ptr<Texture>& texture); // Crea texto animado para ítems
void createMessage(const std::vector<Path>& paths, const std::shared_ptr<Texture>& texture); // Crea mensaje con animación por ruta void createMessage(const std::vector<Path>& paths, const std::shared_ptr<Texture>& texture); // Crea mensaje con animación por ruta
// --- Sistema de globos y enemigos --- // --- Sistema de globos y enemigos ---
void handleBalloonDestruction(const std::shared_ptr<Balloon>& balloon, const std::shared_ptr<Player>& player); // Procesa destrucción de globo void handleBalloonDestruction(const std::shared_ptr<Balloon>& balloon, const std::shared_ptr<Player>& player); // Procesa destrucción de globo
void handleTabeHitEffects(); // Gestiona efectos al golpear a Tabe void handleTabeHitEffects(); // Gestiona efectos al golpear a Tabe
void checkAndUpdateBalloonSpeed(); // Ajusta velocidad de globos según progreso void checkAndUpdateBalloonSpeed(); // Ajusta velocidad de globos según progreso
// --- Gestión de fases y progresión --- // --- Gestión de fases y progresión ---
void updateStage(); // Verifica y actualiza cambio de fase void updateStage(); // Verifica y actualiza cambio de fase
void initDifficultyVars(); // Inicializa variables de dificultad void initDifficultyVars(); // Inicializa variables de dificultad
// --- Sistema de amenaza --- // --- Sistema de amenaza ---
void updateMenace(); // Gestiona el nivel de amenaza del juego void updateMenace(); // Gestiona el nivel de amenaza del juego
void setMenace(); // Calcula y establece amenaza según globos activos void setMenace(); // Calcula y establece amenaza según globos activos
// --- Puntuación y marcador --- // --- Puntuación y marcador ---
void updateHiScore(); // Actualiza el récord máximo si es necesario void updateHiScore(); // Actualiza el récord máximo si es necesario
void updateScoreboard(float delta_time); // Actualiza la visualización del marcador void updateScoreboard(float delta_time); // Actualiza la visualización del marcador
void updateHiScoreName(); // Pone en el marcador el nombre del primer jugador de la tabla void updateHiScoreName(); // Pone en el marcador el nombre del primer jugador de la tabla
void initScoreboard(); // Inicializa el sistema de puntuación void initScoreboard(); // Inicializa el sistema de puntuación
// --- Modo demostración --- // --- Modo demostración ---
void initDemo(Player::Id player_id); // Inicializa variables para el modo demostración void initDemo(Player::Id player_id); // Inicializa variables para el modo demostración
void updateDemo(float delta_time); // Actualiza lógica específica del modo demo void updateDemo(float delta_time); // Actualiza lógica específica del modo demo
// --- Recursos y renderizado --- // --- Recursos y renderizado ---
void setResources(); // Asigna texturas y animaciones a los objetos void setResources(); // Asigna texturas y animaciones a los objetos
void updateBackground(float delta_time); // Actualiza elementos del fondo (time-based) void updateBackground(float delta_time); // Actualiza elementos del fondo (time-based)
void fillCanvas(); // Renderiza elementos del área de juego en su textura void fillCanvas(); // Renderiza elementos del área de juego en su textura
void updateHelper(); // Actualiza variables auxiliares de renderizado void updateHelper(); // Actualiza variables auxiliares de renderizado
// --- Sistema de audio --- // --- Sistema de audio ---
static void playMusic(const std::string& music_file, int loop = -1); // Reproduce la música de fondo static void playMusic(const std::string& music_file, int loop = -1); // Reproduce la música de fondo
void stopMusic() const; // Detiene la reproducción de música void stopMusic() const; // Detiene la reproducción de música
static void pauseMusic(); // Pausa la música static void pauseMusic(); // Pausa la música
static void resumeMusic(); // Retoma la música que eestaba pausada static void resumeMusic(); // Retoma la música que eestaba pausada
void playSound(const std::string& name) const; // Reproduce un efecto de sonido específico void playSound(const std::string& name) const; // Reproduce un efecto de sonido específico
// --- Gestion y dibujado de jugadores en z-order --- // --- Gestion y dibujado de jugadores en z-order ---
static void buildPlayerDrawList(const Players& elements, Players& draw_list); // Construye el draw_list a partir del vector principal static void buildPlayerDrawList(const Players& elements, Players& draw_list); // Construye el draw_list a partir del vector principal
static void updatePlayerDrawList(const Players& elements, Players& draw_list); // Actualiza draw_list tras cambios en los z_order static void updatePlayerDrawList(const Players& elements, Players& draw_list); // Actualiza draw_list tras cambios en los z_order
static void renderPlayerDrawList(const Players& draw_list); // Dibuja en el orden definido static void renderPlayerDrawList(const Players& draw_list); // Dibuja en el orden definido
static auto findPlayerIndex(const Players& elems, const std::shared_ptr<Player>& who) -> size_t; static auto findPlayerIndex(const Players& elems, const std::shared_ptr<Player>& who) -> size_t;
static void sendPlayerToBack(Players& elements, const std::shared_ptr<Player>& who, Players& draw_list); // Envia al jugador al fondo de la pantalla static void sendPlayerToBack(Players& elements, const std::shared_ptr<Player>& who, Players& draw_list); // Envia al jugador al fondo de la pantalla
static void bringPlayerToFront(Players& elements, const std::shared_ptr<Player>& who, Players& draw_list); // Envia al jugador al frente de la pantalla static void bringPlayerToFront(Players& elements, const std::shared_ptr<Player>& who, Players& draw_list); // Envia al jugador al frente de la pantalla
// --- Varios --- // --- Varios ---
void onPauseStateChanged(bool is_paused); void onPauseStateChanged(bool is_paused);
// SISTEMA DE GRABACIÓN (CONDICIONAL) // SISTEMA DE GRABACIÓN (CONDICIONAL)
#ifdef RECORDING #ifdef RECORDING
void updateRecording(float deltaTime); // Actualiza variables durante modo de grabación void updateRecording(float deltaTime); // Actualiza variables durante modo de grabación
#endif #endif
// --- Depuración (solo en modo DEBUG) --- // --- Depuración (solo en modo DEBUG) ---
#ifdef _DEBUG #ifdef _DEBUG
void handleDebugEvents(const SDL_Event& event); // Comprueba los eventos en el modo DEBUG void handleDebugEvents(const SDL_Event& event); // Comprueba los eventos en el modo DEBUG
#endif #endif
}; };
+4 -4
View File
@@ -74,11 +74,11 @@ void HiScoreTable::render() {
SCREEN->start(); // Prepara para empezar a dibujar en la textura de juego SCREEN->start(); // Prepara para empezar a dibujar en la textura de juego
SCREEN->clean(); // Limpia la pantalla SCREEN->clean(); // Limpia la pantalla
background_->render(); // Pinta el fondo background_->render(); // Pinta el fondo
float scroll_offset = elapsed_time_ * SCROLL_SPEED_PPS; // Calcula el desplazamiento del scroll usando velocidad en pixels/segundo float scroll_offset = elapsed_time_ * SCROLL_SPEED_PPS; // Calcula el desplazamiento del scroll usando velocidad en pixels/segundo
view_area_.y = std::round(std::max(0.0F, (param.game.height + 100.0F) - scroll_offset)); // Establece la ventana del backbuffer (redondeado para evitar deformaciones) view_area_.y = std::round(std::max(0.0F, (param.game.height + 100.0F) - scroll_offset)); // Establece la ventana del backbuffer (redondeado para evitar deformaciones)
SDL_RenderTexture(renderer_, backbuffer_, nullptr, &view_area_); // Copia el backbuffer al renderizador SDL_RenderTexture(renderer_, backbuffer_, nullptr, &view_area_); // Copia el backbuffer al renderizador
fade_->render(); // Renderiza el fade fade_->render(); // Renderiza el fade
SCREEN->render(); // Vuelca el contenido del renderizador en pantalla SCREEN->render(); // Vuelca el contenido del renderizador en pantalla
} }
+56 -56
View File
@@ -22,68 +22,68 @@ struct Path;
// Para mejorar la legibilidad de los textos, el objeto que dibuja el fondo es capaz de modificar // Para mejorar la legibilidad de los textos, el objeto que dibuja el fondo es capaz de modificar
// su atenuación. // su atenuación.
class HiScoreTable { class HiScoreTable {
public: public:
// --- Constructor y destructor --- // --- Constructor y destructor ---
HiScoreTable(); HiScoreTable();
~HiScoreTable(); ~HiScoreTable();
// --- Bucle principal --- // --- Bucle principal ---
void run(); void run();
private: private:
// --- Constantes (en segundos) --- // --- Constantes (en segundos) ---
static constexpr float COUNTER_END_S = 800.0F / 60.0F; // Tiempo final (≈13.33s) static constexpr float COUNTER_END_S = 800.0F / 60.0F; // Tiempo final (≈13.33s)
static constexpr float INIT_DELAY_S = 190.0F / 60.0F; // Retraso inicial (≈3.17s) static constexpr float INIT_DELAY_S = 190.0F / 60.0F; // Retraso inicial (≈3.17s)
static constexpr float ENTRY_DELAY_S = 16.0F / 60.0F; // Retraso entre entradas (≈0.27s) static constexpr float ENTRY_DELAY_S = 16.0F / 60.0F; // Retraso entre entradas (≈0.27s)
static constexpr float BACKGROUND_CHANGE_S = 150.0F / 60.0F; // Tiempo cambio fondo (≈2.5s) static constexpr float BACKGROUND_CHANGE_S = 150.0F / 60.0F; // Tiempo cambio fondo (≈2.5s)
static constexpr float ANIM_DURATION_S = 80.0F / 60.0F; // Duración animación (≈1.33s) static constexpr float ANIM_DURATION_S = 80.0F / 60.0F; // Duración animación (≈1.33s)
static constexpr float CLOUDS_SPEED = -6.0F; // Velocidad nubes (pixels/s) static constexpr float CLOUDS_SPEED = -6.0F; // Velocidad nubes (pixels/s)
static constexpr float SCROLL_SPEED_PPS = 60.0F; // Velocidad de scroll (60 pixels por segundo) static constexpr float SCROLL_SPEED_PPS = 60.0F; // Velocidad de scroll (60 pixels por segundo)
// --- Objetos y punteros --- // --- Objetos y punteros ---
SDL_Renderer* renderer_; // El renderizador de la ventana SDL_Renderer* renderer_; // El renderizador de la ventana
SDL_Texture* backbuffer_; // Textura para usar como backbuffer SDL_Texture* backbuffer_; // Textura para usar como backbuffer
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
std::unique_ptr<Sprite> header_; // Sprite con la cabecera del texto std::unique_ptr<Sprite> header_; // Sprite con la cabecera del texto
std::vector<std::shared_ptr<PathSprite>> entry_names_; // Lista con los sprites de cada uno de los nombres de la tabla de records std::vector<std::shared_ptr<PathSprite>> entry_names_; // Lista con los sprites de cada uno de los nombres de la tabla de records
std::vector<Path> paths_; // Vector con los recorridos precalculados std::vector<Path> paths_; // Vector con los recorridos precalculados
// --- Variables --- // --- Variables ---
float elapsed_time_ = 0.0F; // Tiempo transcurrido (segundos) float elapsed_time_ = 0.0F; // Tiempo transcurrido (segundos)
Uint64 last_time_ = 0; // Último timestamp para calcular delta-time Uint64 last_time_ = 0; // Último timestamp para calcular delta-time
SDL_FRect view_area_; // Parte de la textura que se muestra en pantalla SDL_FRect view_area_; // Parte de la textura que se muestra en pantalla
Fade::Mode fade_mode_; // Modo de fade a utilizar Fade::Mode fade_mode_; // Modo de fade a utilizar
Color background_fade_color_; // Color de atenuación del fondo Color background_fade_color_; // Color de atenuación del fondo
std::vector<Color> entry_colors_; // Colores para destacar las entradas en la tabla std::vector<Color> entry_colors_; // Colores para destacar las entradas en la tabla
// --- Flags para eventos basados en tiempo --- // --- Flags para eventos basados en tiempo ---
struct HiScoreFlags { struct HiScoreFlags {
bool background_changed = false; bool background_changed = false;
bool fade_activated = false; bool fade_activated = false;
void reset() { void reset() {
background_changed = false; background_changed = false;
fade_activated = false; fade_activated = false;
} }
} hiscore_flags_; } hiscore_flags_;
// --- Métodos internos --- // --- Métodos internos ---
void update(float delta_time); // Actualiza las variables void update(float delta_time); // Actualiza las variables
void render(); // Pinta en pantalla void render(); // Pinta en pantalla
static void checkEvents(); // Comprueba los eventos static void checkEvents(); // Comprueba los eventos
static void checkInput(); // Comprueba las entradas static void checkInput(); // Comprueba las entradas
static auto format(int number) -> std::string; // Convierte un entero a un string con separadores de miles static auto format(int number) -> std::string; // Convierte un entero a un string con separadores de miles
void fillTexture(); // Dibuja los sprites en la textura void fillTexture(); // Dibuja los sprites en la textura
void updateFade(float delta_time); // Gestiona el fade void updateFade(float delta_time); // Gestiona el fade
void createSprites(); // Crea los sprites con los textos void createSprites(); // Crea los sprites con los textos
void updateSprites(float delta_time); // Actualiza las posiciones de los sprites de texto void updateSprites(float delta_time); // Actualiza las posiciones de los sprites de texto
void initFade(); // Inicializa el fade void initFade(); // Inicializa el fade
void initBackground(); // Inicializa el fondo void initBackground(); // Inicializa el fondo
auto getEntryColor(int counter) -> Color; // Obtiene un color del vector de colores de entradas auto getEntryColor(int counter) -> Color; // Obtiene un color del vector de colores de entradas
void iniEntryColors(); // Inicializa los colores de las entradas void iniEntryColors(); // Inicializa los colores de las entradas
void glowEntryNames(); // Hace brillar los nombres de la tabla de records void glowEntryNames(); // Hace brillar los nombres de la tabla de records
void updateCounter(); // Gestiona el contador void updateCounter(); // Gestiona el contador
auto calculateDeltaTime() -> float; // Calcula el tiempo transcurrido desde el último frame auto calculateDeltaTime() -> float; // Calcula el tiempo transcurrido desde el último frame
}; };
+59 -59
View File
@@ -25,74 +25,74 @@ class TiledBG;
*/ */
// --- Estructuras --- // --- Estructuras ---
struct Line { // Almacena información de línea animada struct Line { // Almacena información de línea animada
int y; // Coordenada Y de la línea int y; // Coordenada Y de la línea
float x; // Coordenada X inicial (usamos float para mayor precisión en el suavizado) float x; // Coordenada X inicial (usamos float para mayor precisión en el suavizado)
int direction; // Dirección de movimiento: -1 para izquierda, 1 para derecha int direction; // Dirección de movimiento: -1 para izquierda, 1 para derecha
float accumulated_time{0}; // Tiempo acumulado desde que empezó la animación (segundos) float accumulated_time{0}; // Tiempo acumulado desde que empezó la animación (segundos)
float delay_time{0}; // Tiempo de retraso antes de comenzar la animación (segundos) float delay_time{0}; // Tiempo de retraso antes de comenzar la animación (segundos)
bool started{false}; // Indica si la línea ha comenzado a moverse bool started{false}; // Indica si la línea ha comenzado a moverse
// Constructor de Line // Constructor de Line
Line(int y, float x, int direction, float delay) Line(int y, float x, int direction, float delay)
: y(y), : y(y),
x(x), x(x),
direction(direction), direction(direction),
delay_time(delay) {} delay_time(delay) {}
}; };
// Clase Instructions // Clase Instructions
class Instructions { class Instructions {
public: public:
// --- Constructor y destructor --- // --- Constructor y destructor ---
Instructions(); Instructions();
~Instructions(); ~Instructions();
// --- Bucle principal --- // --- Bucle principal ---
void run(); void run();
private: private:
// --- Constantes de tiempo (en segundos) --- // --- Constantes de tiempo (en segundos) ---
static constexpr float SPRITE_ANIMATION_CYCLE_S = 36.0F / 60.0F; // Ciclo de animación sprites (≈0.6s) static constexpr float SPRITE_ANIMATION_CYCLE_S = 36.0F / 60.0F; // Ciclo de animación sprites (≈0.6s)
static constexpr float START_DELAY_S = 4.0F; // Retraso antes de mover líneas (4s) static constexpr float START_DELAY_S = 4.0F; // Retraso antes de mover líneas (4s)
static constexpr float LINE_MOVE_DURATION_S = 1.0F; // Duración movimiento líneas (1s) static constexpr float LINE_MOVE_DURATION_S = 1.0F; // Duración movimiento líneas (1s)
static constexpr float LINE_START_DELAY_S = 0.005F; // Retraso entre líneas (5ms = 0.005s) static constexpr float LINE_START_DELAY_S = 0.005F; // Retraso entre líneas (5ms = 0.005s)
static constexpr float SCROLL_SPEED_PPS = 60.0F; // Velocidad de scroll (60 pixels por segundo) static constexpr float SCROLL_SPEED_PPS = 60.0F; // Velocidad de scroll (60 pixels por segundo)
// --- Objetos y punteros --- // --- Objetos y punteros ---
SDL_Renderer* renderer_; // El renderizador de la ventana SDL_Renderer* renderer_; // El renderizador de la ventana
SDL_Texture* texture_; // Textura fija con el texto SDL_Texture* texture_; // Textura fija con el texto
SDL_Texture* backbuffer_; // Textura para usar como backbuffer SDL_Texture* backbuffer_; // Textura para usar como backbuffer
std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items
std::vector<std::unique_ptr<Sprite>> sprites_; // Vector con los sprites de los items std::vector<std::unique_ptr<Sprite>> sprites_; // Vector con los sprites de los items
std::shared_ptr<Text> text_; // Objeto para escribir texto std::shared_ptr<Text> text_; // Objeto para escribir texto
std::unique_ptr<TiledBG> tiled_bg_; // Objeto para dibujar el mosaico animado de fondo std::unique_ptr<TiledBG> tiled_bg_; // Objeto para dibujar el mosaico animado de fondo
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
// --- Variables --- // --- Variables ---
float elapsed_time_ = 0.0F; // Tiempo transcurrido (segundos) float elapsed_time_ = 0.0F; // Tiempo transcurrido (segundos)
Uint64 last_time_ = 0; // Último timestamp para calcular delta-time Uint64 last_time_ = 0; // Último timestamp para calcular delta-time
SDL_FRect view_; // Vista del backbuffer que se va a mostrar por pantalla SDL_FRect view_; // Vista del backbuffer que se va a mostrar por pantalla
SDL_FPoint sprite_pos_ = {0, 0}; // Posición del primer sprite en la lista SDL_FPoint sprite_pos_ = {0, 0}; // Posición del primer sprite en la lista
float item_space_ = 2.0; // Espacio entre los items en pantalla float item_space_ = 2.0; // Espacio entre los items en pantalla
std::vector<Line> lines_; // Vector que contiene las líneas animadas en la pantalla std::vector<Line> lines_; // Vector que contiene las líneas animadas en la pantalla
bool all_lines_off_screen_ = false; // Indica si todas las líneas han salido de la pantalla bool all_lines_off_screen_ = false; // Indica si todas las líneas han salido de la pantalla
float start_delay_timer_ = 0.0F; // Timer para retraso antes de mover líneas (segundos) float start_delay_timer_ = 0.0F; // Timer para retraso antes de mover líneas (segundos)
bool start_delay_triggered_ = false; // Bandera para determinar si el retraso ha comenzado bool start_delay_triggered_ = false; // Bandera para determinar si el retraso ha comenzado
// --- Métodos internos --- // --- Métodos internos ---
void update(float delta_time); // Actualiza las variables void update(float delta_time); // Actualiza las variables
void render(); // Pinta en pantalla void render(); // Pinta en pantalla
static void checkEvents(); // Comprueba los eventos static void checkEvents(); // Comprueba los eventos
static void checkInput(); // Comprueba las entradas static void checkInput(); // Comprueba las entradas
void fillTexture(); // Rellena la textura de texto void fillTexture(); // Rellena la textura de texto
void fillBackbuffer(); // Rellena el backbuffer void fillBackbuffer(); // Rellena el backbuffer
void iniSprites(); // Inicializa los sprites de los items void iniSprites(); // Inicializa los sprites de los items
void updateSprites(); // Actualiza los sprites void updateSprites(); // Actualiza los sprites
static auto initializeLines(int height, float line_delay) -> std::vector<Line>; // Inicializa las líneas animadas static auto initializeLines(int height, float line_delay) -> std::vector<Line>; // Inicializa las líneas animadas
static auto moveLines(std::vector<Line>& lines, int width, float duration, float delta_time) -> bool; // Mueve las líneas usando delta_time puro static auto moveLines(std::vector<Line>& lines, int width, float duration, float delta_time) -> bool; // Mueve las líneas usando delta_time puro
static void renderLines(SDL_Renderer* renderer, SDL_Texture* texture, const std::vector<Line>& lines); // Renderiza las líneas static void renderLines(SDL_Renderer* renderer, SDL_Texture* texture, const std::vector<Line>& lines); // Renderiza las líneas
void updateBackbuffer(float delta_time); // Gestiona la textura con los gráficos void updateBackbuffer(float delta_time); // Gestiona la textura con los gráficos
auto calculateDeltaTime() -> float; // Calcula el tiempo transcurrido desde el último frame auto calculateDeltaTime() -> float; // Calcula el tiempo transcurrido desde el último frame
}; };
+79 -79
View File
@@ -28,96 +28,96 @@
// para facilitar el ajuste fino de la experiencia cinematográfica. // para facilitar el ajuste fino de la experiencia cinematográfica.
class Intro { class Intro {
public: public:
// --- Constructor y destructor --- // --- Constructor y destructor ---
Intro(); Intro();
~Intro() = default; ~Intro() = default;
// --- Bucle principal --- // --- Bucle principal ---
void run(); void run();
private: private:
// --- Constantes de tiempo (en segundos) --- // --- Constantes de tiempo (en segundos) ---
static constexpr float TEXT_DISPLAY_DURATION_S = 3.0F; // Duración de visualización de texto (180 frames a 60fps) static constexpr float TEXT_DISPLAY_DURATION_S = 3.0F; // Duración de visualización de texto (180 frames a 60fps)
static constexpr float POST_BG_STOP_DELAY_S = 1.0F; // Retraso antes de detener el fondo static constexpr float POST_BG_STOP_DELAY_S = 1.0F; // Retraso antes de detener el fondo
static constexpr float POST_END_DELAY_S = 1.0F; // Retraso antes de finalizar intro static constexpr float POST_END_DELAY_S = 1.0F; // Retraso antes de finalizar intro
// --- Constantes de layout --- // --- Constantes de layout ---
static constexpr float CARD_BORDER_SIZE = 2.0F; // Tamaño del borde de tarjetas static constexpr float CARD_BORDER_SIZE = 2.0F; // Tamaño del borde de tarjetas
static constexpr float SHADOW_OFFSET = 8.0F; // Desplazamiento de sombra static constexpr float SHADOW_OFFSET = 8.0F; // Desplazamiento de sombra
static constexpr float TILED_BG_SPEED = 18.0F; // Velocidad del fondo mosaico (pixels/segundo) static constexpr float TILED_BG_SPEED = 18.0F; // Velocidad del fondo mosaico (pixels/segundo)
static constexpr int TEXT_KERNING = -2; // Espaciado entre caracteres static constexpr int TEXT_KERNING = -2; // Espaciado entre caracteres
// --- Constantes de velocidades de texto (segundos entre caracteres) --- // --- Constantes de velocidades de texto (segundos entre caracteres) ---
static constexpr float TEXT_SPEED_NORMAL = 0.133F; // Velocidad normal (8 frames * 16.67ms = 133ms) static constexpr float TEXT_SPEED_NORMAL = 0.133F; // Velocidad normal (8 frames * 16.67ms = 133ms)
static constexpr float TEXT_SPEED_FAST = 0.2F; // Velocidad rápida (12 frames * 16.67ms = 200ms) static constexpr float TEXT_SPEED_FAST = 0.2F; // Velocidad rápida (12 frames * 16.67ms = 200ms)
static constexpr float TEXT_SPEED_VERY_SLOW = 0.0167F; // Velocidad muy lenta (1 frame * 16.67ms = 16.7ms) static constexpr float TEXT_SPEED_VERY_SLOW = 0.0167F; // Velocidad muy lenta (1 frame * 16.67ms = 16.7ms)
static constexpr float TEXT_SPEED_VERY_FAST = 0.267F; // Velocidad muy rápida (16 frames * 16.67ms = 267ms) static constexpr float TEXT_SPEED_VERY_FAST = 0.267F; // Velocidad muy rápida (16 frames * 16.67ms = 267ms)
static constexpr float TEXT_SPEED_SLOW = 0.033F; // Velocidad lenta (2 frames * 16.67ms = 33ms) static constexpr float TEXT_SPEED_SLOW = 0.033F; // Velocidad lenta (2 frames * 16.67ms = 33ms)
static constexpr float TEXT_SPEED_MEDIUM_SLOW = 0.05F; // Velocidad medio-lenta (3 frames * 16.67ms = 50ms) static constexpr float TEXT_SPEED_MEDIUM_SLOW = 0.05F; // Velocidad medio-lenta (3 frames * 16.67ms = 50ms)
static constexpr float TEXT_SPEED_ULTRA_FAST = 0.333F; // Velocidad ultra rápida (20 frames * 16.67ms = 333ms) static constexpr float TEXT_SPEED_ULTRA_FAST = 0.333F; // Velocidad ultra rápida (20 frames * 16.67ms = 333ms)
// --- Constantes de animaciones de tarjetas (duraciones en segundos) --- // --- Constantes de animaciones de tarjetas (duraciones en segundos) ---
static constexpr float CARD_ANIM_DURATION_NORMAL = 100.0F / 60.0F; // ≈ 1.6667 s static constexpr float CARD_ANIM_DURATION_NORMAL = 100.0F / 60.0F; // ≈ 1.6667 s
static constexpr float CARD_ANIM_DURATION_FAST = 40.0F / 60.0F; // ≈ 0.6667 s static constexpr float CARD_ANIM_DURATION_FAST = 40.0F / 60.0F; // ≈ 0.6667 s
static constexpr float CARD_ANIM_DURATION_MEDIUM = 70.0F / 60.0F; // ≈ 1.1667 s static constexpr float CARD_ANIM_DURATION_MEDIUM = 70.0F / 60.0F; // ≈ 1.1667 s
static constexpr float CARD_ANIM_DURATION_SHORT = 80.0F / 60.0F; // ≈ 1.3333 s static constexpr float CARD_ANIM_DURATION_SHORT = 80.0F / 60.0F; // ≈ 1.3333 s
static constexpr float CARD_ANIM_DURATION_SLOW = 250.0F / 60.0F; // ≈ 4.1667 s static constexpr float CARD_ANIM_DURATION_SLOW = 250.0F / 60.0F; // ≈ 4.1667 s
static constexpr float CARD_ANIM_DURATION_VERY_SLOW = 300.0F / 60.0F; // ≈ 5.0000 s static constexpr float CARD_ANIM_DURATION_VERY_SLOW = 300.0F / 60.0F; // ≈ 5.0000 s
static constexpr float CARD_ANIM_DELAY_LONG_S = 7.5F; // Retraso largo antes de animación static constexpr float CARD_ANIM_DELAY_LONG_S = 7.5F; // Retraso largo antes de animación
static constexpr float CARD_OFFSET_MARGIN = 10.0F; // Margen fuera de pantalla static constexpr float CARD_OFFSET_MARGIN = 10.0F; // Margen fuera de pantalla
// --- Estados internos --- // --- Estados internos ---
enum class State { enum class State {
SCENES, SCENES,
POST, POST,
}; };
enum class PostState { enum class PostState {
STOP_BG, STOP_BG,
END, END,
}; };
// --- Objetos --- // --- Objetos ---
std::vector<std::unique_ptr<PathSprite>> card_sprites_; // Vector con los sprites inteligentes para los dibujos de la intro std::vector<std::unique_ptr<PathSprite>> card_sprites_; // Vector con los sprites inteligentes para los dibujos de la intro
std::vector<std::unique_ptr<PathSprite>> shadow_sprites_; // Vector con los sprites inteligentes para las sombras std::vector<std::unique_ptr<PathSprite>> shadow_sprites_; // Vector con los sprites inteligentes para las sombras
std::vector<std::unique_ptr<Writer>> texts_; // Textos de la intro std::vector<std::unique_ptr<Writer>> texts_; // Textos de la intro
std::unique_ptr<TiledBG> tiled_bg_; // Fondo en mosaico std::unique_ptr<TiledBG> tiled_bg_; // Fondo en mosaico
// --- Variables --- // --- Variables ---
Uint64 last_time_ = 0; // Último timestamp para calcular delta-time Uint64 last_time_ = 0; // Último timestamp para calcular delta-time
int scene_ = 0; // Indica qué escena está activa int scene_ = 0; // Indica qué escena está activa
State state_ = State::SCENES; // Estado principal de la intro State state_ = State::SCENES; // Estado principal de la intro
PostState post_state_ = PostState::STOP_BG; // Estado POST PostState post_state_ = PostState::STOP_BG; // Estado POST
float state_start_time_; // Tiempo de inicio del estado actual (segundos) float state_start_time_; // Tiempo de inicio del estado actual (segundos)
Color bg_color_ = param.intro.bg_color; // Color de fondo Color bg_color_ = param.intro.bg_color; // Color de fondo
// --- Métodos internos --- // --- Métodos internos ---
void update(float delta_time); // Actualiza las variables del objeto void update(float delta_time); // Actualiza las variables del objeto
void render(); // Dibuja el objeto en pantalla void render(); // Dibuja el objeto en pantalla
static void checkInput(); // Comprueba las entradas static void checkInput(); // Comprueba las entradas
static void checkEvents(); // Comprueba los eventos static void checkEvents(); // Comprueba los eventos
void updateScenes(); // Actualiza las escenas de la intro void updateScenes(); // Actualiza las escenas de la intro
void initSprites(); // Inicializa las imágenes void initSprites(); // Inicializa las imágenes
void initTexts(); // Inicializa los textos void initTexts(); // Inicializa los textos
void updateSprites(float delta_time); // Actualiza los sprites void updateSprites(float delta_time); // Actualiza los sprites
void updateTexts(float delta_time); // Actualiza los textos void updateTexts(float delta_time); // Actualiza los textos
void renderSprites(); // Dibuja los sprites void renderSprites(); // Dibuja los sprites
void renderTexts(); // Dibuja los textos void renderTexts(); // Dibuja los textos
static void renderTextRect(); // Dibuja el rectangulo de fondo del texto; static void renderTextRect(); // Dibuja el rectangulo de fondo del texto;
void updatePostState(); // Actualiza el estado POST void updatePostState(); // Actualiza el estado POST
auto calculateDeltaTime() -> float; // Calcula el tiempo transcurrido desde el último frame auto calculateDeltaTime() -> float; // Calcula el tiempo transcurrido desde el último frame
// --- Métodos para manejar cada escena individualmente --- // --- Métodos para manejar cada escena individualmente ---
void updateScene0(); void updateScene0();
void updateScene1(); void updateScene1();
void updateScene2(); void updateScene2();
void updateScene3(); void updateScene3();
void updateScene4(); void updateScene4();
void updateScene5(); void updateScene5();
// --- Métodos auxiliares para reducir duplicación de código --- // --- Métodos auxiliares para reducir duplicación de código ---
void enableCardAndShadow(int index); void enableCardAndShadow(int index);
void switchText(int from_index, int to_index); void switchText(int from_index, int to_index);
}; };
+54 -54
View File
@@ -26,66 +26,66 @@ class Texture;
// consistencia visual en diferentes velocidades de procesamiento. // consistencia visual en diferentes velocidades de procesamiento.
class Logo { class Logo {
public: public:
// --- Constructor y destructor --- // --- Constructor y destructor ---
Logo(); Logo();
~Logo(); ~Logo();
// --- Bucle principal --- // --- Bucle principal ---
void run(); void run();
private: private:
// --- Constantes de tiempo (en segundos) --- // --- Constantes de tiempo (en segundos) ---
static constexpr float SOUND_TRIGGER_TIME_S = 0.5F; // Tiempo para activar el sonido del logo static constexpr float SOUND_TRIGGER_TIME_S = 0.5F; // Tiempo para activar el sonido del logo
static constexpr float SHOW_SINCE_SPRITE_TIME_S = 1.167F; // Tiempo para mostrar el sprite "SINCE 1998" static constexpr float SHOW_SINCE_SPRITE_TIME_S = 1.167F; // Tiempo para mostrar el sprite "SINCE 1998"
static constexpr float INIT_FADE_TIME_S = 5.0F; // Tiempo de inicio del fade a negro static constexpr float INIT_FADE_TIME_S = 5.0F; // Tiempo de inicio del fade a negro
static constexpr float END_LOGO_TIME_S = 6.668F; // Tiempo de finalización del logo static constexpr float END_LOGO_TIME_S = 6.668F; // Tiempo de finalización del logo
static constexpr float POST_LOGO_DURATION_S = 0.333F; // Duración adicional después del fade static constexpr float POST_LOGO_DURATION_S = 0.333F; // Duración adicional después del fade
static constexpr float LOGO_SPEED_PX_PER_S = 480.0F; // Velocidad de desplazamiento (píxeles por segundo) - 8.0f/16.67f*1000 static constexpr float LOGO_SPEED_PX_PER_S = 480.0F; // Velocidad de desplazamiento (píxeles por segundo) - 8.0f/16.67f*1000
static constexpr float COLOR_CHANGE_INTERVAL_S = 0.0667F; // Intervalo entre cambios de color (~4 frames a 60fps) static constexpr float COLOR_CHANGE_INTERVAL_S = 0.0667F; // Intervalo entre cambios de color (~4 frames a 60fps)
// --- Constantes de layout --- // --- Constantes de layout ---
static constexpr int SINCE_SPRITE_Y_OFFSET = 83; // Posición Y base del sprite "Since 1998" static constexpr int SINCE_SPRITE_Y_OFFSET = 83; // Posición Y base del sprite "Since 1998"
static constexpr int LOGO_SPACING = 5; // Espaciado entre elementos del logo static constexpr int LOGO_SPACING = 5; // Espaciado entre elementos del logo
static constexpr int LINE_OFFSET_FACTOR = 3; // Factor de desplazamiento inicial por línea static constexpr int LINE_OFFSET_FACTOR = 3; // Factor de desplazamiento inicial por línea
static constexpr int SPRITE_LINE_HEIGHT = 1; // Altura de cada línea sprite static constexpr int SPRITE_LINE_HEIGHT = 1; // Altura de cada línea sprite
// --- Constantes de colores --- // --- Constantes de colores ---
static constexpr int MAX_SINCE_COLOR_INDEX = 7; // Índice máximo para colores del sprite "Since" static constexpr int MAX_SINCE_COLOR_INDEX = 7; // Índice máximo para colores del sprite "Since"
static constexpr int MAX_FADE_COLOR_INDEX = 6; // Índice máximo para colores del fade static constexpr int MAX_FADE_COLOR_INDEX = 6; // Índice máximo para colores del fade
// --- Paleta ZX Spectrum para efectos de logo --- // --- Paleta ZX Spectrum para efectos de logo ---
static constexpr Color SPECTRUM_BLACK = Color(0x00, 0x00, 0x00); // Negro static constexpr Color SPECTRUM_BLACK = Color(0x00, 0x00, 0x00); // Negro
static constexpr Color SPECTRUM_BLUE = Color(0x00, 0x00, 0xd8); // Azul static constexpr Color SPECTRUM_BLUE = Color(0x00, 0x00, 0xd8); // Azul
static constexpr Color SPECTRUM_RED = Color(0xd8, 0x00, 0x00); // Rojo static constexpr Color SPECTRUM_RED = Color(0xd8, 0x00, 0x00); // Rojo
static constexpr Color SPECTRUM_MAGENTA = Color(0xd8, 0x00, 0xd8); // Magenta static constexpr Color SPECTRUM_MAGENTA = Color(0xd8, 0x00, 0xd8); // Magenta
static constexpr Color SPECTRUM_GREEN = Color(0x00, 0xd8, 0x00); // Verde static constexpr Color SPECTRUM_GREEN = Color(0x00, 0xd8, 0x00); // Verde
static constexpr Color SPECTRUM_CYAN = Color(0x00, 0xd8, 0xd8); // Cian static constexpr Color SPECTRUM_CYAN = Color(0x00, 0xd8, 0xd8); // Cian
static constexpr Color SPECTRUM_YELLOW = Color(0xd8, 0xd8, 0x00); // Amarillo static constexpr Color SPECTRUM_YELLOW = Color(0xd8, 0xd8, 0x00); // Amarillo
static constexpr Color SPECTRUM_WHITE = Color(0xFF, 0xFF, 0xFF); // Blanco brillante static constexpr Color SPECTRUM_WHITE = Color(0xFF, 0xFF, 0xFF); // Blanco brillante
static constexpr Color RESET_COLOR = Color(255, 255, 255); // Color de reset static constexpr Color RESET_COLOR = Color(255, 255, 255); // Color de reset
// --- Objetos y punteros --- // --- Objetos y punteros ---
std::shared_ptr<Texture> since_texture_; // Textura con los gráficos "Since 1998" std::shared_ptr<Texture> since_texture_; // Textura con los gráficos "Since 1998"
std::unique_ptr<Sprite> since_sprite_; // Sprite para manejar la since_texture std::unique_ptr<Sprite> since_sprite_; // Sprite para manejar la since_texture
std::shared_ptr<Texture> jail_texture_; // Textura con los gráficos "JAILGAMES" std::shared_ptr<Texture> jail_texture_; // Textura con los gráficos "JAILGAMES"
std::vector<std::unique_ptr<Sprite>> jail_sprite_; // Vector con los sprites de cada línea que forman el bitmap JAILGAMES std::vector<std::unique_ptr<Sprite>> jail_sprite_; // Vector con los sprites de cada línea que forman el bitmap JAILGAMES
// --- Variables --- // --- Variables ---
std::vector<Color> color_; // Vector con los colores para el fade std::vector<Color> color_; // Vector con los colores para el fade
float elapsed_time_s_ = 0.0F; // Tiempo transcurrido en segundos float elapsed_time_s_ = 0.0F; // Tiempo transcurrido en segundos
Uint64 last_time_ = 0; // Último timestamp para calcular delta-time Uint64 last_time_ = 0; // Último timestamp para calcular delta-time
SDL_FPoint dest_; // Posición donde dibujar el logo SDL_FPoint dest_; // Posición donde dibujar el logo
bool sound_triggered_ = false; // Indica si el sonido del logo ya se reprodujo bool sound_triggered_ = false; // Indica si el sonido del logo ya se reprodujo
// --- Métodos internos --- // --- Métodos internos ---
void update(float delta_time); // Actualiza las variables void update(float delta_time); // Actualiza las variables
void render(); // Dibuja en pantalla void render(); // Dibuja en pantalla
static void checkEvents(); // Comprueba el manejador de eventos static void checkEvents(); // Comprueba el manejador de eventos
static void checkInput(); // Comprueba las entradas static void checkInput(); // Comprueba las entradas
void updateJAILGAMES(float delta_time); // Gestiona el logo de JAILGAMES void updateJAILGAMES(float delta_time); // Gestiona el logo de JAILGAMES
void renderJAILGAMES(); // Renderiza el logo de JAILGAMES void renderJAILGAMES(); // Renderiza el logo de JAILGAMES
void updateTextureColors(float delta_time); // Gestiona el color de las texturas void updateTextureColors(float delta_time); // Gestiona el color de las texturas
void handleSound(); // Maneja la reproducción del sonido del logo void handleSound(); // Maneja la reproducción del sonido del logo
auto calculateDeltaTime() -> float; // Calcula el tiempo transcurrido desde el último frame auto calculateDeltaTime() -> float; // Calcula el tiempo transcurrido desde el último frame
}; };
+2 -2
View File
@@ -506,8 +506,8 @@ void Title::setState(State state) {
// Inicializa los jugadores // Inicializa los jugadores
void Title::initPlayers() { void Title::initPlayers() {
std::vector<std::vector<std::shared_ptr<Texture>>> player_textures; // Vector con todas las texturas de los jugadores; std::vector<std::vector<std::shared_ptr<Texture>>> player_textures; // Vector con todas las texturas de los jugadores;
std::vector<std::vector<std::string>> player1_animations; // Vector con las animaciones del jugador 1 std::vector<std::vector<std::string>> player1_animations; // Vector con las animaciones del jugador 1
std::vector<std::vector<std::string>> player2_animations; // Vector con las animaciones del jugador 2 std::vector<std::vector<std::string>> player2_animations; // Vector con las animaciones del jugador 2
// Texturas - Player1 // Texturas - Player1
std::vector<std::shared_ptr<Texture>> player1_textures; std::vector<std::shared_ptr<Texture>> player1_textures;
+95 -95
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 ---
@@ -38,119 +38,119 @@ struct Gamepad;
// La clase utiliza un sistema de tiempo basado en segundos para garantizar // La clase utiliza un sistema de tiempo basado en segundos para garantizar
// comportamiento consistente independientemente del framerate. // comportamiento consistente independientemente del framerate.
class Title { class Title {
public: public:
// --- Constructor y destructor --- // --- Constructor y destructor ---
Title(); Title();
~Title(); ~Title();
// --- Bucle principal --- // --- Bucle principal ---
void run(); void run();
private: private:
// --- Constantes de tiempo (en segundos) --- // --- Constantes de tiempo (en segundos) ---
static constexpr float START_PRESSED_DELAY_S = 1666.67F / 1000.0F; // Tiempo antes de fade tras pulsar start (100 frames a 60fps) static constexpr float START_PRESSED_DELAY_S = 1666.67F / 1000.0F; // Tiempo antes de fade tras pulsar start (100 frames a 60fps)
static constexpr int MUSIC_FADE_OUT_LONG_MS = 1500; // Fade out largo de música static constexpr int MUSIC_FADE_OUT_LONG_MS = 1500; // Fade out largo de música
static constexpr int MUSIC_FADE_OUT_SHORT_MS = 300; // Fade out corto de música static constexpr int MUSIC_FADE_OUT_SHORT_MS = 300; // Fade out corto de música
// --- Constantes de parpadeo (en segundos) --- // --- Constantes de parpadeo (en segundos) ---
static constexpr float LOGO_BLINK_PERIOD_S = 833.0F / 1000.0F; // Período de parpadeo del logo (833ms) static constexpr float LOGO_BLINK_PERIOD_S = 833.0F / 1000.0F; // Período de parpadeo del logo (833ms)
static constexpr float LOGO_BLINK_ON_TIME_S = 583.0F / 1000.0F; // Tiempo encendido del logo (583ms) static constexpr float LOGO_BLINK_ON_TIME_S = 583.0F / 1000.0F; // Tiempo encendido del logo (583ms)
static constexpr float START_BLINK_PERIOD_S = 167.0F / 1000.0F; // Período de parpadeo del start (167ms) static constexpr float START_BLINK_PERIOD_S = 167.0F / 1000.0F; // Período de parpadeo del start (167ms)
static constexpr float START_BLINK_ON_TIME_S = 83.0F / 1000.0F; // Tiempo encendido del start (83ms) static constexpr float START_BLINK_ON_TIME_S = 83.0F / 1000.0F; // Tiempo encendido del start (83ms)
// --- Constantes de layout --- // --- Constantes de layout ---
static constexpr int MINI_LOGO_Y_DIVISOR = 5; // Divisor para posición Y del mini logo static constexpr int MINI_LOGO_Y_DIVISOR = 5; // Divisor para posición Y del mini logo
static constexpr int MINI_LOGO_Y_FACTOR = 4; // Factor para posición Y del mini logo static constexpr int MINI_LOGO_Y_FACTOR = 4; // Factor para posición Y del mini logo
static constexpr int COPYRIGHT_TEXT_SPACING = 3; // Espaciado del texto de copyright static constexpr int COPYRIGHT_TEXT_SPACING = 3; // Espaciado del texto de copyright
// --- Constantes de texto y configuración --- // --- Constantes de texto y configuración ---
static constexpr std::string_view TEXT_COPYRIGHT = "@2020,2025 JailDesigner"; // Texto de copyright static constexpr std::string_view TEXT_COPYRIGHT = "@2020,2025 JailDesigner"; // Texto de copyright
static constexpr bool ALLOW_TITLE_ANIMATION_SKIP = false; // Permite saltar la animación del título static constexpr bool ALLOW_TITLE_ANIMATION_SKIP = false; // Permite saltar la animación del título
// --- Enums --- // --- Enums ---
enum class State { enum class State {
LOGO_ANIMATING, // El logo está animándose LOGO_ANIMATING, // El logo está animándose
LOGO_FINISHED, // El logo ha terminado de animarse LOGO_FINISHED, // El logo ha terminado de animarse
START_HAS_BEEN_PRESSED, // Se ha pulsado el botón de start START_HAS_BEEN_PRESSED, // Se ha pulsado el botón de start
}; };
// --- Estructuras privadas --- // --- Estructuras privadas ---
struct Anchor { struct Anchor {
int mini_logo; // Ancla del logo mini int mini_logo; // Ancla del logo mini
int copyright_text; // Ancla del texto de copyright int copyright_text; // Ancla del texto de copyright
}; };
// --- Objetos y punteros --- // --- Objetos y punteros ---
std::shared_ptr<Text> text_; // Objeto de texto para escribir en pantalla std::shared_ptr<Text> text_; // Objeto de texto para escribir en pantalla
std::unique_ptr<Fade> fade_; // Fundido en pantalla std::unique_ptr<Fade> fade_; // Fundido en pantalla
std::unique_ptr<TiledBG> tiled_bg_; // Fondo animado de tiles std::unique_ptr<TiledBG> tiled_bg_; // Fondo animado de tiles
std::unique_ptr<GameLogo> game_logo_; // Logo del juego std::unique_ptr<GameLogo> game_logo_; // Logo del juego
std::unique_ptr<Sprite> mini_logo_sprite_; // Logo JailGames mini std::unique_ptr<Sprite> mini_logo_sprite_; // Logo JailGames mini
std::vector<std::shared_ptr<Player>> players_; // Vector de jugadores std::vector<std::shared_ptr<Player>> players_; // Vector de jugadores
// --- Variables de estado --- // --- Variables de estado ---
Anchor anchor_; // Anclas para definir la posición de los elementos del título Anchor anchor_; // Anclas para definir la posición de los elementos del título
Section::Name next_section_; // Siguiente sección a cargar Section::Name next_section_; // Siguiente sección a cargar
Section::Options selection_ = Section::Options::TITLE_TIME_OUT; // Opción elegida en el título Section::Options selection_ = Section::Options::TITLE_TIME_OUT; // Opción elegida en el título
State state_; // Estado actual de la sección State state_; // Estado actual de la sección
Uint64 last_time_ = 0; // Último timestamp para calcular delta-time Uint64 last_time_ = 0; // Último timestamp para calcular delta-time
float counter_time_ = 0.0F; // Temporizador para la pantalla de título (en segundos) float counter_time_ = 0.0F; // Temporizador para la pantalla de título (en segundos)
float blink_accumulator_ = 0.0F; // Acumulador para el parpadeo (en segundos) float blink_accumulator_ = 0.0F; // Acumulador para el parpadeo (en segundos)
int num_controllers_; // Número de mandos conectados int num_controllers_; // Número de mandos conectados
bool should_render_start_prompt_ = false; // Indica si se muestra el texto de PRESS START BUTTON TO PLAY bool should_render_start_prompt_ = false; // Indica si se muestra el texto de PRESS START BUTTON TO PLAY
bool player1_start_pressed_ = false; // Indica si se ha pulsado el botón de empezar para el jugador 1 bool player1_start_pressed_ = false; // Indica si se ha pulsado el botón de empezar para el jugador 1
bool player2_start_pressed_ = false; // Indica si se ha pulsado el botón de empezar para el jugador 2 bool player2_start_pressed_ = false; // Indica si se ha pulsado el botón de empezar para el jugador 2
#ifdef _DEBUG #ifdef _DEBUG
Color debug_color_; // Color para depuración en modo debug Color debug_color_; // Color para depuración en modo debug
#endif #endif
// --- Ciclo de vida del título --- // --- Ciclo de vida del título ---
void update(float delta_time); // Actualiza las variables del objeto void update(float delta_time); // Actualiza las variables del objeto
auto calculateDeltaTime() -> float; // Calcula el tiempo transcurrido desde el último frame auto calculateDeltaTime() -> float; // Calcula el tiempo transcurrido desde el último frame
void updateState(float delta_time); // Actualiza el estado actual del título void updateState(float delta_time); // Actualiza el estado actual del título
void setState(State state); // Cambia el estado del título void setState(State state); // Cambia el estado del título
void resetCounter(); // Reinicia el contador interno void resetCounter(); // Reinicia el contador interno
// --- Entrada de usuario --- // --- Entrada de usuario ---
void checkEvents(); // Comprueba los eventos void checkEvents(); // Comprueba los eventos
void checkInput(); // Comprueba las entradas void checkInput(); // Comprueba las entradas
void handleKeyDownEvent(const SDL_Event& event); // Maneja el evento de tecla presionada void handleKeyDownEvent(const SDL_Event& event); // Maneja el evento de tecla presionada
void processKeyboardStart(); // Procesa las entradas del teclado void processKeyboardStart(); // Procesa las entradas del teclado
void processControllerInputs(); // Procesa las entradas de los mandos void processControllerInputs(); // Procesa las entradas de los mandos
[[nodiscard]] static auto isStartButtonPressed(const Options::Gamepad* controller) -> bool; // Comprueba si se ha pulsado el botón Start [[nodiscard]] static auto isStartButtonPressed(const Options::Gamepad* controller) -> bool; // Comprueba si se ha pulsado el botón Start
void handleStartButtonPress(const Options::Gamepad* controller); // Maneja la pulsación del botón Start void handleStartButtonPress(const Options::Gamepad* controller); // Maneja la pulsación del botón Start
[[nodiscard]] auto canProcessStartButton() const -> bool; // Verifica si se puede procesar la pulsación del botón Start [[nodiscard]] auto canProcessStartButton() const -> bool; // Verifica si se puede procesar la pulsación del botón Start
void processPlayer1Start(); // Procesa el inicio del jugador 1 void processPlayer1Start(); // Procesa el inicio del jugador 1
void processPlayer2Start(); // Procesa el inicio del jugador 2 void processPlayer2Start(); // Procesa el inicio del jugador 2
void activatePlayerAndSetState(Player::Id player_id); // Activa al jugador y cambia el estado del título void activatePlayerAndSetState(Player::Id player_id); // Activa al jugador y cambia el estado del título
// --- Gestión de jugadores --- // --- Gestión de jugadores ---
void initPlayers(); // Inicializa los jugadores void initPlayers(); // Inicializa los jugadores
void updatePlayers(float delta_time); // Actualiza los jugadores void updatePlayers(float delta_time); // Actualiza los jugadores
void renderPlayers(); // Renderiza los jugadores void renderPlayers(); // Renderiza los jugadores
auto getPlayer(Player::Id id) -> std::shared_ptr<Player>; // Obtiene un jugador a partir de su "id" auto getPlayer(Player::Id id) -> std::shared_ptr<Player>; // Obtiene un jugador a partir de su "id"
// --- Visualización / Renderizado --- // --- Visualización / Renderizado ---
void render(); // Dibuja el objeto en pantalla void render(); // Dibuja el objeto en pantalla
void updateFade(); // Actualiza el efecto de fundido (fade in/out) void updateFade(); // Actualiza el efecto de fundido (fade in/out)
void updateStartPrompt(float delta_time); // Actualiza el mensaje de "Pulsa Start" void updateStartPrompt(float delta_time); // Actualiza el mensaje de "Pulsa Start"
void renderStartPrompt(); // Dibuja el mensaje de "Pulsa Start" en pantalla void renderStartPrompt(); // Dibuja el mensaje de "Pulsa Start" en pantalla
void renderCopyright(); // Dibuja el aviso de copyright void renderCopyright(); // Dibuja el aviso de copyright
// --- Utilidades estáticas --- // --- Utilidades estáticas ---
static void swapControllers(); // Intercambia la asignación de mandos a los jugadores static void swapControllers(); // Intercambia la asignación de mandos a los jugadores
static void swapKeyboard(); // Intercambia el teclado de jugador static void swapKeyboard(); // Intercambia el teclado de jugador
static void showControllers(); // Muestra información sobre los controles y los jugadores static void showControllers(); // Muestra información sobre los controles y los jugadores
// --- Depuración (solo en modo DEBUG) --- // --- Depuración (solo en modo DEBUG) ---
#ifdef _DEBUG #ifdef _DEBUG
void handleDebugColorKeys(SDL_Keycode key); // Maneja las teclas de depuración para colores void handleDebugColorKeys(SDL_Keycode key); // Maneja las teclas de depuración para colores
static void adjustColorComponent(SDL_Keycode key, Color& color); // Ajusta un componente del color según la tecla static void adjustColorComponent(SDL_Keycode key, Color& color); // Ajusta un componente del color según la tecla
static void incrementColorComponent(uint8_t& component); // Incrementa un componente de color static void incrementColorComponent(uint8_t& component); // Incrementa un componente de color
static void decrementColorComponent(uint8_t& component); // Decrementa un componente de color static void decrementColorComponent(uint8_t& component); // Decrementa un componente de color
static void incrementAllComponents(Color& color); // Incrementa todos los componentes del color static void incrementAllComponents(Color& color); // Incrementa todos los componentes del color
static void decrementAllComponents(Color& color); // Decrementa todos los componentes del color static void decrementAllComponents(Color& color); // Decrementa todos los componentes del color
static void printColorValue(const Color& color); // Imprime el valor actual del color en consola static void printColorValue(const Color& color); // Imprime el valor actual del color en consola
#endif #endif
}; };
+109 -109
View File
@@ -16,142 +16,142 @@
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) {
// Proceso hijo // Proceso hijo
execvp(command, args.data()); execvp(command, args.data());
// Si llegamos aquí, execvp falló // Si llegamos aquí, execvp falló
std::cerr << "Error: No se pudo ejecutar " << command << '\n'; std::cerr << "Error: No se pudo ejecutar " << command << '\n';
_exit(1); _exit(1);
} else if (pid > 0) { } else if (pid > 0) {
// Proceso padre // Proceso padre
int status; int status;
waitpid(pid, &status, 0); waitpid(pid, &status, 0);
return (WEXITSTATUS(status) == 0) ? ShutdownResult::SUCCESS : ShutdownResult::ERROR_SYSTEM_CALL; return (WEXITSTATUS(status) == 0) ? ShutdownResult::SUCCESS : ShutdownResult::ERROR_SYSTEM_CALL;
} 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};
PROCESS_INFORMATION pi = {0}; PROCESS_INFORMATION pi = {0};
si.cb = sizeof(si); si.cb = sizeof(si);
// Crear comando con el delay especificado // Crear comando con el delay especificado
std::string command = "shutdown.exe /s /t " + std::to_string(config.delay_seconds); std::string command = "shutdown.exe /s /t " + std::to_string(config.delay_seconds);
if (config.force_close_apps) { if (config.force_close_apps) {
command += " /f"; command += " /f";
} }
// CreateProcess necesita un array de char modificable // CreateProcess necesita un array de char modificable
char* cmd_buffer = new char[command.length() + 1]; char* cmd_buffer = new char[command.length() + 1];
strcpy(cmd_buffer, command.c_str()); strcpy(cmd_buffer, command.c_str());
bool success = CreateProcessA( bool success = CreateProcessA(
NULL, // lpApplicationName NULL, // lpApplicationName
cmd_buffer, // lpCommandLine cmd_buffer, // lpCommandLine
NULL, // lpProcessAttributes NULL, // lpProcessAttributes
NULL, // lpThreadAttributes NULL, // lpThreadAttributes
FALSE, // bInheritHandles FALSE, // bInheritHandles
0, // dwCreationFlags 0, // dwCreationFlags
NULL, // lpEnvironment NULL, // lpEnvironment
NULL, // lpCurrentDirectory NULL, // lpCurrentDirectory
&si, // lpStartupInfo &si, // lpStartupInfo
&pi // lpProcessInformation &pi // lpProcessInformation
); );
delete[] cmd_buffer; delete[] cmd_buffer;
if (success) { if (success) {
CloseHandle(pi.hProcess); CloseHandle(pi.hProcess);
CloseHandle(pi.hThread); CloseHandle(pi.hThread);
return ShutdownResult::SUCCESS; return ShutdownResult::SUCCESS;
} else { } else {
DWORD error = GetLastError(); DWORD error = GetLastError();
if (error == ERROR_ACCESS_DENIED) { if (error == ERROR_ACCESS_DENIED) {
return ShutdownResult::ERROR_PERMISSION; return ShutdownResult::ERROR_PERMISSION;
}
return ShutdownResult::ERROR_SYSTEM_CALL;
} }
return ShutdownResult::ERROR_SYSTEM_CALL;
}
#elif __APPLE__ #elif __APPLE__
// macOS - apagado inmediato // macOS - apagado inmediato
std::vector<char*> args = { std::vector<char*> args = {
const_cast<char*>("shutdown"), const_cast<char*>("shutdown"),
const_cast<char*>("-h"), const_cast<char*>("-h"),
const_cast<char*>("now"), const_cast<char*>("now"),
nullptr}; nullptr};
return executeUnixShutdown("shutdown", args); return executeUnixShutdown("shutdown", args);
#elif __linux__ #elif __linux__
// Linux - apagado inmediato // Linux - apagado inmediato
std::vector<char*> args = { std::vector<char*> args = {
const_cast<char*>("shutdown"), const_cast<char*>("shutdown"),
const_cast<char*>("-h"), const_cast<char*>("-h"),
const_cast<char*>("now"), const_cast<char*>("now"),
nullptr}; nullptr};
return executeUnixShutdown("shutdown", args); return executeUnixShutdown("shutdown", args);
#else #else
return ShutdownResult::ERROR_UNSUPPORTED; return ShutdownResult::ERROR_UNSUPPORTED;
#endif #endif
}
auto resultToString(ShutdownResult result) -> const char* {
switch (result) {
case ShutdownResult::SUCCESS:
return "Apagado iniciado exitosamente";
case ShutdownResult::ERROR_PERMISSION:
return "Error: Permisos insuficientes";
case ShutdownResult::ERROR_SYSTEM_CALL:
return "Error: Fallo en la llamada al sistema";
case ShutdownResult::ERROR_FORK_FAILED:
return "Error: No se pudo crear proceso hijo";
case ShutdownResult::ERROR_UNSUPPORTED:
return "Error: Sistema operativo no soportado";
default:
return "Error desconocido";
} }
}
auto isShutdownSupported() -> bool { auto resultToString(ShutdownResult result) -> const char* {
switch (result) {
case ShutdownResult::SUCCESS:
return "Apagado iniciado exitosamente";
case ShutdownResult::ERROR_PERMISSION:
return "Error: Permisos insuficientes";
case ShutdownResult::ERROR_SYSTEM_CALL:
return "Error: Fallo en la llamada al sistema";
case ShutdownResult::ERROR_FORK_FAILED:
return "Error: No se pudo crear proceso hijo";
case ShutdownResult::ERROR_UNSUPPORTED:
return "Error: Sistema operativo no soportado";
default:
return "Error desconocido";
}
}
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__)
return "Requiere permisos de root/sudo en Unix"; return "Requiere permisos de root/sudo en Unix";
#else #else
return "Sistema no soportado"; return "Sistema no soportado";
#endif #endif
} }
} // namespace SystemShutdown } // namespace SystemShutdown
+18 -18
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
+30 -30
View File
@@ -9,39 +9,39 @@ class Texture;
// --- Clase SmartSprite: sprite animado que se mueve hacia un destino y puede deshabilitarse automáticamente --- // --- Clase SmartSprite: sprite animado que se mueve hacia un destino y puede deshabilitarse automáticamente ---
class SmartSprite : public AnimatedSprite { class SmartSprite : public AnimatedSprite {
public: public:
// --- Constructor y destructor --- // --- Constructor y destructor ---
explicit SmartSprite(std::shared_ptr<Texture> texture) explicit SmartSprite(std::shared_ptr<Texture> texture)
: AnimatedSprite(std::move(texture)) {} : AnimatedSprite(std::move(texture)) {}
~SmartSprite() override = default; ~SmartSprite() override = default;
// --- Métodos principales --- // --- Métodos principales ---
void update(float delta_time) override; // Actualiza la posición y comprueba si ha llegado a su destino (time-based) void update(float delta_time) override; // Actualiza la posición y comprueba si ha llegado a su destino (time-based)
void render() override; // Dibuja el sprite void render() override; // Dibuja el sprite
// --- Getters --- // --- Getters ---
auto getDestX() const -> int { return dest_x_; } // Obtiene la posición de destino en X auto getDestX() const -> int { return dest_x_; } // Obtiene la posición de destino en X
auto getDestY() const -> int { return dest_y_; } // Obtiene la posición de destino en Y auto getDestY() const -> int { return dest_y_; } // Obtiene la posición de destino en Y
auto isOnDestination() const -> bool { return on_destination_; } // Indica si está en el destino auto isOnDestination() const -> bool { return on_destination_; } // Indica si está en el destino
auto hasFinished() const -> bool { return finished_; } // Indica si ya ha terminado auto hasFinished() const -> bool { return finished_; } // Indica si ya ha terminado
// --- Setters --- // --- Setters ---
void setFinishedDelay(float value) { finished_delay_ms_ = value; } // Establece el retraso para deshabilitarlo (ms) void setFinishedDelay(float value) { finished_delay_ms_ = value; } // Establece el retraso para deshabilitarlo (ms)
void setDestX(int x) { dest_x_ = x; } // Establece la posición de destino en X void setDestX(int x) { dest_x_ = x; } // Establece la posición de destino en X
void setDestY(int y) { dest_y_ = y; } // Establece la posición de destino en Y void setDestY(int y) { dest_y_ = y; } // Establece la posición de destino en Y
void setEnabled(bool value) { enabled_ = value; } // Habilita o deshabilita el objeto void setEnabled(bool value) { enabled_ = value; } // Habilita o deshabilita el objeto
private: private:
// --- Variables de estado --- // --- Variables de estado ---
int dest_x_ = 0; // Posición de destino en el eje X int dest_x_ = 0; // Posición de destino en el eje X
int dest_y_ = 0; // Posición de destino en el eje Y int dest_y_ = 0; // Posición de destino en el eje Y
float finished_delay_ms_ = 0.0F; // Retraso para deshabilitarlo (ms) float finished_delay_ms_ = 0.0F; // Retraso para deshabilitarlo (ms)
float finished_timer_ = 0.0F; // Timer acumulado (ms) float finished_timer_ = 0.0F; // Timer acumulado (ms)
bool on_destination_ = false; // Indica si está en el destino bool on_destination_ = false; // Indica si está en el destino
bool finished_ = false; // Indica si ya ha terminado bool finished_ = false; // Indica si ya ha terminado
bool enabled_ = false; // Indica si el objeto está habilitado bool enabled_ = false; // Indica si el objeto está habilitado
// --- Métodos internos --- // --- Métodos internos ---
void checkFinished(float delta_time); // Comprueba si ha terminado (time-based) void checkFinished(float delta_time); // Comprueba si ha terminado (time-based)
void checkMove(); // Comprueba el movimiento void checkMove(); // Comprueba el movimiento
}; };
+49 -49
View File
@@ -11,62 +11,62 @@ class Texture;
// --- Clase Sprite: representa un objeto gráfico básico con posición, tamaño y textura --- // --- Clase Sprite: representa un objeto gráfico básico con posición, tamaño y textura ---
class Sprite { class Sprite {
public: public:
// --- Constructores y destructor --- // --- Constructores y destructor ---
Sprite(std::shared_ptr<Texture> texture, float pos_x, float pos_y, float width, float height); Sprite(std::shared_ptr<Texture> texture, float pos_x, float pos_y, float width, float height);
Sprite(std::shared_ptr<Texture> texture, SDL_FRect rect); Sprite(std::shared_ptr<Texture> texture, SDL_FRect rect);
explicit Sprite(std::shared_ptr<Texture> texture); explicit Sprite(std::shared_ptr<Texture> texture);
virtual ~Sprite() = default; virtual ~Sprite() = default;
// --- Renderizado y control --- // --- Renderizado y control ---
virtual void render(); // Muestra el sprite por pantalla virtual void render(); // Muestra el sprite por pantalla
virtual void clear(); // Reinicia las variables a cero virtual void clear(); // Reinicia las variables a cero
// --- Getters de posición y tamaño --- // --- Getters de posición y tamaño ---
[[nodiscard]] auto getX() const -> float { return pos_.x; } [[nodiscard]] auto getX() const -> float { return pos_.x; }
[[nodiscard]] auto getY() const -> float { return pos_.y; } [[nodiscard]] auto getY() const -> float { return pos_.y; }
[[nodiscard]] auto getWidth() const -> float { return pos_.w; } [[nodiscard]] auto getWidth() const -> float { return pos_.w; }
[[nodiscard]] auto getHeight() const -> float { return pos_.h; } [[nodiscard]] auto getHeight() const -> float { return pos_.h; }
[[nodiscard]] auto getPosition() const -> SDL_FRect { return pos_; } [[nodiscard]] auto getPosition() const -> SDL_FRect { return pos_; }
auto getRect() -> SDL_FRect& { return pos_; } auto getRect() -> SDL_FRect& { return pos_; }
// --- Setters de posición y tamaño --- // --- Setters de posición y tamaño ---
void setX(float pos_x) { pos_.x = pos_x; } void setX(float pos_x) { pos_.x = pos_x; }
void setY(float pos_y) { pos_.y = pos_y; } void setY(float pos_y) { pos_.y = pos_y; }
void setWidth(float width) { pos_.w = width; } void setWidth(float width) { pos_.w = width; }
void setHeight(float height) { pos_.h = height; } void setHeight(float height) { pos_.h = height; }
void setPosition(float pos_x, float pos_y); void setPosition(float pos_x, float pos_y);
void setPosition(SDL_FPoint point); void setPosition(SDL_FPoint point);
void setPosition(SDL_FRect rect) { pos_ = rect; } void setPosition(SDL_FRect rect) { pos_ = rect; }
// --- Zoom --- // --- Zoom ---
void setZoom(float zoom) { zoom_ = zoom; } void setZoom(float zoom) { zoom_ = zoom; }
// --- Modificación de posición --- // --- Modificación de posición ---
void incX(float value) { pos_.x += value; } void incX(float value) { pos_.x += value; }
void incY(float value) { pos_.y += value; } void incY(float value) { pos_.y += value; }
// --- Sprite clip --- // --- Sprite clip ---
[[nodiscard]] auto getSpriteClip() const -> SDL_FRect { return sprite_clip_; } [[nodiscard]] auto getSpriteClip() const -> SDL_FRect { return sprite_clip_; }
void setSpriteClip(SDL_FRect rect) { sprite_clip_ = rect; } void setSpriteClip(SDL_FRect rect) { sprite_clip_ = rect; }
void setSpriteClip(float pos_x, float pos_y, float width, float height) { sprite_clip_ = SDL_FRect{pos_x, pos_y, width, height}; } void setSpriteClip(float pos_x, float pos_y, float width, float height) { sprite_clip_ = SDL_FRect{pos_x, pos_y, width, height}; }
// --- Textura --- // --- Textura ---
[[nodiscard]] auto getTexture() const -> std::shared_ptr<Texture> { return textures_.at(texture_index_); } [[nodiscard]] auto getTexture() const -> std::shared_ptr<Texture> { return textures_.at(texture_index_); }
void setTexture(std::shared_ptr<Texture> texture) { textures_.at(texture_index_) = std::move(texture); } void setTexture(std::shared_ptr<Texture> texture) { textures_.at(texture_index_) = std::move(texture); }
void addTexture(const std::shared_ptr<Texture>& texture) { textures_.push_back(texture); } void addTexture(const std::shared_ptr<Texture>& texture) { textures_.push_back(texture); }
auto setActiveTexture(size_t index) -> bool; // Cambia la textura activa por índice auto setActiveTexture(size_t index) -> bool; // Cambia la textura activa por índice
[[nodiscard]] auto getActiveTexture() const -> size_t { return texture_index_; } // Alias para getActiveTextureIndex [[nodiscard]] auto getActiveTexture() const -> size_t { return texture_index_; } // Alias para getActiveTextureIndex
[[nodiscard]] auto getTextureCount() const -> size_t { return textures_.size(); } // Obtiene el número total de texturas [[nodiscard]] auto getTextureCount() const -> size_t { return textures_.size(); } // Obtiene el número total de texturas
protected: protected:
// --- Métodos internos --- // --- Métodos internos ---
auto getTextureRef() -> std::shared_ptr<Texture>& { return textures_.at(texture_index_); } // Obtiene referencia a la textura activa auto getTextureRef() -> std::shared_ptr<Texture>& { return textures_.at(texture_index_); } // Obtiene referencia a la textura activa
// --- Variables internas --- // --- Variables internas ---
std::vector<std::shared_ptr<Texture>> textures_; // Lista de texturas std::vector<std::shared_ptr<Texture>> textures_; // Lista de texturas
size_t texture_index_ = 0; // Índice de la textura activa size_t texture_index_ = 0; // Índice de la textura activa
SDL_FRect pos_; // Posición y tamaño donde dibujar el sprite SDL_FRect pos_; // Posición y tamaño donde dibujar el sprite
SDL_FRect sprite_clip_; // Rectángulo de origen de la textura que se dibujará en pantalla SDL_FRect sprite_clip_; // Rectángulo de origen de la textura que se dibujará en pantalla
double zoom_ = 1.0F; // Zoom aplicado a la textura double zoom_ = 1.0F; // Zoom aplicado a la textura
}; };
+72 -72
View File
@@ -22,93 +22,93 @@ enum class StageStatus {
// --- Clase StageData: representa los datos de una fase del juego --- // --- Clase StageData: representa los datos de una fase del juego ---
class StageData { class StageData {
public: public:
// --- Constructor --- // --- Constructor ---
StageData(int power_to_complete, int min_menace, int max_menace, std::string name = ""); // Constructor de una fase StageData(int power_to_complete, int min_menace, int max_menace, std::string name = ""); // Constructor de una fase
// --- Getters --- // --- Getters ---
[[nodiscard]] auto getPowerToComplete() const -> int { return power_to_complete_; } // Obtiene el poder necesario para completar [[nodiscard]] auto getPowerToComplete() const -> int { return power_to_complete_; } // Obtiene el poder necesario para completar
[[nodiscard]] auto getMinMenace() const -> int { return min_menace_; } // Obtiene el nivel mínimo de amenaza [[nodiscard]] auto getMinMenace() const -> int { return min_menace_; } // Obtiene el nivel mínimo de amenaza
[[nodiscard]] auto getMaxMenace() const -> int { return max_menace_; } // Obtiene el nivel máximo de amenaza [[nodiscard]] auto getMaxMenace() const -> int { return max_menace_; } // Obtiene el nivel máximo de amenaza
[[nodiscard]] auto getName() const -> const std::string& { return name_; } // Obtiene el nombre de la fase [[nodiscard]] auto getName() const -> const std::string& { return name_; } // Obtiene el nombre de la fase
[[nodiscard]] auto getStatus() const -> StageStatus { return status_; } // Obtiene el estado actual [[nodiscard]] auto getStatus() const -> StageStatus { return status_; } // Obtiene el estado actual
[[nodiscard]] auto isCompleted() const -> bool { return status_ == StageStatus::COMPLETED; } // Verifica si está completada [[nodiscard]] auto isCompleted() const -> bool { return status_ == StageStatus::COMPLETED; } // Verifica si está completada
// --- Setters --- // --- Setters ---
void setStatus(StageStatus status) { status_ = status; } // Establece el estado de la fase void setStatus(StageStatus status) { status_ = status; } // Establece el estado de la fase
private: private:
// --- Variables de estado --- // --- Variables de estado ---
StageStatus status_; // Estado actual de la fase StageStatus status_; // Estado actual de la fase
std::string name_; // Nombre de la fase std::string name_; // Nombre de la fase
int power_to_complete_; // Poder necesario para completar la fase int power_to_complete_; // Poder necesario para completar la fase
int min_menace_; // Nivel mínimo de amenaza int min_menace_; // Nivel mínimo de amenaza
int max_menace_; // Nivel máximo de amenaza int max_menace_; // Nivel máximo de amenaza
}; };
// --- Clase StageManager: gestor principal del sistema de fases del juego --- // --- Clase StageManager: gestor principal del sistema de fases del juego ---
class StageManager : public IStageInfo { class StageManager : public IStageInfo {
public: public:
// --- Tipos --- // --- Tipos ---
using PowerChangeCallback = std::function<void(int)>; // Callback para cambios de poder using PowerChangeCallback = std::function<void(int)>; // Callback para cambios de poder
// --- Constructor --- // --- Constructor ---
StageManager(); // Constructor principal StageManager(); // Constructor principal
// --- Métodos principales del juego --- // --- Métodos principales del juego ---
void initialize(); // Inicializa el gestor de fases void initialize(); // Inicializa el gestor de fases
void initialize(const std::string& stages_file); // Inicializa con archivo personalizado void initialize(const std::string& stages_file); // Inicializa con archivo personalizado
void reset(); // Reinicia el progreso del juego void reset(); // Reinicia el progreso del juego
auto advanceToNextStage() -> bool; // Avanza a la siguiente fase auto advanceToNextStage() -> bool; // Avanza a la siguiente fase
// --- Gestión de poder --- // --- Gestión de poder ---
auto subtractPower(int amount) -> bool; // Resta poder de la fase actual auto subtractPower(int amount) -> bool; // Resta poder de la fase actual
void enablePowerCollection() override; // Habilita la recolección de poder void enablePowerCollection() override; // Habilita la recolección de poder
void disablePowerCollection(); // Deshabilita la recolección de poder void disablePowerCollection(); // Deshabilita la recolección de poder
// --- Navegación --- // --- Navegación ---
auto jumpToStage(size_t target_stage_index) -> bool; // Salta a una fase específica auto jumpToStage(size_t target_stage_index) -> bool; // Salta a una fase específica
auto setTotalPower(int target_total_power) -> bool; // Establece el poder total y ajusta fase/progreso auto setTotalPower(int target_total_power) -> bool; // Establece el poder total y ajusta fase/progreso
// --- Consultas de estado --- // --- Consultas de estado ---
[[nodiscard]] auto getCurrentStage() const -> std::optional<StageData>; // Obtiene la fase actual [[nodiscard]] auto getCurrentStage() const -> std::optional<StageData>; // Obtiene la fase actual
[[nodiscard]] auto getStage(size_t index) const -> std::optional<StageData>; // Obtiene una fase específica [[nodiscard]] auto getStage(size_t index) const -> std::optional<StageData>; // Obtiene una fase específica
[[nodiscard]] auto getCurrentStageIndex() const -> size_t { return current_stage_index_; } // Obtiene el índice de la fase actual [[nodiscard]] auto getCurrentStageIndex() const -> size_t { return current_stage_index_; } // Obtiene el índice de la fase actual
[[nodiscard]] auto getCurrentPower() const -> int { return current_power_; } // Obtiene el poder actual [[nodiscard]] auto getCurrentPower() const -> int { return current_power_; } // Obtiene el poder actual
[[nodiscard]] auto getTotalPower() const -> int { return total_power_; } // Obtiene el poder total acumulado [[nodiscard]] auto getTotalPower() const -> int { return total_power_; } // Obtiene el poder total acumulado
[[nodiscard]] auto getTotalPowerNeededToCompleteGame() const -> int; // Poder total necesario para completar el juego [[nodiscard]] auto getTotalPowerNeededToCompleteGame() const -> int; // Poder total necesario para completar el juego
[[nodiscard]] auto getPowerNeededToReachStage(size_t target_stage_index) const -> int; // Poder necesario para llegar a la fase X [[nodiscard]] auto getPowerNeededToReachStage(size_t target_stage_index) const -> int; // Poder necesario para llegar a la fase X
[[nodiscard]] auto getTotalStages() const -> size_t { return stages_.size(); } // Obtiene el número total de fases [[nodiscard]] auto getTotalStages() const -> size_t { return stages_.size(); } // Obtiene el número total de fases
// --- Seguimiento de progreso --- // --- Seguimiento de progreso ---
[[nodiscard]] auto isCurrentStageCompleted() const -> bool; // Verifica si la fase actual está completada [[nodiscard]] auto isCurrentStageCompleted() const -> bool; // Verifica si la fase actual está completada
[[nodiscard]] auto isGameCompleted() const -> bool; // Verifica si el juego está completado [[nodiscard]] auto isGameCompleted() const -> bool; // Verifica si el juego está completado
[[nodiscard]] auto getProgressPercentage() const -> double; // Progreso total del juego (0-100%) [[nodiscard]] auto getProgressPercentage() const -> double; // Progreso total del juego (0-100%)
[[nodiscard]] auto getCurrentStageProgressPercentage() const -> double; // Progreso de la fase actual (0-100%) [[nodiscard]] auto getCurrentStageProgressPercentage() const -> double; // Progreso de la fase actual (0-100%)
[[nodiscard]] auto getCurrentStageProgressFraction() const -> double; // Progreso de la fase actual (0.0-1.0) [[nodiscard]] auto getCurrentStageProgressFraction() const -> double; // Progreso de la fase actual (0.0-1.0)
[[nodiscard]] auto getPowerNeededForCurrentStage() const -> int; // Poder restante para completar la fase actual [[nodiscard]] auto getPowerNeededForCurrentStage() const -> int; // Poder restante para completar la fase actual
// --- Gestión de callbacks --- // --- Gestión de callbacks ---
void setPowerChangeCallback(PowerChangeCallback callback); // Establece callback para cambios de poder void setPowerChangeCallback(PowerChangeCallback callback); // Establece callback para cambios de poder
void removePowerChangeCallback(); // Elimina callback de cambios de poder void removePowerChangeCallback(); // Elimina callback de cambios de poder
// --- Implementación de la interfaz IStageInfo --- // --- Implementación de la interfaz IStageInfo ---
[[nodiscard]] auto canCollectPower() const -> bool override; // Verifica si se puede recolectar poder [[nodiscard]] auto canCollectPower() const -> bool override; // Verifica si se puede recolectar poder
void addPower(int amount) override; // Añade poder a la fase actual void addPower(int amount) override; // Añade poder a la fase actual
[[nodiscard]] auto getCurrentMenaceLevel() const -> int override; // Obtiene el nivel de amenaza actual [[nodiscard]] auto getCurrentMenaceLevel() const -> int override; // Obtiene el nivel de amenaza actual
private: private:
// --- Variables de estado --- // --- Variables de estado ---
std::vector<StageData> stages_; // Lista de todas las fases std::vector<StageData> stages_; // Lista de todas las fases
PowerChangeCallback power_change_callback_; // Callback para notificar cambios de poder PowerChangeCallback power_change_callback_; // Callback para notificar cambios de poder
PowerCollectionState power_collection_state_; // Estado de recolección de poder PowerCollectionState power_collection_state_; // Estado de recolección de poder
size_t current_stage_index_; // Índice de la fase actual size_t current_stage_index_; // Índice de la fase actual
int current_power_; // Poder actual en la fase activa int current_power_; // Poder actual en la fase activa
int total_power_; // Poder total acumulado en todo el juego int total_power_; // Poder total acumulado en todo el juego
// --- Métodos internos --- // --- Métodos internos ---
void createDefaultStages(); // Crea las fases predeterminadas del juego void createDefaultStages(); // Crea las fases predeterminadas del juego
auto loadStagesFromFile(const std::string& filename) -> bool; // Carga fases desde archivo auto loadStagesFromFile(const std::string& filename) -> bool; // Carga fases desde archivo
[[nodiscard]] auto validateStageIndex(size_t index) const -> bool; // Valida que un índice de fase sea válido [[nodiscard]] auto validateStageIndex(size_t index) const -> bool; // Valida que un índice de fase sea válido
void updateStageStatuses(); // Actualiza los estados de todas las fases void updateStageStatuses(); // Actualiza los estados de todas las fases
}; };
+8 -8
View File
@@ -6,14 +6,14 @@
* sin requerir acceso a toda la funcionalidad de StageManager. * sin requerir acceso a toda la funcionalidad de StageManager.
*/ */
class IStageInfo { class IStageInfo {
public: public:
virtual ~IStageInfo() = default; virtual ~IStageInfo() = default;
// Interfaz de recolección de poder // Interfaz de recolección de poder
[[nodiscard]] virtual auto canCollectPower() const -> bool = 0; [[nodiscard]] virtual auto canCollectPower() const -> bool = 0;
virtual void enablePowerCollection() = 0; virtual void enablePowerCollection() = 0;
virtual void addPower(int amount) = 0; virtual void addPower(int amount) = 0;
// Ajuste de comportamiento del gameplay // Ajuste de comportamiento del gameplay
[[nodiscard]] virtual auto getCurrentMenaceLevel() const -> int = 0; [[nodiscard]] virtual auto getCurrentMenaceLevel() const -> int = 0;
}; };
+139 -139
View File
@@ -20,172 +20,172 @@
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
if (stat(path.c_str(), &st) == 0) { if (stat(path.c_str(), &st) == 0) {
return Result::SUCCESS; // Ya existe, no es error por defecto return Result::SUCCESS; // Ya existe, no es error por defecto
} }
// Intentar crear la carpeta // Intentar crear la carpeta
int result; int result;
#ifdef _WIN32 #ifdef _WIN32
result = _mkdir(path.c_str()); result = _mkdir(path.c_str());
#else #else
result = mkdir(path.c_str(), permissions); result = mkdir(path.c_str(), permissions);
#endif #endif
if (result == -1) { if (result == -1) {
switch (errno) { switch (errno) {
case EACCES: case EACCES:
return Result::PERMISSION_DENIED; return Result::PERMISSION_DENIED;
case EEXIST: case EEXIST:
return Result::ALREADY_EXISTS; return Result::ALREADY_EXISTS;
case ENAMETOOLONG: case ENAMETOOLONG:
return Result::PATH_TOO_LONG; return Result::PATH_TOO_LONG;
default: default:
return Result::UNKNOWN_ERROR; return Result::UNKNOWN_ERROR;
}
}
return Result::SUCCESS;
}
// Función auxiliar para crear carpetas padre recursivamente
auto createParentFolders(const std::string& path, int permissions) -> Result {
size_t pos = 0;
while ((pos = path.find('/', pos + 1)) != std::string::npos) {
std::string parent = path.substr(0, pos);
if (!parent.empty() && !folderExists(parent)) {
Result result = createSingleFolder(parent, permissions);
if (result != Result::SUCCESS && result != Result::ALREADY_EXISTS) {
return result;
} }
} }
return Result::SUCCESS;
} }
return Result::SUCCESS; // Función auxiliar para crear carpetas padre recursivamente
} auto createParentFolders(const std::string& path, int permissions) -> Result {
size_t pos = 0;
auto createApplicationFolder(const std::string& app_name, std::string& out_path) -> Result { while ((pos = path.find('/', pos + 1)) != std::string::npos) {
FolderConfig config; std::string parent = path.substr(0, pos);
return createApplicationFolder(app_name, out_path, config); if (!parent.empty() && !folderExists(parent)) {
} Result result = createSingleFolder(parent, permissions);
if (result != Result::SUCCESS && result != Result::ALREADY_EXISTS) {
return result;
}
}
}
auto createApplicationFolder(const std::string& app_name, std::string& out_path, const FolderConfig& config) -> Result { return Result::SUCCESS;
out_path = getApplicationDataPath(app_name);
return createFolder(out_path, config);
}
auto createFolder(const std::string& path) -> Result {
FolderConfig config;
return createFolder(path, config);
}
auto createFolder(const std::string& path, const FolderConfig& config) -> Result {
if (path.empty()) {
return Result::INVALID_PATH;
} }
// Verificar si ya existe y si eso es un error auto createApplicationFolder(const std::string& app_name, std::string& out_path) -> Result {
if (folderExists(path) && config.fail_if_exists) { FolderConfig config;
return Result::ALREADY_EXISTS; return createApplicationFolder(app_name, out_path, config);
} }
// Crear carpetas padre si es necesario auto createApplicationFolder(const std::string& app_name, std::string& out_path, const FolderConfig& config) -> Result {
if (config.create_parents) { out_path = getApplicationDataPath(app_name);
Result parent_result = createParentFolders(path, config.permissions); return createFolder(out_path, config);
if (parent_result != Result::SUCCESS) { }
return parent_result;
auto createFolder(const std::string& path) -> Result {
FolderConfig config;
return createFolder(path, config);
}
auto createFolder(const std::string& path, const FolderConfig& config) -> Result {
if (path.empty()) {
return Result::INVALID_PATH;
}
// Verificar si ya existe y si eso es un error
if (folderExists(path) && config.fail_if_exists) {
return Result::ALREADY_EXISTS;
}
// Crear carpetas padre si es necesario
if (config.create_parents) {
Result parent_result = createParentFolders(path, config.permissions);
if (parent_result != Result::SUCCESS) {
return parent_result;
}
}
// Crear la carpeta final
return createSingleFolder(path, config.permissions);
}
auto getApplicationDataPath(const std::string& app_name) -> std::string {
#ifdef _WIN32
char* appdata = getenv("APPDATA");
if (appdata) {
return std::string(appdata) + "/" + app_name;
}
return "C:/Users/Default/AppData/Roaming/" + app_name;
#elif __APPLE__
std::string home = getHomeDirectory();
return home + "/Library/Application Support/" + app_name;
#elif __linux__
std::string home = getHomeDirectory();
return home + "/.config/" + app_name;
#else
// Fallback genérico
std::string home = getHomeDirectory();
return home + "/." + app_name;
#endif
}
auto folderExists(const std::string& path) -> bool {
struct stat st = {.st_dev = 0};
return (stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode));
}
auto resultToString(Result result) -> const char* {
switch (result) {
case Result::SUCCESS:
return "Operación exitosa";
case Result::PERMISSION_DENIED:
return "Error: Permisos insuficientes";
case Result::PATH_TOO_LONG:
return "Error: Ruta demasiado larga";
case Result::ALREADY_EXISTS:
return "Error: La carpeta ya existe";
case Result::INVALID_PATH:
return "Error: Ruta inválida";
case Result::UNKNOWN_ERROR:
return "Error desconocido";
default:
return "Error no identificado";
} }
} }
// Crear la carpeta final auto getHomeDirectory() -> std::string {
return createSingleFolder(path, config.permissions);
}
auto getApplicationDataPath(const std::string& app_name) -> std::string {
#ifdef _WIN32 #ifdef _WIN32
char* appdata = getenv("APPDATA"); char* userprofile = getenv("USERPROFILE");
if (appdata) { if (userprofile) {
return std::string(appdata) + "/" + app_name; return std::string(userprofile);
} }
return "C:/Users/Default/AppData/Roaming/" + app_name; return "C:/Users/Default";
#elif __APPLE__
std::string home = getHomeDirectory();
return home + "/Library/Application Support/" + app_name;
#elif __linux__
std::string home = getHomeDirectory();
return home + "/.config/" + app_name;
#else #else
// Fallback genérico struct passwd* pw = getpwuid(getuid());
std::string home = getHomeDirectory(); if ((pw != nullptr) && (pw->pw_dir != nullptr)) {
return home + "/." + app_name; return {pw->pw_dir};
}
// Fallback
char* home = getenv("HOME");
if (home != nullptr) {
return {home};
}
return "/tmp";
#endif #endif
}
auto folderExists(const std::string& path) -> bool {
struct stat st = {.st_dev = 0};
return (stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode));
}
auto resultToString(Result result) -> const char* {
switch (result) {
case Result::SUCCESS:
return "Operación exitosa";
case Result::PERMISSION_DENIED:
return "Error: Permisos insuficientes";
case Result::PATH_TOO_LONG:
return "Error: Ruta demasiado larga";
case Result::ALREADY_EXISTS:
return "Error: La carpeta ya existe";
case Result::INVALID_PATH:
return "Error: Ruta inválida";
case Result::UNKNOWN_ERROR:
return "Error desconocido";
default:
return "Error no identificado";
} }
}
auto getHomeDirectory() -> std::string { auto getTempDirectory() -> std::string {
#ifdef _WIN32 #ifdef _WIN32
char* userprofile = getenv("USERPROFILE"); char* temp = getenv("TEMP");
if (userprofile) { if (temp) {
return std::string(userprofile); return std::string(temp);
} }
return "C:/Users/Default"; return "C:/Windows/Temp";
#else #else
struct passwd* pw = getpwuid(getuid()); return "/tmp";
if ((pw != nullptr) && (pw->pw_dir != nullptr)) {
return {pw->pw_dir};
}
// Fallback
char* home = getenv("HOME");
if (home != nullptr) {
return {home};
}
return "/tmp";
#endif #endif
}
auto getTempDirectory() -> std::string {
#ifdef _WIN32
char* temp = getenv("TEMP");
if (temp) {
return std::string(temp);
} }
return "C:/Windows/Temp";
#else
return "/tmp";
#endif
}
} // namespace SystemUtils } // namespace SystemUtils
+22 -22
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
+120 -120
View File
@@ -9,142 +9,142 @@
// --- Clase Tabe --- // --- Clase Tabe ---
class Tabe { class Tabe {
public: public:
// --- Enumeraciones para dirección y estado --- // --- Enumeraciones para dirección y estado ---
enum class Direction : int { enum class Direction : int {
TO_THE_LEFT = 0, TO_THE_LEFT = 0,
TO_THE_RIGHT = 1, TO_THE_RIGHT = 1,
}; };
enum class State : int { enum class State : int {
FLY = 0, FLY = 0,
HIT = 1, HIT = 1,
}; };
// --- Constructores y destructor --- // --- Constructores y destructor ---
Tabe(); Tabe();
~Tabe() = default; ~Tabe() = default;
// --- Métodos principales --- // --- Métodos principales ---
void update(float delta_time); // Actualiza la lógica (time-based) void update(float delta_time); // Actualiza la lógica (time-based)
void render(); // Dibuja el objeto void render(); // Dibuja el objeto
void enable(); // Habilita el objeto void enable(); // Habilita el objeto
void setState(State state); // Establece el estado void setState(State state); // Establece el estado
auto tryToGetBonus() -> bool; // Intenta obtener el bonus auto tryToGetBonus() -> bool; // Intenta obtener el bonus
void pauseTimer(bool value); // Detiene/activa el timer void pauseTimer(bool value); // Detiene/activa el timer
void disableSpawning(); // Deshabilita el spawning permanentemente void disableSpawning(); // Deshabilita el spawning permanentemente
void enableSpawning(); // Habilita el spawning nuevamente void enableSpawning(); // Habilita el spawning nuevamente
// --- Getters --- // --- Getters ---
auto getCollider() -> SDL_FRect& { return sprite_->getRect(); } // Obtiene el área de colisión auto getCollider() -> SDL_FRect& { return sprite_->getRect(); } // Obtiene el área de colisión
[[nodiscard]] auto isEnabled() const -> bool { return enabled_; } // Indica si el objeto está activo [[nodiscard]] auto isEnabled() const -> bool { return enabled_; } // Indica si el objeto está activo
private: private:
// --- Constantes --- // --- Constantes ---
static constexpr int WIDTH = 32; static constexpr int WIDTH = 32;
static constexpr int HEIGHT = 32; static constexpr int HEIGHT = 32;
// --- Estructura para el temporizador del Tabe --- // --- Estructura para el temporizador del Tabe ---
struct Timer { struct Timer {
private: private:
static constexpr Uint32 MINUTES_TO_MILLISECONDS = 60000; // Factor de conversión de minutos a milisegundos static constexpr Uint32 MINUTES_TO_MILLISECONDS = 60000; // Factor de conversión de minutos a milisegundos
public: public:
Uint32 time_until_next_spawn; // Tiempo restante para la próxima aparición Uint32 time_until_next_spawn; // Tiempo restante para la próxima aparición
Uint32 min_spawn_time; // Tiempo mínimo entre apariciones (en milisegundos) Uint32 min_spawn_time; // Tiempo mínimo entre apariciones (en milisegundos)
Uint32 max_spawn_time; // Tiempo máximo entre apariciones (en milisegundos) Uint32 max_spawn_time; // Tiempo máximo entre apariciones (en milisegundos)
Uint32 current_time; // Tiempo actual Uint32 current_time; // Tiempo actual
Uint32 delta_time; // Diferencia de tiempo desde la última actualización Uint32 delta_time; // Diferencia de tiempo desde la última actualización
Uint32 last_time; // Tiempo de la última actualización Uint32 last_time; // Tiempo de la última actualización
bool is_paused{false}; // Indica si el temporizador está pausado (por pausa de juego) bool is_paused{false}; // Indica si el temporizador está pausado (por pausa de juego)
bool spawn_disabled{false}; // Indica si el spawning está deshabilitado permanentemente bool spawn_disabled{false}; // Indica si el spawning está deshabilitado permanentemente
// Constructor - los parámetros min_time y max_time están en mintos // Constructor - los parámetros min_time y max_time están en mintos
Timer(float min_time, float max_time) Timer(float min_time, float max_time)
: min_spawn_time(static_cast<Uint32>(min_time * MINUTES_TO_MILLISECONDS)), : min_spawn_time(static_cast<Uint32>(min_time * MINUTES_TO_MILLISECONDS)),
max_spawn_time(static_cast<Uint32>(max_time * MINUTES_TO_MILLISECONDS)), max_spawn_time(static_cast<Uint32>(max_time * MINUTES_TO_MILLISECONDS)),
current_time(SDL_GetTicks()) { current_time(SDL_GetTicks()) {
reset(); reset();
}
// Restablece el temporizador con un nuevo tiempo hasta la próxima aparición
void reset() {
Uint32 range = max_spawn_time - min_spawn_time;
time_until_next_spawn = min_spawn_time + rand() % (range + 1);
last_time = SDL_GetTicks();
}
// Actualiza el temporizador, decrementando el tiempo hasta la próxima aparición
void update() {
current_time = SDL_GetTicks();
// Solo actualizar si no está pausado (ni por juego ni por spawn deshabilitado)
if (!is_paused && !spawn_disabled) {
delta_time = current_time - last_time;
if (time_until_next_spawn > delta_time) {
time_until_next_spawn -= delta_time;
} else {
time_until_next_spawn = 0;
} }
}
// Restablece el temporizador con un nuevo tiempo hasta la próxima aparición // Siempre actualizar last_time para evitar saltos de tiempo al despausar
void reset() { last_time = current_time;
Uint32 range = max_spawn_time - min_spawn_time; }
time_until_next_spawn = min_spawn_time + rand() % (range + 1);
// Pausa o reanuda el temporizador
void setPaused(bool paused) {
if (is_paused != paused) {
is_paused = paused;
// Al despausar, actualizar last_time para evitar saltos
if (!paused) {
last_time = SDL_GetTicks(); last_time = SDL_GetTicks();
} }
}
}
// Actualiza el temporizador, decrementando el tiempo hasta la próxima aparición // Pausa o reanuda el spawning
void update() { void setSpawnDisabled(bool disabled) {
current_time = SDL_GetTicks(); if (spawn_disabled != disabled) {
spawn_disabled = disabled;
// Solo actualizar si no está pausado (ni por juego ni por spawn deshabilitado) // Al reactivar, actualizar last_time para evitar saltos
if (!is_paused && !spawn_disabled) { if (!disabled) {
delta_time = current_time - last_time; last_time = SDL_GetTicks();
if (time_until_next_spawn > delta_time) {
time_until_next_spawn -= delta_time;
} else {
time_until_next_spawn = 0;
}
}
// Siempre actualizar last_time para evitar saltos de tiempo al despausar
last_time = current_time;
} }
}
}
// Pausa o reanuda el temporizador // Indica si el temporizador ha finalizado
void setPaused(bool paused) { [[nodiscard]] auto shouldSpawn() const -> bool {
if (is_paused != paused) { return time_until_next_spawn == 0 && !is_paused && !spawn_disabled;
is_paused = paused; }
// Al despausar, actualizar last_time para evitar saltos };
if (!paused) {
last_time = SDL_GetTicks();
}
}
}
// Pausa o reanuda el spawning // --- Objetos y punteros ---
void setSpawnDisabled(bool disabled) { std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los gráficos y animaciones
if (spawn_disabled != disabled) {
spawn_disabled = disabled;
// Al reactivar, actualizar last_time para evitar saltos
if (!disabled) {
last_time = SDL_GetTicks();
}
}
}
// Indica si el temporizador ha finalizado // --- Variables de estado ---
[[nodiscard]] auto shouldSpawn() const -> bool { float x_ = 0; // Posición X
return time_until_next_spawn == 0 && !is_paused && !spawn_disabled; float y_ = 0; // Posición Y
} float speed_ = 0.0F; // Velocidad de movimiento
}; float accel_ = 0.0F; // Aceleración
int fly_distance_ = 0; // Distancia de vuelo
float waiting_counter_ = 0; // Tiempo que pasa quieto
bool enabled_ = false; // Indica si el objeto está activo
Direction direction_ = Direction::TO_THE_LEFT; // Dirección actual
Direction destiny_ = Direction::TO_THE_LEFT; // Destino
State state_ = State::FLY; // Estado actual
float hit_counter_ = 0; // Contador para el estado HIT
int number_of_hits_ = 0; // Cantidad de disparos recibidos
bool has_bonus_ = true; // Indica si aún tiene el bonus para soltar
Timer timer_; // Temporizador para gestionar la aparición
// --- Objetos y punteros --- // --- Métodos internos ---
std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los gráficos y animaciones void move(float delta_time); // Mueve el objeto (time-based)
void shiftSprite() { sprite_->setPos(x_, y_); } // Actualiza la posición del sprite
// --- Variables de estado --- void setRandomFlyPath(Direction direction, int length); // Establece un vuelo aleatorio
float x_ = 0; // Posición X void updateState(float delta_time); // Actualiza el estado (time-based)
float y_ = 0; // Posición Y void updateTimer(); // Actualiza el temporizador
float speed_ = 0.0F; // Velocidad de movimiento void disable(); // Deshabilita el objeto
float accel_ = 0.0F; // Aceleración
int fly_distance_ = 0; // Distancia de vuelo
float waiting_counter_ = 0; // Tiempo que pasa quieto
bool enabled_ = false; // Indica si el objeto está activo
Direction direction_ = Direction::TO_THE_LEFT; // Dirección actual
Direction destiny_ = Direction::TO_THE_LEFT; // Destino
State state_ = State::FLY; // Estado actual
float hit_counter_ = 0; // Contador para el estado HIT
int number_of_hits_ = 0; // Cantidad de disparos recibidos
bool has_bonus_ = true; // Indica si aún tiene el bonus para soltar
Timer timer_; // Temporizador para gestionar la aparición
// --- Métodos internos ---
void move(float delta_time); // Mueve el objeto (time-based)
void shiftSprite() { sprite_->setPos(x_, y_); } // Actualiza la posición del sprite
void setRandomFlyPath(Direction direction, int length); // Establece un vuelo aleatorio
void updateState(float delta_time); // Actualiza el estado (time-based)
void updateTimer(); // Actualiza el temporizador
void disable(); // Deshabilita el objeto
}; };
+72 -72
View File
@@ -13,90 +13,90 @@ class Texture;
// --- Clase Text: pinta texto en pantalla a partir de un bitmap --- // --- Clase Text: pinta texto en pantalla a partir de un bitmap ---
class Text { class Text {
public: public:
// --- Constantes para flags de texto --- // --- Constantes para flags de texto ---
static constexpr int COLOR = 1; static constexpr int COLOR = 1;
static constexpr int SHADOW = 2; static constexpr int SHADOW = 2;
static constexpr int CENTER = 4; static constexpr int CENTER = 4;
static constexpr int STROKE = 8; static constexpr int STROKE = 8;
// --- Estructuras --- // --- Estructuras ---
struct Offset { struct Offset {
int x, y, w; int x, y, w;
}; };
struct File { struct File {
int box_width; // Anchura de la caja de cada caracter en el png int box_width; // Anchura de la caja de cada caracter en el png
int box_height; // Altura de la caja de cada caracter en el png int box_height; // Altura de la caja de cada caracter en el png
std::array<Offset, 128> offset = {}; // Vector con las posiciones y ancho de cada letra std::array<Offset, 128> offset = {}; // Vector con las posiciones y ancho de cada letra
}; };
struct Style { struct Style {
Uint8 flags; Uint8 flags;
Color text_color; Color text_color;
Color shadow_color; Color shadow_color;
Uint8 shadow_distance; Uint8 shadow_distance;
int kerning; int kerning;
// Constructor con argumentos por defecto // Constructor con argumentos por defecto
Style(Uint8 flags = 0, Style(Uint8 flags = 0,
Color text = Color(), Color text = Color(),
Color shadow = Color(), Color shadow = Color(),
Uint8 distance = 1, Uint8 distance = 1,
int kern = 1) int kern = 1)
: flags(flags), : flags(flags),
text_color(text), text_color(text),
shadow_color(shadow), shadow_color(shadow),
shadow_distance(distance), shadow_distance(distance),
kerning(kern) {} kerning(kern) {}
}; };
// --- Constructores y destructor --- // --- Constructores y destructor ---
Text(const std::shared_ptr<Texture>& texture, const std::string& text_file); Text(const std::shared_ptr<Texture>& texture, const std::string& text_file);
Text(const std::shared_ptr<Texture>& texture, const std::shared_ptr<Text::File>& text_file); Text(const std::shared_ptr<Texture>& texture, const std::shared_ptr<Text::File>& text_file);
Text(const std::shared_ptr<Texture>& texture, const std::shared_ptr<Texture>& white_texture, const std::string& text_file); Text(const std::shared_ptr<Texture>& texture, const std::shared_ptr<Texture>& white_texture, const std::string& text_file);
Text(const std::shared_ptr<Texture>& texture, const std::shared_ptr<Texture>& white_texture, const std::shared_ptr<Text::File>& text_file); Text(const std::shared_ptr<Texture>& texture, const std::shared_ptr<Texture>& white_texture, const std::shared_ptr<Text::File>& text_file);
~Text() = default; ~Text() = default;
// --- Métodos de escritura en pantalla --- // --- Métodos de escritura en pantalla ---
void write(int x, int y, const std::string& text, int kerning = 1, int length = -1); // Escribe el texto en pantalla void write(int x, int y, const std::string& text, int kerning = 1, int length = -1); // Escribe el texto en pantalla
void write2X(int x, int y, const std::string& text, int kerning = 1, int length = -1); // Escribe el texto al doble de tamaño void write2X(int x, int y, const std::string& text, int kerning = 1, int length = -1); // Escribe el texto al doble de tamaño
// --- Escritura en textura --- // --- Escritura en textura ---
auto writeToTexture(const std::string& text, int zoom = 1, int kerning = 1, int length = -1) -> std::shared_ptr<Texture>; // Escribe el texto en una textura auto writeToTexture(const std::string& text, int zoom = 1, int kerning = 1, int length = -1) -> std::shared_ptr<Texture>; // Escribe el texto en una textura
auto writeDXToTexture(Uint8 flags, const std::string& text, int kerning = 1, Color text_color = Color(), Uint8 shadow_distance = 1, Color shadow_color = Color(), int length = -1) -> std::shared_ptr<Texture>; // Escribe el texto con extras en una textura auto writeDXToTexture(Uint8 flags, const std::string& text, int kerning = 1, Color text_color = Color(), Uint8 shadow_distance = 1, Color shadow_color = Color(), int length = -1) -> std::shared_ptr<Texture>; // Escribe el texto con extras en una textura
// --- Métodos de escritura avanzada --- // --- Métodos de escritura avanzada ---
void writeColored(int x, int y, const std::string& text, Color color, int kerning = 1, int length = -1); // Escribe el texto con colores void writeColored(int x, int y, const std::string& text, Color color, int kerning = 1, int length = -1); // Escribe el texto con colores
void writeShadowed(int x, int y, const std::string& text, Color color, Uint8 shadow_distance = 1, int kerning = 1, int length = -1); // Escribe el texto con sombra void writeShadowed(int x, int y, const std::string& text, Color color, Uint8 shadow_distance = 1, int kerning = 1, int length = -1); // Escribe el texto con sombra
void writeCentered(int x, int y, const std::string& text, int kerning = 1, int length = -1); // Escribe el texto centrado en un punto x void writeCentered(int x, int y, const std::string& text, int kerning = 1, int length = -1); // Escribe el texto centrado en un punto x
void writeDX(Uint8 flags, int x, int y, const std::string& text, int kerning = 1, Color text_color = Color(), Uint8 shadow_distance = 1, Color shadow_color = Color(), int length = -1); // Escribe texto con extras void writeDX(Uint8 flags, int x, int y, const std::string& text, int kerning = 1, Color text_color = Color(), Uint8 shadow_distance = 1, Color shadow_color = Color(), int length = -1); // Escribe texto con extras
void writeStyle(int x, int y, const std::string& text, const Style& style, int length = -1); // Escribe texto a partir de un TextStyle void writeStyle(int x, int y, const std::string& text, const Style& style, int length = -1); // Escribe texto a partir de un TextStyle
// --- Utilidades --- // --- Utilidades ---
[[nodiscard]] auto length(const std::string& text, int kerning = 1) const -> int; // Obtiene la longitud en pixels de una cadena [[nodiscard]] auto length(const std::string& text, int kerning = 1) const -> int; // Obtiene la longitud en pixels de una cadena
[[nodiscard]] auto getCharacterSize() const -> int; // Devuelve el tamaño de caracter actual [[nodiscard]] auto getCharacterSize() const -> int; // Devuelve el tamaño de caracter actual
// --- Configuración --- // --- Configuración ---
void setFixedWidth(bool value); // Establece si se usa un tamaño fijo de letra void setFixedWidth(bool value); // Establece si se usa un tamaño fijo de letra
// --- Métodos estáticos --- // --- Métodos estáticos ---
static auto loadFile(const std::string& file_path) -> std::shared_ptr<Text::File>; // Llena una estructura Text::File desde un fichero static auto loadFile(const std::string& file_path) -> std::shared_ptr<Text::File>; // Llena una estructura Text::File desde un fichero
// --- Métodos privados --- // --- Métodos privados ---
void writeColoredWithSprite(Sprite* sprite, int x, int y, const std::string& text, Color color, int kerning = 1, int length = -1); // Escribe con un sprite específico void writeColoredWithSprite(Sprite* sprite, int x, int y, const std::string& text, Color color, int kerning = 1, int length = -1); // Escribe con un sprite específico
void writeStrokeWithAlpha(int x, int y, const std::string& text, int kerning, Color stroke_color, Uint8 shadow_distance, int length = -1); // Escribe stroke con alpha correcto void writeStrokeWithAlpha(int x, int y, const std::string& text, int kerning, Color stroke_color, Uint8 shadow_distance, int length = -1); // Escribe stroke con alpha correcto
void renderShadow(int x, int y, const std::string& text, Color shadow_color, int kerning, int length, Uint8 shadow_distance); // Renderiza sombra del texto void renderShadow(int x, int y, const std::string& text, Color shadow_color, int kerning, int length, Uint8 shadow_distance); // Renderiza sombra del texto
void renderSolidStroke(int x, int y, const std::string& text, Color stroke_color, int kerning, int length, Uint8 shadow_distance); // Renderiza stroke sólido void renderSolidStroke(int x, int y, const std::string& text, Color stroke_color, int kerning, int length, Uint8 shadow_distance); // Renderiza stroke sólido
private: private:
// --- Objetos y punteros --- // --- Objetos y punteros ---
std::unique_ptr<Sprite> sprite_ = nullptr; // Objeto con los gráficos para el texto std::unique_ptr<Sprite> sprite_ = nullptr; // Objeto con los gráficos para el texto
std::unique_ptr<Sprite> white_sprite_ = nullptr; // Objeto con los gráficos en blanco para efectos std::unique_ptr<Sprite> white_sprite_ = nullptr; // Objeto con los gráficos en blanco para efectos
// --- Variables de estado --- // --- Variables de estado ---
std::array<Offset, 128> offset_ = {}; // Vector con las posiciones y ancho de cada letra std::array<Offset, 128> offset_ = {}; // Vector con las posiciones y ancho de cada letra
int box_width_ = 0; // Anchura de la caja de cada caracter en el png int box_width_ = 0; // Anchura de la caja de cada caracter en el png
int box_height_ = 0; // Altura de la caja de cada caracter en el png int box_height_ = 0; // Altura de la caja de cada caracter en el png
bool fixed_width_ = false; // Indica si el texto se ha de escribir con longitud fija bool fixed_width_ = false; // Indica si el texto se ha de escribir con longitud fija
}; };
+51 -51
View File
@@ -16,68 +16,68 @@ using Palette = std::array<Uint32, 256>;
// Definición de Surface para imágenes con paleta // Definición de Surface para imágenes con paleta
struct Surface { struct Surface {
std::shared_ptr<Uint8[]> data; // NOLINT(modernize-avoid-c-arrays) std::shared_ptr<Uint8[]> data; // NOLINT(modernize-avoid-c-arrays)
Uint16 w, h; Uint16 w, h;
// Constructor // Constructor
Surface(Uint16 width, Uint16 height, std::shared_ptr<Uint8[]> pixels) // NOLINT(modernize-avoid-c-arrays) Surface(Uint16 width, Uint16 height, std::shared_ptr<Uint8[]> pixels) // NOLINT(modernize-avoid-c-arrays)
: data(std::move(pixels)), : data(std::move(pixels)),
w(width), w(width),
h(height) {} h(height) {}
}; };
// Clase Texture: gestiona texturas, paletas y renderizado // Clase Texture: gestiona texturas, paletas y renderizado
class Texture { class Texture {
public: public:
// --- Constructores y destructor --- // --- Constructores y destructor ---
explicit Texture(SDL_Renderer* renderer, std::string path = std::string()); explicit Texture(SDL_Renderer* renderer, std::string path = std::string());
~Texture(); ~Texture();
// --- Carga y creación --- // --- Carga y creación ---
auto loadFromFile(const std::string& path) -> bool; // Carga una imagen desde un fichero auto loadFromFile(const std::string& path) -> bool; // Carga una imagen desde un fichero
auto createBlank(int width, int height, SDL_PixelFormat format = SDL_PIXELFORMAT_RGBA8888, SDL_TextureAccess access = SDL_TEXTUREACCESS_STREAMING) -> bool; // Crea una textura en blanco auto createBlank(int width, int height, SDL_PixelFormat format = SDL_PIXELFORMAT_RGBA8888, SDL_TextureAccess access = SDL_TEXTUREACCESS_STREAMING) -> bool; // Crea una textura en blanco
auto reLoad() -> bool; // Recarga la textura auto reLoad() -> bool; // Recarga la textura
// --- Renderizado --- // --- Renderizado ---
void render(int x, int y, SDL_FRect* clip = nullptr, float horizontal_zoom = 1, float vertical_zoom = 1, double angle = 0.0, SDL_FPoint* center = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE); // Renderiza la textura en un punto específico void render(int x, int y, SDL_FRect* clip = nullptr, float horizontal_zoom = 1, float vertical_zoom = 1, double angle = 0.0, SDL_FPoint* center = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE); // Renderiza la textura en un punto específico
void setAsRenderTarget(SDL_Renderer* renderer); // Establece la textura como objetivo de renderizado void setAsRenderTarget(SDL_Renderer* renderer); // Establece la textura como objetivo de renderizado
// --- Modificadores de color y blending --- // --- Modificadores de color y blending ---
void setColor(Uint8 red, Uint8 green, Uint8 blue); // Establece el color para la modulación void setColor(Uint8 red, Uint8 green, Uint8 blue); // Establece el color para la modulación
void setColor(Color color); // Establece el color para la modulación void setColor(Color color); // Establece el color para la modulación
void setBlendMode(SDL_BlendMode blending); // Establece el blending void setBlendMode(SDL_BlendMode blending); // Establece el blending
void setAlpha(Uint8 alpha); // Establece el alpha para la modulación void setAlpha(Uint8 alpha); // Establece el alpha para la modulación
// --- Paletas --- // --- Paletas ---
void addPaletteFromGifFile(const std::string& path, bool quiet = false); // Añade una paleta a la lista void addPaletteFromGifFile(const std::string& path, bool quiet = false); // Añade una paleta a la lista
void addPaletteFromPalFile(const std::string& path); // Añade una paleta a la lista void addPaletteFromPalFile(const std::string& path); // Añade una paleta a la lista
void setPaletteColor(int palette, int index, Uint32 color); // Establece un color de la paleta void setPaletteColor(int palette, int index, Uint32 color); // Establece un color de la paleta
void setPalette(size_t palette); // Cambia la paleta de la textura void setPalette(size_t palette); // Cambia la paleta de la textura
// --- Getters --- // --- Getters ---
[[nodiscard]] auto getWidth() const -> int; // Obtiene el ancho de la imagen [[nodiscard]] auto getWidth() const -> int; // Obtiene el ancho de la imagen
[[nodiscard]] auto getHeight() const -> int; // Obtiene el alto de la imagen [[nodiscard]] auto getHeight() const -> int; // Obtiene el alto de la imagen
auto getSDLTexture() -> SDL_Texture*; // Obtiene la textura SDL auto getSDLTexture() -> SDL_Texture*; // Obtiene la textura SDL
auto getRenderer() -> SDL_Renderer*; // Obtiene el renderizador auto getRenderer() -> SDL_Renderer*; // Obtiene el renderizador
private: private:
// --- Objetos y punteros --- // --- Objetos y punteros ---
SDL_Renderer* renderer_; // Renderizador donde dibujar la textura SDL_Renderer* renderer_; // Renderizador donde dibujar la textura
SDL_Texture* texture_ = nullptr; // La textura SDL_Texture* texture_ = nullptr; // La textura
std::shared_ptr<Surface> surface_ = nullptr; // Surface para usar imágenes en formato gif con paleta std::shared_ptr<Surface> surface_ = nullptr; // Surface para usar imágenes en formato gif con paleta
// --- Variables --- // --- Variables ---
std::string path_; // Ruta de la imagen de la textura std::string path_; // Ruta de la imagen de la textura
int width_ = 0; // Ancho de la imagen int width_ = 0; // Ancho de la imagen
int height_ = 0; // Alto de la imagen int height_ = 0; // Alto de la imagen
std::vector<Palette> palettes_; // Vector con las diferentes paletas std::vector<Palette> palettes_; // Vector con las diferentes paletas
int current_palette_ = 0; // Índice de la paleta en uso int current_palette_ = 0; // Índice de la paleta en uso
// --- Métodos internos --- // --- Métodos internos ---
auto loadSurface(const std::string& file_path) -> std::shared_ptr<Surface>; // Crea una surface desde un fichero .gif auto loadSurface(const std::string& file_path) -> std::shared_ptr<Surface>; // Crea una surface desde un fichero .gif
void flipSurface(); // Vuelca la surface en la textura void flipSurface(); // Vuelca la surface en la textura
static auto loadPaletteFromFile(const std::string& file_path, bool quiet = false) -> Palette; // Carga una paleta desde un fichero static auto loadPaletteFromFile(const std::string& file_path, bool quiet = false) -> Palette; // Carga una paleta desde un fichero
void unloadTexture(); // Libera la memoria de la textura void unloadTexture(); // Libera la memoria de la textura
void unloadSurface(); // Libera la surface actual void unloadSurface(); // Libera la surface actual
static auto readPalFile(const std::string& file_path, bool quiet = false) -> Palette; // Carga una paleta desde un archivo .pal static auto readPalFile(const std::string& file_path, bool quiet = false) -> Palette; // Carga una paleta desde un archivo .pal
}; };
+43 -43
View File
@@ -16,55 +16,55 @@ enum class TiledBGMode : int { // Modos de funcionamiento para el tileado de fo
// Esta clase se sirve de una textura "canvas", que rellena con los tiles. // Esta clase se sirve de una textura "canvas", que rellena con los tiles.
// El rectángulo "window" recorre la textura de diferentes formas para generar el efecto de movimiento. // El rectángulo "window" recorre la textura de diferentes formas para generar el efecto de movimiento.
class TiledBG { class TiledBG {
public: public:
// --- Constructores y destructor --- // --- Constructores y destructor ---
TiledBG(SDL_FRect pos, TiledBGMode mode); TiledBG(SDL_FRect pos, TiledBGMode mode);
~TiledBG(); ~TiledBG();
// --- Métodos principales --- // --- Métodos principales ---
void render(); // Pinta la clase en pantalla void render(); // Pinta la clase en pantalla
void update(float delta_time); // Actualiza la lógica de la clase void update(float delta_time); // Actualiza la lógica de la clase
// --- Configuración --- // --- Configuración ---
void setSpeed(float speed) { speed_ = speed; } // Establece la velocidad void setSpeed(float speed) { speed_ = speed; } // Establece la velocidad
void changeSpeedTo(float target_speed, float duration_s); // Cambia la velocidad gradualmente en X segundos void changeSpeedTo(float target_speed, float duration_s); // Cambia la velocidad gradualmente en X segundos
void stopGracefully() { stopping_ = true; } // Detiene el desplazamiento de forma ordenada void stopGracefully() { stopping_ = true; } // Detiene el desplazamiento de forma ordenada
void setColor(Color color) { SDL_SetTextureColorMod(canvas_, color.r, color.g, color.b); } // Cambia el color de la textura void setColor(Color color) { SDL_SetTextureColorMod(canvas_, color.r, color.g, color.b); } // Cambia el color de la textura
// --- Getters --- // --- Getters ---
[[nodiscard]] auto isStopped() const -> bool { return speed_ == 0.0F; } // Indica si está parado [[nodiscard]] auto isStopped() const -> bool { return speed_ == 0.0F; } // Indica si está parado
[[nodiscard]] auto isChangingSpeed() const -> bool { return changing_speed_; } // Indica si está cambiando velocidad gradualmente [[nodiscard]] auto isChangingSpeed() const -> bool { return changing_speed_; } // Indica si está cambiando velocidad gradualmente
private: private:
// --- Constantes --- // --- Constantes ---
static constexpr int TILE_WIDTH = 64; // Ancho del tile static constexpr int TILE_WIDTH = 64; // Ancho del tile
static constexpr int TILE_HEIGHT = 64; // Alto del tile static constexpr int TILE_HEIGHT = 64; // Alto del tile
static constexpr float STOP_THRESHOLD_FACTOR = 20.0F; // Factor para umbral de parada static constexpr float STOP_THRESHOLD_FACTOR = 20.0F; // Factor para umbral de parada
static constexpr float DECELERATION_FACTOR = 1.05F; // Factor de desaceleración static constexpr float DECELERATION_FACTOR = 1.05F; // Factor de desaceleración
static constexpr float MIN_SPEED = 0.1F; // Velocidad mínima static constexpr float MIN_SPEED = 0.1F; // Velocidad mínima
// --- Objetos y punteros --- // --- Objetos y punteros ---
SDL_Renderer* renderer_; // El renderizador de la ventana SDL_Renderer* renderer_; // El renderizador de la ventana
SDL_Texture* canvas_; // Textura donde dibujar el fondo formado por tiles SDL_Texture* canvas_; // Textura donde dibujar el fondo formado por tiles
// --- Variables de estado --- // --- Variables de estado ---
SDL_FRect pos_; // Posición y tamaño del mosaico SDL_FRect pos_; // Posición y tamaño del mosaico
SDL_FRect window_; // Ventana visible para la textura de fondo del título SDL_FRect window_; // Ventana visible para la textura de fondo del título
TiledBGMode mode_; // Tipo de movimiento del mosaico TiledBGMode mode_; // Tipo de movimiento del mosaico
float desp_ = 0.0F; // Desplazamiento aplicado float desp_ = 0.0F; // Desplazamiento aplicado
float speed_ = 1.0F; // Incremento que se añade al desplazamiento a cada bucle float speed_ = 1.0F; // Incremento que se añade al desplazamiento a cada bucle
bool stopping_ = false; // Indica si se está deteniendo bool stopping_ = false; // Indica si se está deteniendo
// --- Variables para cambio gradual de velocidad --- // --- Variables para cambio gradual de velocidad ---
bool changing_speed_ = false; // Indica si está cambiando velocidad gradualmente bool changing_speed_ = false; // Indica si está cambiando velocidad gradualmente
float initial_speed_ = 0.0F; // Velocidad inicial del cambio float initial_speed_ = 0.0F; // Velocidad inicial del cambio
float target_speed_ = 0.0F; // Velocidad objetivo del cambio float target_speed_ = 0.0F; // Velocidad objetivo del cambio
float change_duration_s_ = 0.0F; // Duración total del cambio en segundos float change_duration_s_ = 0.0F; // Duración total del cambio en segundos
float change_timer_s_ = 0.0F; // Tiempo transcurrido del cambio float change_timer_s_ = 0.0F; // Tiempo transcurrido del cambio
// --- Métodos internos --- // --- Métodos internos ---
void fillTexture(); // Rellena la textura con el contenido void fillTexture(); // Rellena la textura con el contenido
void updateDesp(float delta_time) { desp_ += speed_ * delta_time; } // Actualiza el desplazamiento (time-based) void updateDesp(float delta_time) { desp_ += speed_ * delta_time; } // Actualiza el desplazamiento (time-based)
void updateStop(float delta_time); // Detiene el desplazamiento de forma ordenada (time-based) void updateStop(float delta_time); // Detiene el desplazamiento de forma ordenada (time-based)
void updateSpeedChange(float delta_time); // Actualiza el cambio gradual de velocidad (time-based) void updateSpeedChange(float delta_time); // Actualiza el cambio gradual de velocidad (time-based)
}; };
+71 -71
View File
@@ -5,81 +5,81 @@
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
inline void info(const std::string& msg, const std::string& color = WHITE) {
std::cout << " " << color << msg << RESET << "\n";
}
// Put
inline void put(const std::string& msg, const std::string& color = WHITE) {
std::cout << color << msg << RESET << "\n";
}
// Error
inline void error(const std::string& msg) {
std::cout << RED << msg << RESET << "\n";
}
// CR
inline void cr() {
std::cout << "\n";
}
// Dots genérico
inline void dots(const std::string& prefix,
const std::string& middle,
const std::string& suffix,
const std::string& suffix_color = GREEN) {
size_t field_width = TOTAL_WIDTH > (prefix.size() + suffix.size())
? TOTAL_WIDTH - prefix.size() - suffix.size()
: 0;
std::string field_text;
if (middle.size() < field_width) {
field_text = middle + std::string(field_width - middle.size(), '.');
} else {
field_text = middle.substr(0, field_width);
} }
std::cout << " " << prefix << field_text // Info
<< suffix_color << suffix << RESET inline void info(const std::string& msg, const std::string& color = WHITE) {
<< "\n"; std::cout << " " << color << msg << RESET << "\n";
} }
// Status con true/false, usando dots y sufijos fijos // Put
inline void status(const std::string& name, bool ok) { inline void put(const std::string& msg, const std::string& color = WHITE) {
// Ambos sufijos tienen 9 caracteres → alineación perfecta std::cout << color << msg << RESET << "\n";
constexpr const char* OK_LABEL = "[ OK ]"; }
constexpr const char* ERROR_LABEL = "[ ERROR ]";
// Error
if (ok) { inline void error(const std::string& msg) {
dots(" ", name, OK_LABEL, GREEN); std::cout << RED << msg << RESET << "\n";
} else { }
dots(" ", name, ERROR_LABEL, RED);
// CR
inline void cr() {
std::cout << "\n";
}
// Dots genérico
inline void dots(const std::string& prefix,
const std::string& middle,
const std::string& suffix,
const std::string& suffix_color = GREEN) {
size_t field_width = TOTAL_WIDTH > (prefix.size() + suffix.size())
? TOTAL_WIDTH - prefix.size() - suffix.size()
: 0;
std::string field_text;
if (middle.size() < field_width) {
field_text = middle + std::string(field_width - middle.size(), '.');
} else {
field_text = middle.substr(0, field_width);
}
std::cout << " " << prefix << field_text
<< suffix_color << suffix << RESET
<< "\n";
}
// Status con true/false, usando dots y sufijos fijos
inline void status(const std::string& name, bool ok) {
// Ambos sufijos tienen 9 caracteres → alineación perfecta
constexpr const char* OK_LABEL = "[ OK ]";
constexpr const char* ERROR_LABEL = "[ ERROR ]";
if (ok) {
dots(" ", name, OK_LABEL, GREEN);
} else {
dots(" ", name, ERROR_LABEL, RED);
}
} }
}
} // namespace Logger } // namespace Logger
+157 -157
View File
@@ -13,207 +13,207 @@
// --- Clase MenuOption: interfaz base para todas las opciones del menú --- // --- Clase MenuOption: interfaz base para todas las opciones del menú ---
class MenuOption { class MenuOption {
public: public:
// --- Enums --- // --- Enums ---
enum class Behavior { enum class Behavior {
ADJUST, // Solo puede ajustar valor (como IntOption, BoolOption, ListOption) ADJUST, // Solo puede ajustar valor (como IntOption, BoolOption, ListOption)
SELECT, // Solo puede ejecutar acción (como ActionOption, FolderOption) SELECT, // Solo puede ejecutar acción (como ActionOption, FolderOption)
BOTH // Puede tanto ajustar como ejecutar acción (como ActionListOption) BOTH // Puede tanto ajustar como ejecutar acción (como ActionListOption)
}; };
// --- Constructor y destructor --- // --- Constructor y destructor ---
MenuOption(std::string caption, ServiceMenu::SettingsGroup group, bool hidden = false) MenuOption(std::string caption, ServiceMenu::SettingsGroup group, bool hidden = false)
: caption_(std::move(caption)), : caption_(std::move(caption)),
group_(group), group_(group),
hidden_(hidden) {} hidden_(hidden) {}
virtual ~MenuOption() = default; virtual ~MenuOption() = default;
// --- Getters --- // --- Getters ---
[[nodiscard]] auto getCaption() const -> const std::string& { return caption_; } [[nodiscard]] auto getCaption() const -> const std::string& { return caption_; }
[[nodiscard]] auto getGroup() const -> ServiceMenu::SettingsGroup { return group_; } [[nodiscard]] auto getGroup() const -> ServiceMenu::SettingsGroup { return group_; }
[[nodiscard]] auto isHidden() const -> bool { return hidden_; } [[nodiscard]] auto isHidden() const -> bool { return hidden_; }
void setHidden(bool hidden) { hidden_ = hidden; } void setHidden(bool hidden) { hidden_ = hidden; }
[[nodiscard]] virtual auto getBehavior() const -> Behavior = 0; [[nodiscard]] virtual auto getBehavior() const -> Behavior = 0;
[[nodiscard]] virtual auto getValueAsString() const -> std::string { return ""; } [[nodiscard]] virtual auto getValueAsString() const -> std::string { return ""; }
virtual void adjustValue(bool adjust_up) {} virtual void adjustValue(bool adjust_up) {}
[[nodiscard]] virtual auto getTargetGroup() const -> ServiceMenu::SettingsGroup { return ServiceMenu::SettingsGroup::MAIN; } [[nodiscard]] virtual auto getTargetGroup() const -> ServiceMenu::SettingsGroup { return ServiceMenu::SettingsGroup::MAIN; }
virtual void executeAction() {} virtual void executeAction() {}
virtual auto getMaxValueWidth(Text* text_renderer) const -> int { return 0; } // Método virtual para que cada opción calcule el ancho de su valor más largo virtual auto getMaxValueWidth(Text* text_renderer) const -> int { return 0; } // Método virtual para que cada opción calcule el ancho de su valor más largo
protected: protected:
// --- Variables --- // --- Variables ---
std::string caption_; std::string caption_;
ServiceMenu::SettingsGroup group_; ServiceMenu::SettingsGroup group_;
bool hidden_; bool hidden_;
}; };
// --- Clases Derivadas --- // --- Clases Derivadas ---
class BoolOption : public MenuOption { class BoolOption : public MenuOption {
public: public:
BoolOption(const std::string& cap, ServiceMenu::SettingsGroup grp, bool* var) BoolOption(const std::string& cap, ServiceMenu::SettingsGroup grp, bool* var)
: MenuOption(cap, grp), : MenuOption(cap, grp),
linked_variable_(var) {} linked_variable_(var) {}
[[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::ADJUST; } [[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::ADJUST; }
[[nodiscard]] auto getValueAsString() const -> std::string override { [[nodiscard]] auto getValueAsString() const -> std::string override {
return *linked_variable_ ? Lang::getText("[SERVICE_MENU] ON") : Lang::getText("[SERVICE_MENU] OFF"); return *linked_variable_ ? Lang::getText("[SERVICE_MENU] ON") : Lang::getText("[SERVICE_MENU] OFF");
} }
void adjustValue(bool /*adjust_up*/) override { void adjustValue(bool /*adjust_up*/) override {
*linked_variable_ = !*linked_variable_; *linked_variable_ = !*linked_variable_;
} }
auto getMaxValueWidth(Text* text_renderer) const -> int override { auto getMaxValueWidth(Text* text_renderer) const -> int override {
return std::max( return std::max(
text_renderer->length(Lang::getText("[SERVICE_MENU] ON"), -2), text_renderer->length(Lang::getText("[SERVICE_MENU] ON"), -2),
text_renderer->length(Lang::getText("[SERVICE_MENU] OFF"), -2)); text_renderer->length(Lang::getText("[SERVICE_MENU] OFF"), -2));
} }
private: private:
bool* linked_variable_; bool* linked_variable_;
}; };
class IntOption : public MenuOption { class IntOption : public MenuOption {
public: public:
IntOption(const std::string& cap, ServiceMenu::SettingsGroup grp, int* var, int min, int max, int step) IntOption(const std::string& cap, ServiceMenu::SettingsGroup grp, int* var, int min, int max, int step)
: MenuOption(cap, grp), : MenuOption(cap, grp),
linked_variable_(var), linked_variable_(var),
min_value_(min), min_value_(min),
max_value_(max), max_value_(max),
step_value_(step) {} step_value_(step) {}
[[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::ADJUST; } [[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::ADJUST; }
[[nodiscard]] auto getValueAsString() const -> std::string override { return std::to_string(*linked_variable_); } [[nodiscard]] auto getValueAsString() const -> std::string override { return std::to_string(*linked_variable_); }
void adjustValue(bool adjust_up) override { void adjustValue(bool adjust_up) override {
int new_value = *linked_variable_ + (adjust_up ? step_value_ : -step_value_); int new_value = *linked_variable_ + (adjust_up ? step_value_ : -step_value_);
*linked_variable_ = std::clamp(new_value, min_value_, max_value_); *linked_variable_ = std::clamp(new_value, min_value_, max_value_);
} }
auto getMaxValueWidth(Text* text_renderer) const -> int override { auto getMaxValueWidth(Text* text_renderer) const -> int override {
int max_width = 0; int max_width = 0;
// Iterar por todos los valores posibles en el rango // Iterar por todos los valores posibles en el rango
for (int value = min_value_; value <= max_value_; value += step_value_) { for (int value = min_value_; value <= max_value_; value += step_value_) {
int width = text_renderer->length(std::to_string(value), -2); int width = text_renderer->length(std::to_string(value), -2);
max_width = std::max(max_width, width); max_width = std::max(max_width, width);
}
return max_width;
} }
private: return max_width;
int* linked_variable_; }
int min_value_, max_value_, step_value_;
private:
int* linked_variable_;
int min_value_, max_value_, step_value_;
}; };
class ListOption : public MenuOption { class ListOption : public MenuOption {
public: public:
ListOption(const std::string& cap, ServiceMenu::SettingsGroup grp, std::vector<std::string> values, std::function<std::string()> current_value_getter, std::function<void(const std::string&)> new_value_setter) ListOption(const std::string& cap, ServiceMenu::SettingsGroup grp, std::vector<std::string> values, std::function<std::string()> current_value_getter, std::function<void(const std::string&)> new_value_setter)
: MenuOption(cap, grp), : MenuOption(cap, grp),
value_list_(std::move(values)), value_list_(std::move(values)),
getter_(std::move(current_value_getter)), getter_(std::move(current_value_getter)),
setter_(std::move(new_value_setter)) { setter_(std::move(new_value_setter)) {
sync(); sync();
} }
void sync() { void sync() {
std::string current_value = getter_(); std::string current_value = getter_();
for (size_t i = 0; i < value_list_.size(); ++i) { for (size_t i = 0; i < value_list_.size(); ++i) {
if (value_list_[i] == current_value) { if (value_list_[i] == current_value) {
list_index_ = i; list_index_ = i;
return;
}
}
}
[[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::ADJUST; }
[[nodiscard]] auto getValueAsString() const -> std::string override {
return value_list_.empty() ? "" : value_list_[list_index_];
}
void adjustValue(bool adjust_up) override {
if (value_list_.empty()) {
return; return;
} }
size_t size = value_list_.size();
list_index_ = (adjust_up) ? (list_index_ + 1) % size
: (list_index_ + size - 1) % size;
setter_(value_list_[list_index_]);
}
auto getMaxValueWidth(Text* text_renderer) const -> int override {
int max_w = 0;
for (const auto& val : value_list_) {
max_w = std::max(max_w, text_renderer->length(val, -2));
}
return max_w;
} }
}
private: [[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::ADJUST; }
std::vector<std::string> value_list_; [[nodiscard]] auto getValueAsString() const -> std::string override {
std::function<std::string()> getter_; return value_list_.empty() ? "" : value_list_[list_index_];
std::function<void(const std::string&)> setter_; }
size_t list_index_{0}; void adjustValue(bool adjust_up) override {
if (value_list_.empty()) {
return;
}
size_t size = value_list_.size();
list_index_ = (adjust_up) ? (list_index_ + 1) % size
: (list_index_ + size - 1) % size;
setter_(value_list_[list_index_]);
}
auto getMaxValueWidth(Text* text_renderer) const -> int override {
int max_w = 0;
for (const auto& val : value_list_) {
max_w = std::max(max_w, text_renderer->length(val, -2));
}
return max_w;
}
private:
std::vector<std::string> value_list_;
std::function<std::string()> getter_;
std::function<void(const std::string&)> setter_;
size_t list_index_{0};
}; };
class FolderOption : public MenuOption { class FolderOption : public MenuOption {
public: public:
FolderOption(const std::string& cap, ServiceMenu::SettingsGroup grp, ServiceMenu::SettingsGroup target) FolderOption(const std::string& cap, ServiceMenu::SettingsGroup grp, ServiceMenu::SettingsGroup target)
: MenuOption(cap, grp), : MenuOption(cap, grp),
target_group_(target) {} target_group_(target) {}
[[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::SELECT; } [[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::SELECT; }
[[nodiscard]] auto getTargetGroup() const -> ServiceMenu::SettingsGroup override { return target_group_; } [[nodiscard]] auto getTargetGroup() const -> ServiceMenu::SettingsGroup override { return target_group_; }
private: private:
ServiceMenu::SettingsGroup target_group_; ServiceMenu::SettingsGroup target_group_;
}; };
class ActionOption : public MenuOption { class ActionOption : public MenuOption {
public: public:
ActionOption(const std::string& cap, ServiceMenu::SettingsGroup grp, std::function<void()> action, bool hidden = false) ActionOption(const std::string& cap, ServiceMenu::SettingsGroup grp, std::function<void()> action, bool hidden = false)
: MenuOption(cap, grp, hidden), : MenuOption(cap, grp, hidden),
action_(std::move(action)) {} action_(std::move(action)) {}
[[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::SELECT; } [[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::SELECT; }
void executeAction() override { void executeAction() override {
if (action_) { if (action_) {
action_(); action_();
}
} }
}
private: private:
std::function<void()> action_; std::function<void()> action_;
}; };
// Opción de lista con acción // Opción de lista con acción
class ActionListOption : public MenuOption { class ActionListOption : public MenuOption {
public: public:
using ValueGetter = std::function<std::string()>; using ValueGetter = std::function<std::string()>;
using ValueSetter = std::function<void(const std::string&)>; using ValueSetter = std::function<void(const std::string&)>;
using ActionExecutor = std::function<void()>; using ActionExecutor = std::function<void()>;
ActionListOption(const std::string& caption, ServiceMenu::SettingsGroup group, std::vector<std::string> options, ValueGetter getter, ValueSetter setter, ActionExecutor action_executor, bool hidden = false) ActionListOption(const std::string& caption, ServiceMenu::SettingsGroup group, std::vector<std::string> options, ValueGetter getter, ValueSetter setter, ActionExecutor action_executor, bool hidden = false)
: MenuOption(caption, group, hidden), : MenuOption(caption, group, hidden),
options_(std::move(options)), options_(std::move(options)),
value_getter_(std::move(getter)), value_getter_(std::move(getter)),
value_setter_(std::move(setter)), value_setter_(std::move(setter)),
action_executor_(std::move(action_executor)) { action_executor_(std::move(action_executor)) {
updateCurrentIndex(); updateCurrentIndex();
} }
[[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::BOTH; } [[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::BOTH; }
[[nodiscard]] auto getValueAsString() const -> std::string override; [[nodiscard]] auto getValueAsString() const -> std::string override;
[[nodiscard]] auto getMaxValueWidth(Text* text) const -> int override; [[nodiscard]] auto getMaxValueWidth(Text* text) const -> int override;
void adjustValue(bool up) override; void adjustValue(bool up) override;
void executeAction() override; void executeAction() override;
void sync(); // Sincroniza con el valor actual void sync(); // Sincroniza con el valor actual
private: private:
std::vector<std::string> options_; std::vector<std::string> options_;
ValueGetter value_getter_; ValueGetter value_getter_;
ValueSetter value_setter_; ValueSetter value_setter_;
ActionExecutor action_executor_; ActionExecutor action_executor_;
size_t current_index_{0}; size_t current_index_{0};
void updateCurrentIndex(); void updateCurrentIndex();
[[nodiscard]] auto findCurrentIndex() const -> size_t; [[nodiscard]] auto findCurrentIndex() const -> size_t;
}; };
+93 -93
View File
@@ -15,115 +15,115 @@ class MenuOption;
class Text; class Text;
class MenuRenderer { class MenuRenderer {
public: public:
// --- Nuevo: Enum para el modo de posicionamiento --- // --- Nuevo: Enum para el modo de posicionamiento ---
enum class PositionMode { enum class PositionMode {
CENTERED, // La ventana se centra en el punto especificado CENTERED, // La ventana se centra en el punto especificado
FIXED // La esquina superior izquierda coincide con el punto FIXED // La esquina superior izquierda coincide con el punto
}; };
MenuRenderer(const ServiceMenu* menu_state, std::shared_ptr<Text> element_text, std::shared_ptr<Text> title_text); MenuRenderer(const ServiceMenu* menu_state, std::shared_ptr<Text> element_text, std::shared_ptr<Text> title_text);
// --- Métodos principales de la vista --- // --- Métodos principales de la vista ---
void render(const ServiceMenu* menu_state); void render(const ServiceMenu* menu_state);
void update(const ServiceMenu* menu_state, float delta_time); void update(const ServiceMenu* menu_state, float delta_time);
// --- Nuevos: Métodos de control de visibilidad y animación --- // --- Nuevos: Métodos de control de visibilidad y animación ---
void show(const ServiceMenu* menu_state); void show(const ServiceMenu* menu_state);
void hide(); void hide();
[[nodiscard]] auto isVisible() const -> bool { return visible_; } [[nodiscard]] auto isVisible() const -> bool { return visible_; }
[[nodiscard]] auto isFullyVisible() const -> bool { return visible_ && !show_hide_animation_.active && !resize_animation_.active; } [[nodiscard]] auto isFullyVisible() const -> bool { return visible_ && !show_hide_animation_.active && !resize_animation_.active; }
[[nodiscard]] auto isAnimating() const -> bool { return resize_animation_.active || show_hide_animation_.active; } [[nodiscard]] auto isAnimating() const -> bool { return resize_animation_.active || show_hide_animation_.active; }
// --- Nuevos: Métodos de configuración de posición --- // --- Nuevos: Métodos de configuración de posición ---
void setPosition(float x, float y, PositionMode mode); void setPosition(float x, float y, PositionMode mode);
// Método para notificar al renderer que el layout puede haber cambiado // Método para notificar al renderer que el layout puede haber cambiado
void onLayoutChanged(const ServiceMenu* menu_state); void onLayoutChanged(const ServiceMenu* menu_state);
void setLayout(const ServiceMenu* menu_state); void setLayout(const ServiceMenu* menu_state);
// Getters // Getters
[[nodiscard]] auto getRect() const -> const SDL_FRect& { return rect_; } [[nodiscard]] auto getRect() const -> const SDL_FRect& { return rect_; }
private: private:
// --- Referencias a los renderizadores de texto --- // --- Referencias a los renderizadores de texto ---
std::shared_ptr<Text> element_text_; std::shared_ptr<Text> element_text_;
std::shared_ptr<Text> title_text_; std::shared_ptr<Text> title_text_;
// --- Variables de estado de la vista (layout y animación) --- // --- Variables de estado de la vista (layout y animación) ---
SDL_FRect rect_{}; SDL_FRect rect_{};
SDL_FRect border_rect_{}; SDL_FRect border_rect_{};
size_t width_ = 0; size_t width_ = 0;
size_t height_ = 0; size_t height_ = 0;
size_t options_height_ = 0; size_t options_height_ = 0;
size_t options_padding_ = 0; size_t options_padding_ = 0;
size_t options_y_ = 0; size_t options_y_ = 0;
size_t title_height_ = 0; size_t title_height_ = 0;
size_t title_padding_ = 0; size_t title_padding_ = 0;
size_t upper_height_ = 0; size_t upper_height_ = 0;
size_t lower_height_ = 0; size_t lower_height_ = 0;
size_t lower_padding_ = 0; size_t lower_padding_ = 0;
Uint32 color_counter_ = 0; Uint32 color_counter_ = 0;
bool visible_ = false; bool visible_ = false;
// --- Posicionamiento --- // --- Posicionamiento ---
PositionMode position_mode_ = PositionMode::CENTERED; PositionMode position_mode_ = PositionMode::CENTERED;
float anchor_x_ = 0.0F; float anchor_x_ = 0.0F;
float anchor_y_ = 0.0F; float anchor_y_ = 0.0F;
// --- Límites de tamaño máximo --- // --- Límites de tamaño máximo ---
size_t max_menu_width_ = 0; size_t max_menu_width_ = 0;
size_t max_menu_height_ = 0; size_t max_menu_height_ = 0;
// --- Estructuras de Animación --- // --- Estructuras de Animación ---
struct ResizeAnimation { struct ResizeAnimation {
bool active = false; bool active = false;
float start_width, start_height; float start_width, start_height;
float target_width, target_height; float target_width, target_height;
float elapsed = 0.0F; float elapsed = 0.0F;
float duration = 0.2F; float duration = 0.2F;
void start(float from_w, float from_h, float to_w, float to_h); void start(float from_w, float from_h, float to_w, float to_h);
void stop(); void stop();
} resize_animation_; } resize_animation_;
struct ShowHideAnimation { struct ShowHideAnimation {
enum class Type { NONE, enum class Type { NONE,
SHOWING, SHOWING,
HIDING }; HIDING };
Type type = Type::NONE; Type type = Type::NONE;
bool active = false; bool active = false;
float target_width, target_height; float target_width, target_height;
float elapsed = 0.0F; float elapsed = 0.0F;
float duration = 0.25F; float duration = 0.25F;
void startShow(float to_w, float to_h); void startShow(float to_w, float to_h);
void startHide(); void startHide();
void stop(); void stop();
} show_hide_animation_; } show_hide_animation_;
// --- Anchos precalculados --- // --- Anchos precalculados ---
std::array<int, ServiceMenu::SETTINGS_GROUP_SIZE> group_menu_widths_ = {}; std::array<int, ServiceMenu::SETTINGS_GROUP_SIZE> group_menu_widths_ = {};
// --- Métodos privados de la vista --- // --- Métodos privados de la vista ---
void initializeMaxSizes(); void initializeMaxSizes();
void setAnchors(const ServiceMenu* menu_state); void setAnchors(const ServiceMenu* menu_state);
auto calculateNewRect(const ServiceMenu* menu_state) -> SDL_FRect; auto calculateNewRect(const ServiceMenu* menu_state) -> SDL_FRect;
void resize(const ServiceMenu* menu_state); void resize(const ServiceMenu* menu_state);
void setSize(const ServiceMenu* menu_state); void setSize(const ServiceMenu* menu_state);
void updateAnimations(float delta_time); void updateAnimations(float delta_time);
void updateResizeAnimation(float delta_time); void updateResizeAnimation(float delta_time);
void updateShowHideAnimation(float delta_time); void updateShowHideAnimation(float delta_time);
void updatePosition(); void updatePosition();
void precalculateMenuWidths(const std::vector<std::unique_ptr<MenuOption>>& all_options, const ServiceMenu* menu_state); void precalculateMenuWidths(const std::vector<std::unique_ptr<MenuOption>>& all_options, const ServiceMenu* menu_state);
[[nodiscard]] auto getMenuWidthForGroup(ServiceMenu::SettingsGroup group) const -> int; [[nodiscard]] auto getMenuWidthForGroup(ServiceMenu::SettingsGroup group) const -> int;
[[nodiscard]] auto getAnimatedSelectedColor() const -> Color; [[nodiscard]] auto getAnimatedSelectedColor() const -> Color;
void updateColorCounter(); void updateColorCounter();
auto setRect(SDL_FRect rect) -> SDL_FRect; auto setRect(SDL_FRect rect) -> SDL_FRect;
[[nodiscard]] auto getTruncatedValueWidth(const std::string& value, int available_width) const -> int; [[nodiscard]] auto getTruncatedValueWidth(const std::string& value, int available_width) const -> int;
[[nodiscard]] auto getTruncatedValue(const std::string& value, int available_width) const -> std::string; [[nodiscard]] auto getTruncatedValue(const std::string& value, int available_width) const -> std::string;
[[nodiscard]] static auto easeOut(float t) -> float; [[nodiscard]] static auto easeOut(float t) -> float;
[[nodiscard]] auto shouldShowContent() const -> bool; [[nodiscard]] auto shouldShowContent() const -> bool;
}; };
+81 -81
View File
@@ -15,98 +15,98 @@ class Texture;
// --- Clase Notifier: gestiona las notificaciones en pantalla (singleton) --- // --- Clase Notifier: gestiona las notificaciones en pantalla (singleton) ---
class Notifier { class Notifier {
public: public:
// --- Enums --- // --- Enums ---
enum class Position { enum class Position {
TOP, // Parte superior TOP, // Parte superior
BOTTOM, // Parte inferior BOTTOM, // Parte inferior
LEFT, // Lado izquierdo LEFT, // Lado izquierdo
MIDDLE, // Centro MIDDLE, // Centro
RIGHT, // Lado derecho RIGHT, // Lado derecho
}; };
// --- Métodos de singleton --- // --- Métodos de singleton ---
static void init(const std::string& icon_file, std::shared_ptr<Text> text); // Inicializa el singleton static void init(const std::string& icon_file, std::shared_ptr<Text> text); // Inicializa el singleton
static void destroy(); // Libera el singleton static void destroy(); // Libera el singleton
static auto get() -> Notifier*; // Obtiene la instancia static auto get() -> Notifier*; // Obtiene la instancia
// --- Métodos principales --- // --- Métodos principales ---
void render(); // Dibuja las notificaciones por pantalla void render(); // Dibuja las notificaciones por pantalla
void update(float delta_time); // Actualiza el estado de las notificaciones void update(float delta_time); // Actualiza el estado de las notificaciones
// --- Gestión de notificaciones --- // --- Gestión de notificaciones ---
void show(std::vector<std::string> texts, int icon = -1, const std::string& code = std::string()); // Muestra una notificación de texto por pantalla void show(std::vector<std::string> texts, int icon = -1, const std::string& code = std::string()); // Muestra una notificación de texto por pantalla
[[nodiscard]] auto isActive() const -> bool { return !notifications_.empty(); } // Indica si hay notificaciones activas [[nodiscard]] auto isActive() const -> bool { return !notifications_.empty(); } // Indica si hay notificaciones activas
auto getCodes() -> std::vector<std::string>; // Obtiene los códigos de las notificaciones activas auto getCodes() -> std::vector<std::string>; // Obtiene los códigos de las notificaciones activas
auto checkCode(const std::string& code) -> bool { return stringInVector(getCodes(), code); } // Comprueba si hay alguna notificación con un código concreto auto checkCode(const std::string& code) -> bool { return stringInVector(getCodes(), code); } // Comprueba si hay alguna notificación con un código concreto
private: private:
// --- Constantes de tiempo (en segundos) --- // --- Constantes de tiempo (en segundos) ---
static constexpr float STAY_DURATION_S = 2.5F; // Tiempo que se ve la notificación (150 frames @ 60fps) static constexpr float STAY_DURATION_S = 2.5F; // Tiempo que se ve la notificación (150 frames @ 60fps)
static constexpr float ANIMATION_SPEED_PX_PER_S = 60.0F; // Velocidad de animación (1 pixel/frame @ 60fps) static constexpr float ANIMATION_SPEED_PX_PER_S = 60.0F; // Velocidad de animación (1 pixel/frame @ 60fps)
// --- Enums privados --- // --- Enums privados ---
enum class State { enum class State {
RISING, // Apareciendo RISING, // Apareciendo
STAY, // Visible STAY, // Visible
VANISHING, // Desapareciendo VANISHING, // Desapareciendo
FINISHED, // Terminada FINISHED, // Terminada
}; };
enum class Shape { enum class Shape {
ROUNDED, // Forma redondeada ROUNDED, // Forma redondeada
SQUARED, // Forma cuadrada SQUARED, // Forma cuadrada
}; };
// --- Estructuras privadas --- // --- Estructuras privadas ---
struct Notification { struct Notification {
std::shared_ptr<Texture> texture; // Textura de la notificación std::shared_ptr<Texture> texture; // Textura de la notificación
std::shared_ptr<Sprite> sprite; // Sprite asociado std::shared_ptr<Sprite> sprite; // Sprite asociado
std::vector<std::string> texts; // Textos a mostrar std::vector<std::string> texts; // Textos a mostrar
SDL_FRect rect; // Rectángulo de la notificación SDL_FRect rect; // Rectángulo de la notificación
std::string code; // Código identificador de la notificación std::string code; // Código identificador de la notificación
State state{State::RISING}; // Estado de la notificación State state{State::RISING}; // Estado de la notificación
Shape shape{Shape::SQUARED}; // Forma de la notificación Shape shape{Shape::SQUARED}; // Forma de la notificación
float timer{0.0F}; // Timer en segundos float timer{0.0F}; // Timer en segundos
int y{0}; // Posición vertical int y{0}; // Posición vertical
int travel_dist{0}; // Distancia a recorrer int travel_dist{0}; // Distancia a recorrer
// Constructor // Constructor
explicit Notification() explicit Notification()
: texture(nullptr), : texture(nullptr),
sprite(nullptr), sprite(nullptr),
rect{0, 0, 0, 0} {} rect{0, 0, 0, 0} {}
}; };
// --- Objetos y punteros --- // --- Objetos y punteros ---
SDL_Renderer* renderer_; // El renderizador de la ventana SDL_Renderer* renderer_; // El renderizador de la ventana
std::shared_ptr<Texture> icon_texture_; // Textura para los iconos de las notificaciones std::shared_ptr<Texture> icon_texture_; // Textura para los iconos de las notificaciones
std::shared_ptr<Text> text_; // Objeto para dibujar texto std::shared_ptr<Text> text_; // Objeto para dibujar texto
// --- Variables de estado --- // --- Variables de estado ---
std::vector<Notification> notifications_; // Lista de notificaciones activas std::vector<Notification> notifications_; // Lista de notificaciones activas
Color bg_color_; // Color de fondo de las notificaciones Color bg_color_; // Color de fondo de las notificaciones
// Nota: wait_time_ eliminado, ahora se usa STAY_DURATION_S // Nota: wait_time_ eliminado, ahora se usa STAY_DURATION_S
bool stack_; // Indica si las notificaciones se apilan bool stack_; // Indica si las notificaciones se apilan
bool has_icons_; // Indica si el notificador tiene textura para iconos bool has_icons_; // Indica si el notificador tiene textura para iconos
// --- Métodos internos --- // --- Métodos internos ---
void clearFinishedNotifications(); // Elimina las notificaciones cuyo estado es FINISHED void clearFinishedNotifications(); // Elimina las notificaciones cuyo estado es FINISHED
void clearAllNotifications(); // Elimina todas las notificaciones activas, sin importar el estado void clearAllNotifications(); // Elimina todas las notificaciones activas, sin importar el estado
[[nodiscard]] auto shouldProcessNotification(int index) const -> bool; // Determina si una notificación debe ser procesada (según su estado y posición) [[nodiscard]] auto shouldProcessNotification(int index) const -> bool; // Determina si una notificación debe ser procesada (según su estado y posición)
void processNotification(int index, float delta_time); // Procesa una notificación en la posición dada: actualiza su estado y comportamiento visual void processNotification(int index, float delta_time); // Procesa una notificación en la posición dada: actualiza su estado y comportamiento visual
static void playNotificationSoundIfNeeded(const Notification& notification); // Reproduce sonido asociado si es necesario (dependiendo del estado o contenido) static void playNotificationSoundIfNeeded(const Notification& notification); // Reproduce sonido asociado si es necesario (dependiendo del estado o contenido)
void updateNotificationState(int index, float delta_time); // Actualiza el estado interno de una notificación (ej. de RISING a STAY) void updateNotificationState(int index, float delta_time); // Actualiza el estado interno de una notificación (ej. de RISING a STAY)
void handleRisingState(int index, float delta_time); // Lógica de animación para el estado RISING (apareciendo) void handleRisingState(int index, float delta_time); // Lógica de animación para el estado RISING (apareciendo)
void handleStayState(int index); // Lógica para mantener una notificación visible en el estado STAY void handleStayState(int index); // Lógica para mantener una notificación visible en el estado STAY
void handleVanishingState(int index, float delta_time); // Lógica de animación para el estado VANISHING (desapareciendo) void handleVanishingState(int index, float delta_time); // Lógica de animación para el estado VANISHING (desapareciendo)
static void moveNotificationVertically(Notification& notification, float pixels_to_move); // Mueve verticalmente una notificación con la cantidad de pixels especificada static void moveNotificationVertically(Notification& notification, float pixels_to_move); // Mueve verticalmente una notificación con la cantidad de pixels especificada
void transitionToStayState(int index); // Cambia el estado de una notificación de RISING a STAY cuando ha alcanzado su posición final void transitionToStayState(int index); // Cambia el estado de una notificación de RISING a STAY cuando ha alcanzado su posición final
// --- Constructores y destructor privados (singleton) --- // --- Constructores y destructor privados (singleton) ---
Notifier(const std::string& icon_file, std::shared_ptr<Text> text); // Constructor privado Notifier(const std::string& icon_file, std::shared_ptr<Text> text); // Constructor privado
~Notifier() = default; // Destructor privado ~Notifier() = default; // Destructor privado
// --- Instancia singleton --- // --- Instancia singleton ---
static Notifier* instance; // Instancia única de Notifier static Notifier* instance; // Instancia única de Notifier
}; };
+95 -95
View File
@@ -17,112 +17,112 @@ class MenuOption;
class MenuRenderer; class MenuRenderer;
class ServiceMenu { class ServiceMenu {
public: public:
// --- Enums y constantes --- // --- Enums y constantes ---
enum class SettingsGroup { enum class SettingsGroup {
CONTROLS, CONTROLS,
VIDEO, VIDEO,
AUDIO, AUDIO,
SETTINGS, SETTINGS,
SYSTEM, SYSTEM,
MAIN MAIN
}; };
enum class GroupAlignment { enum class GroupAlignment {
CENTERED, CENTERED,
LEFT LEFT
}; };
static constexpr size_t OPTIONS_HORIZONTAL_PADDING = 20; static constexpr size_t OPTIONS_HORIZONTAL_PADDING = 20;
static constexpr size_t MIN_WIDTH = 240; static constexpr size_t MIN_WIDTH = 240;
static constexpr size_t MIN_GAP_OPTION_VALUE = 30; static constexpr size_t MIN_GAP_OPTION_VALUE = 30;
static constexpr size_t SETTINGS_GROUP_SIZE = 6; static constexpr size_t SETTINGS_GROUP_SIZE = 6;
using StateChangeCallback = std::function<void(bool is_active)>; using StateChangeCallback = std::function<void(bool is_active)>;
// --- Métodos de singleton --- // --- Métodos de singleton ---
static void init(); static void init();
static void destroy(); static void destroy();
static auto get() -> ServiceMenu*; static auto get() -> ServiceMenu*;
ServiceMenu(const ServiceMenu&) = delete; ServiceMenu(const ServiceMenu&) = delete;
auto operator=(const ServiceMenu&) -> ServiceMenu& = delete; auto operator=(const ServiceMenu&) -> ServiceMenu& = delete;
// --- Métodos principales --- // --- Métodos principales ---
void toggle(); void toggle();
void render(); void render();
void update(float delta_time); void update(float delta_time);
void reset(); void reset();
// --- Lógica de navegación --- // --- Lógica de navegación ---
void setSelectorUp(); void setSelectorUp();
void setSelectorDown(); void setSelectorDown();
void adjustOption(bool adjust_up); void adjustOption(bool adjust_up);
void selectOption(); void selectOption();
void moveBack(); void moveBack();
// --- Método para manejar eventos --- // --- Método para manejar eventos ---
void handleEvent(const SDL_Event& event); void handleEvent(const SDL_Event& event);
auto checkInput() -> bool; auto checkInput() -> bool;
// --- Método principal para refresco externo --- // --- Método principal para refresco externo ---
void refresh(); // Refresca los valores y el layout del menú bajo demanda void refresh(); // Refresca los valores y el layout del menú bajo demanda
// --- Método para registrar el callback --- // --- Método para registrar el callback ---
void setStateChangeCallback(StateChangeCallback callback); void setStateChangeCallback(StateChangeCallback callback);
// --- Getters para el estado --- // --- Getters para el estado ---
[[nodiscard]] auto isDefiningButtons() const -> bool; [[nodiscard]] auto isDefiningButtons() const -> bool;
[[nodiscard]] auto isAnimating() const -> bool; // Nuevo getter [[nodiscard]] auto isAnimating() const -> bool; // Nuevo getter
// --- Getters para que el Renderer pueda leer el estado --- // --- Getters para que el Renderer pueda leer el estado ---
[[nodiscard]] auto isEnabled() const -> bool { return enabled_; } [[nodiscard]] auto isEnabled() const -> bool { return enabled_; }
[[nodiscard]] auto getTitle() const -> const std::string& { return title_; } [[nodiscard]] auto getTitle() const -> const std::string& { return title_; }
[[nodiscard]] auto getCurrentGroup() const -> SettingsGroup { return current_settings_group_; } [[nodiscard]] auto getCurrentGroup() const -> SettingsGroup { return current_settings_group_; }
[[nodiscard]] auto getCurrentGroupAlignment() const -> GroupAlignment; [[nodiscard]] auto getCurrentGroupAlignment() const -> GroupAlignment;
[[nodiscard]] auto getDisplayOptions() const -> const std::vector<MenuOption*>& { return display_options_; } [[nodiscard]] auto getDisplayOptions() const -> const std::vector<MenuOption*>& { return display_options_; }
[[nodiscard]] auto getAllOptions() const -> const std::vector<std::unique_ptr<MenuOption>>& { return options_; } [[nodiscard]] auto getAllOptions() const -> const std::vector<std::unique_ptr<MenuOption>>& { return options_; }
[[nodiscard]] auto getSelectedIndex() const -> size_t { return selected_; } [[nodiscard]] auto getSelectedIndex() const -> size_t { return selected_; }
[[nodiscard]] auto getOptionPairs() const -> const std::vector<std::pair<std::string, std::string>>& { return option_pairs_; } [[nodiscard]] auto getOptionPairs() const -> const std::vector<std::pair<std::string, std::string>>& { return option_pairs_; }
[[nodiscard]] auto countOptionsInGroup(SettingsGroup group) const -> size_t; [[nodiscard]] auto countOptionsInGroup(SettingsGroup group) const -> size_t;
private: private:
bool enabled_ = false; bool enabled_ = false;
std::vector<std::unique_ptr<MenuOption>> options_; std::vector<std::unique_ptr<MenuOption>> options_;
std::vector<MenuOption*> display_options_; std::vector<MenuOption*> display_options_;
std::vector<std::pair<std::string, std::string>> option_pairs_; std::vector<std::pair<std::string, std::string>> option_pairs_;
SettingsGroup current_settings_group_; SettingsGroup current_settings_group_;
SettingsGroup previous_settings_group_; SettingsGroup previous_settings_group_;
std::string title_; std::string title_;
size_t selected_ = 0; size_t selected_ = 0;
size_t main_menu_selected_ = 0; size_t main_menu_selected_ = 0;
std::unique_ptr<UIMessage> restart_message_ui_; std::unique_ptr<UIMessage> restart_message_ui_;
bool last_pending_changes_ = false; bool last_pending_changes_ = false;
std::unique_ptr<DefineButtons> define_buttons_; std::unique_ptr<DefineButtons> define_buttons_;
std::unique_ptr<MenuRenderer> renderer_; std::unique_ptr<MenuRenderer> renderer_;
StateChangeCallback state_change_callback_; StateChangeCallback state_change_callback_;
// --- Métodos de lógica interna --- // --- Métodos de lógica interna ---
void updateDisplayOptions(); void updateDisplayOptions();
void updateOptionPairs(); void updateOptionPairs();
void initializeOptions(); void initializeOptions();
void updateMenu(); void updateMenu();
void applySettings(); void applySettings();
void applyControlsSettings(); void applyControlsSettings();
void applyVideoSettings(); void applyVideoSettings();
static void applyAudioSettings(); static void applyAudioSettings();
void applySettingsSettings(); void applySettingsSettings();
[[nodiscard]] auto getOptionByCaption(const std::string& caption) const -> MenuOption*; [[nodiscard]] auto getOptionByCaption(const std::string& caption) const -> MenuOption*;
void adjustListValues(); void adjustListValues();
static void playMoveSound(); static void playMoveSound();
static void playAdjustSound(); static void playAdjustSound();
static void playSelectSound(); static void playSelectSound();
static void playBackSound(); static void playBackSound();
[[nodiscard]] static auto settingsGroupToString(SettingsGroup group) -> std::string; [[nodiscard]] static auto settingsGroupToString(SettingsGroup group) -> std::string;
void setHiddenOptions(); void setHiddenOptions();
void setEnabledInternal(bool enabled); // Método privado para cambiar estado y notificar void setEnabledInternal(bool enabled); // Método privado para cambiar estado y notificar
// --- Constructores y destructor privados (singleton) --- // --- Constructores y destructor privados (singleton) ---
ServiceMenu(); ServiceMenu();
~ServiceMenu() = default; ~ServiceMenu() = default;
// --- Instancia singleton --- // --- Instancia singleton ---
static ServiceMenu* instance; static ServiceMenu* instance;
}; };
+34 -34
View File
@@ -9,48 +9,48 @@ class Text;
// Clase para mostrar mensajes animados en la interfaz de usuario // Clase para mostrar mensajes animados en la interfaz de usuario
class UIMessage { class UIMessage {
public: public:
// Constructor: recibe el renderizador de texto, el mensaje y el color // Constructor: recibe el renderizador de texto, el mensaje y el color
UIMessage(std::shared_ptr<Text> text_renderer, std::string message_text, const Color& color); UIMessage(std::shared_ptr<Text> text_renderer, std::string message_text, const Color& color);
// Muestra el mensaje con animación de entrada // Muestra el mensaje con animación de entrada
void show(); void show();
// Oculta el mensaje con animación de salida // Oculta el mensaje con animación de salida
void hide(); void hide();
// Actualiza el estado de la animación (debe llamarse cada frame) // Actualiza el estado de la animación (debe llamarse cada frame)
void update(float delta_time); void update(float delta_time);
// Dibuja el mensaje en pantalla si está visible // Dibuja el mensaje en pantalla si está visible
void render(); void render();
// Indica si el mensaje está visible actualmente // Indica si el mensaje está visible actualmente
[[nodiscard]] auto isVisible() const -> bool; [[nodiscard]] auto isVisible() const -> bool;
// Permite actualizar la posición del mensaje (por ejemplo, si el menú se mueve) // Permite actualizar la posición del mensaje (por ejemplo, si el menú se mueve)
void setPosition(float new_base_x, float new_base_y); void setPosition(float new_base_x, float new_base_y);
private: private:
// --- Configuración --- // --- Configuración ---
std::shared_ptr<Text> text_renderer_; // Renderizador de texto std::shared_ptr<Text> text_renderer_; // Renderizador de texto
std::string text_; // Texto del mensaje a mostrar std::string text_; // Texto del mensaje a mostrar
Color color_; // Color del texto Color color_; // Color del texto
// --- Estado --- // --- Estado ---
bool visible_ = false; // Indica si el mensaje está visible bool visible_ = false; // Indica si el mensaje está visible
bool animating_ = false; // Indica si el mensaje está en proceso de animación bool animating_ = false; // Indica si el mensaje está en proceso de animación
float base_x_ = 0.0F; // Posición X base donde se muestra el mensaje float base_x_ = 0.0F; // Posición X base donde se muestra el mensaje
float base_y_ = 0.0F; // Posición Y base donde se muestra el mensaje float base_y_ = 0.0F; // Posición Y base donde se muestra el mensaje
float y_offset_ = 0.0F; // Desplazamiento vertical actual del mensaje (para animación) float y_offset_ = 0.0F; // Desplazamiento vertical actual del mensaje (para animación)
// --- Animación --- // --- Animación ---
float start_y_ = 0.0F; // Posición Y inicial de la animación float start_y_ = 0.0F; // Posición Y inicial de la animación
float target_y_ = 0.0F; // Posición Y objetivo de la animación float target_y_ = 0.0F; // Posición Y objetivo de la animación
float animation_timer_ = 0.0F; // Timer actual de la animación en segundos float animation_timer_ = 0.0F; // Timer actual de la animación en segundos
static constexpr float ANIMATION_DURATION_S = 0.133F; // Duración total de la animación (8 frames @ 60fps) static constexpr float ANIMATION_DURATION_S = 0.133F; // Duración total de la animación (8 frames @ 60fps)
static constexpr float DESP = -8.0F; // Distancia a desplazarse static constexpr float DESP = -8.0F; // Distancia a desplazarse
// Actualiza la interpolación de la animación (ease out/in cubic) // Actualiza la interpolación de la animación (ease out/in cubic)
void updateAnimation(float delta_time); void updateAnimation(float delta_time);
}; };
+197 -197
View File
@@ -12,232 +12,232 @@
#include "text.hpp" // Para Text #include "text.hpp" // Para Text
class WindowMessage { class WindowMessage {
public: public:
enum class PositionMode { enum class PositionMode {
CENTERED, // La ventana se centra en el punto especificado CENTERED, // La ventana se centra en el punto especificado
FIXED // La esquina superior izquierda coincide con el punto FIXED // La esquina superior izquierda coincide con el punto
}; };
struct Config { struct Config {
// Colores // Colores
Color bg_color; Color bg_color;
Color border_color; Color border_color;
Color title_color; Color title_color;
Color text_color; Color text_color;
// Espaciado y dimensiones // Espaciado y dimensiones
float padding{15.0F}; float padding{15.0F};
float line_spacing{5.0F}; float line_spacing{5.0F};
float title_separator_spacing{10.0F}; // Espacio extra para separador del título float title_separator_spacing{10.0F}; // Espacio extra para separador del título
// Límites de tamaño // Límites de tamaño
float min_width{200.0F}; float min_width{200.0F};
float min_height{100.0F}; float min_height{100.0F};
float max_width_ratio{0.8F}; // % máximo de ancho de pantalla float max_width_ratio{0.8F}; // % máximo de ancho de pantalla
float max_height_ratio{0.8F}; // % máximo de alto de pantalla float max_height_ratio{0.8F}; // % máximo de alto de pantalla
// Margen de seguridad para texto // Margen de seguridad para texto
float text_safety_margin{20.0F}; // Margen extra para evitar texto cortado float text_safety_margin{20.0F}; // Margen extra para evitar texto cortado
// Animaciones // Animaciones
float animation_duration{0.3F}; // Duración en segundos para todas las animaciones float animation_duration{0.3F}; // Duración en segundos para todas las animaciones
// Constructor con valores por defecto // Constructor con valores por defecto
Config() Config()
: bg_color{40, 40, 60, 220}, : bg_color{40, 40, 60, 220},
border_color{100, 100, 120, 255}, border_color{100, 100, 120, 255},
title_color{255, 255, 255, 255}, title_color{255, 255, 255, 255},
text_color{200, 200, 200, 255} {} text_color{200, 200, 200, 255} {}
// Constructor que convierte desde ParamServiceMenu::WindowMessage // Constructor que convierte desde ParamServiceMenu::WindowMessage
Config(const ParamServiceMenu::WindowMessage& param_config) Config(const ParamServiceMenu::WindowMessage& param_config)
: bg_color(param_config.bg_color), : bg_color(param_config.bg_color),
border_color(param_config.border_color), border_color(param_config.border_color),
title_color(param_config.title_color), title_color(param_config.title_color),
text_color(param_config.text_color), text_color(param_config.text_color),
padding(param_config.padding), padding(param_config.padding),
line_spacing(param_config.line_spacing), line_spacing(param_config.line_spacing),
title_separator_spacing(param_config.title_separator_spacing), title_separator_spacing(param_config.title_separator_spacing),
min_width(param_config.min_width), min_width(param_config.min_width),
min_height(param_config.min_height), min_height(param_config.min_height),
max_width_ratio(param_config.max_width_ratio), max_width_ratio(param_config.max_width_ratio),
max_height_ratio(param_config.max_height_ratio), max_height_ratio(param_config.max_height_ratio),
text_safety_margin(param_config.text_safety_margin), text_safety_margin(param_config.text_safety_margin),
animation_duration(param_config.animation_duration) {} animation_duration(param_config.animation_duration) {}
}; };
WindowMessage( WindowMessage(
std::shared_ptr<Text> text_renderer, std::shared_ptr<Text> text_renderer,
std::string title = "", std::string title = "",
const Config& config = Config{}); const Config& config = Config{});
// Métodos principales // Métodos principales
void render(); void render();
void update(float delta_time); void update(float delta_time);
// Control de visibilidad // Control de visibilidad
void show(); void show();
void hide(); void hide();
[[nodiscard]] auto isVisible() const -> bool { return visible_; } [[nodiscard]] auto isVisible() const -> bool { return visible_; }
[[nodiscard]] auto isFullyVisible() const -> bool { return visible_ && !show_hide_animation_.active; } [[nodiscard]] auto isFullyVisible() const -> bool { return visible_ && !show_hide_animation_.active; }
[[nodiscard]] auto isAnimating() const -> bool { return resize_animation_.active || show_hide_animation_.active; } [[nodiscard]] auto isAnimating() const -> bool { return resize_animation_.active || show_hide_animation_.active; }
// Configuración de contenido // Configuración de contenido
void setTitle(const std::string& title); void setTitle(const std::string& title);
void setText(const std::string& text); void setText(const std::string& text);
void setTexts(const std::vector<std::string>& texts); void setTexts(const std::vector<std::string>& texts);
void addText(const std::string& text); void addText(const std::string& text);
void clearTexts(); void clearTexts();
// Control de redimensionado automático // Control de redimensionado automático
void enableAutoResize(bool enabled) { auto_resize_enabled_ = enabled; } void enableAutoResize(bool enabled) { auto_resize_enabled_ = enabled; }
[[nodiscard]] auto isAutoResizeEnabled() const -> bool { return auto_resize_enabled_; } [[nodiscard]] auto isAutoResizeEnabled() const -> bool { return auto_resize_enabled_; }
// Configuración de posición y tamaño // Configuración de posición y tamaño
void setPosition(float x, float y, PositionMode mode = PositionMode::CENTERED); void setPosition(float x, float y, PositionMode mode = PositionMode::CENTERED);
void setSize(float width, float height); void setSize(float width, float height);
void centerOnScreen(); void centerOnScreen();
void autoSize(); // Ajusta automáticamente al contenido y reposiciona si es necesario void autoSize(); // Ajusta automáticamente al contenido y reposiciona si es necesario
// Configuración de colores // Configuración de colores
void setBackgroundColor(const Color& color) { config_.bg_color = color; } void setBackgroundColor(const Color& color) { config_.bg_color = color; }
void setBorderColor(const Color& color) { config_.border_color = color; } void setBorderColor(const Color& color) { config_.border_color = color; }
void setTitleColor(const Color& color) { void setTitleColor(const Color& color) {
config_.title_color = color; config_.title_color = color;
updateStyles(); updateStyles();
} }
void setTextColor(const Color& color) { void setTextColor(const Color& color) {
config_.text_color = color; config_.text_color = color;
updateStyles(); updateStyles();
}
// Configuración de espaciado
void setPadding(float padding) { config_.padding = padding; }
void setLineSpacing(float spacing) { config_.line_spacing = spacing; }
// Configuración avanzada
void setConfig(const Config& config) {
config_ = config;
updateStyles();
}
[[nodiscard]] auto getConfig() const -> const Config& { return config_; }
// Getters
[[nodiscard]] auto getRect() const -> const SDL_FRect& { return rect_; }
[[nodiscard]] auto getPositionMode() const -> PositionMode { return position_mode_; }
[[nodiscard]] auto getAnchorPoint() const -> SDL_FPoint { return anchor_; }
private:
std::shared_ptr<Text> text_renderer_;
Config config_;
// Estado de visibilidad y redimensionado
bool visible_ = false;
bool auto_resize_enabled_ = true; // Por defecto habilitado
// Contenido
std::string title_;
std::vector<std::string> texts_;
// Posición y tamaño
SDL_FRect rect_{0, 0, 300, 200};
PositionMode position_mode_ = PositionMode::CENTERED;
SDL_FPoint anchor_{0.0F, 0.0F};
// Animación de redimensionado
struct ResizeAnimation {
bool active = false;
float start_width, start_height;
float target_width, target_height;
float elapsed = 0.0F;
void start(float from_w, float from_h, float to_w, float to_h) {
start_width = from_w;
start_height = from_h;
target_width = to_w;
target_height = to_h;
elapsed = 0.0F;
active = true;
} }
// Configuración de espaciado void stop() {
void setPadding(float padding) { config_.padding = padding; } active = false;
void setLineSpacing(float spacing) { config_.line_spacing = spacing; } elapsed = 0.0F;
// Configuración avanzada
void setConfig(const Config& config) {
config_ = config;
updateStyles();
} }
[[nodiscard]] auto getConfig() const -> const Config& { return config_; }
// Getters [[nodiscard]] auto isFinished(float duration) const -> bool {
[[nodiscard]] auto getRect() const -> const SDL_FRect& { return rect_; } return elapsed >= duration;
[[nodiscard]] auto getPositionMode() const -> PositionMode { return position_mode_; } }
[[nodiscard]] auto getAnchorPoint() const -> SDL_FPoint { return anchor_; }
private: [[nodiscard]] auto getProgress(float duration) const -> float {
std::shared_ptr<Text> text_renderer_; return std::min(elapsed / duration, 1.0F);
Config config_; }
} resize_animation_;
// Estado de visibilidad y redimensionado // Animación de mostrar/ocultar
bool visible_ = false; struct ShowHideAnimation {
bool auto_resize_enabled_ = true; // Por defecto habilitado enum class Type { NONE,
SHOWING,
HIDING };
// Contenido Type type = Type::NONE;
std::string title_; bool active = false;
std::vector<std::string> texts_; float target_width, target_height; // Tamaño final al mostrar
float elapsed = 0.0F;
// Posición y tamaño void startShow(float to_w, float to_h) {
SDL_FRect rect_{0, 0, 300, 200}; type = Type::SHOWING;
PositionMode position_mode_ = PositionMode::CENTERED; target_width = to_w;
SDL_FPoint anchor_{0.0F, 0.0F}; target_height = to_h;
elapsed = 0.0F;
active = true;
}
// Animación de redimensionado void startHide() {
struct ResizeAnimation { type = Type::HIDING;
bool active = false; elapsed = 0.0F;
float start_width, start_height; active = true;
float target_width, target_height; }
float elapsed = 0.0F;
void start(float from_w, float from_h, float to_w, float to_h) { void stop() {
start_width = from_w; type = Type::NONE;
start_height = from_h; active = false;
target_width = to_w; elapsed = 0.0F;
target_height = to_h; }
elapsed = 0.0F;
active = true;
}
void stop() { [[nodiscard]] auto isFinished(float duration) const -> bool {
active = false; return elapsed >= duration;
elapsed = 0.0F; }
}
[[nodiscard]] auto isFinished(float duration) const -> bool { [[nodiscard]] auto getProgress(float duration) const -> float {
return elapsed >= duration; return std::min(elapsed / duration, 1.0F);
} }
} show_hide_animation_;
[[nodiscard]] auto getProgress(float duration) const -> float { // Estilos
return std::min(elapsed / duration, 1.0F); Text::Style title_style_;
} Text::Style text_style_;
} resize_animation_;
// Animación de mostrar/ocultar // Métodos privados
struct ShowHideAnimation { void calculateAutoSize();
enum class Type { NONE, void updatePosition(); // Actualiza la posición según el modo y punto de anclaje
SHOWING, void updateStyles(); // Actualiza los estilos de texto cuando cambian los colores
HIDING }; void ensureTextFits(); // Verifica y ajusta para que todo el texto sea visible
void triggerAutoResize(); // Inicia redimensionado automático si está habilitado
void updateAnimation(float delta_time); // Actualiza la animación de redimensionado
void updateShowHideAnimation(float delta_time); // Actualiza la animación de mostrar/ocultar
void updateResizeAnimation(float delta_time); // Actualiza la animación de redimensionado
Type type = Type::NONE; // Función de suavizado (ease-out)
bool active = false; [[nodiscard]] static auto easeOut(float t) -> float;
float target_width, target_height; // Tamaño final al mostrar
float elapsed = 0.0F;
void startShow(float to_w, float to_h) { // Métodos para manejo de texto durante animación
type = Type::SHOWING; [[nodiscard]] auto getTruncatedText(const std::string& text, float available_width) const -> std::string;
target_width = to_w; [[nodiscard]] auto getAvailableTextWidth() const -> float;
target_height = to_h; [[nodiscard]] auto shouldShowContent() const -> bool; // Si mostrar el contenido (texto, líneas, etc.)
elapsed = 0.0F;
active = true;
}
void startHide() { [[nodiscard]] auto calculateContentHeight() const -> float;
type = Type::HIDING; [[nodiscard]] auto calculateContentWidth() const -> float;
elapsed = 0.0F; [[nodiscard]] static auto getScreenWidth() -> float;
active = true; [[nodiscard]] static auto getScreenHeight() -> float;
}
void stop() {
type = Type::NONE;
active = false;
elapsed = 0.0F;
}
[[nodiscard]] auto isFinished(float duration) const -> bool {
return elapsed >= duration;
}
[[nodiscard]] auto getProgress(float duration) const -> float {
return std::min(elapsed / duration, 1.0F);
}
} show_hide_animation_;
// Estilos
Text::Style title_style_;
Text::Style text_style_;
// Métodos privados
void calculateAutoSize();
void updatePosition(); // Actualiza la posición según el modo y punto de anclaje
void updateStyles(); // Actualiza los estilos de texto cuando cambian los colores
void ensureTextFits(); // Verifica y ajusta para que todo el texto sea visible
void triggerAutoResize(); // Inicia redimensionado automático si está habilitado
void updateAnimation(float delta_time); // Actualiza la animación de redimensionado
void updateShowHideAnimation(float delta_time); // Actualiza la animación de mostrar/ocultar
void updateResizeAnimation(float delta_time); // Actualiza la animación de redimensionado
// Función de suavizado (ease-out)
[[nodiscard]] static auto easeOut(float t) -> float;
// Métodos para manejo de texto durante animación
[[nodiscard]] auto getTruncatedText(const std::string& text, float available_width) const -> std::string;
[[nodiscard]] auto getAvailableTextWidth() const -> float;
[[nodiscard]] auto shouldShowContent() const -> bool; // Si mostrar el contenido (texto, líneas, etc.)
[[nodiscard]] auto calculateContentHeight() const -> float;
[[nodiscard]] auto calculateContentWidth() const -> float;
[[nodiscard]] static auto getScreenWidth() -> float;
[[nodiscard]] static auto getScreenHeight() -> float;
}; };
+19 -19
View File
@@ -13,32 +13,32 @@ constexpr int BLOCK = 8;
// --- Estructuras --- // --- Estructuras ---
struct Overrides { struct Overrides {
std::string param_file; // Fichero de parametros a utilizar std::string param_file; // Fichero de parametros a utilizar
bool clear_hi_score_table{false}; // Reinicia la tabla de records bool clear_hi_score_table{false}; // Reinicia la tabla de records
Overrides() = default; Overrides() = default;
}; };
struct Circle { struct Circle {
int x, y, r; // Coordenadas y radio int x, y, r; // Coordenadas y radio
Circle() Circle()
: x(0), : x(0),
y(0), y(0),
r(0) {} r(0) {}
Circle(int x_coord, int y_coord, int radius) Circle(int x_coord, int y_coord, int radius)
: x(x_coord), : x(x_coord),
y(y_coord), y(y_coord),
r(radius) {} r(radius) {}
}; };
struct Zone { struct Zone {
SDL_FRect rect; // Rectangulo que define la zona SDL_FRect rect; // Rectangulo que define la zona
float center_x; // Anclaje al 50% del eje X float center_x; // Anclaje al 50% del eje X
float first_quarter_x; // Anclaje al 25% del eje X float first_quarter_x; // Anclaje al 25% del eje X
float third_quarter_x; // Anclaje al 75% del eje X float third_quarter_x; // Anclaje al 75% del eje X
float center_y; // Anclaje al 50% del eje Y float center_y; // Anclaje al 50% del eje Y
float first_quarter_y; // Anclaje al 25% del eje Y float first_quarter_y; // Anclaje al 25% del eje Y
float third_quarter_y; // Anclaje al 75% del eje Y float third_quarter_y; // Anclaje al 75% del eje Y
}; };
// --- Variables --- // --- Variables ---
+40 -40
View File
@@ -8,50 +8,50 @@ class Text;
// --- Clase Writer: pinta texto en pantalla letra a letra --- // --- Clase Writer: pinta texto en pantalla letra a letra ---
class Writer { class Writer {
public: public:
// --- Constructor y destructor --- // --- Constructor y destructor ---
explicit Writer(std::shared_ptr<Text> text) explicit Writer(std::shared_ptr<Text> text)
: text_(std::move(text)) {} : text_(std::move(text)) {}
~Writer() = default; ~Writer() = default;
// --- Métodos principales --- // --- Métodos principales ---
void update(float delta_time); // Actualiza el objeto (delta_time en ms) void update(float delta_time); // Actualiza el objeto (delta_time en ms)
void updateS(float delta_time); // Actualiza el objeto (delta_time en segundos) void updateS(float delta_time); // Actualiza el objeto (delta_time en segundos)
void render() const; // Dibuja el objeto en pantalla void render() const; // Dibuja el objeto en pantalla
// --- Setters --- // --- Setters ---
void setPosX(int value); // Establece la posición X void setPosX(int value); // Establece la posición X
void setPosY(int value); // Establece la posición Y void setPosY(int value); // Establece la posición Y
void setKerning(int value); // Establece el kerning (espaciado entre caracteres) void setKerning(int value); // Establece el kerning (espaciado entre caracteres)
void setCaption(const std::string& text); // Establece el texto a escribir void setCaption(const std::string& text); // Establece el texto a escribir
void setSpeed(int value); // Establece la velocidad de escritura (frames) void setSpeed(int value); // Establece la velocidad de escritura (frames)
void setSpeedS(float value); // Establece la velocidad de escritura (segundos entre caracteres) void setSpeedS(float value); // Establece la velocidad de escritura (segundos entre caracteres)
void setEnabled(bool value); // Habilita o deshabilita el objeto void setEnabled(bool value); // Habilita o deshabilita el objeto
void setFinishedTimerMs(float time_ms); // Establece el temporizador para deshabilitar el objeto (en ms) void setFinishedTimerMs(float time_ms); // Establece el temporizador para deshabilitar el objeto (en ms)
void setFinishedTimerS(float time_s); // Establece el temporizador para deshabilitar el objeto (en segundos) void setFinishedTimerS(float time_s); // Establece el temporizador para deshabilitar el objeto (en segundos)
void center(int x); // Centra la cadena de texto a un punto X void center(int x); // Centra la cadena de texto a un punto X
// --- Getters --- // --- Getters ---
[[nodiscard]] auto isEnabled() const -> bool; // Indica si el objeto está habilitado [[nodiscard]] auto isEnabled() const -> bool; // Indica si el objeto está habilitado
[[nodiscard]] auto hasFinished() const -> bool; // Indica si ya ha terminado [[nodiscard]] auto hasFinished() const -> bool; // Indica si ya ha terminado
private: private:
// --- Objetos y punteros --- // --- Objetos y punteros ---
std::shared_ptr<Text> text_; // Objeto encargado de escribir el texto std::shared_ptr<Text> text_; // Objeto encargado de escribir el texto
// --- Variables de estado --- // --- Variables de estado ---
std::string caption_; // El texto para escribir std::string caption_; // El texto para escribir
int pos_x_ = 0; // Posición en el eje X donde empezar a escribir el texto int pos_x_ = 0; // Posición en el eje X donde empezar a escribir el texto
int pos_y_ = 0; // Posición en el eje Y donde empezar a escribir el texto int pos_y_ = 0; // Posición en el eje Y donde empezar a escribir el texto
int kerning_ = 0; // Kerning del texto, es decir, espaciado entre caracteres int kerning_ = 0; // Kerning del texto, es decir, espaciado entre caracteres
float speed_interval_ = 0.0F; // Intervalo entre caracteres (ms para compatibilidad) float speed_interval_ = 0.0F; // Intervalo entre caracteres (ms para compatibilidad)
float writing_timer_ = 0.0F; // Temporizador de escritura para cada caracter float writing_timer_ = 0.0F; // Temporizador de escritura para cada caracter
int index_ = 0; // Posición del texto que se está escribiendo int index_ = 0; // Posición del texto que se está escribiendo
int length_ = 0; // Longitud de la cadena a escribir int length_ = 0; // Longitud de la cadena a escribir
float enabled_timer_ = 0.0F; // Temporizador para deshabilitar el objeto float enabled_timer_ = 0.0F; // Temporizador para deshabilitar el objeto
float enabled_timer_target_ = 0.0F; // Tiempo objetivo para deshabilitar el objeto float enabled_timer_target_ = 0.0F; // Tiempo objetivo para deshabilitar el objeto
bool completed_ = false; // Indica si se ha escrito todo el texto bool completed_ = false; // Indica si se ha escrito todo el texto
bool enabled_ = false; // Indica si el objeto está habilitado bool enabled_ = false; // Indica si el objeto está habilitado
bool finished_ = false; // Indica si ya ha terminado bool finished_ = false; // Indica si ya ha terminado
}; };