Pasaeta de linters

This commit is contained in:
2025-08-06 13:05:04 +02:00
parent 8ed2dbcd4f
commit 1224af2a9b
40 changed files with 623 additions and 592 deletions

View File

@@ -4,5 +4,5 @@ SOURCEPATH=../source/
for i in "$SOURCEPATH"/*.cpp for i in "$SOURCEPATH"/*.cpp
do do
include-what-you-use -D DEBUG -D VERBOSE -std=c++20 -Wall "$i" include-what-you-use -D _DEBUG -std=c++20 -Wall "$i"
done done

View File

@@ -25,7 +25,7 @@ class Audio {
auto operator=(const Audio &) -> Audio & = delete; // Evitar asignación auto operator=(const Audio &) -> Audio & = delete; // Evitar asignación
// --- Método principal --- // --- Método principal ---
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

View File

@@ -2,10 +2,11 @@
#include <SDL3/SDL.h> // Para Uint8, Uint16, SDL_FRect, Uint32 #include <SDL3/SDL.h> // Para Uint8, Uint16, SDL_FRect, Uint32
#include <array> // Para array #include <array> // Para array
#include <memory> // Para allocator, shared_ptr, unique_ptr #include <memory> // Para allocator, shared_ptr, unique_ptr
#include <string> // Para basic_string, string #include <string> // Para basic_string, string
#include <vector> // Para vector #include <string_view> // Para string_view
#include <vector> // Para vector
#include "animated_sprite.h" // Para AnimatedSprite #include "animated_sprite.h" // Para AnimatedSprite
#include "utils.h" // Para Circle #include "utils.h" // Para Circle
@@ -23,10 +24,10 @@ class Balloon {
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};
const std::array<std::string, 4> BOUNCING_SOUND = { static constexpr std::array<std::string_view, 4> BOUNCING_SOUND = {
"balloon_bounce0.wav", "balloon_bounce1.wav", "balloon_bounce2.wav", "balloon_bounce3.wav"}; "balloon_bounce0.wav", "balloon_bounce1.wav", "balloon_bounce2.wav", "balloon_bounce3.wav"};
const std::array<std::string, 4> POPPING_SOUND = { static constexpr std::array<std::string_view, 4> POPPING_SOUND = {
"balloon_pop0.wav", "balloon_pop1.wav", "balloon_pop2.wav", "balloon_pop3.wav"}; "balloon_pop0.wav", "balloon_pop1.wav", "balloon_pop2.wav", "balloon_pop3.wav"};
static constexpr float VELX_POSITIVE = 0.7F; static constexpr float VELX_POSITIVE = 0.7F;
@@ -111,22 +112,22 @@ class Balloon {
static constexpr int BOUNCE_FRAMES = 10; // Cantidad de elementos del vector de deformación static constexpr int BOUNCE_FRAMES = 10; // Cantidad de elementos del vector de deformación
// Tablas de valores predefinidos para el efecto de rebote // Tablas de valores predefinidos para el efecto de rebote
static constexpr std::array<float, BOUNCE_FRAMES> horizontal_zoom_values = { 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}; 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 = { 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}; 0.90F, 0.95F, 1.00F, 1.05F, 1.10F, 1.05F, 1.00F, 0.98F, 0.95F, 0.98F};
// Estado del efecto // Estado del efecto
bool enabled = false; // Si el efecto está activo bool enabled_ = false; // Si el efecto está activo
Uint8 counter = 0; // Contador para el efecto Uint8 counter_ = 0; // Contador para el efecto
Uint8 speed = 2; // Velocidad del efecto Uint8 speed_ = 2; // Velocidad del efecto
// Valores actuales de transformación // Valores actuales de transformación
float horizontal_zoom = 1.0F; // Zoom en anchura float horizontal_zoom_ = 1.0F; // Zoom en anchura
float verical_zoom = 1.0F; // Zoom en altura float verical_zoom_ = 1.0F; // Zoom en altura
float x_offset = 0.0F; // Desplazamiento X antes de pintar float x_offset_ = 0.0F; // Desplazamiento X antes de pintar
float y_offset = 0.0F; // Desplazamiento Y antes de pintar float y_offset_ = 0.0F; // Desplazamiento Y antes de pintar
public: public:
// Constructor por defecto // Constructor por defecto
@@ -134,18 +135,18 @@ class Balloon {
// Reinicia el efecto a sus valores iniciales // Reinicia el efecto a sus valores iniciales
void reset() { void reset() {
counter = 0; counter_ = 0;
horizontal_zoom = 1.0F; horizontal_zoom_ = 1.0F;
verical_zoom = 1.0F; verical_zoom_ = 1.0F;
x_offset = 0.0F; x_offset_ = 0.0F;
y_offset = 0.0F; y_offset_ = 0.0F;
} }
// Aplica la deformación visual al sprite // Aplica la deformación visual al sprite
void apply(AnimatedSprite* sprite) { void apply(AnimatedSprite* sprite) const {
if (sprite) { if (sprite != nullptr) {
sprite->setHorizontalZoom(horizontal_zoom); sprite->setHorizontalZoom(horizontal_zoom_);
sprite->setVerticalZoom(verical_zoom); sprite->setVerticalZoom(verical_zoom_);
} }
} }
@@ -155,46 +156,46 @@ class Balloon {
if (balloon_size == Size::SMALL) { if (balloon_size == Size::SMALL) {
return; return;
} }
enabled = true; enabled_ = true;
reset(); reset();
apply(sprite); apply(sprite);
} }
// Detiene el efecto de rebote // Detiene el efecto de rebote
void disable(AnimatedSprite* sprite) { void disable(AnimatedSprite* sprite) {
enabled = false; enabled_ = false;
reset(); reset();
apply(sprite); apply(sprite);
} }
// Actualiza el efecto en cada frame // Actualiza el efecto en cada frame
void update(AnimatedSprite* sprite) { void update(AnimatedSprite* sprite) {
if (!enabled) { if (!enabled_) {
return; return;
} }
// Calcula el índice basado en el contador y velocidad // Calcula el índice basado en el contador y velocidad
const int INDEX = counter / speed; const int INDEX = counter_ / speed_;
// Actualiza los valores de zoom desde las tablas predefinidas // Actualiza los valores de zoom desde las tablas predefinidas
horizontal_zoom = horizontal_zoom_values.at(INDEX); horizontal_zoom_ = HORIZONTAL_ZOOM_VALUES.at(INDEX);
verical_zoom = vertical_zoom_values.at(INDEX); verical_zoom_ = VERTICAL_ZOOM_VALUES.at(INDEX);
// Aplica la deformación al sprite // Aplica la deformación al sprite
apply(sprite); apply(sprite);
// Incrementa el contador y verifica si el efecto debe terminar // Incrementa el contador y verifica si el efecto debe terminar
if (++counter / speed >= BOUNCE_FRAMES) { if (++counter_ / speed_ >= BOUNCE_FRAMES) {
disable(sprite); disable(sprite);
} }
} }
// Getters para acceso a los valores actuales // Getters para acceso a los valores actuales
bool isEnabled() const { return enabled; } [[nodiscard]] auto isEnabled() const -> bool { return enabled_; }
float getHorizontalZoom() const { return horizontal_zoom; } [[nodiscard]] auto getHorizontalZoom() const -> float { return horizontal_zoom_; }
float getVerticalZoom() const { return verical_zoom; } [[nodiscard]] auto getVerticalZoom() const -> float { return verical_zoom_; }
float GetXOffset() const { return x_offset; } [[nodiscard]] auto getXOffset() const -> float { return x_offset_; }
float GetYOffset() const { return y_offset; } [[nodiscard]] auto getYOffset() const -> float { return y_offset_; }
}; };
// --- Objetos y punteros --- // --- Objetos y punteros ---

View File

@@ -1,17 +1,18 @@
#include "balloon_formations.h" #include "balloon_formations.h"
#include <algorithm> // Para max #include <algorithm> // Para max, min, copy
#include <array> // Para array #include <array> // Para array
#include <cctype> // Para isdigit #include <cctype> // Para isdigit
#include <cstddef> // Para size_t #include <cstddef> // Para size_t
#include <exception> // Para exception #include <exception> // Para exception
#include <fstream> // Para basic_istream, basic_ifstream, ifstream, istringstream #include <fstream> // Para basic_istream, basic_ifstream, ifstream, istringstream
#include <map> // Para map, operator== #include <iterator> // Para reverse_iterator
#include <map> // Para map, operator==, _Rb_tree_iterator
#include <sstream> // Para basic_istringstream #include <sstream> // Para basic_istringstream
#include <string> // Para allocator, char_traits, operator==, string, operator<=>, basic_string, stoi, getline #include <string> // Para string, char_traits, allocator, operator==, stoi, getline, operator<=>, basic_string
#include "asset.h" // Para Asset #include "asset.h" // Para Asset
#include "balloon.h" // Para Balloon::SIZE, Balloon::Size, Balloon::Type, Balloon::VELX_NEGATIVE, Balloon::VELX_POSITIVE #include "balloon.h" // Para Balloon
#include "param.h" // Para Param, ParamGame, param #include "param.h" // Para Param, ParamGame, param
#include "utils.h" // Para Zone, BLOCK #include "utils.h" // Para Zone, BLOCK
@@ -224,8 +225,7 @@ void BalloonFormations::createFloaterVariants() {
std::vector<SpawnParams> floater_params; std::vector<SpawnParams> floater_params;
floater_params.reserve(formations_.at(k).balloons.size()); floater_params.reserve(formations_.at(k).balloons.size());
for (size_t i = 0; i < formations_.at(k).balloons.size(); i++) { for (const auto& original : formations_.at(k).balloons) {
const auto& original = formations_.at(k).balloons.at(i);
floater_params.emplace_back(original.x, original.y, original.vel_x, Balloon::Type::FLOATER, original.size, original.creation_counter); floater_params.emplace_back(original.x, original.y, original.vel_x, Balloon::Type::FLOATER, original.size, original.creation_counter);
} }

View File

@@ -1,12 +1,14 @@
#pragma once #pragma once
#include <algorithm> // Para copy #include <algorithm> // Para copy, max
#include <cstddef> // Para size_t
#include <map> // Para map #include <map> // Para map
#include <optional> // Para optional #include <optional> // Para optional
#include <string> // Para string #include <string> // Para string
#include <utility> // Para pair
#include <vector> // Para vector #include <vector> // Para vector
#include "balloon.h" // Para Balloon::Size, Balloon::Type #include "balloon.h" // Para Balloon
// --- Clase BalloonFormations --- // --- Clase BalloonFormations ---
class BalloonFormations { class BalloonFormations {

View File

@@ -1,10 +1,9 @@
#define _USE_MATH_DEFINES #define _USE_MATH_DEFINES
#include "color.h" #include "color.h"
#include <stdint.h> // Para uint8_t
#include <cctype> // Para isxdigit #include <cctype> // Para isxdigit
#include <cmath> // Para sinf, fmaxf, fminf, M_PI, fmodf, roundf, fmod #include <cmath> // Para sinf, fmaxf, fminf, M_PI, fmodf, roundf, fmod
#include <cstdint> // Para uint8_t
#include <stdexcept> // Para invalid_argument #include <stdexcept> // Para invalid_argument
#include <string> // Para basic_string, stoi, string #include <string> // Para basic_string, stoi, string

View File

@@ -1,7 +1,7 @@
// IWYU pragma: no_include <bits/std_abs.h> // IWYU pragma: no_include <bits/std_abs.h>
#pragma once #pragma once
#include <SDL3/SDL.h> // Para Uint8 #include <SDL3/SDL.h> // Para Uint8
#include <algorithm> // Para max, min #include <algorithm> // Para max, min
#include <array> // Para array #include <array> // Para array

View File

@@ -1,38 +1,38 @@
#include "define_buttons.h" #include "define_buttons.h"
#include <algorithm> // Para max, __all_of_fn, all_of #include <algorithm> // Para __all_of_fn, all_of
#include <functional> // Para identity #include <functional> // Para identity
#include <memory> // Para allocator, shared_ptr, __shared_ptr_access, operator==
#include "input.h" // Para Input, InputAction #include "input.h" // Para Input
#include "lang.h" // Para getText #include "input_types.h" // Para InputAction
#include "options.h" // Para GamepadOptions, controllers #include "lang.h" // Para getText
#include "param.h" // Para Param, param, ParamGame, ParamTitle #include "options.h" // Para Gamepad
#include "resource.h" // Para Resource #include "param.h" // Para Param, param, ParamGame, ParamTitle
#include "text.h" // Para Text #include "resource.h" // Para Resource
#include "text.h" // Para Text
// Constructor // Constructor
DefineButtons::DefineButtons() DefineButtons::DefineButtons()
: input_(Input::get()), : input_(Input::get()),
enabled_(false),
finished_(false),
x_(param.game.width / 2), x_(param.game.width / 2),
y_(param.title.press_start_position), y_(param.title.press_start_position) {
index_button_(0) {
clearButtons(); clearButtons();
auto gamepads = input_->getGamepads(); auto gamepads = input_->getGamepads();
for (auto gamepad : gamepads) { for (auto gamepad : gamepads) {
controller_names_.emplace_back(input_->getControllerName(gamepad)); controller_names_.emplace_back(Input::getControllerName(gamepad));
} }
} }
// Dibuja el objeto en pantalla // Dibuja el objeto en pantalla
void DefineButtons::render() { void DefineButtons::render() {
static auto text = Resource::get()->getText("8bithud"); static auto text_ = Resource::get()->getText("8bithud");
if (enabled_) { if (enabled_) {
text->writeCentered(x_, y_ - 10, Lang::getText("[DEFINE_BUTTONS] PLAYER") + std::to_string(static_cast<int>(options_gamepad_->player_id))); text_->writeCentered(x_, y_ - 10, Lang::getText("[DEFINE_BUTTONS] PLAYER") + std::to_string(static_cast<int>(options_gamepad_->player_id)));
text->writeCentered(x_, y_, options_gamepad_->name); text_->writeCentered(x_, y_, options_gamepad_->name);
text->writeCentered(x_, y_ + 10, buttons_.at(index_button_).label); text_->writeCentered(x_, y_ + 10, buttons_.at(index_button_).label);
} }
} }
@@ -55,12 +55,12 @@ void DefineButtons::doControllerButtonDown(const SDL_GamepadButtonEvent &event)
// Asigna los botones definidos al input_ // Asigna los botones definidos al input_
void DefineButtons::bindButtons(Options::Gamepad *options_gamepad) { void DefineButtons::bindButtons(Options::Gamepad *options_gamepad) {
for (const auto &button : buttons_) { for (const auto &button : buttons_) {
input_->bindGameControllerButton(options_gamepad->instance, button.action, button.button); Input::bindGameControllerButton(options_gamepad->instance, button.action, button.button);
} }
// Remapea los inputs a inputs // Remapea los inputs a inputs
input_->bindGameControllerButton(options_gamepad->instance, Input::Action::SM_SELECT, Input::Action::FIRE_LEFT); Input::bindGameControllerButton(options_gamepad->instance, Input::Action::SM_SELECT, Input::Action::FIRE_LEFT);
input_->bindGameControllerButton(options_gamepad->instance, Input::Action::SM_BACK, Input::Action::FIRE_CENTER); Input::bindGameControllerButton(options_gamepad->instance, Input::Action::SM_BACK, Input::Action::FIRE_CENTER);
} }
// Comprueba los eventos // Comprueba los eventos
@@ -121,9 +121,9 @@ void DefineButtons::clearButtons() {
// Comprueba si ha finalizado // Comprueba si ha finalizado
void DefineButtons::checkEnd() { void DefineButtons::checkEnd() {
if (finished_) { if (finished_) {
bindButtons(options_gamepad_); // Asigna los botones definidos al input_ bindButtons(options_gamepad_); // Asigna los botones definidos al input_
input_->saveGamepadConfigFromGamepad(options_gamepad_->instance); // Guarda los cambios input_->saveGamepadConfigFromGamepad(options_gamepad_->instance); // Guarda los cambios
input_->resetInputStates(); // Reinicia los estados de las pulsaciones de los botones input_->resetInputStates(); // Reinicia los estados de las pulsaciones de los botones
enabled_ = false; // Deshabilita enabled_ = false; // Deshabilita
} }
} }

View File

@@ -3,13 +3,15 @@
#include <SDL3/SDL.h> // Para SDL_GamepadButton, SDL_Event, SDL_GamepadButtonEvent #include <SDL3/SDL.h> // Para SDL_GamepadButton, SDL_Event, SDL_GamepadButtonEvent
#include <cstddef> // Para size_t #include <cstddef> // Para size_t
#include <memory> // Para shared_ptr #include <string> // Para string
#include <string> // Para basic_string, string #include <utility> // Para move
#include <utility> #include <vector> // Para vector
#include <vector> // Para vector
#include "input.h" #include "input.h" // Para Input
#include "options.h"
namespace Options {
struct Gamepad;
} // namespace Options
// Clase DefineButtons // Clase DefineButtons
class DefineButtons { class DefineButtons {

View File

@@ -1,33 +1,32 @@
// IWYU pragma: no_include <bits/chrono.h> // IWYU pragma: no_include <bits/chrono.h>
#include "director.h" #include "director.h"
#include <SDL3/SDL.h> // Para SDL_Scancode, SDL_GamepadButton, SDL_LogCategory, SDL_LogInfo, SDL_SetLogPriority, SDL_LogPriority, SDL_Quit #include <SDL3/SDL.h> // Para SDL_LogCategory, SDL_LogInfo, SDL_SetLogPriority, SDL_LogPriority, SDL_Quit
#include <sys/stat.h> // Para mkdir, stat, S_IRWXU #include <sys/stat.h> // Para mkdir, stat, S_IRWXU
#include <unistd.h> // Para getuid #include <unistd.h> // Para getuid
#include <algorithm> // Para min
#include <cerrno> // Para errno, EEXIST, EACCES, ENAMETOOLONG #include <cerrno> // Para errno, EEXIST, EACCES, ENAMETOOLONG
#include <cstdio> // Para printf, perror #include <cstdio> // Para printf, perror
#include <cstdlib> // Para exit, EXIT_FAILURE, size_t, srand, rand, system #include <cstdlib> // Para exit, EXIT_FAILURE, srand, rand, system
#include <ctime> // Para time #include <ctime> // Para time
#include <memory> // Para make_unique, unique_ptr #include <memory> // Para make_unique, unique_ptr
#include <span> // Para span #include <span> // Para span
#include <stdexcept> // Para runtime_error #include <stdexcept> // Para runtime_error
#include <string> // Para operator+, allocator, char_traits, operator==, string, basic_string #include <string> // Para operator+, allocator, char_traits, operator==, string, basic_string
#include <vector> // Para vector
#include "asset.h" // Para Asset, AssetType #include "asset.h" // Para Asset, AssetType
#include "audio.h" // Para Audio #include "audio.h" // Para Audio
#include "input.h" // Para Input, InputAction #include "input.h" // Para Input
#include "lang.h" // Para setLanguage #include "lang.h" // Para setLanguage
#include "manage_hiscore_table.h" // Para ManageHiScoreTable #include "manage_hiscore_table.h" // Para ManageHiScoreTable
#include "options.h" // Para GamepadOptions, controllers, loadFromFile, saveToFile, SettingsOptions, settings, getPlayerWhoUsesKeyboard, setKeyboardToPlayer #include "options.h" // Para loadFromFile, saveToFile, Settings, settings, setConfigFile, setControllersFile
#include "param.h" // Para loadParamsFromFile #include "param.h" // Para loadParamsFromFile
#include "player.h" // Para Player
#include "resource.h" // Para Resource #include "resource.h" // Para Resource
#include "screen.h" // Para Screen #include "screen.h" // Para Screen
#include "section.hpp" // Para Name, Options, name, options, AttractMode, attract_mode #include "section.hpp" // Para Name, Options, name, options, AttractMode, attract_mode
#include "sections/credits.h" // Para Credits #include "sections/credits.h" // Para Credits
#include "sections/game.h" // Para Game, GAME_MODE_DEMO_OFF, GAME_MODE_DEMO_ON #include "sections/game.h" // Para Game
#include "sections/hiscore_table.h" // Para HiScoreTable #include "sections/hiscore_table.h" // Para HiScoreTable
#include "sections/instructions.h" // Para Instructions #include "sections/instructions.h" // Para Instructions
#include "sections/intro.h" // Para Intro #include "sections/intro.h" // Para Intro
@@ -82,8 +81,8 @@ Director::~Director() {
// Inicializa todo // Inicializa todo
void Director::init() { void Director::init() {
// Configuración inicial de parametros // Configuración inicial de parametros
Asset::init(executable_path_); // Inicializa el sistema de gestión de archivos Asset::init(executable_path_); // Inicializa el sistema de gestión de archivos
setFileList(); // Crea el índice de archivos setFileList(); // Crea el índice de archivos
Input::init( Input::init(
Asset::get()->get("gamecontrollerdb.txt"), Asset::get()->get("gamecontrollerdb.txt"),
@@ -100,7 +99,7 @@ void Director::init() {
Screen::init(); // Inicializa la pantalla y el sistema de renderizado Screen::init(); // Inicializa la pantalla y el sistema de renderizado
Audio::init(); // Activa el sistema de audio Audio::init(); // Activa el sistema de audio
Resource::init(); // Inicializa el sistema de gestión de recursos Resource::init(); // Inicializa el sistema de gestión de recursos
//bindInputs(); // Asigna los controles a la entrada del sistema // bindInputs(); // Asigna los controles a la entrada del sistema
ServiceMenu::init(); // Inicializa el menú de servicio ServiceMenu::init(); // Inicializa el menú de servicio
Notifier::init(std::string(), Resource::get()->getText("8bithud")); // Inicialización del sistema de notificaciones Notifier::init(std::string(), Resource::get()->getText("8bithud")); // Inicialización del sistema de notificaciones

View File

@@ -1,8 +1,13 @@
#ifndef JA_USESDLMIXER #ifndef JA_USESDLMIXER
#include "jail_audio.h" #include "jail_audio.h"
#include "stb_vorbis.h"
#include <SDL3/SDL.h> #include <SDL3/SDL.h> // Para SDL_AudioFormat, SDL_BindAudioStream, SDL_SetAudioStreamGain, SDL_PutAudioStreamData, SDL_DestroyAudioStream, SDL_GetAudioStreamAvailable, Uint8, SDL_CreateAudioStream, SDL_UnbindAudioStream, Uint32, SDL_CloseAudioDevice, SDL_GetTicks, SDL_Log, SDL_free, SDL_AudioSpec, SDL_AudioStream, SDL_IOFromMem, SDL_LoadWAV, SDL_LoadWAV_IO, SDL_OpenAudioDevice, SDL_clamp, SDL_malloc, SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, SDL_AudioDeviceID, SDL_memcpy
#include <stdio.h> #include <stdint.h> // Para uint32_t, uint8_t
#include <stdio.h> // Para NULL, fseek, printf, fclose, fopen, fread, ftell, FILE, SEEK_END, SEEK_SET
#include <stdlib.h> // Para free, malloc
#include <string.h> // Para strcpy, strlen
#include "stb_vorbis.h" // Para stb_vorbis_decode_memory
#define JA_MAX_SIMULTANEOUS_CHANNELS 20 #define JA_MAX_SIMULTANEOUS_CHANNELS 20
#define JA_MAX_GROUPS 2 #define JA_MAX_GROUPS 2

View File

@@ -1,10 +1,11 @@
#pragma once #pragma once
#include <external/json.hpp>
#include <fstream> #include <fstream>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <utility>
#include <vector> #include <vector>
#include "external/json.hpp"
#include "input_types.h" // Solo incluimos los tipos compartidos #include "input_types.h" // Solo incluimos los tipos compartidos
struct GamepadConfig { struct GamepadConfig {
@@ -12,9 +13,9 @@ struct GamepadConfig {
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(const std::string& name, const std::string& path) GamepadConfig(std::string name, std::string path)
: name(name), : name(std::move(name)),
path(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},
@@ -33,28 +34,28 @@ using GamepadConfigs = std::vector<GamepadConfig>;
class GamepadConfigManager { class GamepadConfigManager {
public: public:
// Escribir vector de GamepadConfig a archivo JSON // Escribir vector de GamepadConfig a archivo JSON
static bool writeToJson(const GamepadConfigs& configs, const std::string& filename) { static auto writeToJson(const GamepadConfigs& configs, const std::string& filename) -> bool {
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 gamepadJson; nlohmann::json gamepad_json;
gamepadJson["name"] = config.name; gamepad_json["name"] = config.name;
gamepadJson["path"] = config.path; gamepad_json["path"] = config.path;
gamepadJson["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 actionIt = actionToString.find(action); auto action_it = ACTION_TO_STRING.find(action);
auto buttonIt = buttonToString.find(button); auto button_it = BUTTON_TO_STRING.find(button);
if (actionIt != actionToString.end() && buttonIt != buttonToString.end()) { if (action_it != ACTION_TO_STRING.end() && button_it != BUTTON_TO_STRING.end()) {
gamepadJson["bindings"][actionIt->second] = buttonIt->second; gamepad_json["bindings"][action_it->second] = button_it->second;
} }
} }
j["gamepads"].push_back(gamepadJson); j["gamepads"].push_back(gamepad_json);
} }
// Escribir al archivo // Escribir al archivo
@@ -74,7 +75,7 @@ class GamepadConfigManager {
} }
// Leer vector de GamepadConfig desde archivo JSON // Leer vector de GamepadConfig desde archivo JSON
static bool readFromJson(GamepadConfigs& configs, const std::string& filename) { static auto readFromJson(GamepadConfigs& configs, const std::string& filename) -> bool {
try { try {
std::ifstream file(filename); std::ifstream file(filename);
if (!file.is_open()) { if (!file.is_open()) {
@@ -91,25 +92,25 @@ class GamepadConfigManager {
return false; return false;
} }
for (const auto& gamepadJson : j["gamepads"]) { for (const auto& gamepad_json : j["gamepads"]) {
if (!gamepadJson.contains("name") || !gamepadJson.contains("bindings")) { if (!gamepad_json.contains("name") || !gamepad_json.contains("bindings")) {
continue; // Saltar configuraciones malformadas continue; // Saltar configuraciones malformadas
} }
// Leer el campo path si existe, si no dejarlo vacío // Leer el campo path si existe, si no dejarlo vacío
std::string path = gamepadJson.contains("path") ? gamepadJson["path"].get<std::string>() : ""; std::string path = gamepad_json.contains("path") ? gamepad_json["path"].get<std::string>() : "";
GamepadConfig config(gamepadJson["name"], path); GamepadConfig config(gamepad_json["name"], path);
// Limpiar bindings por defecto para cargar los del archivo // Limpiar bindings por defecto para cargar los del archivo
config.bindings.clear(); config.bindings.clear();
// Cargar bindings desde JSON // Cargar bindings desde JSON
for (const auto& [actionStr, buttonStr] : gamepadJson["bindings"].items()) { for (const auto& [actionStr, buttonStr] : gamepad_json["bindings"].items()) {
auto actionIt = stringToAction.find(actionStr); auto action_it = STRING_TO_ACTION.find(actionStr);
auto buttonIt = stringToButton.find(buttonStr); auto button_it = STRING_TO_BUTTON.find(buttonStr);
if (actionIt != stringToAction.end() && buttonIt != stringToButton.end()) { if (action_it != STRING_TO_ACTION.end() && button_it != STRING_TO_BUTTON.end()) {
config.bindings[actionIt->second] = buttonIt->second; config.bindings[action_it->second] = button_it->second;
} }
} }
@@ -125,7 +126,7 @@ class GamepadConfigManager {
} }
// Método auxiliar para verificar si un archivo existe // Método auxiliar para verificar si un archivo existe
static bool fileExists(const std::string& filename) { static auto fileExists(const std::string& filename) -> bool {
std::ifstream file(filename); std::ifstream file(filename);
return file.good(); return file.good();
} }

View File

@@ -2,10 +2,10 @@
#include <SDL3/SDL.h> // Para SDL_LogInfo, SDL_LogCategory #include <SDL3/SDL.h> // Para SDL_LogInfo, SDL_LogCategory
#include "input.h"
#include "mouse.h" // Para handleEvent #include "mouse.h" // Para handleEvent
#include "screen.h" #include "screen.h"
#include "section.hpp" // Para Name, Options, name, options #include "section.hpp" // Para Name, Options, name, options
#include "input.h"
namespace GlobalEvents { namespace GlobalEvents {
// Comprueba los eventos que se pueden producir en cualquier sección del juego // Comprueba los eventos que se pueden producir en cualquier sección del juego
@@ -31,7 +31,7 @@ void check(const SDL_Event &event) {
Mouse::handleEvent(event); Mouse::handleEvent(event);
static auto input = Input::get(); static auto *input_ = Input::get();
input->handleEvent(event); input_->handleEvent(event);
} }
} // namespace GlobalEvents } // namespace GlobalEvents

View File

@@ -1,13 +1,15 @@
#include "global_inputs.h" #include "global_inputs.h"
#include <memory> // Para shared_ptr
#include <string> // Para operator+, allocator, char_traits, to_string, string #include <string> // Para operator+, allocator, char_traits, to_string, string
#include <vector> // Para vector #include <vector> // Para vector
#include "asset.h" // Para Asset #include "asset.h" // Para Asset
#include "audio.h" // Para Audio #include "audio.h" // Para Audio
#include "input.h" // Para Input, Input::DO_NOT_ALLOW_REPEAT, InputAction, InputDevice #include "input.h" // Para Input
#include "input_types.h" // Para InputAction
#include "lang.h" // Para getText, Code, getNextLangCode, loadFromFile #include "lang.h" // Para getText, Code, getNextLangCode, loadFromFile
#include "options.h" // Para SettingsOptions, settings, VideoOptions, WindowOptions, video, window, AudioOptions, audio #include "options.h" // Para Settings, settings, Video, Window, video, window, Audio, audio
#include "screen.h" // Para Screen #include "screen.h" // Para Screen
#include "section.hpp" // Para Name, name, Options, options, AttractMode, attract_mode #include "section.hpp" // Para Name, name, Options, options, AttractMode, attract_mode
#include "ui/notifier.h" // Para Notifier #include "ui/notifier.h" // Para Notifier
@@ -228,7 +230,7 @@ auto checkServiceInputs() -> bool {
// Mandos // Mandos
{ {
auto gamepads = Input::get()->getGamepads(); auto gamepads = Input::get()->getGamepads();
for (auto gamepad : gamepads) { for (auto gamepad : gamepads) {
// Arriba // Arriba
if (Input::get()->checkAction(Input::Action::UP, Input::DO_NOT_ALLOW_REPEAT, Input::DO_NOT_CHECK_KEYBOARD, gamepad)) { if (Input::get()->checkAction(Input::Action::UP, Input::DO_NOT_ALLOW_REPEAT, Input::DO_NOT_CHECK_KEYBOARD, gamepad)) {

View File

@@ -11,10 +11,10 @@
struct Hit { struct Hit {
private: private:
// Indica si el Hit está activo o no // Indica si el Hit está activo o no
bool enabled{false}; bool enabled_{false};
// Sprite asociado al Hit, gestionado con un puntero único // Sprite asociado al Hit, gestionado con un puntero único
std::unique_ptr<Sprite> sprite; std::unique_ptr<Sprite> sprite_;
public: public:
// Elimina el constructor por defecto para obligar a pasar una textura // Elimina el constructor por defecto para obligar a pasar una textura
@@ -23,22 +23,22 @@ struct Hit {
// Constructor que obliga a pasar una textura compartida para crear el Sprite // Constructor que obliga a pasar una textura compartida para crear el Sprite
// Esto evita que se pueda crear un Hit sin recursos gráficos válidos // Esto evita que se pueda crear un Hit sin recursos gráficos válidos
explicit Hit(std::shared_ptr<Texture> texture) explicit Hit(std::shared_ptr<Texture> texture)
: sprite(std::make_unique<Sprite>(texture)) {} : sprite_(std::make_unique<Sprite>(texture)) {}
// Establece la posición del Sprite en el espacio // Establece la posición del Sprite en el espacio
void setPos(SDL_FPoint position) { void setPos(SDL_FPoint position) {
SDL_FPoint centered_position = {position.x - (sprite->getWidth() / 2), position.y - (sprite->getHeight() / 2)}; SDL_FPoint centered_position = {position.x - (sprite_->getWidth() / 2), position.y - (sprite_->getHeight() / 2)};
sprite->setPosition(centered_position); sprite_->setPosition(centered_position);
} }
// Activa o desactiva el Hit // Activa o desactiva el Hit
void enable(bool value) { void enable(bool value) {
enabled = value; enabled_ = value;
} }
// Consulta si el Hit está activo // Consulta si el Hit está activo
bool isEnabled() const { [[nodiscard]] auto isEnabled() const -> bool {
return enabled; return enabled_;
} }
// Crea un "Hit" en la posición especificada // Crea un "Hit" en la posición especificada
@@ -49,13 +49,13 @@ struct Hit {
// Dibuja el hit // Dibuja el hit
void render() { void render() {
if (enabled) { if (enabled_) {
sprite->render(); sprite_->render();
} }
} }
// Deshabilita el hit // Deshabilita el hit
void disable() { void disable() {
enabled = false; enabled_ = false;
} }
}; };

View File

@@ -1,13 +1,12 @@
#include "input.h" #include "input.h"
#include <SDL3/SDL.h> // Para SDL_LogInfo, SDL_LogCategory, SDL_GetGamepa... #include <SDL3/SDL.h> // Para SDL_GamepadButton, SDL_GetGamepadAxis, SDL_GetError, SDL_GamepadAxis, SDL_JoystickID, SDL_AddGamepadMappingsFromFile, SDL_Event, SDL_EventType, SDL_GetGamepadButton, SDL_GetKeyboardState, SDL_INIT_GAMEPAD, SDL_InitSubSystem, SDL_LogCategory, SDL_LogError, SDL_LogInfo, SDL_OpenGamepad, SDL_PollEvent, SDL_WasInit, SDL_Gamepad, SDL_Scancode
#include <algorithm> // Para find #include <algorithm> // Para find_if, remove_if
#include <cstddef> // Para size_t #include <iostream> // Para basic_ostream, operator<<, endl, cout, cerr
#include <iterator> // Para distance #include <memory> // Para shared_ptr, __shared_ptr_access, allocator, operator==, make_shared
#include <memory> // Para std::unique_ptr #include <unordered_map> // Para unordered_map, operator==, _Node_iterator_base, _Node_iterator, _Node_const_iterator
#include <unordered_map> // Para unordered_map, _Node_const_iterator, operat... #include <utility> // Para pair, move
#include <utility> // Para pair
// Singleton // Singleton
Input *Input::instance = nullptr; Input *Input::instance = nullptr;
@@ -29,9 +28,6 @@ Input::Input(std::string game_controller_db_path, std::string gamepad_configs_fi
gamepad_configs_file_(std::move(gamepad_configs_file)) { gamepad_configs_file_(std::move(gamepad_configs_file)) {
// Inicializa el subsistema SDL_INIT_GAMEPAD // Inicializa el subsistema SDL_INIT_GAMEPAD
initSDLGamePad(); initSDLGamePad();
// Listado de los inputs para jugar que utilizan botones, ni palancas ni crucetas
button_inputs_ = {Action::FIRE_LEFT, Action::FIRE_CENTER, Action::FIRE_RIGHT, Action::START};
} }
// Asigna inputs a teclas // Asigna inputs a teclas
@@ -47,13 +43,13 @@ void Input::bindGameControllerButton(std::shared_ptr<Gamepad> gamepad, Action ac
} }
// Asigna inputs a botones del mando // Asigna inputs a botones del mando
void Input::bindGameControllerButton(std::shared_ptr<Gamepad> gamepad, Action input_target, Action input_source) { void Input::bindGameControllerButton(std::shared_ptr<Gamepad> gamepad, Action action_target, Action action_source) {
if (gamepad != nullptr) { if (gamepad != nullptr) {
gamepad->bindings[input_target].button = gamepad->bindings[input_source].button; gamepad->bindings[action_target].button = gamepad->bindings[action_source].button;
} }
} }
// Comprueba si un input esta activo // Comprueba si alguna acción está activa
auto Input::checkAction(Action action, bool repeat, bool check_keyboard, std::shared_ptr<Gamepad> gamepad) -> bool { auto Input::checkAction(Action action, bool repeat, bool check_keyboard, std::shared_ptr<Gamepad> gamepad) -> bool {
bool success_keyboard = false; bool success_keyboard = false;
bool success_controller = false; bool success_controller = false;
@@ -81,7 +77,7 @@ auto Input::checkAction(Action action, bool repeat, bool check_keyboard, std::sh
return (success_keyboard || success_controller); return (success_keyboard || success_controller);
} }
// Comprueba si hay almenos un input activo // Comprueba si hay almenos una acción activa
auto Input::checkAnyInput(bool check_keyboard, std::shared_ptr<Gamepad> gamepad) -> bool { auto Input::checkAnyInput(bool check_keyboard, std::shared_ptr<Gamepad> gamepad) -> bool {
// Obtenemos el número total de acciones posibles para iterar sobre ellas. // Obtenemos el número total de acciones posibles para iterar sobre ellas.
@@ -115,7 +111,7 @@ auto Input::checkAnyInput(bool check_keyboard, std::shared_ptr<Gamepad> gamepad)
// Comprueba si hay algún botón pulsado // Comprueba si hay algún botón pulsado
auto Input::checkAnyButton(bool repeat) -> bool { auto Input::checkAnyButton(bool repeat) -> bool {
// Solo comprueba los botones definidos previamente // Solo comprueba los botones definidos previamente
for (auto bi : button_inputs_) { for (auto bi : BUTTON_INPUTS) {
// Comprueba el teclado // Comprueba el teclado
if (checkAction(bi, repeat, CHECK_KEYBOARD)) { if (checkAction(bi, repeat, CHECK_KEYBOARD)) {
return true; return true;
@@ -136,7 +132,7 @@ auto Input::checkAnyButton(bool repeat) -> bool {
auto Input::gameControllerFound() const -> bool { return !gamepads_.empty(); } auto Input::gameControllerFound() const -> bool { return !gamepads_.empty(); }
// Obten el nombre de un mando de juego // Obten el nombre de un mando de juego
auto Input::getControllerName(std::shared_ptr<Gamepad> gamepad) const -> std::string { return gamepad == nullptr ? std::string() : gamepad->name; } auto Input::getControllerName(std::shared_ptr<Gamepad> gamepad) -> std::string { return gamepad == nullptr ? std::string() : gamepad->name; }
// Obtiene la lista de nombres de mandos // Obtiene la lista de nombres de mandos
auto Input::getControllerNames() const -> std::vector<std::string> { auto Input::getControllerNames() const -> std::vector<std::string> {
@@ -151,7 +147,7 @@ auto Input::getControllerNames() const -> std::vector<std::string> {
auto Input::getNumGamepads() const -> int { return gamepads_.size(); } auto Input::getNumGamepads() const -> int { return gamepads_.size(); }
// Obtiene el gamepad a partir de un event.id // Obtiene el gamepad a partir de un event.id
std::shared_ptr<Input::Gamepad> Input::getGamepad(SDL_JoystickID id) const { auto Input::getGamepad(SDL_JoystickID id) const -> std::shared_ptr<Input::Gamepad> {
for (const auto &gamepad : gamepads_) { for (const auto &gamepad : gamepads_) {
if (gamepad->instance_id == id) { if (gamepad->instance_id == id) {
return gamepad; return gamepad;
@@ -160,7 +156,7 @@ std::shared_ptr<Input::Gamepad> Input::getGamepad(SDL_JoystickID id) const {
return nullptr; return nullptr;
} }
std::shared_ptr<Input::Gamepad> Input::getGamepadByName(const std::string &name) const { auto Input::getGamepadByName(const std::string &name) const -> std::shared_ptr<Input::Gamepad> {
for (const auto &gamepad : gamepads_) { for (const auto &gamepad : gamepads_) {
if (gamepad && gamepad->name == name) { if (gamepad && gamepad->name == name) {
return gamepad; return gamepad;
@@ -169,14 +165,14 @@ std::shared_ptr<Input::Gamepad> Input::getGamepadByName(const std::string &name)
return nullptr; return nullptr;
} }
// Obtiene el SDL_GamepadButton asignado a un input // Obtiene el SDL_GamepadButton asignado a un action
auto Input::getControllerBinding(std::shared_ptr<Gamepad> gamepad, Action input) const -> SDL_GamepadButton { auto Input::getControllerBinding(std::shared_ptr<Gamepad> gamepad, Action action) -> SDL_GamepadButton {
return gamepad->bindings[input].button; return gamepad->bindings[action].button;
} }
// Convierte un InputAction a std::string // Convierte un InputAction a std::string
auto Input::inputToString(Action input) -> std::string { auto Input::inputToString(Action action) -> std::string {
switch (input) { switch (action) {
case Action::FIRE_LEFT: case Action::FIRE_LEFT:
return "input_fire_left"; return "input_fire_left";
case Action::FIRE_CENTER: case Action::FIRE_CENTER:
@@ -206,11 +202,11 @@ auto Input::stringToInput(const std::string &name) -> Action {
} }
// Comprueba el eje del mando // Comprueba el eje del mando
auto Input::checkAxisInput(Action input, std::shared_ptr<Gamepad> gamepad, bool repeat) -> bool { auto Input::checkAxisInput(Action action, std::shared_ptr<Gamepad> gamepad, bool repeat) -> bool {
// Umbral para considerar el eje como activo // Umbral para considerar el eje como activo
bool axis_active_now = false; bool axis_active_now = false;
switch (input) { switch (action) {
case Action::LEFT: case Action::LEFT:
axis_active_now = SDL_GetGamepadAxis(gamepad->pad, SDL_GAMEPAD_AXIS_LEFTX) < -AXIS_THRESHOLD; axis_active_now = SDL_GetGamepadAxis(gamepad->pad, SDL_GAMEPAD_AXIS_LEFTX) < -AXIS_THRESHOLD;
break; break;
@@ -228,7 +224,7 @@ auto Input::checkAxisInput(Action input, std::shared_ptr<Gamepad> gamepad, bool
} }
// Referencia al binding correspondiente // Referencia al binding correspondiente
auto &binding = gamepad->bindings[input]; auto &binding = gamepad->bindings[action];
if (repeat) { if (repeat) {
// Si se permite repetir, simplemente devolvemos el estado actual // Si se permite repetir, simplemente devolvemos el estado actual
@@ -315,17 +311,17 @@ void Input::update() {
void Input::handleEvent(const SDL_Event &event) { void Input::handleEvent(const SDL_Event &event) {
switch (event.type) { switch (event.type) {
case SDL_EVENT_GAMEPAD_ADDED: case SDL_EVENT_GAMEPAD_ADDED:
add_gamepad(event.gdevice.which); addGamepad(event.gdevice.which);
break; break;
case SDL_EVENT_GAMEPAD_REMOVED: case SDL_EVENT_GAMEPAD_REMOVED:
remove_gamepad(event.gdevice.which); removeGamepad(event.gdevice.which);
break; break;
} }
} }
void Input::add_gamepad(int device_index) { void Input::addGamepad(int device_index) {
SDL_Gamepad *pad = SDL_OpenGamepad(device_index); SDL_Gamepad *pad = SDL_OpenGamepad(device_index);
if (!pad) { if (pad == nullptr) {
std::cerr << "Error al abrir el gamepad: " << SDL_GetError() << std::endl; std::cerr << "Error al abrir el gamepad: " << SDL_GetError() << std::endl;
return; return;
} }
@@ -337,7 +333,7 @@ void Input::add_gamepad(int device_index) {
gamepads_.push_back(std::move(gamepad)); gamepads_.push_back(std::move(gamepad));
} }
void Input::remove_gamepad(SDL_JoystickID id) { void Input::removeGamepad(SDL_JoystickID id) {
auto it = std::remove_if(gamepads_.begin(), gamepads_.end(), [id](const std::shared_ptr<Gamepad> &gamepad) { auto it = std::remove_if(gamepads_.begin(), gamepads_.end(), [id](const std::shared_ptr<Gamepad> &gamepad) {
return gamepad->instance_id == id; return gamepad->instance_id == id;
}); });
@@ -358,7 +354,7 @@ void Input::printConnectedGamepads() const {
std::cout << "Gamepads conectados:\n"; std::cout << "Gamepads conectados:\n";
for (const auto &gamepad : gamepads_) { for (const auto &gamepad : gamepads_) {
std::string name = gamepad->name == "" ? "Desconocido" : gamepad->name; std::string name = gamepad->name.empty() ? "Desconocido" : gamepad->name;
std::cout << " - ID: " << gamepad->instance_id std::cout << " - ID: " << gamepad->instance_id
<< ", Nombre: " << name << ")" << std::endl; << ", Nombre: " << name << ")" << std::endl;
} }
@@ -375,20 +371,19 @@ void Input::saveGamepadConfigs() {
} }
void Input::applyGamepadConfig(std::shared_ptr<Gamepad> gamepad) { void Input::applyGamepadConfig(std::shared_ptr<Gamepad> gamepad) {
if (!gamepad || gamepad->path.empty()) { // No podemos aplicar config sin una ruta if (!gamepad || gamepad->path.empty()) { // No podemos aplicar config sin una ruta
return; return;
} }
// --- Buscar configuración por RUTA (path) --- // --- Buscar configuración por RUTA (path) ---
auto configIt = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(), auto config_it = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(), [&gamepad](const GamepadConfig &config) {
[&gamepad](const GamepadConfig &config) { return config.path == gamepad->path;
return config.path == gamepad->path;
}); });
if (configIt != gamepad_configs_.end()) { if (config_it != gamepad_configs_.end()) {
// Se encontró una configuración específica para este puerto/dispositivo. La aplicamos. // Se encontró una configuración específica para este puerto/dispositivo. La aplicamos.
std::cout << "Applying custom config for gamepad at path: " << gamepad->path << std::endl; std::cout << "Applying custom config for gamepad at path: " << gamepad->path << std::endl;
for (const auto &[action, button] : configIt->bindings) { for (const auto &[action, button] : config_it->bindings) {
if (gamepad->bindings.find(action) != gamepad->bindings.end()) { if (gamepad->bindings.find(action) != gamepad->bindings.end()) {
gamepad->bindings[action].button = button; gamepad->bindings[action].button = button;
} }
@@ -398,31 +393,30 @@ void Input::applyGamepadConfig(std::shared_ptr<Gamepad> gamepad) {
} }
void Input::saveGamepadConfigFromGamepad(std::shared_ptr<Gamepad> gamepad) { void Input::saveGamepadConfigFromGamepad(std::shared_ptr<Gamepad> gamepad) {
if (!gamepad || gamepad->path.empty()) { // No podemos guardar una config sin una ruta if (!gamepad || gamepad->path.empty()) { // No podemos guardar una config sin una ruta
return; return;
} }
// --- CAMBIO CLAVE: Buscar si ya existe una configuración por RUTA (path) --- // --- CAMBIO CLAVE: Buscar si ya existe una configuración por RUTA (path) ---
auto configIt = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(), auto config_it = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(), [&gamepad](const GamepadConfig &config) {
[&gamepad](const GamepadConfig &config) { return config.path == gamepad->path;
return config.path == gamepad->path;
}); });
// Crear nueva configuración desde el gamepad, incluyendo nombre y ruta // Crear nueva configuración desde el gamepad, incluyendo nombre y ruta
GamepadConfig newConfig(gamepad->name, gamepad->path); // <--- CAMBIO: Pasamos ambos GamepadConfig new_config(gamepad->name, gamepad->path); // <--- CAMBIO: Pasamos ambos
newConfig.bindings.clear(); new_config.bindings.clear();
// Copiar todos los bindings actuales del gamepad // Copiar todos los bindings actuales del gamepad
for (const auto &[action, buttonState] : gamepad->bindings) { for (const auto &[action, buttonState] : gamepad->bindings) {
newConfig.bindings[action] = buttonState.button; new_config.bindings[action] = buttonState.button;
} }
if (configIt != gamepad_configs_.end()) { if (config_it != gamepad_configs_.end()) {
// Sobreescribir configuración existente para esta ruta // Sobreescribir configuración existente para esta ruta
*configIt = newConfig; *config_it = new_config;
} else { } else {
// Añadir nueva configuración // Añadir nueva configuración
gamepad_configs_.push_back(newConfig); gamepad_configs_.push_back(new_config);
} }
// Guardar cambios inmediatamente // Guardar cambios inmediatamente
@@ -436,22 +430,22 @@ void Input::setGamepadConfigsFile(const std::string &filename) {
} }
// Método para obtener configuración de un gamepad específico (opcional) // Método para obtener configuración de un gamepad específico (opcional)
GamepadConfig *Input::getGamepadConfig(const std::string &gamepadName) { auto Input::getGamepadConfig(const std::string &gamepad_name) -> GamepadConfig * {
auto configIt = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(), [&gamepadName](const GamepadConfig &config) { auto config_it = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(), [&gamepad_name](const GamepadConfig &config) {
return config.name == gamepadName; return config.name == gamepad_name;
}); });
return (configIt != gamepad_configs_.end()) ? &(*configIt) : nullptr; return (config_it != gamepad_configs_.end()) ? &(*config_it) : nullptr;
} }
// Método para eliminar configuración de gamepad (opcional) // Método para eliminar configuración de gamepad (opcional)
bool Input::removeGamepadConfig(const std::string &gamepadName) { auto Input::removeGamepadConfig(const std::string &gamepad_name) -> bool {
auto configIt = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(), [&gamepadName](const GamepadConfig &config) { auto config_it = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(), [&gamepad_name](const GamepadConfig &config) {
return config.name == gamepadName; return config.name == gamepad_name;
}); });
if (configIt != gamepad_configs_.end()) { if (config_it != gamepad_configs_.end()) {
gamepad_configs_.erase(configIt); gamepad_configs_.erase(config_it);
saveGamepadConfigs(); saveGamepadConfigs();
return true; return true;
} }
@@ -459,7 +453,7 @@ bool Input::removeGamepadConfig(const std::string &gamepadName) {
return false; return false;
} }
std::shared_ptr<Input::Gamepad> Input::findAvailableGamepadByName(const std::string &gamepad_name) { auto Input::findAvailableGamepadByName(const std::string &gamepad_name) -> std::shared_ptr<Input::Gamepad> {
// Si no hay gamepads disponibles, devolver gamepad por defecto // Si no hay gamepads disponibles, devolver gamepad por defecto
if (gamepads_.empty()) { if (gamepads_.empty()) {
return nullptr; return nullptr;

View File

@@ -1,15 +1,15 @@
#pragma once #pragma once
#include <SDL3/SDL.h> #include <SDL3/SDL.h> // Para SDL_Scancode, SDL_GamepadButton, SDL_JoystickID, SDL_CloseGamepad, SDL_Gamepad, SDL_GetGamepadJoystick, SDL_GetGamepadName, SDL_GetGamepadPath, SDL_GetJoystickID, Uint8, SDL_Event, Sint16
#include <iostream> #include <array> // Para array
#include <memory> #include <memory> // Para shared_ptr, allocator
#include <string> #include <string> // Para string
#include <unordered_map> #include <unordered_map> // Para unordered_map
#include <vector> #include <vector> // Para vector
#include "gamepad_config_manager.h" #include "gamepad_config_manager.h" // Para GamepadConfig (ptr only), GamepadConfigs
#include "input_types.h" #include "input_types.h" // Para InputAction
// Clase Input: gestiona la entrada de teclado y mandos (singleton) // Clase Input: gestiona la entrada de teclado y mandos (singleton)
class Input { class Input {
@@ -121,7 +121,7 @@ class Input {
{Action::SM_BACK, ButtonState(SDL_GAMEPAD_BUTTON_NORTH)}} {} {Action::SM_BACK, ButtonState(SDL_GAMEPAD_BUTTON_NORTH)}} {}
~Gamepad() { ~Gamepad() {
if (pad) { if (pad != nullptr) {
SDL_CloseGamepad(pad); SDL_CloseGamepad(pad);
} }
} }
@@ -140,28 +140,28 @@ class Input {
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 input, SDL_Scancode code); void bindKey(Action action, SDL_Scancode code);
void bindGameControllerButton(std::shared_ptr<Gamepad> gamepad, Action input, SDL_GamepadButton button); static void bindGameControllerButton(std::shared_ptr<Gamepad> gamepad, Action action, SDL_GamepadButton button);
void bindGameControllerButton(std::shared_ptr<Gamepad> gamepad, Action input_target, Action input_source); static void bindGameControllerButton(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 input, bool repeat = true, bool check_keyboard = true, std::shared_ptr<Gamepad> gamepad = nullptr) -> bool; auto checkAction(Action action, bool repeat = true, bool check_keyboard = true, std::shared_ptr<Gamepad> gamepad = nullptr) -> bool;
auto checkAnyInput(bool check_keyboard = true, std::shared_ptr<Gamepad> gamepad = nullptr) -> bool; auto checkAnyInput(bool check_keyboard = true, 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;
auto getControllerName(std::shared_ptr<Gamepad> gamepad) const -> std::string; static auto getControllerName(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;
std::shared_ptr<Gamepad> getGamepad(SDL_JoystickID id) const; auto getGamepad(SDL_JoystickID id) const -> std::shared_ptr<Gamepad>;
std::shared_ptr<Input::Gamepad> getGamepadByName(const std::string &name) const; auto getGamepadByName(const std::string &name) const -> std::shared_ptr<Input::Gamepad>;
const Gamepads &getGamepads() const { return gamepads_; } auto getGamepads() const -> const Gamepads & { return gamepads_; }
// --- Métodos de consulta y utilidades --- // --- Métodos de consulta y utilidades ---
[[nodiscard]] auto getControllerBinding(std::shared_ptr<Gamepad> gamepad, Action input) const -> SDL_GamepadButton; [[nodiscard]] static auto getControllerBinding(std::shared_ptr<Gamepad> gamepad, Action action) -> SDL_GamepadButton;
[[nodiscard]] static auto inputToString(Action input) -> 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 ---
@@ -172,26 +172,26 @@ class Input {
void printConnectedGamepads() const; void printConnectedGamepads() const;
std::shared_ptr<Gamepad> findAvailableGamepadByName(const std::string &gamepad_name); 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 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::vector<Action> button_inputs_;
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();
auto checkAxisInput(Action input, std::shared_ptr<Gamepad> gamepad, bool repeat) -> bool; static auto checkAxisInput(Action action, std::shared_ptr<Gamepad> gamepad, bool repeat) -> bool;
void add_gamepad(int device_index); void addGamepad(int device_index);
void remove_gamepad(SDL_JoystickID id); void removeGamepad(SDL_JoystickID id);
void addGamepadMappingsFromFile(); void addGamepadMappingsFromFile();
void discoverGamepads(); void discoverGamepads();
@@ -202,8 +202,8 @@ class Input {
// Métodos auxiliares opcionales // Métodos auxiliares opcionales
void setGamepadConfigsFile(const std::string &filename); void setGamepadConfigsFile(const std::string &filename);
GamepadConfig *getGamepadConfig(const std::string &gamepadName); auto getGamepadConfig(const std::string &gamepad_name) -> GamepadConfig *;
bool removeGamepadConfig(const std::string &gamepadName); 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);

View File

@@ -1,7 +1,7 @@
#include "input_types.h" #include "input_types.h"
// Definición de los mapas // Definición de los mapas
const std::unordered_map<InputAction, std::string> actionToString = { const std::unordered_map<InputAction, std::string> ACTION_TO_STRING = {
{InputAction::FIRE_LEFT, "FIRE_LEFT"}, {InputAction::FIRE_LEFT, "FIRE_LEFT"},
{InputAction::FIRE_CENTER, "FIRE_CENTER"}, {InputAction::FIRE_CENTER, "FIRE_CENTER"},
{InputAction::FIRE_RIGHT, "FIRE_RIGHT"}, {InputAction::FIRE_RIGHT, "FIRE_RIGHT"},
@@ -29,10 +29,9 @@ const std::unordered_map<InputAction, std::string> actionToString = {
{InputAction::CONFIG, "CONFIG"}, {InputAction::CONFIG, "CONFIG"},
{InputAction::SWAP_CONTROLLERS, "SWAP_CONTROLLERS"}, {InputAction::SWAP_CONTROLLERS, "SWAP_CONTROLLERS"},
{InputAction::TOGGLE_AUTO_FIRE, "TOGGLE_AUTO_FIRE"}, {InputAction::TOGGLE_AUTO_FIRE, "TOGGLE_AUTO_FIRE"},
{InputAction::NONE, "NONE"} {InputAction::NONE, "NONE"}};
};
const std::unordered_map<std::string, InputAction> stringToAction = { const std::unordered_map<std::string, InputAction> STRING_TO_ACTION = {
{"FIRE_LEFT", InputAction::FIRE_LEFT}, {"FIRE_LEFT", InputAction::FIRE_LEFT},
{"FIRE_CENTER", InputAction::FIRE_CENTER}, {"FIRE_CENTER", InputAction::FIRE_CENTER},
{"FIRE_RIGHT", InputAction::FIRE_RIGHT}, {"FIRE_RIGHT", InputAction::FIRE_RIGHT},
@@ -60,10 +59,9 @@ const std::unordered_map<std::string, InputAction> stringToAction = {
{"CONFIG", InputAction::CONFIG}, {"CONFIG", InputAction::CONFIG},
{"SWAP_CONTROLLERS", InputAction::SWAP_CONTROLLERS}, {"SWAP_CONTROLLERS", InputAction::SWAP_CONTROLLERS},
{"TOGGLE_AUTO_FIRE", InputAction::TOGGLE_AUTO_FIRE}, {"TOGGLE_AUTO_FIRE", InputAction::TOGGLE_AUTO_FIRE},
{"NONE", InputAction::NONE} {"NONE", InputAction::NONE}};
};
const std::unordered_map<SDL_GamepadButton, std::string> buttonToString = { const std::unordered_map<SDL_GamepadButton, std::string> BUTTON_TO_STRING = {
{SDL_GAMEPAD_BUTTON_WEST, "WEST"}, {SDL_GAMEPAD_BUTTON_WEST, "WEST"},
{SDL_GAMEPAD_BUTTON_NORTH, "NORTH"}, {SDL_GAMEPAD_BUTTON_NORTH, "NORTH"},
{SDL_GAMEPAD_BUTTON_EAST, "EAST"}, {SDL_GAMEPAD_BUTTON_EAST, "EAST"},
@@ -75,10 +73,9 @@ const std::unordered_map<SDL_GamepadButton, std::string> buttonToString = {
{SDL_GAMEPAD_BUTTON_DPAD_UP, "DPAD_UP"}, {SDL_GAMEPAD_BUTTON_DPAD_UP, "DPAD_UP"},
{SDL_GAMEPAD_BUTTON_DPAD_DOWN, "DPAD_DOWN"}, {SDL_GAMEPAD_BUTTON_DPAD_DOWN, "DPAD_DOWN"},
{SDL_GAMEPAD_BUTTON_DPAD_LEFT, "DPAD_LEFT"}, {SDL_GAMEPAD_BUTTON_DPAD_LEFT, "DPAD_LEFT"},
{SDL_GAMEPAD_BUTTON_DPAD_RIGHT, "DPAD_RIGHT"} {SDL_GAMEPAD_BUTTON_DPAD_RIGHT, "DPAD_RIGHT"}};
};
const std::unordered_map<std::string, SDL_GamepadButton> stringToButton = { const std::unordered_map<std::string, SDL_GamepadButton> STRING_TO_BUTTON = {
{"WEST", SDL_GAMEPAD_BUTTON_WEST}, {"WEST", SDL_GAMEPAD_BUTTON_WEST},
{"NORTH", SDL_GAMEPAD_BUTTON_NORTH}, {"NORTH", SDL_GAMEPAD_BUTTON_NORTH},
{"EAST", SDL_GAMEPAD_BUTTON_EAST}, {"EAST", SDL_GAMEPAD_BUTTON_EAST},
@@ -90,10 +87,9 @@ const std::unordered_map<std::string, SDL_GamepadButton> stringToButton = {
{"DPAD_UP", SDL_GAMEPAD_BUTTON_DPAD_UP}, {"DPAD_UP", SDL_GAMEPAD_BUTTON_DPAD_UP},
{"DPAD_DOWN", SDL_GAMEPAD_BUTTON_DPAD_DOWN}, {"DPAD_DOWN", SDL_GAMEPAD_BUTTON_DPAD_DOWN},
{"DPAD_LEFT", SDL_GAMEPAD_BUTTON_DPAD_LEFT}, {"DPAD_LEFT", SDL_GAMEPAD_BUTTON_DPAD_LEFT},
{"DPAD_RIGHT", SDL_GAMEPAD_BUTTON_DPAD_RIGHT} {"DPAD_RIGHT", SDL_GAMEPAD_BUTTON_DPAD_RIGHT}};
};
const std::unordered_map<InputAction, InputAction> actionToAction = { const std::unordered_map<InputAction, InputAction> ACTION_TO_ACTION = {
{InputAction::SM_SELECT, InputAction::FIRE_LEFT}, {InputAction::SM_SELECT, InputAction::FIRE_LEFT},
{InputAction::SM_BACK, InputAction::FIRE_CENTER}, {InputAction::SM_BACK, InputAction::FIRE_CENTER},
}; };

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
@@ -47,8 +48,8 @@ enum class InputAction : int {
}; };
// Mapas para convertir entre enums y strings // Mapas para convertir entre enums y strings
extern const std::unordered_map<InputAction, std::string> actionToString; extern const std::unordered_map<InputAction, std::string> ACTION_TO_STRING;
extern const std::unordered_map<std::string, InputAction> stringToAction; extern const std::unordered_map<std::string, InputAction> STRING_TO_ACTION;
extern const std::unordered_map<SDL_GamepadButton, std::string> buttonToString; extern const std::unordered_map<SDL_GamepadButton, std::string> BUTTON_TO_STRING;
extern const std::unordered_map<std::string, SDL_GamepadButton> stringToButton; extern const std::unordered_map<std::string, SDL_GamepadButton> STRING_TO_BUTTON;
extern const std::unordered_map<InputAction, InputAction> actionToAction; extern const std::unordered_map<InputAction, InputAction> ACTION_TO_ACTION;

View File

@@ -35,8 +35,7 @@ void MovingSprite::clear() {
} }
// Elimina el movimiento del sprite // Elimina el movimiento del sprite
void MovingSprite::stop() void MovingSprite::stop() {
{
x_ = 0.0F; // Posición en el eje X x_ = 0.0F; // Posición en el eje X
y_ = 0.0F; // Posición en el eje Y y_ = 0.0F; // Posición en el eje Y

View File

@@ -1,9 +1,9 @@
#include "options.h" #include "options.h"
#include <SDL3/SDL.h> // Para SDL_ScaleMode, SDL_GamepadButton, SDL_LogCategory, SDL_LogInfo, SDL_LogError, SDL_LogWarn #include <SDL3/SDL.h> // Para SDL_ScaleMode, SDL_GamepadButton, SDL_LogCategory, SDL_LogInfo, SDL_LogError, SDL_LogWarn
#include <stddef.h> // Para size_t
#include <algorithm> // Para clamp, max #include <algorithm> // Para clamp, max
#include <cstddef> // Para size_t
#include <fstream> // Para basic_ostream, operator<<, basic_ostream::operator<<, basic_ofstream, basic_istream, basic_ifstream, ifstream, ofstream #include <fstream> // Para basic_ostream, operator<<, basic_ostream::operator<<, basic_ofstream, basic_istream, basic_ifstream, ifstream, ofstream
#include <functional> // Para function #include <functional> // Para function
#include <map> // Para map, operator==, _Rb_tree_const_iterator #include <map> // Para map, operator==, _Rb_tree_const_iterator
@@ -274,7 +274,7 @@ void checkPendingChanges() {
} }
// Buscar y asignar un mando disponible por nombre // Buscar y asignar un mando disponible por nombre
bool assignGamepadByName(const std::string& gamepad_name_to_find, Player::Id player_id) { auto assignGamepadByName(const std::string& gamepad_name_to_find, Player::Id player_id) -> bool {
auto found_gamepad = Input::get()->findAvailableGamepadByName(gamepad_name_to_find); auto found_gamepad = Input::get()->findAvailableGamepadByName(gamepad_name_to_find);
if (found_gamepad) { if (found_gamepad) {
@@ -284,7 +284,7 @@ bool assignGamepadByName(const std::string& gamepad_name_to_find, Player::Id pla
} }
// Obtener información de un gamepad específico // Obtener información de un gamepad específico
std::string getGamepadInfo(Player::Id player_id) { auto getGamepadInfo(Player::Id player_id) -> std::string {
try { try {
const auto& gamepad = gamepad_manager.getGamepad(player_id); const auto& gamepad = gamepad_manager.getGamepad(player_id);
return "Player " + std::to_string(static_cast<int>(player_id)) + return "Player " + std::to_string(static_cast<int>(player_id)) +
@@ -300,73 +300,77 @@ void GamepadManager::assignAndLinkGamepads() {
auto physical_gamepads = Input::get()->getGamepads(); auto physical_gamepads = Input::get()->getGamepads();
// 2. Reiniciamos las asignaciones actuales y guardamos los datos deseados de la config. // 2. Reiniciamos las asignaciones actuales y guardamos los datos deseados de la config.
std::array<std::string, MAX_PLAYERS> desired_paths; // <--- CAMBIO: Guardamos las rutas deseadas. std::array<std::string, MAX_PLAYERS> desired_paths;
for (size_t i = 0; i < MAX_PLAYERS; ++i) { for (size_t i = 0; i < MAX_PLAYERS; ++i) {
desired_paths[i] = gamepads[i].path; // <--- CAMBIO: Obtenemos la ruta. desired_paths[i] = gamepads_[i].path;
gamepads[i].instance = nullptr; // Limpiamos la instancia gamepads_[i].instance = nullptr;
} }
// 3. Vector para rastrear los mandos físicos que ya hemos asignado. // 3. Vector para rastrear los mandos físicos que ya hemos asignado.
std::vector<std::shared_ptr<Input::Gamepad>> assigned_instances; std::vector<std::shared_ptr<Input::Gamepad>> assigned_instances;
// --- PRIMERA PASADA: Buscar coincidencias exactas por RUTA (path) --- // --- Ejecutamos las pasadas de asignación ---
// Este es el método más fiable para identificar un mando de forma única. assignGamepadsByPath(desired_paths, physical_gamepads, assigned_instances);
assignRemainingGamepads(physical_gamepads, assigned_instances);
}
// --- 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) { for (size_t i = 0; i < MAX_PLAYERS; ++i) {
const std::string& desired_path = desired_paths[i]; // <--- CAMBIO: Usamos la ruta. const std::string& desired_path = desired_paths[i];
if (desired_path.empty()) { if (desired_path.empty()) {
continue; // Si no hay una ruta guardada para este slot, lo saltamos. continue; // No hay ruta guardada para este slot.
} }
// Buscamos un mando físico que coincida con la ruta deseada. // Buscamos un mando físico que coincida con la ruta y no esté ya asignado.
for (const auto& physical_gamepad : physical_gamepads) { for (const auto& physical_gamepad : physical_gamepads) {
if (physical_gamepad->path == desired_path) { // <--- CAMBIO: Comparamos por ruta. if (physical_gamepad->path == desired_path && !isGamepadAssigned(physical_gamepad, assigned_instances)) {
// ¡Coincidencia por ruta! Es casi seguro que es el mando correcto. gamepads_[i].instance = physical_gamepad;
// La comprobación de 'already_assigned' es una seguridad extra. assigned_instances.push_back(physical_gamepad);
bool already_assigned = false; break; // Mando encontrado para este jugador, pasamos al siguiente.
for (const auto& assigned : assigned_instances) {
if (assigned == physical_gamepad) {
already_assigned = true;
break;
}
}
if (!already_assigned) {
gamepads[i].instance = physical_gamepad; // Enlazamos la instancia
// No actualizamos el nombre ni la ruta aquí, ya que coinciden con la config.
assigned_instances.push_back(physical_gamepad); // Lo marcamos como asignado
break; // Mando encontrado para este jugador, pasamos al siguiente.
}
}
}
}
// --- SEGUNDA PASADA: Asignar los mandos restantes a los jugadores sin mando ---
// Esto se ejecuta para slots vacíos o si un mando guardado no se encontró (p. ej. se desconectó).
for (size_t i = 0; i < MAX_PLAYERS; ++i) {
if (gamepads[i].instance == nullptr) { // Si este jugador aún no tiene mando...
// ...buscamos un mando físico que todavía esté libre.
for (const auto& physical_gamepad : physical_gamepads) {
bool already_assigned = false;
for (const auto& assigned : assigned_instances) {
if (assigned == physical_gamepad) {
already_assigned = true;
break;
}
}
if (!already_assigned) {
gamepads[i].instance = physical_gamepad; // Se lo asignamos
// MUY IMPORTANTE: Actualizamos la configuración para reflejar la realidad.
gamepads[i].name = physical_gamepad->name; // Actualizamos el nombre
gamepads[i].path = physical_gamepad->path; // <--- AÑADIDO: Y también la ruta!
assigned_instances.push_back(physical_gamepad); // Lo marcamos como asignado
break; // Mando encontrado, pasamos al siguiente jugador.
}
} }
} }
} }
} }
// --- SEGUNDA PASADA: Asigna los mandos físicos restantes a los jugadores libres ---
void GamepadManager::assignRemainingGamepads(
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) {
if (gamepads_[i].instance != nullptr) {
continue; // Este jugador ya tiene un mando.
}
// Buscamos un mando físico que todavía esté libre.
for (const auto& physical_gamepad : physical_gamepads) {
if (!isGamepadAssigned(physical_gamepad, assigned_instances)) {
gamepads_[i].instance = physical_gamepad;
// MUY IMPORTANTE: Actualizamos la configuración para reflejar la realidad.
gamepads_[i].name = physical_gamepad->name;
gamepads_[i].path = physical_gamepad->path;
assigned_instances.push_back(physical_gamepad);
break; // Mando encontrado, pasamos al siguiente jugador.
}
}
}
}
// 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.
auto GamepadManager::isGamepadAssigned(
const std::shared_ptr<Input::Gamepad>& physical_gamepad,
const std::vector<std::shared_ptr<Input::Gamepad>>& assigned_instances) -> bool {
for (const auto& assigned : assigned_instances) {
if (assigned == physical_gamepad) {
return true; // Encontrado, por lo tanto, ya está asignado.
}
}
return false; // No se encontró en la lista.
}
} // namespace Options } // namespace Options

View File

@@ -1,19 +1,21 @@
#pragma once #pragma once
#include <SDL3/SDL.h> // Para SDL_GamepadButton, SDL_ScaleMode #include <SDL3/SDL.h> // Para SDL_ScaleMode
#include <algorithm> // Para copy #include <algorithm> // Para copy
#include <array> // Para array #include <array> // Para array
#include <fstream> // Para ofstream #include <cstddef> // Para size_t
#include <stdexcept> // Para excepciones #include <exception> // Para exception
#include <string> // Para allocator, string #include <fstream> // Para basic_ostream, operator<<, basic_ofstream, basic_ostream::operator<<, ofstream
#include <unordered_map> #include <memory> // Para shared_ptr, swap
#include <vector> // Para vector #include <stdexcept> // Para out_of_range, invalid_argument
#include <string> // Para char_traits, string, allocator, operator==, swap, operator<<, basic_string, stoi
#include <vector> // Para vector
#include "difficulty.h" // Para Code #include "difficulty.h" // Para Code
#include "input.h" // Para InputAction, InputDevice #include "input.h" // Para Input
#include "lang.h" // Para Code #include "lang.h" // Para Code
#include "manage_hiscore_table.h" // Para HiScoreEntry #include "manage_hiscore_table.h" // Para ManageHiScoreTable, Table
#include "player.h" // Para Player #include "player.h" // Para Player
namespace Options { namespace Options {
@@ -106,51 +108,39 @@ struct Gamepad {
// --- Manager para los gamepads --- // --- Manager para los gamepads ---
class GamepadManager { class GamepadManager {
private:
static constexpr size_t MAX_PLAYERS = 2;
std::array<Gamepad, MAX_PLAYERS> gamepads;
// Convierte Player::Id a índice del array
size_t playerIdToIndex(Player::Id player_id) const {
switch (player_id) {
case Player::Id::PLAYER1:
return 0;
case Player::Id::PLAYER2:
return 1;
default:
throw std::invalid_argument("Invalid player ID");
}
}
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);
} }
// Acceso directo por player_id (más intuitivo) // Acceso directo por player_id (más intuitivo)
Gamepad& getGamepad(Player::Id player_id) { auto getGamepad(Player::Id player_id) -> Gamepad& {
return gamepads[playerIdToIndex(player_id)]; return gamepads_[playerIdToIndex(player_id)];
} }
const Gamepad& getGamepad(Player::Id player_id) const { [[nodiscard]] auto getGamepad(Player::Id player_id) const -> const Gamepad& {
return gamepads[playerIdToIndex(player_id)]; return gamepads_[playerIdToIndex(player_id)];
} }
// Acceso por índice (más eficiente si ya tienes el índice) // Acceso por índice (más eficiente si ya tienes el índice)
Gamepad& operator[](size_t index) { auto operator[](size_t index) -> Gamepad& {
if (index >= MAX_PLAYERS) throw std::out_of_range("Invalid gamepad index"); if (index >= MAX_PLAYERS) {
return gamepads[index]; throw std::out_of_range("Invalid gamepad index");
}
return gamepads_[index];
} }
const Gamepad& operator[](size_t index) const { auto operator[](size_t index) const -> const Gamepad& {
if (index >= MAX_PLAYERS) throw std::out_of_range("Invalid gamepad index"); if (index >= MAX_PLAYERS) {
return gamepads[index]; throw std::out_of_range("Invalid gamepad index");
}
return gamepads_[index];
} }
bool assignGamepadToPlayer(Player::Id player_id, auto assignGamepadToPlayer(Player::Id player_id,
std::shared_ptr<Input::Gamepad> instance, std::shared_ptr<Input::Gamepad> instance,
const std::string& name) { const std::string& name) -> bool {
try { try {
auto& gamepad = getGamepad(player_id); auto& gamepad = getGamepad(player_id);
gamepad.instance = instance; gamepad.instance = instance;
@@ -162,15 +152,15 @@ class GamepadManager {
} }
void swapPlayers() { void swapPlayers() {
std::swap(gamepads[0].instance, gamepads[1].instance); std::swap(gamepads_[0].instance, gamepads_[1].instance);
std::swap(gamepads[0].name, gamepads[1].name); std::swap(gamepads_[0].name, gamepads_[1].name);
std::swap(gamepads[0].path, gamepads[1].path); std::swap(gamepads_[0].path, gamepads_[1].path);
} }
// Para serialización/deserialización // Para serialización/deserialización
void saveToFile(std::ofstream& file) const { void saveToFile(std::ofstream& file) const {
for (size_t i = 0; i < MAX_PLAYERS; ++i) { for (size_t i = 0; i < MAX_PLAYERS; ++i) {
const auto& gamepad = gamepads[i]; const auto& gamepad = gamepads_[i];
file << "controller." << i << ".name=" << gamepad.name << "\n"; file << "controller." << i << ".name=" << gamepad.name << "\n";
file << "controller." << i << ".path=" << gamepad.path << "\n"; file << "controller." << i << ".path=" << gamepad.path << "\n";
file << "controller." << i << ".player=" << static_cast<int>(gamepad.player_id) << "\n"; file << "controller." << i << ".player=" << static_cast<int>(gamepad.player_id) << "\n";
@@ -178,28 +168,33 @@ class GamepadManager {
} }
// Método helper para parseAndSetController // Método helper para parseAndSetController
bool setControllerProperty(size_t controller_index, auto setControllerProperty(size_t controller_index,
const std::string& property, const std::string& property,
const std::string& value) { const std::string& value) -> bool {
if (controller_index >= MAX_PLAYERS) return false; if (controller_index >= MAX_PLAYERS) {
return false;
}
auto& gamepad = gamepads[controller_index]; auto& gamepad = gamepads_[controller_index];
if (property == "name") { if (property == "name") {
gamepad.name = value; gamepad.name = value;
return true; return true;
} else if (property == "path") { }
if (property == "path") {
gamepad.path = value; gamepad.path = value;
return true; return true;
} else if (property == "player") { }
if (property == "player") {
try { try {
int player_int = std::stoi(value); int player_int = std::stoi(value);
if (player_int == 1) if (player_int == 1) {
gamepad.player_id = Player::Id::PLAYER1; gamepad.player_id = Player::Id::PLAYER1;
else if (player_int == 2) } else if (player_int == 2) {
gamepad.player_id = Player::Id::PLAYER2; gamepad.player_id = Player::Id::PLAYER2;
else } else {
return false; return false;
}
return true; return true;
} catch (const std::exception&) { } catch (const std::exception&) {
return false; return false;
@@ -213,12 +208,39 @@ class GamepadManager {
void assignAndLinkGamepads(); void assignAndLinkGamepads();
// Iteradores // Iteradores
auto begin() { return gamepads.begin(); } auto begin() { return gamepads_.begin(); }
auto end() { return gamepads.end(); } auto end() { return gamepads_.end(); }
auto begin() const { return gamepads.begin(); } [[nodiscard]] auto begin() const { return gamepads_.begin(); }
auto end() const { return gamepads.end(); } [[nodiscard]] auto end() const { return gamepads_.end(); }
size_t size() const { return MAX_PLAYERS; } [[nodiscard]] static auto size() -> size_t { return MAX_PLAYERS; }
private:
static constexpr size_t MAX_PLAYERS = 2;
std::array<Gamepad, MAX_PLAYERS> gamepads_;
// Convierte Player::Id a índice del array
[[nodiscard]] static auto playerIdToIndex(Player::Id player_id) -> size_t {
switch (player_id) {
case Player::Id::PLAYER1:
return 0;
case Player::Id::PLAYER2:
return 1;
default:
throw std::invalid_argument("Invalid player ID");
}
}
void 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);
void assignRemainingGamepads(
const std::vector<std::shared_ptr<Input::Gamepad>>& physical_gamepads,
std::vector<std::shared_ptr<Input::Gamepad>>& assigned_instances);
[[nodiscard]] static auto isGamepadAssigned(
const std::shared_ptr<Input::Gamepad>& physical_gamepad,
const std::vector<std::shared_ptr<Input::Gamepad>>& assigned_instances) -> bool;
}; };
struct Keyboard { struct Keyboard {
@@ -245,16 +267,16 @@ 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 de configuración --- // --- Funciones de configuración ---
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
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
bool assignGamepadByName(const std::string& gamepad_name, Player::Id player_id); // Buscar y asignar un mando disponible por nombre auto assignGamepadByName(const std::string& gamepad_name, Player::Id player_id) -> bool; // Buscar y asignar un mando disponible por nombre
} // namespace Options } // namespace Options

View File

@@ -1,6 +1,6 @@
#include "player.h" #include "player.h"
#include <SDL3/SDL.h> // Para SDL_GetTicks, SDL_FlipMode, SDL_FRect #include <SDL3/SDL.h> // Para SDL_GetTicks, SDL_FlipMode
#include <algorithm> // Para clamp, max, min #include <algorithm> // Para clamp, max, min
#include <cstdlib> // Para rand #include <cstdlib> // Para rand
@@ -8,24 +8,25 @@
#include "animated_sprite.h" // Para AnimatedSprite #include "animated_sprite.h" // Para AnimatedSprite
#include "asset.h" // Para Asset #include "asset.h" // Para Asset
#include "audio.h" // Para Audio #include "audio.h" // Para Audio
#include "input.h" // Para InputAction #include "input.h" // Para Input
#include "input_types.h" // Para InputAction
#include "manage_hiscore_table.h" // Para ManageHiScoreTable, HiScoreEntry #include "manage_hiscore_table.h" // Para ManageHiScoreTable, HiScoreEntry
#include "param.h" // Para Param, ParamGame, param #include "param.h" // Para Param, ParamGame, param
#include "scoreboard.h" // Para ScoreboardMode, Scoreboard #include "scoreboard.h" // Para Scoreboard
#include "stage.h" // Para power_can_be_added #include "stage.h" // Para power_can_be_added
#include "texture.h" // Para Texture #include "texture.h" // Para Texture
// Constructor // Constructor
Player::Player(const Config& config) Player::Player(const Config &config)
: player_sprite_(std::make_unique<AnimatedSprite>(config.texture.at(0), config.animations.at(0))), : player_sprite_(std::make_unique<AnimatedSprite>(config.texture.at(0), config.animations.at(0))),
power_sprite_(std::make_unique<AnimatedSprite>(config.texture.at(1), config.animations.at(1))), power_sprite_(std::make_unique<AnimatedSprite>(config.texture.at(1), config.animations.at(1))),
enter_name_(std::make_unique<EnterName>()), enter_name_(std::make_unique<EnterName>()),
id_(config.id),
play_area_(*config.play_area),
default_pos_x_(config.x),
default_pos_y_(config.y),
hi_score_table_(*config.hi_score_table), hi_score_table_(*config.hi_score_table),
glowing_entry_(*config.glowing_entry), glowing_entry_(*config.glowing_entry),
play_area_(*config.play_area),
id_(config.id),
default_pos_x_(config.x),
default_pos_y_(config.y),
demo_(config.demo) { demo_(config.demo) {
// Configura objetos // Configura objetos
player_sprite_->getTexture()->setPalette(coffees_); player_sprite_->getTexture()->setPalette(coffees_);

View File

@@ -2,20 +2,18 @@
#include <SDL3/SDL.h> // Para Uint32, SDL_FRect #include <SDL3/SDL.h> // Para Uint32, SDL_FRect
#include <memory> // Para allocator, unique_ptr, shared_ptr #include <memory> // Para shared_ptr, allocator, unique_ptr
#include <string> // Para string #include <string> // Para string
#include <vector> // Para vector #include <vector> // Para vector
#include "animated_sprite.h" // Para AnimatedSprite #include "animated_sprite.h" // Para AnimatedSprite
#include "enter_name.h" // Para EnterName #include "enter_name.h" // Para EnterName
#include "input.h" #include "input.h" // Para Input
#include "manage_hiscore_table.h" // Para HiScoreEntry #include "manage_hiscore_table.h" // Para Table
#include "scoreboard.h" // Para Scoreboard #include "scoreboard.h" // Para Scoreboard
#include "utils.h" // Para Circle #include "utils.h" // Para Circle
class Texture; class Texture;
enum class Action : int;
enum class Mode;
// --- Clase Player --- // --- Clase Player ---
class Player { class Player {
@@ -88,7 +86,7 @@ class Player {
}; };
// --- 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 ---
@@ -185,11 +183,11 @@ class Player {
void addCredit() { ++credits_used_; } void addCredit() { ++credits_used_; }
void setGamepad(std::shared_ptr<Input::Gamepad> gamepad) { gamepad_ = gamepad; } void setGamepad(std::shared_ptr<Input::Gamepad> gamepad) { gamepad_ = gamepad; }
[[nodiscard]] std::shared_ptr<Input::Gamepad> getGamepad() const { 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]] bool getUsesKeyboard() const { return uses_keyboard_; } [[nodiscard]] auto getUsesKeyboard() const -> bool { return uses_keyboard_; }
void setHiScoreTable(const Table &table) { hi_score_table_ = table; } void setHiScoreTable(const Table &table) { hi_score_table_ = table; }
const Table &getHiScoreTable() const { return hi_score_table_; } [[nodiscard]] auto getHiScoreTable() const -> const Table & { return hi_score_table_; }
void setGlowingEntry(const int &entry) { glowing_entry_ = entry; } void setGlowingEntry(const int &entry) { glowing_entry_ = entry; }
private: private:
@@ -202,56 +200,64 @@ class Player {
static constexpr int WAITING_COUNTER = 1000; static constexpr int WAITING_COUNTER = 1000;
// --- 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::shared_ptr<Input::Gamepad> gamepad_ = nullptr; // Dispositivo asociado
Table &hi_score_table_; // Tabla de máximas puntuaciones
int &glowing_entry_; // Entrada de la tabla de puntuaciones para hacerla brillar
std::string name_; // Nombre del jugador
std::string last_enter_name_; // Último nombre introducido en la tabla de puntuaciones
// --- Variables de estado --- // --- Estructuras y enums ---
Id id_; // Identificador para el jugador
SDL_FRect play_area_; // Rectángulo con la zona de juego SDL_FRect play_area_; // Rectángulo con la zona de juego
float pos_x_ = 0.0F; // Posición en el eje X Circle collider_ = Circle(0, 0, 9); // Círculo de colisión del jugador
int pos_y_ = 0; // Posición en el eje Y Scoreboard::Id scoreboard_panel_ = Scoreboard::Id::LEFT; // Panel del marcador asociado al jugador
float default_pos_x_; // Posición inicial para el jugador Id id_; // Identificador para el jugador
int default_pos_y_; // Posición inicial para el jugador
float vel_x_ = 0.0F; // Cantidad de píxeles a desplazarse en el eje X
int vel_y_ = 0.0F; // Cantidad de píxeles a desplazarse en el eje Y
int cant_fire_counter_ = 0; // Contador durante el cual no puede disparar
int recoiling_state_counter_ = 0; // Contador para la animación del estado de retroceso
int recoiling_state_duration_ = 0; // Numero de frames que dura el estado de retroceso
int cooling_state_counter_ = 0; // Contador para la animación del estado cooling
int score_ = 0; // Puntos del jugador
float score_multiplier_ = 1.0F; // Multiplicador de puntos
bool qualifies_for_high_score_ = false; // Indica si tiene una puntuación que le permite entrar en la tabla de records
Table &hi_score_table_; // Tabla de maximas puntuaciones
int &glowing_entry_; // Entrada de la tabla de puntuaciones para hacerla brillar
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
bool invulnerable_ = true; // Indica si el jugador es invulnerable
int invulnerable_counter_ = INVULNERABLE_COUNTER; // Contador para la invulnerabilidad // --- Variables float ---
bool extra_hit_ = false; // Indica si el jugador tiene un toque extra float pos_x_ = 0.0F; // Posición en el eje X
int coffees_ = 0; // Indica cuántos cafés lleva acumulados float default_pos_x_; // Posición inicial para el jugador
bool power_up_ = false; // Indica si el jugador tiene activo el modo PowerUp float vel_x_ = 0.0F; // Cantidad de píxeles a desplazarse en el eje X
int power_up_counter_ = POWERUP_COUNTER; // Temporizador para el modo PowerUp float score_multiplier_ = 1.0F; // Multiplicador de puntos
int power_up_x_offset_ = 0; // Desplazamiento del sprite de PowerUp respecto al sprite del jugador
Circle collider_ = Circle(0, 0, 9); // Círculo de colisión del jugador // --- Variables int ---
int continue_counter_ = 10; // Contador para poder continuar int pos_y_ = 0; // Posición en el eje Y
Uint32 continue_ticks_ = 0; // Variable para poder cambiar el contador de continue en función del tiempo int default_pos_y_; // Posición inicial para el jugador
Scoreboard::Id scoreboard_panel_ = Scoreboard::Id::LEFT; // Panel del marcador asociado al jugador int vel_y_ = 0; // Cantidad de píxeles a desplazarse en el eje Y
std::string name_; // Nombre del jugador int cant_fire_counter_ = 0; // Contador durante el cual no puede disparar
int controller_index_ = 0; // Índice del array de mandos que utilizará para moverse int recoiling_state_counter_ = 0; // Contador para la animación del estado de retroceso
bool demo_ = false; // Para que el jugador sepa si está en el modo demostración int recoiling_state_duration_ = 0; // Número de frames que dura el estado de retroceso
int name_entry_idle_counter_ = 0; // Contador para poner nombre int cooling_state_counter_ = 0; // Contador para la animación del estado cooling
int name_entry_total_counter_ = 0; // Segundos totales que lleva acumulados poniendo nombre int invulnerable_counter_ = INVULNERABLE_COUNTER; // Contador para la invulnerabilidad
Uint32 name_entry_ticks_ = 0; // Variable para poder cambiar el contador de poner nombre en función del tiempo int score_ = 0; // Puntos del jugador
Uint32 showing_name_ticks_ = 0; // Tiempo en el que se entra al estado SHOWING_NAME int coffees_ = 0; // Indica cuántos cafés lleva acumulados
int step_counter_ = 0; // Cuenta los pasos para los estados en los que camina automáticamente int power_up_counter_ = POWERUP_COUNTER; // Temporizador para el modo PowerUp
bool game_completed_ = false; // Indica si ha completado el juego int power_up_x_offset_ = 0; // Desplazamiento del sprite de PowerUp respecto al sprite del jugador
int credits_used_ = 0; // Indica el número de veces que ha continuado int continue_counter_ = 10; // Contador para poder continuar
std::string last_enter_name_; // Último nombre introducido en la tabla de puntuaciones int controller_index_ = 0; // Índice del array de mandos que utilizará para moverse
int waiting_counter_ = 0; // Contador para el estado de espera int name_entry_idle_counter_ = 0; // Contador para poner nombre
std::shared_ptr<Input::Gamepad> gamepad_ = nullptr; // Dispositivo asociado int name_entry_total_counter_ = 0; // Segundos totales que lleva acumulados poniendo nombre
bool uses_keyboard_ = false; // Indica si usa el teclado como dispositivo de control 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 waiting_counter_ = 0; // Contador para el estado de espera
// --- Variables Uint32 ---
Uint32 continue_ticks_ = 0; // Variable para poder cambiar el contador de continue en función del tiempo
Uint32 name_entry_ticks_ = 0; // Variable para poder cambiar el contador de poner nombre en función del tiempo
Uint32 showing_name_ticks_ = 0; // Tiempo en el que se entra al estado SHOWING_NAME
// --- Flags booleanas ---
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 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 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 uses_keyboard_ = false; // Indica si usa el teclado como dispositivo de control
// --- 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

View File

@@ -104,17 +104,16 @@ void Credits::update() {
fillCanvas(); fillCanvas();
} }
static const auto audio = Audio::get(); Audio::update();
audio->update();
} }
// Dibuja Credits::en patalla // Dibuja Credits::en patalla
void Credits::render() { void Credits::render() {
static const auto screen = Screen::get(); static auto *const SCREEN = Screen::get();
screen->start(); // Prepara para empezar a dibujar en la textura de juego SCREEN->start(); // Prepara para empezar a dibujar en la textura de juego
SDL_RenderTexture(screen->getRenderer(), canvas_, nullptr, nullptr); // Copia la textura con la zona de juego a la pantalla SDL_RenderTexture(SCREEN->getRenderer(), canvas_, nullptr, nullptr); // Copia la textura con la zona de juego a la pantalla
screen->render(); // Vuelca el contenido del renderizador en pantalla SCREEN->render(); // Vuelca el contenido del renderizador en pantalla
} }
// Comprueba el manejador de eventos // Comprueba el manejador de eventos

View File

@@ -1,19 +1,20 @@
#include "game.h" #include "game.h"
#include <SDL3/SDL.h> // Para SDL_GetTicks, SDL_SetRenderTarget, SDL_EventType, SDL_CreateTexture, SDL_Delay, SDL_DestroyTexture, SDL_Event, SDL_GetRenderTarget, SDL_PollEvent, SDL_RenderTexture, SDL_SetTextureBlendMode, SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_5, SDLK_6, SDLK_7, SDLK_8, SDLK_9, SDL_BLENDMODE_BLEND, SDL_PixelFormat, SDL_Point, SDL_TextureAccess #include <SDL3/SDL.h> // Para SDL_GetTicks, SDL_SetRenderTarget, SDL_EventType, SDL_CreateTexture, SDL_Delay, SDL_DestroyTexture, SDL_Event, SDL_GetRenderTarget, SDL_PollEvent, SDL_RenderTexture, SDL_SetTextureBlendMode, SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_5, SDLK_6, SDLK_7, SDLK_8, SDLK_9, SDLK_KP_MINUS, SDLK_KP_PLUS, SDL_BLENDMODE_BLEND, SDL_PixelFormat, SDL_Point, SDL_TextureAccess
#include <algorithm> // Para max, find_if, clamp, find, min #include <algorithm> // Para max, find, clamp, find_if, min
#include <array> // Para array #include <array> // Para array
#include <cstdlib> // Para rand, size_t #include <cstdlib> // Para rand, size_t
#include <functional> // Para function #include <functional> // Para function
#include <iostream> // Para std::cout, std::endl #include <iostream> // Para basic_ostream, basic_ostream::operator<<, cout, endl
#include <iterator> // Para distance, size #include <iterator> // Para size
#include <memory> // Para std::make_unique #include <memory> // Para shared_ptr, unique_ptr, __shared_ptr_access, allocator, make_unique, operator==, make_shared
#include <utility> // Para move
#include "asset.h" // Para Asset #include "asset.h" // Para Asset
#include "audio.h" // Para Audio #include "audio.h" // Para Audio
#include "background.h" // Para Background #include "background.h" // Para Background
#include "balloon.h" // Para Balloon, Balloon::SPEED #include "balloon.h" // Para Balloon
#include "balloon_manager.h" // Para BalloonManager #include "balloon_manager.h" // Para BalloonManager
#include "bullet.h" // Para Bullet, BulletType, BulletMoveStatus #include "bullet.h" // Para Bullet, BulletType, BulletMoveStatus
#include "color.h" // Para Color, FLASH_COLOR #include "color.h" // Para Color, FLASH_COLOR
@@ -22,20 +23,21 @@
#include "global_events.h" // Para check #include "global_events.h" // Para check
#include "global_inputs.h" // Para check #include "global_inputs.h" // Para check
#include "hit.h" // Para Hit #include "hit.h" // Para Hit
#include "input.h" // Para InputAction, Input, Input::DO_NOT_ALLOW_REPEAT, Input::ALLOW_REPEAT, InputDevice #include "input.h" // Para Input
#include "input_types.h" // Para InputAction
#include "item.h" // Para Item, ItemType #include "item.h" // Para Item, ItemType
#include "lang.h" // Para getText #include "lang.h" // Para getText
#include "manage_hiscore_table.h" // Para ManageHiScoreTable, HiScoreEntry #include "manage_hiscore_table.h" // Para HiScoreEntry, ManageHiScoreTable
#include "param.h" // Para Param, param, ParamGame, ParamScoreboard, ParamFade, ParamBalloon #include "param.h" // Para Param, param, ParamGame, ParamScoreboard, ParamFade, ParamBalloon
#include "path_sprite.h" // Para Path, PathSprite, createPath, PathType #include "path_sprite.h" // Para Path, PathSprite, createPath, PathType
#include "player.h" // Para Player, PlayerState #include "player.h" // Para Player
#include "resource.h" // Para Resource #include "resource.h" // Para Resource
#include "scoreboard.h" // Para Scoreboard, ScoreboardMode, SCOREBOARD_LEFT_PANEL, SCOREBOARD_RIGHT_PANEL, SCOREBOARD_CENTER_PANEL #include "scoreboard.h" // Para Scoreboard
#include "screen.h" // Para Screen #include "screen.h" // Para Screen
#include "section.hpp" // Para Name, name, AttractMode, Options, attract_mode, options #include "section.hpp" // Para Name, name, AttractMode, Options, attract_mode, options
#include "smart_sprite.h" // Para SmartSprite #include "smart_sprite.h" // Para SmartSprite
#include "stage.h" // Para number, Stage, get, total_power, power, addPower, init, power_can_be_added, stages #include "stage.h" // Para number, Stage, get, total_power, power, addPower, init, power_can_be_added, stages
#include "tabe.h" // Para Tabe, TabeState #include "tabe.h" // Para Tabe
#include "text.h" // Para Text #include "text.h" // Para Text
#include "texture.h" // Para Texture #include "texture.h" // Para Texture
#include "ui/notifier.h" // Para Notifier #include "ui/notifier.h" // Para Notifier
@@ -903,8 +905,7 @@ void Game::update() {
fillCanvas(); fillCanvas();
} }
static const auto audio = Audio::get(); Audio::update();
audio->update();
} }
// Dibuja el juego // Dibuja el juego
@@ -1834,8 +1835,8 @@ void Game::playSound(const std::string &name) const {
return; return;
} }
static auto audio = Audio::get(); static auto *audio_ = Audio::get();
audio->playSound(name); audio_->playSound(name);
} }
// Organiza los jugadores para que los vivos se pinten sobre los muertos // Organiza los jugadores para que los vivos se pinten sobre los muertos
@@ -1903,7 +1904,7 @@ void Game::sendPlayerToTheFront(const std::shared_ptr<Player> &player) {
#ifdef _DEBUG #ifdef _DEBUG
// Comprueba los eventos en el modo DEBUG // Comprueba los eventos en el modo DEBUG
void Game::checkDebugEvents(const SDL_Event &event) { void Game::checkDebugEvents(const SDL_Event &event) {
static int formation_id = 0; static int formation_id_ = 0;
if (event.type == SDL_EVENT_KEY_DOWN && static_cast<int>(event.key.repeat) == 0) { if (event.type == SDL_EVENT_KEY_DOWN && static_cast<int>(event.key.repeat) == 0) {
switch (event.key.key) { switch (event.key.key) {
case SDLK_1: // Crea una powerball case SDLK_1: // Crea una powerball
@@ -1966,17 +1967,17 @@ void Game::checkDebugEvents(const SDL_Event &event) {
break; break;
} }
case SDLK_KP_PLUS: { case SDLK_KP_PLUS: {
++formation_id; ++formation_id_;
balloon_manager_->destroyAllBalloons(); balloon_manager_->destroyAllBalloons();
balloon_manager_->deployFormation(formation_id); balloon_manager_->deployFormation(formation_id_);
std::cout << formation_id << std::endl; std::cout << formation_id_ << std::endl;
break; break;
} }
case SDLK_KP_MINUS: { case SDLK_KP_MINUS: {
--formation_id; --formation_id_;
balloon_manager_->destroyAllBalloons(); balloon_manager_->destroyAllBalloons();
balloon_manager_->deployFormation(formation_id); balloon_manager_->deployFormation(formation_id_);
std::cout << formation_id << std::endl; std::cout << formation_id_ << std::endl;
break; break;
} }
default: default:

View File

@@ -171,12 +171,12 @@ class Game {
void updateGameStateGameOver(); // Gestiona el estado de fin de partida void updateGameStateGameOver(); // Gestiona el 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(); // Actualiza las variables y estados de los jugadores void updatePlayers(); // Actualiza las variables y estados de los jugadores
void renderPlayers(); // Renderiza todos los jugadores en pantalla void renderPlayers(); // Renderiza todos los jugadores en pantalla
void sortPlayersByZOrder(); // Reorganiza el orden de dibujado de jugadores void sortPlayersByZOrder(); // Reorganiza el orden de dibujado de jugadores
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
@@ -209,11 +209,11 @@ class Game {
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
// --- Sistema de balas y proyectiles --- // --- Sistema de balas y proyectiles ---
void updateBullets(); // Actualiza posición y estado de todas las balas void updateBullets(); // Actualiza posición y estado de todas las balas
void renderBullets(); // Renderiza todas las balas activas void renderBullets(); // Renderiza todas las balas activas
void createBullet(int x, int y, BulletType kind, bool powered_up, Player::Id owner); // Crea una nueva bala void createBullet(int x, int y, BulletType kind, bool powered_up, Player::Id owner); // Crea una nueva bala
void checkBulletCollision(); // Verifica colisiones de todas las balas void checkBulletCollision(); // Verifica colisiones de todas las balas
void freeBullets(); // Libera memoria del vector de balas void freeBullets(); // Libera memoria del vector de balas
// --- Colisiones específicas de balas --- // --- Colisiones específicas de balas ---
auto checkBulletTabeCollision(std::shared_ptr<Bullet> bullet) -> bool; // Detecta colisión bala-Tabe auto checkBulletTabeCollision(std::shared_ptr<Bullet> bullet) -> bool; // Detecta colisión bala-Tabe
@@ -274,7 +274,7 @@ class Game {
// --- 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(); // Actualiza lógica específica del modo demo void updateDemo(); // 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
@@ -285,8 +285,8 @@ class Game {
// --- Sistema de audio --- // --- Sistema de audio ---
static void playMusic(); // Reproduce la música de fondo static void playMusic(); // 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
void pauseMusic(); // Pausa la música static void pauseMusic(); // Pausa la música
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
// --- Utilidades y servicios --- // --- Utilidades y servicios ---

View File

@@ -66,23 +66,22 @@ void HiScoreTable::update() {
fillTexture(); // Dibuja los sprites en la textura fillTexture(); // Dibuja los sprites en la textura
} }
static const auto audio = Audio::get(); Audio::update();
audio->update();
} }
// Pinta en pantalla // Pinta en pantalla
void HiScoreTable::render() { void HiScoreTable::render() {
static const auto screen = Screen::get(); static auto *const SCREEN = Screen::get();
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
view_area_.y = std::max(0.0F, param.game.height - counter_ + 100); // Establece la ventana del backbuffer view_area_.y = std::max(0.0F, param.game.height - counter_ + 100); // Establece la ventana del backbuffer
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
} }
// Dibuja los sprites en la textura // Dibuja los sprites en la textura

View File

@@ -209,26 +209,25 @@ void Instructions::update() {
ticks_ = SDL_GetTicks(); // Actualiza el contador de ticks ticks_ = SDL_GetTicks(); // Actualiza el contador de ticks
Screen::get()->update(); // Actualiza el objeto screen Screen::get()->update(); // Actualiza el objeto screen
counter_++; // Incrementa el contador counter_++; // Incrementa el contador
updateSprites(); // Actualiza los sprites updateSprites(); // Actualiza los sprites
updateBackbuffer(); // Gestiona la textura con los graficos updateBackbuffer(); // Gestiona la textura con los graficos
tiled_bg_->update(); // Actualiza el mosaico de fondo tiled_bg_->update(); // Actualiza el mosaico de fondo
fade_->update(); // Actualiza el objeto "fade" fade_->update(); // Actualiza el objeto "fade"
fillBackbuffer(); // Rellena el backbuffer fillBackbuffer(); // Rellena el backbuffer
} }
static const auto audio = Audio::get(); Audio::update();
audio->update();
} }
// Pinta en pantalla // Pinta en pantalla
void Instructions::render() { void Instructions::render() {
static const auto screen = Screen::get(); static auto *const SCREEN = Screen::get();
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
tiled_bg_->render();// Dibuja el mosacico de fondo tiled_bg_->render(); // Dibuja el mosacico de fondo
// Copia la textura y el backbuffer al renderizador // Copia la textura y el backbuffer al renderizador
if (view_.y == 0) { if (view_.y == 0) {
@@ -237,9 +236,9 @@ void Instructions::render() {
SDL_RenderTexture(renderer_, backbuffer_, nullptr, &view_); SDL_RenderTexture(renderer_, backbuffer_, nullptr, &view_);
} }
fade_->render(); // Renderiza el fundido fade_->render(); // Renderiza el fundido
screen->render();// Vuelca el contenido del renderizador en pantalla SCREEN->render(); // Vuelca el contenido del renderizador en pantalla
} }
// Comprueba los eventos // Comprueba los eventos

View File

@@ -225,7 +225,7 @@ void Intro::update() {
ticks_ = SDL_GetTicks(); // Actualiza el contador de ticks ticks_ = SDL_GetTicks(); // Actualiza el contador de ticks
Screen::get()->update(); // Actualiza el objeto screen Screen::get()->update(); // Actualiza el objeto screen
tiled_bg_->update(); // Actualiza el fondo tiled_bg_->update(); // Actualiza el fondo
switch (state_) { switch (state_) {
case IntroState::SCENES: case IntroState::SCENES:
@@ -240,18 +240,17 @@ void Intro::update() {
} }
} }
static const auto audio = Audio::get(); Audio::update();
audio->update();
} }
// Dibuja el objeto en pantalla // Dibuja el objeto en pantalla
void Intro::render() { void Intro::render() {
static const auto screen = Screen::get(); static auto *const SCREEN = Screen::get();
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
tiled_bg_->render();// Dibuja el fondo tiled_bg_->render(); // Dibuja el fondo
switch (state_) { switch (state_) {
case IntroState::SCENES: { case IntroState::SCENES: {
@@ -264,7 +263,7 @@ void Intro::render() {
break; break;
} }
screen->render();// Vuelca el contenido del renderizador en pantalla SCREEN->render(); // Vuelca el contenido del renderizador en pantalla
} }
// Bucle principal // Bucle principal

View File

@@ -135,25 +135,24 @@ void Logo::update() {
ticks_ = SDL_GetTicks(); // Actualiza el contador de ticks ticks_ = SDL_GetTicks(); // Actualiza el contador de ticks
Screen::get()->update(); // Actualiza el objeto screen Screen::get()->update(); // Actualiza el objeto screen
updateJAILGAMES(); // Actualiza el logo de JAILGAMES updateJAILGAMES(); // Actualiza el logo de JAILGAMES
updateTextureColors(); // Actualiza los colores de las texturas updateTextureColors(); // Actualiza los colores de las texturas
++counter_; // Gestiona el contador ++counter_; // Gestiona el contador
} }
static const auto audio = Audio::get(); Audio::update();
audio->update();
} }
// Dibuja en pantalla // Dibuja en pantalla
void Logo::render() { void Logo::render() {
static const auto screen = Screen::get(); static auto *const SCREEN = Screen::get();
screen->start(); SCREEN->start();
screen->clean(); SCREEN->clean();
renderJAILGAMES(); renderJAILGAMES();
screen->render(); SCREEN->render();
} }
// Bucle para el logo del juego // Bucle para el logo del juego

View File

@@ -1,34 +1,34 @@
#include "title.h" #include "title.h"
#include <SDL3/SDL.h> // Para SDL_GetTicks, Uint32, SDL_EventType #include <SDL3/SDL.h> // Para SDL_GetTicks, Uint32, SDL_Keycode, SDL_Event, SDL_PollEvent, SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_5, SDLK_A, SDLK_C, SDLK_D, SDLK_F, SDLK_S, SDLK_V, SDLK_X, SDLK_Z, SDL_EventType
#include <algorithm> // Para find_if #include <algorithm> // Para max, find_if
#include <cstddef> // Para size_t #include <iostream> // Para basic_ostream, basic_ostream::operator<<, operator<<, cout, endl, hex
#include <iostream> // Para basic_ostream, basic_ostream::operator<< #include <string> // Para char_traits, operator+, to_string, string, basic_string
#include <string> // Para basic_string, char_traits, operator+
#include <vector> // Para vector #include <vector> // Para vector
#include "audio.h" // Para Audio #include "audio.h" // Para Audio
#include "color.h" // Para Color, Zone, NO_TEXT_COLOR, TITLE_SHADO... #include "color.h" // Para Color, NO_TEXT_COLOR, TITLE_SHADOW_TEXT_COLOR
#include "define_buttons.h" // Para DefineButtons #include "define_buttons.h" // Para DefineButtons
#include "fade.h" // Para Fade, FadeType #include "fade.h" // Para Fade, FadeType
#include "game_logo.h" // Para GameLogo #include "game_logo.h" // Para GameLogo
#include "global_events.h" // Para check #include "global_events.h" // Para check
#include "global_inputs.h" // Para check #include "global_inputs.h" // Para check
#include "input.h" // Para Input, Input::DO_NOT_ALLOW_REPEAT, Input... #include "input.h" // Para Input
#include "input_types.h" // Para InputAction
#include "lang.h" // Para getText #include "lang.h" // Para getText
#include "options.h" // Para GamepadOptions, controllers, getPlayerW... #include "options.h" // Para Gamepad, GamepadManager, gamepad_manager, Settings, settings, getPlayerWhoUsesKeyboard, swapControllers, swapKeyboard
#include "param.h" // Para Param, param, ParamGame, ParamTitle #include "param.h" // Para Param, param, ParamGame, ParamTitle, ParamFade
#include "player.h" // Para Player, PlayerState #include "player.h" // Para Player
#include "resource.h" // Para Resource #include "resource.h" // Para Resource
#include "screen.h" // Para Screen #include "screen.h" // Para Screen
#include "section.hpp" // Para Name, name, Options, options, AttractMode #include "section.hpp" // Para Name, name, Options, options, AttractMode, attract_mode
#include "sprite.h" // Para Sprite #include "sprite.h" // Para Sprite
#include "text.h" // Para TEXT_CENTER, TEXT_SHADOW, Text #include "text.h" // Para TEXT_CENTER, TEXT_SHADOW, Text
#include "tiled_bg.h" // Para TiledBG, TiledBGMode #include "tiled_bg.h" // Para TiledBG, TiledBGMode
#include "ui/notifier.h" // Para Notifier #include "ui/notifier.h" // Para Notifier
#include "ui/service_menu.h" // Para ServiceMenu #include "ui/service_menu.h" // Para ServiceMenu
#include "utils.h" #include "utils.h" // Para Zone, BLOCK
class Texture; class Texture;
@@ -87,16 +87,15 @@ void Title::update() {
updatePlayers(); updatePlayers();
} }
static const auto audio = Audio::get(); Audio::update();
audio->update();
} }
// Dibuja el objeto en pantalla // Dibuja el objeto en pantalla
void Title::render() { void Title::render() {
static const auto screen = Screen::get(); static auto* const SCREEN = Screen::get();
screen->start(); SCREEN->start();
screen->clean(); SCREEN->clean();
tiled_bg_->render(); tiled_bg_->render();
game_logo_->render(); game_logo_->render();
@@ -106,7 +105,7 @@ void Title::render() {
define_buttons_->render(); define_buttons_->render();
fade_->render(); fade_->render();
screen->render(); SCREEN->render();
} }
// Comprueba los eventos // Comprueba los eventos

View File

@@ -1,8 +1,8 @@
#pragma once #pragma once
#include <SDL3/SDL.h> // Para SDL_Keycode, SDL_Event, Uint64 #include <SDL3/SDL.h> // Para SDL_Keycode, SDL_Event, Uint64
#include <stdint.h> // Para uint8_t
#include <cstdint> // Para uint8_t
#include <memory> // Para unique_ptr, shared_ptr #include <memory> // Para unique_ptr, shared_ptr
#include <string_view> // Para string_view #include <string_view> // Para string_view
#include <vector> // Para vector #include <vector> // Para vector
@@ -87,18 +87,18 @@ class Title {
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 handleControlKeys(SDL_Keycode key); // Maneja las teclas de control específicas void handleControlKeys(SDL_Keycode key); // Maneja las teclas de control específicas
[[nodiscard]] auto shouldSkipInputCheck() const -> bool; // Determina si se debe omitir la comprobación de entrada [[nodiscard]] auto shouldSkipInputCheck() const -> bool; // Determina si se debe omitir la comprobación de entrada
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

View File

@@ -51,21 +51,21 @@ void MenuRenderer::render(const ServiceMenu *menu_state) {
if (menu_state->getCurrentGroupAlignment() == ServiceMenu::GroupAlignment::LEFT) { if (menu_state->getCurrentGroupAlignment() == ServiceMenu::GroupAlignment::LEFT) {
// Para opciones alineadas a la izquierda, truncamos el valor si es necesario // Para opciones alineadas a la izquierda, truncamos el valor si es necesario
const int available_width = rect_.w - (ServiceMenu::OPTIONS_HORIZONTAL_PADDING * 2) - const int AVAILABLE_WIDTH = rect_.w - (ServiceMenu::OPTIONS_HORIZONTAL_PADDING * 2) -
element_text_->lenght(option_pairs.at(i).first, -2) - element_text_->lenght(option_pairs.at(i).first, -2) -
ServiceMenu::MIN_GAP_OPTION_VALUE; ServiceMenu::MIN_GAP_OPTION_VALUE;
const std::string truncated_value = getTruncatedValue(option_pairs.at(i).second, available_width); const std::string TRUNCATED_VALUE = getTruncatedValue(option_pairs.at(i).second, AVAILABLE_WIDTH);
element_text_->writeColored(rect_.x + ServiceMenu::OPTIONS_HORIZONTAL_PADDING, y, option_pairs.at(i).first, current_color, -2); element_text_->writeColored(rect_.x + ServiceMenu::OPTIONS_HORIZONTAL_PADDING, y, option_pairs.at(i).first, current_color, -2);
const int X = rect_.x + rect_.w - ServiceMenu::OPTIONS_HORIZONTAL_PADDING - element_text_->lenght(truncated_value, -2); const int X = rect_.x + rect_.w - ServiceMenu::OPTIONS_HORIZONTAL_PADDING - element_text_->lenght(TRUNCATED_VALUE, -2);
element_text_->writeColored(X, y, truncated_value, current_color, -2); element_text_->writeColored(X, y, TRUNCATED_VALUE, current_color, -2);
} else { } else {
// Para opciones centradas, también truncamos si es necesario // Para opciones centradas, también truncamos si es necesario
const int available_width = rect_.w - (ServiceMenu::OPTIONS_HORIZONTAL_PADDING * 2); const int AVAILABLE_WIDTH = rect_.w - (ServiceMenu::OPTIONS_HORIZONTAL_PADDING * 2);
const std::string truncated_caption = getTruncatedValue(option_pairs.at(i).first, available_width); const std::string TRUNCATED_CAPTION = getTruncatedValue(option_pairs.at(i).first, AVAILABLE_WIDTH);
element_text_->writeDX(TEXT_CENTER | TEXT_COLOR, rect_.x + rect_.w / 2, y, truncated_caption, -2, current_color); element_text_->writeDX(TEXT_CENTER | TEXT_COLOR, rect_.x + rect_.w / 2, y, TRUNCATED_CAPTION, -2, current_color);
} }
y += options_height_ + options_padding_; y += options_height_ + options_padding_;
} }
@@ -96,8 +96,8 @@ void MenuRenderer::setLayout(const ServiceMenu *menu_state) {
void MenuRenderer::initializeMaxSizes() { void MenuRenderer::initializeMaxSizes() {
// Establecemos los límites máximos basados en el tamaño de la pantalla // Establecemos los límites máximos basados en el tamaño de la pantalla
// Dejamos un margen del 10% en cada lado para que el menú no ocupe toda la pantalla // Dejamos un margen del 10% en cada lado para que el menú no ocupe toda la pantalla
max_menu_width_ = static_cast<size_t>(param.game.game_area.rect.w * 0.9f); max_menu_width_ = static_cast<size_t>(param.game.game_area.rect.w * 0.9F);
max_menu_height_ = static_cast<size_t>(param.game.game_area.rect.h * 0.9f); max_menu_height_ = static_cast<size_t>(param.game.game_area.rect.h * 0.9F);
} }
void MenuRenderer::setAnchors(const ServiceMenu *menu_state) { void MenuRenderer::setAnchors(const ServiceMenu *menu_state) {
@@ -188,8 +188,8 @@ void MenuRenderer::precalculateMenuWidths(const std::vector<std::unique_ptr<Menu
if (menu_state->getCurrentGroupAlignment() == ServiceMenu::GroupAlignment::LEFT) { if (menu_state->getCurrentGroupAlignment() == ServiceMenu::GroupAlignment::LEFT) {
// Para calcular el ancho máximo, necesitamos considerar la truncación // Para calcular el ancho máximo, necesitamos considerar la truncación
int max_available_value_width = static_cast<int>(max_menu_width_) - max_option_width - int max_available_value_width = static_cast<int>(max_menu_width_) - max_option_width -
(ServiceMenu::OPTIONS_HORIZONTAL_PADDING * 2) - (ServiceMenu::OPTIONS_HORIZONTAL_PADDING * 2) -
ServiceMenu::MIN_GAP_OPTION_VALUE; ServiceMenu::MIN_GAP_OPTION_VALUE;
int actual_value_width = getTruncatedValueWidth(option->getValueAsString(), max_available_value_width); int actual_value_width = getTruncatedValueWidth(option->getValueAsString(), max_available_value_width);
max_value_width = std::max(max_value_width, actual_value_width); max_value_width = std::max(max_value_width, actual_value_width);
@@ -200,7 +200,7 @@ void MenuRenderer::precalculateMenuWidths(const std::vector<std::unique_ptr<Menu
total_width += ServiceMenu::MIN_GAP_OPTION_VALUE + max_value_width; total_width += ServiceMenu::MIN_GAP_OPTION_VALUE + max_value_width;
} }
group_menu_widths_[group] = std::min(std::max((int)ServiceMenu::MIN_WIDTH, (int)total_width), group_menu_widths_[group] = std::min(std::max((int)ServiceMenu::MIN_WIDTH, (int)total_width),
static_cast<int>(max_menu_width_)); static_cast<int>(max_menu_width_));
} }
} }
@@ -239,12 +239,12 @@ auto MenuRenderer::getTruncatedValueWidth(const std::string &value, int availabl
int available_for_text = available_width - ellipsis_width; int available_for_text = available_width - ellipsis_width;
if (available_for_text <= 0) { if (available_for_text <= 0) {
return ellipsis_width; // Solo mostramos los puntos suspensivos return ellipsis_width; // Solo mostramos los puntos suspensivos
} }
// Calculamos aproximadamente cuántos caracteres caben // Calculamos aproximadamente cuántos caracteres caben
float char_width = static_cast<float>(value_width) / value.length(); float char_width = static_cast<float>(value_width) / value.length();
size_t max_chars = static_cast<size_t>(available_for_text / char_width); auto max_chars = static_cast<size_t>(available_for_text / char_width);
// Verificamos el ancho real del texto truncado // Verificamos el ancho real del texto truncado
std::string truncated = truncateWithEllipsis(value, max_chars); std::string truncated = truncateWithEllipsis(value, max_chars);
@@ -262,12 +262,12 @@ auto MenuRenderer::getTruncatedValue(const std::string &value, int available_wid
int available_for_text = available_width - ellipsis_width; int available_for_text = available_width - ellipsis_width;
if (available_for_text <= 0) { if (available_for_text <= 0) {
return "..."; // Solo mostramos los puntos suspensivos return "..."; // Solo mostramos los puntos suspensivos
} }
// Calculamos aproximadamente cuántos caracteres caben // Calculamos aproximadamente cuántos caracteres caben
float char_width = static_cast<float>(value_width) / value.length(); float char_width = static_cast<float>(value_width) / value.length();
size_t max_chars = static_cast<size_t>(available_for_text / char_width); auto max_chars = static_cast<size_t>(available_for_text / char_width);
// Ajustamos iterativamente hasta que el texto quepa // Ajustamos iterativamente hasta que el texto quepa
std::string truncated = truncateWithEllipsis(value, max_chars); std::string truncated = truncateWithEllipsis(value, max_chars);

View File

@@ -5,6 +5,7 @@
#include <array> // Para array #include <array> // Para array
#include <cstddef> // Para size_t #include <cstddef> // Para size_t
#include <memory> // Para shared_ptr, unique_ptr #include <memory> // Para shared_ptr, unique_ptr
#include <string> // Para string
#include <vector> // Para vector #include <vector> // Para vector
#include "color.h" // Para Color #include "color.h" // Para Color

View File

@@ -3,12 +3,14 @@
#include <algorithm> // Para max #include <algorithm> // Para max
#include "audio.h" // Para Audio #include "audio.h" // Para Audio
#include "difficulty.h" // Para Difficulty #include "difficulty.h" // Para getCodeFromName, getNameFromCode
#include "input.h" // Para Input
#include "lang.h" // Para getText, getCodeFromName, getNameFromCode #include "lang.h" // Para getText, getCodeFromName, getNameFromCode
#include "menu_option.h" // Para MenuOption, BoolOption, ActionOption, IntOption, FolderOption, ListOption #include "menu_option.h" // Para MenuOption, ListOption, ActionOption, BoolOption, FolderOption, IntOption
#include "menu_renderer.h" // Para MenuRenderer #include "menu_renderer.h" // Para MenuRenderer
#include "options.h" // Para PendingChanges, VideoOptions, pending_changes, video, AudioOptions, SettingsOptions, audio, checkPendingChanges, settings, WindowOptions, getDifficultyCodeFromName, getDifficultyNameFromCode, window, MusicOptions, SoundOptions #include "options.h" // Para PendingChanges, pending_changes, checkPendingChanges, GamepadManager, Video, gamepad_manager, video, Audio, Settings, audio, settings, Gamepad, Window, window, Music, Sound
#include "param.h" // Para Param, param, ParamGame, ParamServiceMenu #include "param.h" // Para Param, param, ParamGame, ParamServiceMenu
#include "player.h" // Para Player
#include "resource.h" // Para Resource #include "resource.h" // Para Resource
#include "screen.h" // Para Screen #include "screen.h" // Para Screen
#include "section.hpp" // Para Name, name, Options, options #include "section.hpp" // Para Name, name, Options, options
@@ -285,7 +287,7 @@ void ServiceMenu::initializeOptions() {
options_.push_back(std::make_unique<ActionOption>( options_.push_back(std::make_unique<ActionOption>(
Lang::getText("[SERVICE_MENU] SWAP_CONTROLLERS"), Lang::getText("[SERVICE_MENU] SWAP_CONTROLLERS"),
SettingsGroup::CONTROLS, SettingsGroup::CONTROLS,
[this]() { []() {
Options::gamepad_manager.swapPlayers(); Options::gamepad_manager.swapPlayers();
})); }));

View File

@@ -42,7 +42,6 @@ auto getCollisionPoint(const Circle &a, const Circle &b) -> SDL_FPoint {
return contact; return contact;
} }
// Detector de colisiones entre dos circulos // Detector de colisiones entre dos circulos
auto checkCollision(const Circle &a, const Circle &b) -> bool { auto checkCollision(const Circle &a, const Circle &b) -> bool {
// Calcula el radio total al cuadrado // Calcula el radio total al cuadrado
@@ -264,24 +263,24 @@ auto easeOutElastic(double time) -> double {
// Ease Out Expo - Muy suave al final (más dramático) // Ease Out Expo - Muy suave al final (más dramático)
auto easeOutExpo(double time) -> double { auto easeOutExpo(double time) -> double {
return time == 1.0f ? 1.0f : 1.0f - pow(2.0f, -10.0f * time); return time == 1.0F ? 1.0F : 1.0F - pow(2.0F, -10.0F * time);
} }
// Ease In Expo - Arranque muy gradual // Ease In Expo - Arranque muy gradual
auto easeInExpo(double time) -> double { auto easeInExpo(double time) -> double {
return time == 0.0f ? 0.0f : pow(2.0f, 10.0f * (time - 1.0f)); return time == 0.0F ? 0.0F : pow(2.0F, 10.0F * (time - 1.0F));
} }
// Ease Out Back - Con un pequeño "rebote" // Ease Out Back - Con un pequeño "rebote"
auto easeOutBack(double time) -> double { auto easeOutBack(double time) -> double {
const double C1 = 1.70158f; const double C1 = 1.70158F;
const double C3 = C1 + 1.0f; const double C3 = C1 + 1.0F;
return 1.0f + C3 * pow(time - 1.0f, 3.0f) + C1 * pow(time - 1.0f, 2.0f); return 1.0F + C3 * pow(time - 1.0F, 3.0F) + C1 * pow(time - 1.0F, 2.0F);
} }
// Ease Out Cubic - Desaceleración suave al final // Ease Out Cubic - Desaceleración suave al final
auto easeOutCubic(double time) -> double { auto easeOutCubic(double time) -> double {
return 1.0f - pow(1.0f - time, 3.0f); return 1.0F - pow(1.0F - time, 3.0F);
} }
// Ease In Cubic - Aceleración gradual // Ease In Cubic - Aceleración gradual
@@ -391,7 +390,6 @@ auto truncateWithEllipsis(const std::string &input, size_t length) -> std::strin
return input; return input;
} }
if (length <= 3) { if (length <= 3) {
// Not enough space for any content plus ellipsis
return std::string(length, '.'); return std::string(length, '.');
} }
return input.substr(0, length) + "..."; return input.substr(0, length) + "...";

View File

@@ -3,6 +3,7 @@
#include <SDL3/SDL.h> // Para Uint8, SDL_FRect, SDL_FPoint, SDL_Renderer #include <SDL3/SDL.h> // Para Uint8, SDL_FRect, SDL_FPoint, SDL_Renderer
#include <cstddef> // Para size_t
#include <cstdint> // Para int32_t #include <cstdint> // Para int32_t
#include <string> // Para string #include <string> // Para string
#include <vector> // Para vector #include <vector> // Para vector