afegit soport per a axis del mando

This commit is contained in:
2025-03-16 17:45:07 +01:00
parent 64ee2d1e45
commit 0a5996f220
6 changed files with 273 additions and 217 deletions

View File

@@ -203,11 +203,8 @@ void Director::createSystemFolder(const std::string &folder)
// Inicia las variables necesarias para arrancar el programa
void Director::initInput()
{
// Establece si ha de mostrar mensajes
Input::get()->setVerbose(options.console);
// Busca si hay un mando conectado
Input::get()->discoverGameController();
Input::get()->discoverGameControllers();
// Teclado - Movimiento
if (options.keys == ControlScheme::CURSOR)
@@ -250,24 +247,29 @@ void Director::initInput()
Input::get()->bindKey(InputAction::TOGGLE_MUSIC, SDL_SCANCODE_M);
Input::get()->bindKey(InputAction::TOGGLE_BORDER, SDL_SCANCODE_B);
// Mando - Movimiento
Input::get()->bindGameControllerButton(InputAction::JUMP, SDL_CONTROLLER_BUTTON_B);
Input::get()->bindGameControllerButton(InputAction::LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
Input::get()->bindGameControllerButton(InputAction::RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
// MANDO
const int NUM_GAMEPADS = Input::get()->getNumControllers();
for (int i = 0; i < NUM_GAMEPADS; ++i)
{
// Movimiento
Input::get()->bindGameControllerButton(i, InputAction::JUMP, SDL_CONTROLLER_BUTTON_B);
Input::get()->bindGameControllerButton(i, InputAction::LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
Input::get()->bindGameControllerButton(i, InputAction::RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
// Mando - Otros
Input::get()->bindGameControllerButton(InputAction::ACCEPT, SDL_CONTROLLER_BUTTON_B);
Input::get()->bindGameControllerButton(InputAction::CANCEL, SDL_CONTROLLER_BUTTON_A);
// Otros
Input::get()->bindGameControllerButton(i, InputAction::ACCEPT, SDL_CONTROLLER_BUTTON_B);
Input::get()->bindGameControllerButton(i, InputAction::CANCEL, SDL_CONTROLLER_BUTTON_A);
#ifdef GAME_CONSOLE
Input::get()->bindGameControllerButton(InputAction::input_pause, SDL_CONTROLLER_BUTTON_BACK);
Input::get()->bindGameControllerButton(InputAction::input_exit, SDL_CONTROLLER_BUTTON_START);
Input::get()->bindGameControllerButton(i, InputAction::input_pause, SDL_CONTROLLER_BUTTON_BACK);
Input::get()->bindGameControllerButton(i, InputAction::input_exit, SDL_CONTROLLER_BUTTON_START);
#else
Input::get()->bindGameControllerButton(InputAction::PAUSE, SDL_CONTROLLER_BUTTON_START);
Input::get()->bindGameControllerButton(InputAction::EXIT, SDL_CONTROLLER_BUTTON_BACK);
Input::get()->bindGameControllerButton(i, InputAction::PAUSE, SDL_CONTROLLER_BUTTON_START);
Input::get()->bindGameControllerButton(i, InputAction::EXIT, SDL_CONTROLLER_BUTTON_BACK);
#endif
Input::get()->bindGameControllerButton(InputAction::NEXT_PALETTE, SDL_CONTROLLER_BUTTON_LEFTSHOULDER);
Input::get()->bindGameControllerButton(InputAction::TOGGLE_MUSIC, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);
Input::get()->bindGameControllerButton(InputAction::TOGGLE_BORDER, SDL_CONTROLLER_BUTTON_X);
Input::get()->bindGameControllerButton(i, InputAction::NEXT_PALETTE, SDL_CONTROLLER_BUTTON_LEFTSHOULDER);
Input::get()->bindGameControllerButton(i, InputAction::TOGGLE_MUSIC, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);
Input::get()->bindGameControllerButton(i, InputAction::TOGGLE_BORDER, SDL_CONTROLLER_BUTTON_X);
}
}
// Inicializa JailAudio

View File

@@ -9,7 +9,7 @@
#include "defines.h" // Para BLOCK, PLAY_AREA_HEIGHT, BORDER_BOTTOM
#include "global_events.h" // Para check
#include "global_inputs.h" // Para check
#include "input.h" // Para Input, InputAction, REPEAT_FALSE
#include "input.h" // Para Input, InputAction, INPUT_DO_NOT_ALLOW_REPEAT
#include "item_tracker.h" // Para ItemTracker
#include "jail_audio.h" // Para JA_PauseMusic, JA_GetMusicState, JA_P...
#include "notifier.h" // Para Notifier, NotificationText, CHEEVO_NO...
@@ -82,14 +82,14 @@ void Game::checkEvents()
// Comprueba el teclado
void Game::checkInput()
{
if (Input::get()->checkInput(InputAction::TOGGLE_MUSIC, REPEAT_FALSE))
if (Input::get()->checkInput(InputAction::TOGGLE_MUSIC, INPUT_DO_NOT_ALLOW_REPEAT))
{
board_->music = !board_->music;
board_->music ? JA_ResumeMusic() : JA_PauseMusic();
Notifier::get()->show({"MUSIC " + std::string(board_->music ? "ENABLED" : "DISABLED")}, NotificationText::CENTER);
}
else if (Input::get()->checkInput(InputAction::PAUSE, REPEAT_FALSE))
else if (Input::get()->checkInput(InputAction::PAUSE, INPUT_DO_NOT_ALLOW_REPEAT))
{
togglePause();
Notifier::get()->show({std::string(paused_ ? "GAME PAUSED" : "GAME RUNNING")}, NotificationText::CENTER);

View File

@@ -3,7 +3,7 @@
#include <SDL2/SDL_stdinc.h> // Para SDL_FALSE, SDL_TRUE
#include <string> // Para allocator, operator+, char_traits, string
#include <vector> // Para vector
#include "input.h" // Para Input, InputAction, REPEAT_FALSE
#include "input.h" // Para Input, InputAction, INPUT_DO_NOT_ALLOW_REPEAT
#include "notifier.h" // Para Notifier, NotificationText
#include "options.h" // Para Options, options, OptionsVideo, Section
#include "screen.h" // Para Screen
@@ -51,29 +51,29 @@ namespace globalInputs
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
void check()
{
if (Input::get()->checkInput(InputAction::EXIT, REPEAT_FALSE))
if (Input::get()->checkInput(InputAction::EXIT, INPUT_DO_NOT_ALLOW_REPEAT))
{
quit();
}
else if (Input::get()->checkInput(InputAction::ACCEPT, REPEAT_FALSE))
else if (Input::get()->checkInput(InputAction::ACCEPT, INPUT_DO_NOT_ALLOW_REPEAT))
{
skip_section();
}
else if (Input::get()->checkInput(InputAction::TOGGLE_BORDER, REPEAT_FALSE))
else if (Input::get()->checkInput(InputAction::TOGGLE_BORDER, INPUT_DO_NOT_ALLOW_REPEAT))
{
Screen::get()->toggleBorder();
Notifier::get()->show({"BORDER " + std::string(options.video.border.enabled ? "ENABLED" : "DISABLED")}, NotificationText::CENTER);
}
else if (Input::get()->checkInput(InputAction::TOGGLE_VIDEOMODE, REPEAT_FALSE))
else if (Input::get()->checkInput(InputAction::TOGGLE_VIDEOMODE, INPUT_DO_NOT_ALLOW_REPEAT))
{
Screen::get()->toggleVideoMode();
Notifier::get()->show({"FULLSCREEN " + std::string(options.video.mode == 0 ? "DISABLED" : "ENABLED")}, NotificationText::CENTER);
}
else if (Input::get()->checkInput(InputAction::WINDOW_DEC_ZOOM, REPEAT_FALSE))
else if (Input::get()->checkInput(InputAction::WINDOW_DEC_ZOOM, INPUT_DO_NOT_ALLOW_REPEAT))
{
if (Screen::get()->decWindowZoom())
{
@@ -81,7 +81,7 @@ namespace globalInputs
}
}
else if (Input::get()->checkInput(InputAction::WINDOW_INC_ZOOM, REPEAT_FALSE))
else if (Input::get()->checkInput(InputAction::WINDOW_INC_ZOOM, INPUT_DO_NOT_ALLOW_REPEAT))
{
if (Screen::get()->incWindowZoom())
{
@@ -89,25 +89,25 @@ namespace globalInputs
}
}
else if (Input::get()->checkInput(InputAction::TOGGLE_SHADERS, REPEAT_FALSE))
else if (Input::get()->checkInput(InputAction::TOGGLE_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT))
{
Screen::get()->toggleShaders();
Notifier::get()->show({"SHADERS " + std::string(options.video.shaders ? "ENABLED" : "DISABLED")}, NotificationText::CENTER);
}
else if (Input::get()->checkInput(InputAction::NEXT_PALETTE, REPEAT_FALSE))
else if (Input::get()->checkInput(InputAction::NEXT_PALETTE, INPUT_DO_NOT_ALLOW_REPEAT))
{
Screen::get()->nextPalette();
Notifier::get()->show({"PALETTE " + options.video.palette}, NotificationText::CENTER);
}
else if (Input::get()->checkInput(InputAction::PREVIOUS_PALETTE, REPEAT_FALSE))
else if (Input::get()->checkInput(InputAction::PREVIOUS_PALETTE, INPUT_DO_NOT_ALLOW_REPEAT))
{
Screen::get()->previousPalette();
Notifier::get()->show({"PALETTE " + options.video.palette}, NotificationText::CENTER);
}
else if (Input::get()->checkInput(InputAction::TOGGLE_INTEGER_SCALE, REPEAT_FALSE))
else if (Input::get()->checkInput(InputAction::TOGGLE_INTEGER_SCALE, INPUT_DO_NOT_ALLOW_REPEAT))
{
options.video.integer_scale = !options.video.integer_scale;
SDL_RenderSetIntegerScale(Screen::get()->getRenderer(), options.video.integer_scale ? SDL_TRUE : SDL_FALSE);

View File

@@ -2,9 +2,12 @@
#include <SDL2/SDL.h> // Para SDL_INIT_GAMECONTROLLER, SDL_InitSubS...
#include <SDL2/SDL_error.h> // Para SDL_GetError
#include <SDL2/SDL_events.h> // Para SDL_ENABLE
#include <SDL2/SDL_joystick.h> // Para SDL_NumJoysticks
#include <SDL2/SDL_keyboard.h> // Para SDL_GetKeyboardState
#include <iostream> // Para basic_ostream, operator<<, cout, basi...
#include <algorithm> // Para find
#include <iostream> // Para basic_ostream, operator<<, cout, endl
#include <iterator> // Para distance
#include <unordered_map> // Para unordered_map, operator==, _Node_cons...
#include <utility> // Para pair
// [SINGLETON]
Input *Input::input_ = nullptr;
@@ -29,18 +32,17 @@ Input *Input::get()
// Constructor
Input::Input(const std::string &game_controller_db_path)
: db_path_(game_controller_db_path)
: game_controller_db_path_(game_controller_db_path)
{
// Inicializa las variables
KeyBindings kb;
kb.scancode = 0;
kb.active = false;
key_bindings_.resize(static_cast<int>(InputAction::SIZE), kb);
// Busca si hay mandos conectados
discoverGameControllers();
GameControllerBindings gcb;
gcb.button = SDL_CONTROLLER_BUTTON_INVALID;
gcb.active = false;
game_controller_bindings_.resize(static_cast<int>(InputAction::SIZE), gcb);
// Inicializa los vectores
key_bindings_.resize(static_cast<int>(InputAction::SIZE), KeyBindings());
controller_bindings_.resize(num_gamepads_, std::vector<ControllerBindings>(static_cast<int>(InputAction::SIZE), ControllerBindings()));
// Listado de los inputs para jugar que utilizan botones, ni palancas ni crucetas
button_inputs_ = {InputAction::JUMP};
}
// Asigna inputs a teclas
@@ -50,133 +52,117 @@ void Input::bindKey(InputAction input, SDL_Scancode code)
}
// Asigna inputs a botones del mando
void Input::bindGameControllerButton(InputAction input, SDL_GameControllerButton button)
void Input::bindGameControllerButton(int controller_index, InputAction input, SDL_GameControllerButton button)
{
game_controller_bindings_.at(static_cast<int>(input)).button = button;
if (controller_index < num_gamepads_)
{
controller_bindings_.at(controller_index).at(static_cast<int>(input)).button = button;
}
}
// Asigna inputs a botones del mando
void Input::bindGameControllerButton(int controller_index, InputAction input_target, InputAction input_source)
{
if (controller_index < num_gamepads_)
{
controller_bindings_.at(controller_index).at(static_cast<int>(input_target)).button = controller_bindings_.at(controller_index).at(static_cast<int>(input_source)).button;
}
}
// Comprueba si un input esta activo
bool Input::checkInput(InputAction input, bool repeat, int device, int index)
bool Input::checkInput(InputAction input, bool repeat, InputDeviceToUse device, int controller_index)
{
if (!enabled_)
{
return false;
}
bool success_keyboard = false;
bool success_controller = false;
const int input_index = static_cast<int>(input);
bool successKeyboard = false;
bool successGameController = false;
if (device == INPUT_USE_ANY)
{
index = 0;
}
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY)
if (device == InputDeviceToUse::KEYBOARD || device == InputDeviceToUse::ANY)
{
const Uint8 *keyStates = SDL_GetKeyboardState(nullptr);
if (repeat)
{
if (keyStates[key_bindings_.at(static_cast<int>(input)).scancode] != 0)
{
successKeyboard = true;
}
else
{
successKeyboard = false;
}
success_keyboard = keyStates[key_bindings_[input_index].scancode] != 0;
}
else
{
if (!key_bindings_.at(static_cast<int>(input)).active)
if (!key_bindings_[input_index].active)
{
if (keyStates[key_bindings_.at(static_cast<int>(input)).scancode] != 0)
if (keyStates[key_bindings_[input_index].scancode] != 0)
{
key_bindings_.at(static_cast<int>(input)).active = true;
successKeyboard = true;
key_bindings_[input_index].active = true;
success_keyboard = true;
}
else
{
successKeyboard = false;
success_keyboard = false;
}
}
else
{
if (keyStates[key_bindings_.at(static_cast<int>(input)).scancode] == 0)
if (keyStates[key_bindings_[input_index].scancode] == 0)
{
key_bindings_.at(static_cast<int>(input)).active = false;
successKeyboard = false;
key_bindings_[input_index].active = false;
}
success_keyboard = false;
}
}
}
if (gameControllerFound() && controller_index >= 0 && controller_index < num_gamepads_)
{
if ((device == InputDeviceToUse::CONTROLLER) || (device == InputDeviceToUse::ANY))
{
success_controller = checkAxisInput(input, controller_index, repeat);
if (!success_controller)
{
if (repeat)
{
success_controller = SDL_GameControllerGetButton(connected_controllers_.at(controller_index), controller_bindings_.at(controller_index).at(input_index).button) != 0;
}
else
{
successKeyboard = false;
if (!controller_bindings_.at(controller_index).at(input_index).active)
{
if (SDL_GameControllerGetButton(connected_controllers_.at(controller_index), controller_bindings_.at(controller_index).at(input_index).button) != 0)
{
controller_bindings_.at(controller_index).at(input_index).active = true;
success_controller = true;
}
else
{
success_controller = false;
}
}
else
{
if (SDL_GameControllerGetButton(connected_controllers_.at(controller_index), controller_bindings_.at(controller_index).at(input_index).button) == 0)
{
controller_bindings_.at(controller_index).at(input_index).active = false;
}
success_controller = false;
}
}
}
}
}
if (gameControllerFound())
if ((device == INPUT_USE_GAMECONTROLLER) || (device == INPUT_USE_ANY))
{
if (repeat)
{
if (SDL_GameControllerGetButton(connected_controllers_.at(index), game_controller_bindings_.at(static_cast<int>(input)).button) != 0)
{
successGameController = true;
}
else
{
successGameController = false;
}
}
else
{
if (!game_controller_bindings_.at(static_cast<int>(input)).active)
{
if (SDL_GameControllerGetButton(connected_controllers_.at(index), game_controller_bindings_.at(static_cast<int>(input)).button) != 0)
{
game_controller_bindings_.at(static_cast<int>(input)).active = true;
successGameController = true;
}
else
{
successGameController = false;
}
}
else
{
if (SDL_GameControllerGetButton(connected_controllers_.at(index), game_controller_bindings_.at(static_cast<int>(input)).button) == 0)
{
game_controller_bindings_.at(static_cast<int>(input)).active = false;
successGameController = false;
}
else
{
successGameController = false;
}
}
}
}
return (successKeyboard || successGameController);
return (success_keyboard || success_controller);
}
// Comprueba si hay almenos un input activo
bool Input::checkAnyInput(int device, int index)
bool Input::checkAnyInput(InputDeviceToUse device, int controller_index)
{
if (device == INPUT_USE_ANY)
{
index = 0;
}
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY)
if (device == InputDeviceToUse::KEYBOARD || device == InputDeviceToUse::ANY)
{
const Uint8 *mKeystates = SDL_GetKeyboardState(nullptr);
for (int i = 0; i < (int)key_bindings_.size(); ++i)
{
if (mKeystates[key_bindings_[i].scancode] != 0)
if (mKeystates[key_bindings_[i].scancode] != 0 && !key_bindings_[i].active)
{
key_bindings_[i].active = true;
return true;
}
}
@@ -184,12 +170,13 @@ bool Input::checkAnyInput(int device, int index)
if (gameControllerFound())
{
if (device == INPUT_USE_GAMECONTROLLER || device == INPUT_USE_ANY)
if (device == InputDeviceToUse::CONTROLLER || device == InputDeviceToUse::ANY)
{
for (int i = 0; i < (int)game_controller_bindings_.size(); ++i)
for (int i = 0; i < (int)controller_bindings_.size(); ++i)
{
if (SDL_GameControllerGetButton(connected_controllers_.at(index), game_controller_bindings_[i].button) != 0)
if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][i].button) != 0 && !controller_bindings_[controller_index][i].active)
{
controller_bindings_[controller_index][i].active = true;
return true;
}
}
@@ -199,8 +186,8 @@ bool Input::checkAnyInput(int device, int index)
return false;
}
// Busca si hay un mando conectado
bool Input::discoverGameController()
// Busca si hay mandos conectados
bool Input::discoverGameControllers()
{
bool found = false;
@@ -209,30 +196,35 @@ bool Input::discoverGameController()
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
}
if (SDL_GameControllerAddMappingsFromFile(db_path_.c_str()) < 0)
if (SDL_GameControllerAddMappingsFromFile(game_controller_db_path_.c_str()) < 0)
{
if (verbose_)
{
std::cout << "Error, could not load " << db_path_.c_str() << " file: " << SDL_GetError() << std::endl;
}
std::cout << "Error, could not load " << game_controller_db_path_.c_str() << " file: " << SDL_GetError() << std::endl;
}
const int nJoysticks = SDL_NumJoysticks();
num_joysticks_ = SDL_NumJoysticks();
num_gamepads_ = 0;
// Cuenta el numero de mandos
for (int i = 0; i < nJoysticks; ++i)
// Cuenta el número de mandos
joysticks_.clear();
for (int i = 0; i < num_joysticks_; ++i)
{
auto joy = SDL_JoystickOpen(i);
joysticks_.push_back(joy);
if (SDL_IsGameController(i))
{
num_gamepads_++;
}
}
if (verbose_)
std::cout << "\n** LOOKING FOR GAME CONTROLLERS" << std::endl;
if (num_joysticks_ != num_gamepads_)
{
std::cout << "\nChecking for game controllers...\n";
std::cout << nJoysticks << " joysticks found, " << num_gamepads_ << " are gamepads\n";
std::cout << "Joysticks found: " << num_joysticks_ << std::endl;
std::cout << "Gamepads found : " << num_gamepads_ << std::endl;
}
else
{
std::cout << "Gamepads found: " << num_gamepads_ << std::endl;
}
if (num_gamepads_ > 0)
@@ -242,69 +234,110 @@ bool Input::discoverGameController()
for (int i = 0; i < num_gamepads_; i++)
{
// Abre el mando y lo añade a la lista
SDL_GameController *pad = SDL_GameControllerOpen(i);
auto pad = SDL_GameControllerOpen(i);
if (SDL_GameControllerGetAttached(pad) == 1)
{
connected_controllers_.push_back(pad);
const std::string separator(" #");
std::string name = SDL_GameControllerNameForIndex(i);
name.resize(25);
name = name + separator + std::to_string(i);
if (verbose_)
{
std::cout << name << std::endl;
}
const std::string name = SDL_GameControllerNameForIndex(i);
std::cout << "#" << i << ": " << name << std::endl;
controller_names_.push_back(name);
}
else
{
if (verbose_)
{
std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl;
}
std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl;
}
}
SDL_GameControllerEventState(SDL_ENABLE);
}
std::cout << "\n** FINISHED LOOKING FOR GAME CONTROLLERS" << std::endl;
return found;
}
// Comprueba si hay algun mando conectado
bool Input::gameControllerFound()
{
if (num_gamepads_ > 0)
{
return true;
}
else
{
return false;
}
}
bool Input::gameControllerFound() { return num_gamepads_ > 0 ? true : false; }
// Obten el nombre de un mando de juego
std::string Input::getControllerName(int index)
std::string Input::getControllerName(int controller_index) const { return num_gamepads_ > 0 ? controller_names_.at(controller_index) : std::string(); }
// Obten el número de mandos conectados
int Input::getNumControllers() const { return num_gamepads_; }
// Obtiene el indice del controlador a partir de un event.id
int Input::getJoyIndex(int id) const
{
if (num_gamepads_ > 0)
for (int i = 0; i < num_joysticks_; ++i)
{
return controller_names_[index];
if (SDL_JoystickInstanceID(joysticks_[i]) == id)
{
return i;
}
}
return -1;
}
// Obtiene el SDL_GameControllerButton asignado a un input
SDL_GameControllerButton Input::getControllerBinding(int controller_index, InputAction input) const
{
return controller_bindings_[controller_index][static_cast<int>(input)].button;
}
// Obtiene el indice a partir del nombre del mando
int Input::getIndexByName(const std::string &name) const
{
auto it = std::find(controller_names_.begin(), controller_names_.end(), name);
return it != controller_names_.end() ? std::distance(controller_names_.begin(), it) : -1;
}
// Comprueba el eje del mando
bool Input::checkAxisInput(InputAction input, int controller_index, bool repeat)
{
// Umbral para considerar el eje como activo
const Sint16 threshold = 30000;
bool axis_active_now = false;
switch (input)
{
case InputAction::LEFT:
axis_active_now = SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) < -threshold;
break;
case InputAction::RIGHT:
axis_active_now = SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) > threshold;
break;
case InputAction::UP:
axis_active_now = SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) < -threshold;
break;
case InputAction::DOWN:
axis_active_now = SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) > threshold;
break;
default:
return false;
}
// Referencia al binding correspondiente
auto &binding = controller_bindings_.at(controller_index).at(static_cast<int>(input));
if (repeat)
{
// Si se permite repetir, simplemente devolvemos el estado actual
return axis_active_now;
}
else
{
return "";
// Si no se permite repetir, aplicamos la lógica de transición
if (axis_active_now && !binding.axis_active)
{
// Transición de inactivo a activo
binding.axis_active = true;
return true;
}
else if (!axis_active_now && binding.axis_active)
{
// Transición de activo a inactivo
binding.axis_active = false;
}
// Mantener el estado actual
return false;
}
}
// Obten el numero de mandos conectados
int Input::getNumControllers()
{
return num_gamepads_;
}
// Establece si ha de mostrar mensajes
void Input::setVerbose(bool value)
{
verbose_ = value;
}

View File

@@ -7,18 +7,20 @@
#include <vector> // Para vector
// Definiciones de repetición
constexpr bool REPEAT_TRUE = true;
constexpr bool REPEAT_FALSE = false;
constexpr bool INPUT_ALLOW_REPEAT = true;
constexpr bool INPUT_DO_NOT_ALLOW_REPEAT = false;
// Tipos de entrada
constexpr int INPUT_USE_KEYBOARD = 0;
constexpr int INPUT_USE_GAMECONTROLLER = 1;
constexpr int INPUT_USE_ANY = 2;
enum class InputDeviceToUse : int
{
KEYBOARD = 0,
CONTROLLER = 1,
ANY = 2,
};
enum class InputAction
{
// Inputs obligatorios
NONE,
UP,
DOWN,
LEFT,
@@ -41,6 +43,7 @@ enum class InputAction
TOGGLE_SHADERS,
// Input obligatorio
NONE,
SIZE
};
@@ -54,25 +57,36 @@ private:
{
Uint8 scancode; // Scancode asociado
bool active; // Indica si está activo
// Constructor
explicit KeyBindings(Uint8 sc = 0, bool act = false)
: scancode(sc), active(act) {}
};
struct GameControllerBindings
struct ControllerBindings
{
SDL_GameControllerButton button; // GameControllerButton asociado
bool active; // Indica si está activo
bool axis_active; // Estado del eje
// Constructor
explicit ControllerBindings(SDL_GameControllerButton btn = SDL_CONTROLLER_BUTTON_INVALID, bool act = false, bool axis_act = false)
: button(btn), active(act), axis_active(axis_act) {}
};
// Objetos y punteros
std::vector<SDL_GameController *> connected_controllers_; // Vector con todos los mandos conectados
// Variables
std::vector<KeyBindings> key_bindings_; // Vector con las teclas asociadas a los inputs predefinidos
std::vector<GameControllerBindings> game_controller_bindings_; // Vector con las teclas asociadas a los inputs predefinidos
std::vector<std::string> controller_names_; // Vector con los nombres de los mandos
int num_gamepads_ = 0; // Numero de mandos conectados
std::string db_path_; // Ruta al archivo gamecontrollerdb.txt
bool verbose_ = true; // Indica si ha de mostrar mensajes
bool enabled_ = true; // Indica si está habilitado
std::vector<SDL_GameController *> connected_controllers_; // Vector con todos los mandos conectados
std::vector<SDL_Joystick *> joysticks_; // Vector con todos los joysticks conectados
std::vector<KeyBindings> key_bindings_; // Vector con las teclas asociadas a los inputs predefinidos
std::vector<std::vector<ControllerBindings>> controller_bindings_; // Vector con los botones asociadas a los inputs predefinidos para cada mando
std::vector<std::string> controller_names_; // Vector con los nombres de los mandos
std::vector<InputAction> button_inputs_; // Inputs asignados al jugador y a botones, excluyendo direcciones
int num_joysticks_ = 0; // Número de joysticks conectados
int num_gamepads_ = 0; // Número de mandos conectados
std::string game_controller_db_path_; // Ruta al archivo gamecontrollerdb.txt
// Comprueba el eje del mando
bool checkAxisInput(InputAction input, int controller_index, bool repeat);
// Constructor
explicit Input(const std::string &game_controller_db_path);
@@ -94,26 +108,33 @@ public:
void bindKey(InputAction input, SDL_Scancode code);
// Asigna inputs a botones del mando
void bindGameControllerButton(InputAction input, SDL_GameControllerButton button);
void bindGameControllerButton(int controller_index, InputAction input, SDL_GameControllerButton button);
void bindGameControllerButton(int controller_index, InputAction inputTarget, InputAction inputSource);
// Comprueba si un input esta activo
bool checkInput(InputAction input, bool repeat = true, int device = INPUT_USE_ANY, int index = 0);
bool checkInput(InputAction input, bool repeat = true, InputDeviceToUse device = InputDeviceToUse::ANY, int controller_index = 0);
// Comprueba si hay almenos un input activo
bool checkAnyInput(int device = INPUT_USE_ANY, int index = 0);
bool checkAnyInput(InputDeviceToUse device = InputDeviceToUse::ANY, int controller_index = 0);
// Busca si hay un mando conectado
bool discoverGameController();
// Busca si hay mandos conectados
bool discoverGameControllers();
// Comprueba si hay algun mando conectado
bool gameControllerFound();
// Obten el numero de mandos conectados
int getNumControllers();
// Obten el número de mandos conectados
int getNumControllers() const;
// Obten el nombre de un mando de juego
std::string getControllerName(int index);
std::string getControllerName(int controller_index) const;
// Establece si ha de mostrar mensajes
void setVerbose(bool value);
// Obtiene el indice del controlador a partir de un event.id
int getJoyIndex(int id) const;
// Obtiene el SDL_GameControllerButton asignado a un input
SDL_GameControllerButton getControllerBinding(int controller_index, InputAction input) const;
// Obtiene el indice a partir del nombre del mando
int getIndexByName(const std::string &name) const;
};

View File

@@ -7,7 +7,7 @@
#include "defines.h" // Para PLAY_AREA_CENTER_X, GAMECANVAS_WIDTH
#include "global_events.h" // Para check
#include "global_inputs.h" // Para check
#include "input.h" // Para Input, InputAction, REPEAT_FALSE, REP...
#include "input.h" // Para Input, InputAction, INPUT_DO_NOT_ALLOW_REPEAT, REP...
#include "options.h" // Para Options, options, SectionState, Section
#include "resource.h" // Para Resource
#include "s_sprite.h" // Para SSprite
@@ -96,22 +96,22 @@ void Title::checkInput()
{
if (show_cheevos_)
{
if (Input::get()->checkInput(InputAction::DOWN, REPEAT_TRUE))
if (Input::get()->checkInput(InputAction::DOWN, INPUT_ALLOW_REPEAT))
{
moveCheevosList(1);
}
else if (Input::get()->checkInput(InputAction::UP, REPEAT_TRUE))
else if (Input::get()->checkInput(InputAction::UP, INPUT_ALLOW_REPEAT))
{
moveCheevosList(0);
}
else if (Input::get()->checkInput(InputAction::ACCEPT, REPEAT_FALSE))
else if (Input::get()->checkInput(InputAction::ACCEPT, INPUT_DO_NOT_ALLOW_REPEAT))
{
hideCheevosList();
counter_ = 0;
}
}
if (Input::get()->checkInput(InputAction::ACCEPT, REPEAT_FALSE))
if (Input::get()->checkInput(InputAction::ACCEPT, INPUT_DO_NOT_ALLOW_REPEAT))
{
if (state_ == TitleState::SHOW_LOADING_SCREEN)
{