From c066cc32d38e3f2e613480764c076a71e90927c6 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Fri, 1 Aug 2025 12:51:24 +0200 Subject: [PATCH] migrant input: ja guarda i llig configuracions de gamepad en fitxer --- CMakeLists.txt | 1 + source/director.cpp | 14 +- source/gamepad_config_manager.h | 6 +- source/input.cpp | 126 ++++++++++++++++- source/input.h | 235 +++++++++++++++++--------------- source/options.cpp | 2 +- source/param.cpp | 3 +- 7 files changed, 260 insertions(+), 127 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index eb004c5..67ab240 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,6 +76,7 @@ set(APP_SOURCES source/color.cpp source/define_buttons.cpp source/difficulty.cpp + source/input_types.cpp source/mouse.cpp source/options.cpp source/stage.cpp diff --git a/source/director.cpp b/source/director.cpp index 0a63b6c..b18d502 100644 --- a/source/director.cpp +++ b/source/director.cpp @@ -91,12 +91,14 @@ void Director::init() { loadScoreFile(); // Carga el archivo de puntuaciones // Inicialización de subsistemas principales - Lang::setLanguage(Options::settings.language); // Carga el archivo de idioma - Screen::init(); // Inicializa la pantalla y el sistema de renderizado - Audio::init(); // Activa el sistema de audio - Resource::init(); // Inicializa el sistema de gestión de recursos - Input::init(Asset::get()->get("gamecontrollerdb.txt")); // Carga configuración de controles - bindInputs(); // Asigna los controles a la entrada del sistema + Lang::setLanguage(Options::settings.language); // Carga el archivo de idioma + Screen::init(); // Inicializa la pantalla y el sistema de renderizado + Audio::init(); // Activa el sistema de audio + Resource::init(); // Inicializa el sistema de gestión de recursos + Input::init( + Asset::get()->get("gamecontrollerdb.txt"), + Asset::get()->get("controllers.json")); // Carga configuración de controles + bindInputs(); // Asigna los controles a la entrada del sistema auto gamepads = Input::get()->getGamepads(); if (!gamepads.empty()) diff --git a/source/gamepad_config_manager.h b/source/gamepad_config_manager.h index e2e287d..eea87b9 100644 --- a/source/gamepad_config_manager.h +++ b/source/gamepad_config_manager.h @@ -26,10 +26,12 @@ struct GamepadConfig { } }; +using GamepadConfigs = std::vector; + class GamepadConfigManager { public: // Escribir vector de GamepadConfig a archivo JSON - static bool writeToJson(const std::vector& configs, const std::string& filename) { + static bool writeToJson(const GamepadConfigs& configs, const std::string& filename) { try { nlohmann::json j; j["gamepads"] = nlohmann::json::array(); @@ -69,7 +71,7 @@ class GamepadConfigManager { } // Leer vector de GamepadConfig desde archivo JSON - static bool readFromJson(std::vector& configs, const std::string& filename) { + static bool readFromJson(GamepadConfigs& configs, const std::string& filename) { try { std::ifstream file(filename); if (!file.is_open()) { diff --git a/source/input.cpp b/source/input.cpp index dbc2885..8c22823 100644 --- a/source/input.cpp +++ b/source/input.cpp @@ -13,7 +13,9 @@ Input *Input::instance = nullptr; // Inicializa la instancia única del singleton -void Input::init(const std::string &game_controller_db_path) { Input::instance = new Input(game_controller_db_path); } +void Input::init(const std::string &game_controller_db_path, const std::string &gamepad_configs_file) { + Input::instance = new Input(game_controller_db_path, gamepad_configs_file); +} // Libera la instancia void Input::destroy() { delete Input::instance; } @@ -22,8 +24,9 @@ void Input::destroy() { delete Input::instance; } auto Input::get() -> Input * { return Input::instance; } // Constructor -Input::Input(std::string game_controller_db_path) - : game_controller_db_path_(std::move(game_controller_db_path)) { +Input::Input(std::string game_controller_db_path, std::string gamepad_configs_file) + : game_controller_db_path_(std::move(game_controller_db_path)), + gamepad_configs_file_(std::move(gamepad_configs_file)) { // Inicializa el subsistema SDL_INIT_GAMEPAD initSDLGamePad(); @@ -226,15 +229,27 @@ auto Input::checkAxisInput(Action input, std::shared_ptr gamepad, bool return false; } +void Input::addGamepadMappingsFromFile() { + if (SDL_AddGamepadMappingsFromFile(game_controller_db_path_.c_str()) < 0) { + std::cout << "Error, could not load " << game_controller_db_path_.c_str() << " file: " << SDL_GetError() << std::endl; + } +} + +void Input::discoverGamepads() { + SDL_Event event; + while (SDL_PollEvent(&event)) { + handleEvent(event); // Comprueba mandos conectados + } +} + void Input::initSDLGamePad() { if (SDL_WasInit(SDL_INIT_GAMEPAD) != 1) { if (!SDL_InitSubSystem(SDL_INIT_GAMEPAD)) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_GAMEPAD could not initialize! SDL Error: %s", SDL_GetError()); } else { - SDL_Event event; - while (SDL_PollEvent(&event)) { - handleEvent(event); // Comprueba mandos conectados - } + addGamepadMappingsFromFile(); + loadGamepadConfigs(); + discoverGamepads(); SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "** Input System initialized successfully\n"); } } @@ -299,6 +314,8 @@ void Input::add_gamepad(int device_index) { auto gamepad = std::make_shared(pad); std::cout << "Gamepad connected (" << gamepad->name << ")" << std::endl; + applyGamepadConfig(gamepad); + saveGamepadConfigFromGamepad(gamepad); gamepads_.push_back(std::move(gamepad)); } @@ -328,3 +345,98 @@ void Input::printConnectedGamepads() const { << ", Nombre: " << name << ")" << std::endl; } } + +void Input::loadGamepadConfigs() { + if (GamepadConfigManager::fileExists(gamepad_configs_file_)) { + GamepadConfigManager::readFromJson(gamepad_configs_, gamepad_configs_file_); + } +} + +void Input::saveGamepadConfigs() { + GamepadConfigManager::writeToJson(gamepad_configs_, gamepad_configs_file_); +} + +void Input::applyGamepadConfig(std::shared_ptr gamepad) { + if (!gamepad) { + return; + } + + // Buscar configuración por nombre del gamepad + auto configIt = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(), + [&gamepad](const GamepadConfig& config) { + return config.name == gamepad->name; + }); + + if (configIt != gamepad_configs_.end()) { + // Aplicar la configuración encontrada al gamepad + for (const auto& [action, button] : configIt->bindings) { + if (gamepad->bindings.find(action) != gamepad->bindings.end()) { + gamepad->bindings[action].button = button; + } + } + } +} + +void Input::saveGamepadConfigFromGamepad(std::shared_ptr gamepad) { + if (!gamepad) { + return; + } + + // Buscar si ya existe una configuración con este nombre + auto configIt = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(), + [&gamepad](const GamepadConfig& config) { + return config.name == gamepad->name; + }); + + // Crear nueva configuración desde el gamepad + GamepadConfig newConfig(gamepad->name); + newConfig.bindings.clear(); // Limpiar bindings por defecto + + // Copiar todos los bindings del gamepad + for (const auto& [action, buttonState] : gamepad->bindings) { + newConfig.bindings[action] = buttonState.button; + } + + if (configIt != gamepad_configs_.end()) { + // Sobreescribir configuración existente + *configIt = newConfig; + } else { + // Añadir nueva configuración + gamepad_configs_.push_back(newConfig); + } + + // Guardar cambios inmediatamente + saveGamepadConfigs(); +} + +// Método para establecer el archivo de configuración (opcional) +void Input::setGamepadConfigsFile(const std::string& filename) { + gamepad_configs_file_ = filename; + loadGamepadConfigs(); // Recargar con el nuevo archivo +} + +// Método para obtener configuración de un gamepad específico (opcional) +GamepadConfig* Input::getGamepadConfig(const std::string& gamepadName) { + auto configIt = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(), + [&gamepadName](const GamepadConfig& config) { + return config.name == gamepadName; + }); + + return (configIt != gamepad_configs_.end()) ? &(*configIt) : nullptr; +} + +// Método para eliminar configuración de gamepad (opcional) +bool Input::removeGamepadConfig(const std::string& gamepadName) { + auto configIt = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(), + [&gamepadName](const GamepadConfig& config) { + return config.name == gamepadName; + }); + + if (configIt != gamepad_configs_.end()) { + gamepad_configs_.erase(configIt); + saveGamepadConfigs(); + return true; + } + + return false; +} \ No newline at end of file diff --git a/source/input.h b/source/input.h index aae75ca..94bda29 100644 --- a/source/input.h +++ b/source/input.h @@ -1,17 +1,19 @@ #pragma once -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include + +#include "gamepad_config_manager.h" #include "input_types.h" // Forward declaration para evitar dependencia circular -struct GamepadConfig; -class GamepadConfigManager; +// struct GamepadConfig; +// class GamepadConfigManager; // Clase Input: gestiona la entrada de teclado y mandos (singleton) class Input { @@ -28,162 +30,177 @@ class Input { // --- Estructuras --- struct KeyState { - Uint8 scancode; // Scancode asociado - bool is_held; // Está pulsada ahora mismo - bool just_pressed; // Se acaba de pulsar en este fotograma + Uint8 scancode; // Scancode asociado + bool is_held; // Está pulsada ahora mismo + bool just_pressed; // Se acaba de pulsar en este fotograma - KeyState(Uint8 scancode = 0, bool is_held = false, bool just_pressed = false) - : scancode(scancode), is_held(is_held), just_pressed(just_pressed) {} + KeyState(Uint8 scancode = 0, bool is_held = false, bool just_pressed = false) + : scancode(scancode), is_held(is_held), just_pressed(just_pressed) {} }; struct ButtonState { - SDL_GamepadButton button; // GameControllerButton asociado - bool is_held; // Está pulsada ahora mismo - bool just_pressed; // Se acaba de pulsar en este fotograma - bool axis_active; // Estado del eje + SDL_GamepadButton button; // GameControllerButton asociado + bool is_held; // Está pulsada ahora mismo + bool just_pressed; // Se acaba de pulsar en este fotograma + bool axis_active; // Estado del eje - ButtonState(SDL_GamepadButton btn = SDL_GAMEPAD_BUTTON_INVALID, bool is_held = false, bool just_pressed = false, bool axis_act = false) - : button(btn), is_held(is_held), just_pressed(just_pressed), axis_active(axis_act) {} + ButtonState(SDL_GamepadButton btn = SDL_GAMEPAD_BUTTON_INVALID, bool is_held = false, bool just_pressed = false, bool axis_act = false) + : button(btn), is_held(is_held), just_pressed(just_pressed), axis_active(axis_act) {} }; struct Keyboard { - std::unordered_map bindings; + std::unordered_map bindings; - Keyboard() - : bindings{ - // Teclado - Movimiento del jugador - {InputAction::UP, KeyState(SDL_SCANCODE_UP)}, - {InputAction::DOWN, KeyState(SDL_SCANCODE_DOWN)}, - {InputAction::LEFT, KeyState(SDL_SCANCODE_LEFT)}, - {InputAction::RIGHT, KeyState(SDL_SCANCODE_RIGHT)}, + Keyboard() + : bindings{ + // Teclado - Movimiento del jugador + {InputAction::UP, KeyState(SDL_SCANCODE_UP)}, + {InputAction::DOWN, KeyState(SDL_SCANCODE_DOWN)}, + {InputAction::LEFT, KeyState(SDL_SCANCODE_LEFT)}, + {InputAction::RIGHT, KeyState(SDL_SCANCODE_RIGHT)}, - // Teclado - Disparo del jugador - {InputAction::FIRE_LEFT, KeyState(SDL_SCANCODE_Q)}, - {InputAction::FIRE_CENTER, KeyState(SDL_SCANCODE_W)}, - {InputAction::FIRE_RIGHT, KeyState(SDL_SCANCODE_E)}, + // Teclado - Disparo del jugador + {InputAction::FIRE_LEFT, KeyState(SDL_SCANCODE_Q)}, + {InputAction::FIRE_CENTER, KeyState(SDL_SCANCODE_W)}, + {InputAction::FIRE_RIGHT, KeyState(SDL_SCANCODE_E)}, - // Teclado - Interfaz - {InputAction::START, KeyState(SDL_SCANCODE_RETURN)}, + // Teclado - Interfaz + {InputAction::START, KeyState(SDL_SCANCODE_RETURN)}, - // Teclado - Menu de servicio - {InputAction::SERVICE, KeyState(SDL_SCANCODE_0)}, - {InputAction::SM_SELECT, KeyState(SDL_SCANCODE_RETURN)}, - {InputAction::SM_BACK, KeyState(SDL_SCANCODE_BACKSPACE)}, + // Teclado - Menu de servicio + {InputAction::SERVICE, KeyState(SDL_SCANCODE_0)}, + {InputAction::SM_SELECT, KeyState(SDL_SCANCODE_RETURN)}, + {InputAction::SM_BACK, KeyState(SDL_SCANCODE_BACKSPACE)}, - // Teclado - Control del programa - {InputAction::EXIT, KeyState(SDL_SCANCODE_ESCAPE)}, - {InputAction::PAUSE, KeyState(SDL_SCANCODE_P)}, - {InputAction::BACK, KeyState(SDL_SCANCODE_BACKSPACE)}, + // Teclado - Control del programa + {InputAction::EXIT, KeyState(SDL_SCANCODE_ESCAPE)}, + {InputAction::PAUSE, KeyState(SDL_SCANCODE_P)}, + {InputAction::BACK, KeyState(SDL_SCANCODE_BACKSPACE)}, - {InputAction::WINDOW_DEC_SIZE, KeyState(SDL_SCANCODE_F1)}, - {InputAction::WINDOW_INC_SIZE, KeyState(SDL_SCANCODE_F2)}, - {InputAction::WINDOW_FULLSCREEN, KeyState(SDL_SCANCODE_F3)}, - {InputAction::TOGGLE_VIDEO_SHADERS, KeyState(SDL_SCANCODE_F4)}, - {InputAction::TOGGLE_VIDEO_INTEGER_SCALE, KeyState(SDL_SCANCODE_F5)}, - {InputAction::TOGGLE_VIDEO_VSYNC, KeyState(SDL_SCANCODE_F6)}, + {InputAction::WINDOW_DEC_SIZE, KeyState(SDL_SCANCODE_F1)}, + {InputAction::WINDOW_INC_SIZE, KeyState(SDL_SCANCODE_F2)}, + {InputAction::WINDOW_FULLSCREEN, KeyState(SDL_SCANCODE_F3)}, + {InputAction::TOGGLE_VIDEO_SHADERS, KeyState(SDL_SCANCODE_F4)}, + {InputAction::TOGGLE_VIDEO_INTEGER_SCALE, KeyState(SDL_SCANCODE_F5)}, + {InputAction::TOGGLE_VIDEO_VSYNC, KeyState(SDL_SCANCODE_F6)}, - {InputAction::TOGGLE_AUDIO, KeyState(SDL_SCANCODE_F7)}, - {InputAction::TOGGLE_AUTO_FIRE, KeyState(SDL_SCANCODE_F8)}, - {InputAction::CHANGE_LANG, KeyState(SDL_SCANCODE_F9)}, + {InputAction::TOGGLE_AUDIO, KeyState(SDL_SCANCODE_F7)}, + {InputAction::TOGGLE_AUTO_FIRE, KeyState(SDL_SCANCODE_F8)}, + {InputAction::CHANGE_LANG, KeyState(SDL_SCANCODE_F9)}, - {InputAction::RESET, KeyState(SDL_SCANCODE_F10)}, - {InputAction::SHOW_INFO, KeyState(SDL_SCANCODE_F12)}} {} + {InputAction::RESET, KeyState(SDL_SCANCODE_F10)}, + {InputAction::SHOW_INFO, KeyState(SDL_SCANCODE_F12)}} {} }; struct Gamepad { - SDL_Gamepad *pad; - SDL_JoystickID instance_id; - std::string name; - std::unordered_map bindings; + SDL_Gamepad *pad; + SDL_JoystickID instance_id; + std::string name; + std::unordered_map bindings; - Gamepad(SDL_Gamepad *gamepad) - : pad(gamepad), - instance_id(SDL_GetJoystickID(SDL_GetGamepadJoystick(gamepad))), - name(std::string(SDL_GetGamepadName(gamepad))), - bindings{ - // Mando - Movimiento del jugador - {InputAction::UP, ButtonState(SDL_GAMEPAD_BUTTON_DPAD_UP)}, - {InputAction::DOWN, ButtonState(SDL_GAMEPAD_BUTTON_DPAD_DOWN)}, - {InputAction::LEFT, ButtonState(SDL_GAMEPAD_BUTTON_DPAD_LEFT)}, - {InputAction::RIGHT, ButtonState(SDL_GAMEPAD_BUTTON_DPAD_RIGHT)}, + Gamepad(SDL_Gamepad *gamepad) + : pad(gamepad), + instance_id(SDL_GetJoystickID(SDL_GetGamepadJoystick(gamepad))), + name(std::string(SDL_GetGamepadName(gamepad))), + bindings{ + // Mando - Movimiento del jugador + {InputAction::UP, ButtonState(SDL_GAMEPAD_BUTTON_DPAD_UP)}, + {InputAction::DOWN, ButtonState(SDL_GAMEPAD_BUTTON_DPAD_DOWN)}, + {InputAction::LEFT, ButtonState(SDL_GAMEPAD_BUTTON_DPAD_LEFT)}, + {InputAction::RIGHT, ButtonState(SDL_GAMEPAD_BUTTON_DPAD_RIGHT)}, - // Mando - Disparo del jugador - {InputAction::FIRE_LEFT, ButtonState(SDL_GAMEPAD_BUTTON_WEST)}, - {InputAction::FIRE_CENTER, ButtonState(SDL_GAMEPAD_BUTTON_NORTH)}, - {InputAction::FIRE_RIGHT, ButtonState(SDL_GAMEPAD_BUTTON_EAST)}, + // Mando - Disparo del jugador + {InputAction::FIRE_LEFT, ButtonState(SDL_GAMEPAD_BUTTON_WEST)}, + {InputAction::FIRE_CENTER, ButtonState(SDL_GAMEPAD_BUTTON_NORTH)}, + {InputAction::FIRE_RIGHT, ButtonState(SDL_GAMEPAD_BUTTON_EAST)}, - // Mando - Interfaz - {InputAction::START, ButtonState(SDL_GAMEPAD_BUTTON_START)}, - {InputAction::SERVICE, ButtonState(SDL_GAMEPAD_BUTTON_BACK)}} {} + // Mando - Interfaz + {InputAction::START, ButtonState(SDL_GAMEPAD_BUTTON_START)}, + {InputAction::SERVICE, ButtonState(SDL_GAMEPAD_BUTTON_BACK)}} {} - ~Gamepad() { - if (pad) { - SDL_CloseGamepad(pad); + ~Gamepad() { + if (pad) { + SDL_CloseGamepad(pad); + } + } + + // Reasigna un botón a una acción + void rebindAction(InputAction action, SDL_GamepadButton new_button) { + bindings[action] = new_button; } - } }; // --- Métodos de singleton --- - static void init(const std::string &game_controller_db_path); - static void destroy(); - static auto get() -> Input *; + static void init(const std::string &game_controller_db_path, const std::string &gamepad_configs_file); + static void destroy(); + static auto get() -> Input *; // --- Métodos de configuración de controles --- - void bindKey(Action input, SDL_Scancode code); - void bindGameControllerButton(std::shared_ptr gamepad, Action input, SDL_GamepadButton button); - void bindGameControllerButton(std::shared_ptr gamepad, Action input_target, Action input_source); + void bindKey(Action input, SDL_Scancode code); + void bindGameControllerButton(std::shared_ptr gamepad, Action input, SDL_GamepadButton button); + void bindGameControllerButton(std::shared_ptr gamepad, Action input_target, Action input_source); // --- Métodos de consulta de entrada --- - void update(); - auto checkAction(Action input, bool repeat = true, bool check_keyboard = true, std::shared_ptr gamepad = nullptr) -> bool; - auto checkAnyInput(bool check_keyboard = true, std::shared_ptr gamepad = nullptr) -> bool; - auto checkAnyButton(bool repeat = DO_NOT_ALLOW_REPEAT) -> bool; + void update(); + auto checkAction(Action input, bool repeat = true, bool check_keyboard = true, std::shared_ptr gamepad = nullptr) -> bool; + auto checkAnyInput(bool check_keyboard = true, std::shared_ptr gamepad = nullptr) -> bool; + auto checkAnyButton(bool repeat = DO_NOT_ALLOW_REPEAT) -> bool; // --- Métodos de gestión de mandos --- - [[nodiscard]] auto gameControllerFound() const -> bool; - auto getControllerName(std::shared_ptr gamepad) const -> std::string; - [[nodiscard]] auto getNumControllers() const -> int; - [[nodiscard]] auto getJoyIndex(SDL_JoystickID id) const -> int; + [[nodiscard]] auto gameControllerFound() const -> bool; + auto getControllerName(std::shared_ptr gamepad) const -> std::string; + [[nodiscard]] auto getNumControllers() const -> int; + [[nodiscard]] auto getJoyIndex(SDL_JoystickID id) const -> int; // --- Métodos de consulta y utilidades --- - [[nodiscard]] auto getControllerBinding(std::shared_ptr gamepad, Action input) const -> SDL_GamepadButton; - [[nodiscard]] static auto inputToString(Action input) -> std::string; - [[nodiscard]] static auto stringToInput(const std::string &name) -> Action; + [[nodiscard]] auto getControllerBinding(std::shared_ptr gamepad, Action input) const -> SDL_GamepadButton; + [[nodiscard]] static auto inputToString(Action input) -> std::string; + [[nodiscard]] static auto stringToInput(const std::string &name) -> Action; // --- Métodos de reseteo de estado de entrada --- - void resetInputStates(); + void resetInputStates(); // --- Eventos --- - void handleEvent(const SDL_Event &event); + void handleEvent(const SDL_Event &event); void printConnectedGamepads() const; [[nodiscard]] auto getGamepads() const -> const std::vector> & { return gamepads_; } - // --- Métodos para integración con GamepadConfigManager --- - void loadGamepadConfigs(const std::string& filename); - void saveGamepadConfigs(const std::string& filename) const; - void applyConfigToGamepad(std::shared_ptr gamepad, const GamepadConfig& config); - private: // --- Constantes --- static constexpr Sint16 AXIS_THRESHOLD = 30000; // --- Variables internas --- - std::vector> gamepads_; - Keyboard keyboard_; - std::vector button_inputs_; - std::string game_controller_db_path_; + std::vector> gamepads_; + Keyboard keyboard_; + std::vector button_inputs_; + std::string game_controller_db_path_; + std::string gamepad_configs_file_; + GamepadConfigs gamepad_configs_; // --- Métodos internos --- - void initSDLGamePad(); - auto checkAxisInput(Action input, std::shared_ptr gamepad, bool repeat) -> bool; + void initSDLGamePad(); + auto checkAxisInput(Action input, std::shared_ptr gamepad, bool repeat) -> bool; void add_gamepad(int device_index); void remove_gamepad(SDL_JoystickID id); + void addGamepadMappingsFromFile(); + void discoverGamepads(); + + // --- Métodos para integración con GamepadConfigManager --- + void loadGamepadConfigs(); + void saveGamepadConfigs(); + void applyGamepadConfig(std::shared_ptr gamepad); + void saveGamepadConfigFromGamepad(std::shared_ptr gamepad); + + // Métodos auxiliares opcionales + void setGamepadConfigsFile(const std::string& filename); + GamepadConfig* getGamepadConfig(const std::string& gamepadName); + bool removeGamepadConfig(const std::string& gamepadName); // --- Constructor y destructor --- - explicit Input(std::string game_controller_db_path); - ~Input() = default; + explicit Input(std::string game_controller_db_path, std::string gamepad_configs_file); + ~Input() = default; // --- Singleton --- static Input *instance; diff --git a/source/options.cpp b/source/options.cpp index 51de11a..2a603f2 100644 --- a/source/options.cpp +++ b/source/options.cpp @@ -47,7 +47,7 @@ void init() { controllers.emplace_back(GamepadOptions(2)); setKeyboardToPlayer(1); - // Opciones pendientes + // Opciones de cambios pendientes pending_changes.new_language = settings.language; pending_changes.new_difficulty = settings.difficulty; pending_changes.has_pending_changes = false; diff --git a/source/param.cpp b/source/param.cpp index c971902..04f55e1 100644 --- a/source/param.cpp +++ b/source/param.cpp @@ -30,8 +30,7 @@ void initParam() { param.game.play_area.rect = {0, 0, param.game.width, 216}; param.game.name_entry_idle_time = 10; param.game.name_entry_total_time = 60; - // param.game.speed = 15; - param.game.speed = 1000 / 60; + param.game.speed = 15; param.game.hit_stop = true; param.game.hit_stop_ms = 300; precalculateZones();