diff --git a/source/common/input.cpp b/source/common/input.cpp index de90b7b..6521fb6 100644 --- a/source/common/input.cpp +++ b/source/common/input.cpp @@ -404,18 +404,38 @@ void Input::printBindings(int device, int index) } // Muestra el nombre del mando - std::cout << "\n" << controllerNames[index] << std::endl; + std::cout << "\n" + << controllerNames[index] << std::endl; // Muestra los botones asignados for (auto bi : buttonInputs) { - std::cout << to_String(bi) << " : " << gameControllerBindings[index][bi].button << std::endl; + std::cout << to_string(bi) << " : " << gameControllerBindings[index][bi].button << std::endl; } } } +// Obtiene el SDL_GameControllerButton asignado a un input +SDL_GameControllerButton Input::getControllerBinding(int index, inputs_e input) +{ + return gameControllerBindings[index][input].button; +} + +// Obtiene el indice a partir del nombre del mando +int Input::getIndexByName(std::string name) +{ + for (int i = 0; i < numGamepads; ++i) + { + if (controllerNames[i] == name) + { + return i; + } + } + return -1; +} + // Convierte un inputs_e a std::string -std::string Input::to_String(inputs_e input) +std::string Input::to_string(inputs_e input) { if (input == input_fire_left) { @@ -438,4 +458,30 @@ std::string Input::to_String(inputs_e input) } return ""; +} + +// Convierte un std::string a inputs_e +inputs_e Input::to_inputs_e(std::string name) +{ + if (name == "input_fire_left") + { + return input_fire_left; + } + + if (name == "input_fire_center") + { + return input_fire_center; + } + + if (name == "input_fire_right") + { + return input_fire_right; + } + + if (name == "input_start") + { + return input_start; + } + + return input_null; } \ No newline at end of file diff --git a/source/common/input.h b/source/common/input.h index 30fd911..541d51c 100644 --- a/source/common/input.h +++ b/source/common/input.h @@ -89,9 +89,6 @@ private: i_disable_e disabledUntil; // Tiempo que esta deshabilitado bool enabled; // Indica si está habilitado - // Convierte un inputs_e a std::string - std::string to_String(inputs_e input); - public: // Constructor Input(std::string file); @@ -140,6 +137,18 @@ public: // Muestra por consola los controles asignados void printBindings(int device = INPUT_USE_KEYBOARD, int index = 0); + + // Obtiene el SDL_GameControllerButton asignado a un input + SDL_GameControllerButton getControllerBinding(int index, inputs_e input); + + // Convierte un inputs_e a std::string + std::string to_string(inputs_e input); + + // Convierte un std::string a inputs_e + inputs_e to_inputs_e(std::string name); + + // Obtiene el indice a partir del nombre del mando + int getIndexByName(std::string name); }; #endif diff --git a/source/common/utils.h b/source/common/utils.h index 30adfbf..7407c4f 100644 --- a/source/common/utils.h +++ b/source/common/utils.h @@ -3,6 +3,7 @@ #include #include "texture.h" #include "jail_audio.h" +#include "input.h" #include #include @@ -86,14 +87,6 @@ struct demoKeys_t Uint8 fireRight; }; -// Estructura para albergar métodos de control -struct input_t -{ - int id; // Identificador en el vector de mandos - std::string name; // Nombre del dispositivo - Uint8 deviceType; // Tipo de dispositivo (teclado o mando) -}; - // Estructura con las opciones para el borde struct op_border_t { @@ -149,19 +142,28 @@ struct op_audio_t // Estructura para las opciones del juego struct op_game_t { - Uint8 difficulty; // Dificultad del juego - Uint8 playerSelected; // Jugador seleccionado para el modo 1P - std::vector input; // Modo de control (teclado o mando) - Uint8 language; // Idioma usado en el juego + Uint8 difficulty; // Dificultad del juego + Uint8 language; // Idioma usado en el juego +}; + +// Estructura para los controles del juego +struct op_controller_t +{ + int index; // Indice en el vector de mandos + Uint8 deviceType; // Indica si se utilizará teclado o mando o ambos + std::string name; // Nombre del dispositivo + std::vector inputs; // Listado de inputs + std::vector buttons; // Listado de botones asignados a cada input }; // Estructura con todas las opciones de configuración del programa struct options_t { - bool console; // Indica si ha de mostrar información por la consola de texto - op_game_t game; // Opciones para el propio juego - op_video_t video; // Opciones relativas a la clase screen - op_audio_t audio; // Opciones para el audio + bool console; // Indica si ha de mostrar información por la consola de texto + op_game_t game; // Opciones para el propio juego + op_video_t video; // Opciones relativas a la clase screen + op_audio_t audio; // Opciones para el audio + std::vector controller; // Opciones con las asignaciones del mando para cada jugador }; // Estructura para almacenar todos los parámetros del juego diff --git a/source/define_buttons.cpp b/source/define_buttons.cpp index 18b07fa..7989d28 100644 --- a/source/define_buttons.cpp +++ b/source/define_buttons.cpp @@ -72,8 +72,6 @@ void DefineButtons::render() text->writeCentered(x, y - 20, "PLAYER " + std::to_string(indexController + 1)); text->writeCentered(x, y - 10, controllerNames[indexController]); text->writeCentered(x, y, buttons[indexButton].label); - if (indexButton > 0) - text->writeCentered(x, y + 10, std::to_string(buttons[indexButton - 1].button)); } } @@ -123,8 +121,6 @@ void DefineButtons::enable(int index) enabled = true; indexController = index; indexButton = 0; - - input->printBindings(INPUT_USE_GAMECONTROLLER, indexController); } // Comprueba si está habilitado @@ -143,11 +139,24 @@ void DefineButtons::incIndexButton() { // Asigna los botones definidos al input bindButtons(); - input->printBindings(INPUT_USE_GAMECONTROLLER, indexController); + + // Guarda los cambios en las opciones + saveBindingsToOptions(); // Reinicia variables indexButton = 0; indexController = 0; enabled = false; } +} + +// Guarda los cambios en las opciones +void DefineButtons::saveBindingsToOptions() +{ + // Modifica las opciones para colocar los valores asignados + options->controller[indexController].name = input->getControllerName(indexController); + for (int j = 0; j < (int)options->controller[indexController].inputs.size(); ++j) + { + options->controller[indexController].buttons[j] = input->getControllerBinding(indexController, options->controller[indexController].inputs[j]); + } } \ No newline at end of file diff --git a/source/define_buttons.h b/source/define_buttons.h index d26547b..5acd04e 100644 --- a/source/define_buttons.h +++ b/source/define_buttons.h @@ -43,6 +43,9 @@ private: // Asigna los botones definidos al input void bindButtons(); + // Guarda los cambios en las opciones + void saveBindingsToOptions(); + public: // Constructor DefineButtons(SDL_Renderer *renderer, Input *input, Text *text, param_t *param, options_t *options); diff --git a/source/director.cpp b/source/director.cpp index bdeb902..35df178 100644 --- a/source/director.cpp +++ b/source/director.cpp @@ -98,7 +98,6 @@ void Director::initInput() #endif // Busca si hay mandos conectados input->discoverGameControllers(); - const int numGamePads = input->getNumControllers(); // Teclado - Movimiento del jugador input->bindKey(input_up, SDL_SCANCODE_UP); @@ -120,8 +119,9 @@ void Director::initInput() input->bindKey(input_window_fullscreen, SDL_SCANCODE_F3); input->bindKey(input_video_shaders, SDL_SCANCODE_F4); + const int numGamePads = input->getNumControllers(); for (int i = 0; i < numGamePads; ++i) - { + { // Mando - Movimiento del jugador input->bindGameControllerButton(i, input_up, SDL_CONTROLLER_BUTTON_DPAD_UP); input->bindGameControllerButton(i, input_down, SDL_CONTROLLER_BUTTON_DPAD_DOWN); @@ -139,19 +139,24 @@ void Director::initInput() input->bindGameControllerButton(i, input_exit, SDL_CONTROLLER_BUTTON_BACK); } - // Pone valores por defecto a las opciones de control - options->game.input.clear(); + // Comprueba si ha de modificar las asignaciones por las que hay en las opciones en caso de coincidir el nombre del mando + for (int i = 0; i < numGamePads; ++i) + for (int index = 0; index < (int)options->controller.size(); ++index) + if (input->getControllerName(i) == options->controller[index].name) + for (int j = 0; j < (int)options->controller[index].inputs.size(); ++j) + { + input->bindGameControllerButton(i, options->controller[index].inputs[j], options->controller[index].buttons[j]); + } - input_t i; - i.id = 0; - i.name = "MANDO 1"; - i.deviceType = INPUT_USE_ANY; - options->game.input.push_back(i); - - i.id = 1; - i.name = "MANDO 2"; - i.deviceType = INPUT_USE_GAMECONTROLLER; - options->game.input.push_back(i); + // Modifica las opciones para colocar los valores asignados + for (int index = 0; index < numGamePads; ++index) + { + options->controller[index].name = input->getControllerName(index); + for (int j = 0; j < (int)options->controller[index].inputs.size(); ++j) + { + options->controller[index].buttons[j] = input->getControllerBinding(index, options->controller[index].inputs[j]); + } + } } // Inicializa JailAudio @@ -411,19 +416,10 @@ void Director::initOptions() // Crea el puntero a la estructura de opciones options = new options_t; - // Pone unos valores por defecto para las opciones de control - options->game.input.clear(); + // Pone unos valores por defecto para las opciones - input_t inp; - inp.id = 0; - inp.name = "GAME CONTROLLER"; - inp.deviceType = INPUT_USE_GAMECONTROLLER; - options->game.input.push_back(inp); - - inp.id = 1; - inp.name = "GAME CONTROLLER"; - inp.deviceType = INPUT_USE_GAMECONTROLLER; - options->game.input.push_back(inp); + // Opciones varias + options->console = false; // Opciones de video options->video.mode = 0; @@ -443,11 +439,38 @@ void Director::initOptions() options->audio.sound.enabled = true; options->audio.sound.volume = 64; - // Opciones varios - options->game.playerSelected = 0; + // Opciones de juego options->game.difficulty = DIFFICULTY_NORMAL; options->game.language = ba_BA; - options->console = false; + + // Opciones de control + options->controller.clear(); + op_controller_t c; + + const int numPlayers = 2; + for (int index = 0; index < numPlayers; ++index) + { + c.index = index; + c.deviceType = INPUT_USE_GAMECONTROLLER; + c.name = "NO NAME"; + + c.inputs.clear(); + c.inputs.push_back(input_fire_left); + c.inputs.push_back(input_fire_center); + c.inputs.push_back(input_fire_right); + c.inputs.push_back(input_start); + c.inputs.push_back(input_exit); + + c.buttons.clear(); + c.buttons.push_back(SDL_CONTROLLER_BUTTON_X); + c.buttons.push_back(SDL_CONTROLLER_BUTTON_Y); + c.buttons.push_back(SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); + c.buttons.push_back(SDL_CONTROLLER_BUTTON_START); + c.buttons.push_back(SDL_CONTROLLER_BUTTON_BACK); + + options->controller.push_back(c); + } + options->controller[0].deviceType = INPUT_USE_ANY; // El primer jugador puede usar tanto el teclado como el primer mando } // Comprueba los parametros del programa @@ -653,12 +676,33 @@ bool Director::saveConfigFile() // Opciones del juego file << "\n\n## GAME\n"; + file << "## game.language [0: spanish, 1: valencian, 2: english]\n"; + file << "## game.difficulty [0: easy, 1: normal, 2: hard]\n"; file << "\n"; file << "game.language=" + std::to_string(options->game.language) + "\n"; file << "game.difficulty=" + std::to_string(options->game.difficulty) + "\n"; - file << "game.input0=" + std::to_string(options->game.input[0].deviceType) + "\n"; - file << "game.input1=" + std::to_string(options->game.input[1].deviceType) + "\n"; + + // Opciones de mandos + file << "\n\n## CONTROLLERS\n"; + file << "\n"; + + const int numPlayers = 2; + for (int index = 0; index < numPlayers; ++index) + { + const std::string joyIndex = std::to_string(index + 1); + file << "controller" + joyIndex + ".name=" + options->controller[index].name + "\n"; + file << "controller" + joyIndex + ".inputs.fire_left=" + std::to_string((int)options->controller[index].buttons[0]) + "\n"; + file << "controller" + joyIndex + ".inputs.fire_center=" + std::to_string((int)options->controller[index].buttons[1]) + "\n"; + file << "controller" + joyIndex + ".inputs.fire_right=" + std::to_string((int)options->controller[index].buttons[2]) + "\n"; + file << "controller" + joyIndex + ".inputs.fire_start=" + std::to_string((int)options->controller[index].buttons[3]) + "\n"; + file << "controller" + joyIndex + ".inputs.fire_exit=" + std::to_string((int)options->controller[index].buttons[4]) + "\n"; + + if (index < numPlayers - 1) + { + file << "\n"; + } + } // Cierra el fichero file.close(); @@ -924,14 +968,65 @@ bool Director::setOptions(options_t *options, std::string var, std::string value options->game.difficulty = std::stoi(value); } - else if (var == "game.input0") + // Opciones de mandos + else if (var == "controller1.name") { - options->game.input[0].deviceType = std::stoi(value); + options->controller[0].name = value; } - else if (var == "game.input1") + else if (var == "controller1.inputs.fire_left") { - options->game.input[1].deviceType = std::stoi(value); + options->controller[0].buttons[0] = (SDL_GameControllerButton)std::stoi(value); + } + + else if (var == "controller1.inputs.fire_center") + { + options->controller[0].buttons[1] = (SDL_GameControllerButton)std::stoi(value); + } + + else if (var == "controller1.inputs.fire_right") + { + options->controller[0].buttons[2] = (SDL_GameControllerButton)std::stoi(value); + } + + else if (var == "controller1.inputs.fire_start") + { + options->controller[0].buttons[3] = (SDL_GameControllerButton)std::stoi(value); + } + + else if (var == "controller1.inputs.fire_exit") + { + options->controller[0].buttons[4] = (SDL_GameControllerButton)std::stoi(value); + } + + else if (var == "controller2.name") + { + options->controller[1].name = value; + } + + else if (var == "controller2.inputs.fire_left") + { + options->controller[1].buttons[0] = (SDL_GameControllerButton)std::stoi(value); + } + + else if (var == "controller2.inputs.fire_center") + { + options->controller[1].buttons[1] = (SDL_GameControllerButton)std::stoi(value); + } + + else if (var == "controller2.inputs.fire_right") + { + options->controller[1].buttons[2] = (SDL_GameControllerButton)std::stoi(value); + } + + else if (var == "controller2.inputs.fire_start") + { + options->controller[1].buttons[3] = (SDL_GameControllerButton)std::stoi(value); + } + + else if (var == "controller2.inputs.fire_exit") + { + options->controller[1].buttons[4] = (SDL_GameControllerButton)std::stoi(value); } // Lineas vacias o que empiezan por comentario diff --git a/source/game.cpp b/source/game.cpp index 5923aeb..ebb5789 100644 --- a/source/game.cpp +++ b/source/game.cpp @@ -2817,7 +2817,7 @@ void Game::checkInput() if (player->isAlive() && player->isEnabled()) { // Input a la izquierda - if (input->checkInput(input_left, ALLOW_REPEAT, options->game.input[i].deviceType, options->game.input[i].id)) + if (input->checkInput(input_left, ALLOW_REPEAT, options->controller[i].deviceType, options->controller[i].index)) { player->setInput(input_left); #ifdef RECORDING @@ -2827,7 +2827,7 @@ void Game::checkInput() else { // Input a la derecha - if (input->checkInput(input_right, ALLOW_REPEAT, options->game.input[i].deviceType, options->game.input[i].id)) + if (input->checkInput(input_right, ALLOW_REPEAT, options->controller[i].deviceType, options->controller[i].index)) { player->setInput(input_right); #ifdef RECORDING @@ -2844,7 +2844,7 @@ void Game::checkInput() } } // Comprueba el input de disparar al centro - if (input->checkInput(input_fire_center, ALLOW_REPEAT, options->game.input[i].deviceType, options->game.input[i].id)) + if (input->checkInput(input_fire_center, ALLOW_REPEAT, options->controller[i].deviceType, options->controller[i].index)) { if (player->canFire()) { @@ -2861,7 +2861,7 @@ void Game::checkInput() } // Comprueba el input de disparar a la izquierda - else if (input->checkInput(input_fire_left, ALLOW_REPEAT, options->game.input[i].deviceType, options->game.input[i].id)) + else if (input->checkInput(input_fire_left, ALLOW_REPEAT, options->controller[i].deviceType, options->controller[i].index)) { if (player->canFire()) { @@ -2878,7 +2878,7 @@ void Game::checkInput() } // Comprueba el input de disparar a la derecha - else if (input->checkInput(input_fire_right, ALLOW_REPEAT, options->game.input[i].deviceType, options->game.input[i].id)) + else if (input->checkInput(input_fire_right, ALLOW_REPEAT, options->controller[i].deviceType, options->controller[i].index)) { if (player->canFire()) { @@ -2906,7 +2906,7 @@ void Game::checkInput() } else { - if (input->checkInput(input_start, ALLOW_REPEAT, options->game.input[i].deviceType, options->game.input[i].id)) + if (input->checkInput(input_start, ALLOW_REPEAT, options->controller[i].deviceType, options->controller[i].index)) { player->enable(true); }