Compare commits

14 Commits

Author SHA1 Message Date
e0e82ee273 Retocs en Texture::loadPaletteFromFile 2024-11-03 20:43:52 +01:00
371c477d0d Varios arreglos 2024-11-03 20:28:01 +01:00
f29eb2f411 Les notificacions ara accepten un vector de cadenes en lloc de una o dos cadenes 2024-11-03 18:12:46 +01:00
69a92cba66 Apanyats alguns bugs que quedaven respecte a lo del teclat 2024-11-03 17:25:31 +01:00
86cd7b0f16 Ja es pot gastar el teclat com a control independent del primer mando
Ja pot jugar un jugador amb teclat i altre amb mando
Es pot asignar el teclat a qualsevol dels dos jugadors
Continua podentse gastar mando i teclat a l'hora per al mateix jugador
2024-11-03 11:07:58 +01:00
a1ccb6102a Abans de clavar-li ma a Input 2024-11-01 20:01:17 +01:00
2dd8bbbbf7 Moguts els checkInputs de Screen a GlobalInputs 2024-11-01 19:07:19 +01:00
c66cc965f1 define_buttons ja acaba be de definir els buttons 2024-11-01 18:39:10 +01:00
0757f63b73 Eliminat checkModInput 2024-11-01 18:20:18 +01:00
80a110e1d7 Abans de llevar checkInputMod 2024-11-01 16:48:03 +01:00
cd68c5ffea Al redefinir botons, ja no pots repetir botó. Util per als qui tenim la ma tremolosa i apretem dos voltes sense voler 2024-11-01 14:32:27 +01:00
f786cb7776 Implementat el final del joc 2024-11-01 13:05:11 +01:00
2e0d27a95c Modificats parámetres 2024-11-01 12:56:09 +01:00
861a9411d3 Nous textos 2024-11-01 12:55:37 +01:00
37 changed files with 1187 additions and 1536 deletions

View File

@@ -6,7 +6,7 @@ game.play_area.rect.x 0 # Rectangulo con la posición de la zona de juego
game.play_area.rect.y 0 # Rectangulo con la posición de la zona de juego game.play_area.rect.y 0 # Rectangulo con la posición de la zona de juego
game.play_area.rect.w 320 # Rectangulo con la posición de la zona de juego game.play_area.rect.w 320 # Rectangulo con la posición de la zona de juego
game.play_area.rect.h 200 # Rectangulo con la posición de la zona de juego game.play_area.rect.h 200 # Rectangulo con la posición de la zona de juego
game.enter_name_seconds 30 # Duración en segundos para introducir el nombre al finalizar la partida game.enter_name_seconds 60 # Duración en segundos para introducir el nombre al finalizar la partida
## FADE ## FADE
fade.num_squares_width 160 fade.num_squares_width 160

View File

@@ -6,8 +6,7 @@ game.play_area.rect.x 0 # Rectangulo con la posición de la zona de juego
game.play_area.rect.y 0 # Rectangulo con la posición de la zona de juego game.play_area.rect.y 0 # Rectangulo con la posición de la zona de juego
game.play_area.rect.w 320 # Rectangulo con la posición de la zona de juego game.play_area.rect.w 320 # Rectangulo con la posición de la zona de juego
game.play_area.rect.h 216 # Rectangulo con la posición de la zona de juego game.play_area.rect.h 216 # Rectangulo con la posición de la zona de juego
game.enter_name_seconds 30 # Duración en segundos para introducir el nombre al finalizar la partida game.enter_name_seconds 60 # Duración en segundos para introducir el nombre al finalizar la partida
game.game_text.dest_y
## FADE ## FADE
fade.num_squares_width 160 fade.num_squares_width 160

View File

@@ -79,7 +79,7 @@ frames=32,33,34,35
[/animation] [/animation]
[animation] [animation]
name=celeb name=celebration
speed=10 speed=10
loop=-1 loop=-1
frames=36,36,36,36,36,36,37,38,39,40,40,40,40,40,40,39,39,39,40,40,40,39,39,39,38,37,36,36,36 frames=36,36,36,36,36,36,37,38,39,40,40,40,40,40,40,39,39,39,40,40,40,39,39,39,38,37,36,36,36

View File

@@ -206,7 +206,7 @@ NORMAL
DIFICIL DIFICIL
## 69 - MENU DE OPCIONES ## 69 - MENU DE OPCIONES
TECLAT Teclat
## 70 - MENU DE OPCIONES ## 70 - MENU DE OPCIONES
MANDO MANDO
@@ -357,3 +357,6 @@ SuperPoder!
## 119 - GAME TEXT ## 119 - GAME TEXT
Temps! Temps!
## 120 - SCOREBOARD
Puntuacio

View File

@@ -206,7 +206,7 @@ NORMAL
HARD HARD
## 69 - MENU DE OPCIONES ## 69 - MENU DE OPCIONES
KEYBOARD Keyboard
## 70 - MENU DE OPCIONES ## 70 - MENU DE OPCIONES
GAME CONTROLLER GAME CONTROLLER
@@ -357,3 +357,6 @@ PowerUp
## 119 - GAME TEXT ## 119 - GAME TEXT
Stop! Stop!
## 120 - SCOREBOARD
Score

View File

@@ -206,7 +206,7 @@ NORMAL
DIFICIL DIFICIL
## 69 - MENU DE OPCIONES ## 69 - MENU DE OPCIONES
TECLADO Teclado
## 70 - MENU DE OPCIONES ## 70 - MENU DE OPCIONES
MANDO MANDO
@@ -357,3 +357,6 @@ Potenciador
## 119 - GAME TEXT ## 119 - GAME TEXT
Tiempo! Tiempo!
## 120 - SCOREBOARD
Puntuacion

View File

@@ -16,11 +16,7 @@ DefineButtons::DefineButtons(std::unique_ptr<Text> text_)
x_ = param.game.width / 2; x_ = param.game.width / 2;
y_ = param.title.press_start_position; y_ = param.title.press_start_position;
buttons_.emplace_back(lang::getText(95), InputType::FIRE_LEFT, SDL_CONTROLLER_BUTTON_X); clearButtons();
buttons_.emplace_back(lang::getText(96), InputType::FIRE_CENTER, SDL_CONTROLLER_BUTTON_Y);
buttons_.emplace_back(lang::getText(97), InputType::FIRE_RIGHT, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);
buttons_.emplace_back(lang::getText(98), InputType::START, SDL_CONTROLLER_BUTTON_START);
buttons_.emplace_back(lang::getText(99), InputType::EXIT, SDL_CONTROLLER_BUTTON_BACK);
for (int i = 0; i < input_->getNumControllers(); ++i) for (int i = 0; i < input_->getNumControllers(); ++i)
{ {
@@ -33,38 +29,40 @@ void DefineButtons::render()
{ {
if (enabled_) if (enabled_)
{ {
text_->writeCentered(x_, y_ - 10, lang::getText(100) + std::to_string(options.controller[index_controller_].player_id)); text_->writeCentered(x_, y_ - 10, lang::getText(100) + std::to_string(options.controllers.at(index_controller_).player_id));
text_->writeCentered(x_, y_, controller_names_[index_controller_]); text_->writeCentered(x_, y_, controller_names_.at(index_controller_));
text_->writeCentered(x_, y_ + 10, buttons_[index_button_].label); text_->writeCentered(x_, y_ + 10, buttons_.at(index_button_).label);
} }
} }
// Comprueba el botón que se ha pulsado // Comprueba el botón que se ha pulsado
void DefineButtons::doControllerButtonDown(SDL_ControllerButtonEvent *event) void DefineButtons::doControllerButtonDown(const SDL_ControllerButtonEvent &event)
{ {
int i = input_->getJoyIndex(event->which); // Solo pilla botones del mando que toca
if (input_->getJoyIndex(event.which) != static_cast<int>(index_controller_))
// Solo pillamos botones del mando que toca
if (i != index_controller_)
{ {
return; return;
} }
buttons_[index_button_].button = (SDL_GameControllerButton)event->button; const auto button = static_cast<SDL_GameControllerButton>(event.button);
if (checkButtonNotInUse(button))
{
buttons_.at(index_button_).button = button;
incIndexButton(); incIndexButton();
} }
}
// Asigna los botones definidos al input_ // Asigna los botones definidos al input_
void DefineButtons::bindButtons() void DefineButtons::bindButtons()
{ {
for (int i = 0; i < (int)buttons_.size(); ++i) for (const auto &button : buttons_)
{ {
input_->bindGameControllerButton(index_controller_, buttons_[i].input, buttons_[i].button); input_->bindGameControllerButton(index_controller_, button.input, button.button);
} }
} }
// Comprueba las entradas // Comprueba los eventos
void DefineButtons::checkInput() void DefineButtons::checkEvents()
{ {
if (enabled_) if (enabled_)
{ {
@@ -81,13 +79,11 @@ void DefineButtons::checkInput()
section::options = section::Options::QUIT_WITH_KEYBOARD; section::options = section::Options::QUIT_WITH_KEYBOARD;
break; break;
} }
case SDL_CONTROLLERBUTTONDOWN: case SDL_CONTROLLERBUTTONDOWN:
{ {
doControllerButtonDown(&event.cbutton); doControllerButtonDown(event.cbutton);
break; break;
} }
default: default:
break; break;
} }
@@ -103,6 +99,7 @@ bool DefineButtons::enable(int index)
enabled_ = true; enabled_ = true;
index_controller_ = index; index_controller_ = index;
index_button_ = 0; index_button_ = 0;
clearButtons();
return true; return true;
} }
@@ -110,18 +107,15 @@ bool DefineButtons::enable(int index)
} }
// Comprueba si está habilitado // Comprueba si está habilitado
bool DefineButtons::isEnabled() bool DefineButtons::isEnabled() { return enabled_; }
{
return enabled_;
}
// Incrementa el indice de los botones // Incrementa el indice de los botones
void DefineButtons::incIndexButton() void DefineButtons::incIndexButton()
{ {
index_button_++; ++index_button_;
// Comprueba si ha finalizado // Comprueba si ha finalizado
if (index_button_ == (int)buttons_.size()) if (index_button_ == buttons_.size())
{ {
// Asigna los botones definidos al input_ // Asigna los botones definidos al input_
bindButtons(); bindButtons();
@@ -129,11 +123,7 @@ void DefineButtons::incIndexButton()
// Guarda los cambios en las opciones // Guarda los cambios en las opciones
saveBindingsToOptions(); saveBindingsToOptions();
// input_->allActive(index_controller_); // Deshabilita
// Reinicia variables
index_button_ = 0;
index_controller_ = 0;
enabled_ = false; enabled_ = false;
} }
} }
@@ -142,17 +132,34 @@ void DefineButtons::incIndexButton()
void DefineButtons::saveBindingsToOptions() void DefineButtons::saveBindingsToOptions()
{ {
// Modifica las opciones para colocar los valores asignados // Modifica las opciones para colocar los valores asignados
options.controller[index_controller_].name = input_->getControllerName(index_controller_); auto &controller = options.controllers.at(index_controller_);
for (int j = 0; j < (int)options.controller[index_controller_].inputs.size(); ++j) controller.name = input_->getControllerName(index_controller_);
for (size_t j = 0; j < controller.inputs.size(); ++j)
{ {
options.controller[index_controller_].buttons[j] = input_->getControllerBinding(index_controller_, options.controller[index_controller_].inputs[j]); controller.buttons.at(j) = input_->getControllerBinding(index_controller_, controller.inputs.at(j));
} }
} }
// Intercambia los jugadores asignados a los dos primeros mandos // Comprueba que un botón no esté ya asignado
void DefineButtons::swapControllers() bool DefineButtons::checkButtonNotInUse(SDL_GameControllerButton button)
{ {
const int temp = options.controller[0].player_id; for (const auto &b : buttons_)
options.controller[0].player_id = options.controller[1].player_id; {
options.controller[1].player_id = temp; if (b.button == button)
{
return false;
}
}
return true;
}
// Limpia la asignación de botones
void DefineButtons::clearButtons()
{
buttons_.clear();
buttons_.emplace_back(lang::getText(95), InputType::FIRE_LEFT, SDL_CONTROLLER_BUTTON_INVALID);
buttons_.emplace_back(lang::getText(96), InputType::FIRE_CENTER, SDL_CONTROLLER_BUTTON_INVALID);
buttons_.emplace_back(lang::getText(97), InputType::FIRE_RIGHT, SDL_CONTROLLER_BUTTON_INVALID);
buttons_.emplace_back(lang::getText(98), InputType::START, SDL_CONTROLLER_BUTTON_INVALID);
buttons_.emplace_back(lang::getText(99), InputType::SERVICE, SDL_CONTROLLER_BUTTON_INVALID);
} }

View File

@@ -1,13 +1,14 @@
#pragma once #pragma once
#include <SDL2/SDL_events.h> // para SDL_ControllerButtonEvent #include <SDL2/SDL_events.h> // Para SDL_ControllerButtonEvent
#include <SDL2/SDL_gamecontroller.h> // para SDL_GameControllerButton #include <SDL2/SDL_gamecontroller.h> // Para SDL_GameControllerButton
#include <memory> // para shared_ptr, unique_ptr #include <stddef.h> // Para size_t
#include <string> // para string #include <memory> // Para shared_ptr, unique_ptr
#include <vector> // para vector #include <string> // Para string
class Input; #include <vector> // Para vector
class Text; class Input; // lines 8-8
enum class InputType : int; class Text; // lines 9-9
enum class InputType : int; // lines 10-10
struct DefineButtonsButton struct DefineButtonsButton
{ {
@@ -33,15 +34,15 @@ private:
int x_; // Posición donde dibujar el texto int x_; // Posición donde dibujar el texto
int y_; // Posición donde dibujar el texto int y_; // Posición donde dibujar el texto
std::vector<DefineButtonsButton> buttons_; // Vector con las nuevas definiciones de botones/acciones std::vector<DefineButtonsButton> buttons_; // Vector con las nuevas definiciones de botones/acciones
int index_controller_ = 0; // Indice del controlador a reasignar size_t index_controller_ = 0; // Indice del controlador a reasignar
int index_button_ = 0; // Indice para saber qué bot´çon se está definiendo size_t index_button_ = 0; // Indice para saber qué botón se está definiendo
std::vector<std::string> controller_names_; // Nombres de los mandos std::vector<std::string> controller_names_; // Nombres de los mandos
// Incrementa el indice de los botones // Incrementa el indice de los botones
void incIndexButton(); void incIndexButton();
// Comprueba el botón que se ha pulsado // Comprueba el botón que se ha pulsado
void doControllerButtonDown(SDL_ControllerButtonEvent *event); void doControllerButtonDown(const SDL_ControllerButtonEvent &event);
// Asigna los botones definidos al input // Asigna los botones definidos al input
void bindButtons(); void bindButtons();
@@ -49,6 +50,12 @@ private:
// Guarda los cambios en las opciones // Guarda los cambios en las opciones
void saveBindingsToOptions(); void saveBindingsToOptions();
// Comprueba que un botón no esté ya asignado
bool checkButtonNotInUse(SDL_GameControllerButton button);
// Limpia la asignación de botones
void clearButtons();
public: public:
// Constructor // Constructor
explicit DefineButtons(std::unique_ptr<Text> text); explicit DefineButtons(std::unique_ptr<Text> text);
@@ -59,15 +66,12 @@ public:
// Dibuja el objeto en pantalla // Dibuja el objeto en pantalla
void render(); void render();
// Comprueba las entradas // Comprueba los eventos
void checkInput(); void checkEvents();
// Habilita el objeto // Habilita el objeto
bool enable(int index); bool enable(int index);
// Comprueba si está habilitado // Comprueba si está habilitado
bool isEnabled(); bool isEnabled();
// Intercambia los jugadores asignados a los dos primeros mandos
void swapControllers();
}; };

View File

@@ -7,17 +7,17 @@
#include <SDL2/SDL_hints.h> // Para SDL_SetHint, SDL_HINT_RENDER_DR... #include <SDL2/SDL_hints.h> // Para SDL_SetHint, SDL_HINT_RENDER_DR...
#include <SDL2/SDL_scancode.h> // Para SDL_SCANCODE_0, SDL_SCANCODE_DOWN #include <SDL2/SDL_scancode.h> // Para SDL_SCANCODE_0, SDL_SCANCODE_DOWN
#include <SDL2/SDL_stdinc.h> // Para SDL_bool, Uint32 #include <SDL2/SDL_stdinc.h> // Para SDL_bool, Uint32
#include <SDL2/SDL_timer.h> // Para SDL_GetTicks #include <bits/chrono.h> // Para duration, system_clock
#include <errno.h> // Para errno, EEXIST, EACCES, ENAMETOO... #include <errno.h> // Para errno, EEXIST, EACCES, ENAMETOO...
#include <stdio.h> // Para printf, perror #include <stdio.h> // Para printf, perror
#include <string.h> // Para strcmp
#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 <cstdlib> // Para exit, EXIT_FAILURE, rand, srand #include <algorithm> // Para min
#include <iostream> // Para basic_ostream, operator<<, cout #include <cstdlib> // Para exit, EXIT_FAILURE, size_t, rand
#include <iostream> // Para basic_ostream, operator<<, basi...
#include <memory> // Para make_unique, unique_ptr, make_s... #include <memory> // Para make_unique, unique_ptr, make_s...
#include <stdexcept> // Para runtime_error #include <stdexcept> // Para runtime_error
#include <string> // Para operator+, allocator, char_traits #include <string> // Para operator+, char_traits, allocator
#include <vector> // Para vector #include <vector> // Para vector
#include "asset.h" // Para Asset, AssetType #include "asset.h" // Para Asset, AssetType
#include "dbgtxt.h" // Para dbg_init #include "dbgtxt.h" // Para dbg_init
@@ -27,13 +27,13 @@
#include "input.h" // Para Input, InputType #include "input.h" // Para Input, InputType
#include "instructions.h" // Para Instructions #include "instructions.h" // Para Instructions
#include "intro.h" // Para Intro #include "intro.h" // Para Intro
#include "jail_audio.h" // Para JA_EnableMusic, JA_EnableSound #include "jail_audio.h" // Para JA_SetMusicVolume, JA_SetSoundV...
#include "lang.h" // Para Code, loadFromFile #include "lang.h" // Para Code, loadFromFile
#include "logo.h" // Para Logo #include "logo.h" // Para Logo
#include "manage_hiscore_table.h" // Para ManageHiScoreTable #include "manage_hiscore_table.h" // Para ManageHiScoreTable
#include "notifier.h" // Para Notifier #include "notifier.h" // Para Notifier
#include "on_screen_help.h" // Para OnScreenHelp #include "on_screen_help.h" // Para OnScreenHelp
#include "options.h" // Para Options, options, OptionsContro... #include "options.h" // Para Options, OptionsController, opt...
#include "param.h" // Para Param, ParamGame, param, loadPa... #include "param.h" // Para Param, ParamGame, param, loadPa...
#include "resource.h" // Para Resource #include "resource.h" // Para Resource
#include "screen.h" // Para Screen #include "screen.h" // Para Screen
@@ -46,6 +46,13 @@
#include <pwd.h> // para getpwuid, passwd #include <pwd.h> // para getpwuid, passwd
#endif #endif
// Inicia la semilla aleatoria
void initRand()
{
unsigned int seed = static_cast<unsigned int>(std::chrono::system_clock::now().time_since_epoch().count());
std::srand(seed);
}
// Constructor // Constructor
Director::Director(int argc, const char *argv[]) Director::Director(int argc, const char *argv[])
{ {
@@ -67,6 +74,8 @@ Director::Director(int argc, const char *argv[])
std::cout << "Game start" << std::endl; std::cout << "Game start" << std::endl;
initRand();
// Comprueba los parametros del programa // Comprueba los parametros del programa
checkProgramArguments(argc, argv); checkProgramArguments(argc, argv);
@@ -89,7 +98,7 @@ Director::Director(int argc, const char *argv[])
#else #else
const std::string paramFilePath = overrides.param_file == "--320x240" ? Asset::get()->get("param_320x240.txt") : Asset::get()->get("param_320x256.txt"); const std::string paramFilePath = overrides.param_file == "--320x240" ? Asset::get()->get("param_320x240.txt") : Asset::get()->get("param_320x256.txt");
#endif #endif
loadParams(paramFilePath); loadParamsFromFile(paramFilePath);
// Carga el fichero de puntuaciones // Carga el fichero de puntuaciones
{ {
@@ -100,30 +109,18 @@ Director::Director(int argc, const char *argv[])
manager->loadFromFile(Asset::get()->get("score.bin")); manager->loadFromFile(Asset::get()->get("score.bin"));
} }
// Inicializa SDL // Inicializa todo
initSDL(); initSDL();
// Inicializa JailAudio
initJailAudio(); initJailAudio();
// Inicializa el texto de debug
dbg_init(renderer_); dbg_init(renderer_);
lang::loadFromFile(getLangFile(static_cast<lang::Code>(options.game.language)));
// Crea los objetos
lang::loadFromFile(getLangFile((lang::Code)options.game.language));
Screen::init(window_, renderer_); Screen::init(window_, renderer_);
Resource::init(); Resource::init();
Input::init(Asset::get()->get("gamecontrollerdb.txt")); Input::init(Asset::get()->get("gamecontrollerdb.txt"));
bindInputs(); bindInputs();
auto notifier_text = std::make_shared<Text>(Resource::get()->getTexture("8bithud.png"), Resource::get()->getTextFile("8bithud.txt")); auto notifier_text = std::make_shared<Text>(Resource::get()->getTexture("8bithud.png"), Resource::get()->getTextFile("8bithud.txt"));
Notifier::init(std::string(), notifier_text, Asset::get()->get("notify.wav")); Notifier::init(std::string(), notifier_text, Asset::get()->get("notify.wav"));
OnScreenHelp::init(); OnScreenHelp::init();
globalInputs::init(); globalInputs::init();
} }
@@ -191,25 +188,21 @@ void Director::bindInputs()
// Mando - Control del programa // Mando - Control del programa
Input::get()->bindGameControllerButton(i, InputType::SERVICE, SDL_CONTROLLER_BUTTON_BACK); Input::get()->bindGameControllerButton(i, InputType::SERVICE, SDL_CONTROLLER_BUTTON_BACK);
Input::get()->bindGameControllerButton(i, InputType::EXIT, InputType::START);
Input::get()->bindGameControllerButton(i, InputType::PAUSE, InputType::FIRE_RIGHT);
Input::get()->bindGameControllerButton(i, InputType::VIDEO_SHADERS, InputType::FIRE_LEFT);
Input::get()->bindGameControllerButton(i, InputType::MUTE, InputType::LEFT);
Input::get()->bindGameControllerButton(i, InputType::SHOWINFO, InputType::RIGHT);
Input::get()->bindGameControllerButton(i, InputType::RESET, InputType::FIRE_CENTER);
Input::get()->bindGameControllerButton(i, InputType::CONFIG, InputType::DOWN);
Input::get()->bindGameControllerButton(i, InputType::SWAP_CONTROLLERS, InputType::UP);
} }
// Mapea las asignaciones a los botones desde el archivo de configuración, si se da el caso // Mapea las asignaciones a los botones desde el archivo de configuración, si se da el caso
for (int i = 0; i < num_gamepads; ++i) const size_t max_controllers = std::min(2, num_gamepads);
for (int index = 0; index < (int)options.controller.size(); ++index) for (size_t i = 0; i < max_controllers; ++i)
if (Input::get()->getControllerName(i) == options.controller[index].name)
{ {
options.controller[index].plugged = true; for (auto &controller : options.controllers)
for (int j = 0; j < (int)options.controller[index].inputs.size(); ++j)
{ {
Input::get()->bindGameControllerButton(i, options.controller[index].inputs[j], options.controller[index].buttons[j]); if (Input::get()->getControllerName(i) == controller.name)
{
for (size_t j = 0; j < controller.inputs.size(); ++j)
{
Input::get()->bindGameControllerButton(i, controller.inputs.at(j), controller.buttons.at(j));
}
}
} }
} }
@@ -226,15 +219,25 @@ void Director::bindInputs()
Input::get()->bindGameControllerButton(i, InputType::SWAP_CONTROLLERS, InputType::UP); Input::get()->bindGameControllerButton(i, InputType::SWAP_CONTROLLERS, InputType::UP);
} }
// Guarda las asignaciones de botones en las opciones // Guarda las asignaciones de botones en las opciones de los dos primeros mandos
for (int i = 0; i < num_gamepads; ++i) for (size_t i = 0; i < max_controllers; ++i)
{ {
options.controller[i].name = Input::get()->getControllerName(i); // Variables asociadas al mando
for (int j = 0; j < (int)options.controller[i].inputs.size(); ++j) options.controllers.at(i).index = i;
options.controllers.at(i).name = Input::get()->getControllerName(i);
options.controllers.at(i).plugged = true;
// Asignaciones de botones
for (size_t j = 0; j < options.controllers.at(i).inputs.size(); ++j)
{ {
options.controller[i].buttons[j] = Input::get()->getControllerBinding(i, options.controller[i].inputs[j]); options.controllers.at(i).buttons.at(j) = Input::get()->getControllerBinding(i, options.controllers.at(i).inputs.at(j));
} }
} }
// Asegura que algún jugador tenga el teclado asignado
if (getPlayerWhoUsesKeyboard() == 0)
{
setKeyboardToPlayer(1);
}
} }
// Inicializa JailAudio // Inicializa JailAudio
@@ -267,34 +270,35 @@ bool Director::initSDL()
} }
else else
{ {
// Inicia el generador de numeros aleatorios /*
std::srand(static_cast<unsigned int>(SDL_GetTicks()));
// Muestra información de la pantalla // Muestra información de la pantalla
/*std::cout << "\nDisplay modes list:" << std::endl; std::cout << "\nDisplay modes list:" << std::endl;
for (int i = 0; i < SDL_GetNumDisplayModes(0); ++i) for (int i = 0; i < SDL_GetNumDisplayModes(0); ++i)
{ {
SDL_DisplayMode DM; SDL_DisplayMode DM;
SDL_GetDisplayMode(0,i,&DM); SDL_GetDisplayMode(0,i,&DM);
std::cout << " - " + std::to_string(DM.w) + "x" + std::to_string(DM.h) + " @ " + std::to_string(DM.refresh_rate) + "Hz" << std::endl; std::cout << " - " << DM.w << "x" << DM.h << " @ " << DM.refresh_rate << "Hz" << std::endl;
}*/ }
*/
SDL_DisplayMode DM; SDL_DisplayMode DM;
SDL_GetCurrentDisplayMode(0, &DM); SDL_GetCurrentDisplayMode(0, &DM);
std::cout << "\nCurrent display mode: " + std::to_string(DM.w) + "x" + std::to_string(DM.h) + " @ " + std::to_string(DM.refresh_rate) + "Hz" << std::endl; std::cout << "\nCurrent display mode: " << DM.w << "x" << DM.h << " @ " << DM.refresh_rate << "Hz" << std::endl;
std::cout << "Window resolution : " + std::to_string(param.game.width) + "x" + std::to_string(param.game.height) + " x" + std::to_string(options.video.window.size) << std::endl; std::cout << "Window resolution : " << param.game.width << "x" << param.game.height << " x" << options.video.window.size << std::endl;
// Establece el filtro de la textura // Establece el filtro de la textura
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, std::to_string(static_cast<int>(options.video.filter)).c_str())) if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, std::to_string(static_cast<int>(options.video.filter)).c_str()))
{ {
std::cout << "Warning: texture filtering not enabled!\n"; std::cout << "Warning: texture filtering not enabled!\n";
} }
#ifndef NO_SHADERS #ifndef NO_SHADERS
if (!SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl")) if (!SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"))
{ {
std::cout << "Warning: opengl not enabled!\n"; std::cout << "Warning: opengl not enabled!\n";
} }
#endif // NO_SHADERS #endif
// Crea la ventana // Crea la ventana
window_ = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, param.game.width * options.video.window.size, param.game.height * options.video.window.size, SDL_WINDOW_HIDDEN); window_ = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, param.game.width * options.video.window.size, param.game.height * options.video.window.size, SDL_WINDOW_HIDDEN);
if (!window_) if (!window_)
@@ -310,10 +314,12 @@ bool Director::initSDL()
{ {
flags = SDL_RENDERER_PRESENTVSYNC; flags = SDL_RENDERER_PRESENTVSYNC;
} }
#ifndef NO_SHADERS #ifndef NO_SHADERS
// La aceleración se activa según el define // La aceleración se activa según el define
flags = flags | SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE; flags = flags | SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE;
#endif #endif
renderer_ = SDL_CreateRenderer(window_, -1, flags); renderer_ = SDL_CreateRenderer(window_, -1, flags);
if (!renderer_) if (!renderer_)
@@ -323,14 +329,9 @@ bool Director::initSDL()
} }
else else
{ {
// Inicializa el color de renderizado
SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF); SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF);
// Establece el tamaño del buffer de renderizado
SDL_RenderSetLogicalSize(renderer_, param.game.width, param.game.height); SDL_RenderSetLogicalSize(renderer_, param.game.width, param.game.height);
SDL_RenderSetIntegerScale(renderer_, static_cast<SDL_bool>(options.video.integer_scale)); SDL_RenderSetIntegerScale(renderer_, static_cast<SDL_bool>(options.video.integer_scale));
// Establece el modo de mezcla
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND); SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND);
} }
} }
@@ -506,40 +507,22 @@ void Director::setFileList()
throw std::runtime_error("Falta algun fichero"); throw std::runtime_error("Falta algun fichero");
} }
// Carga los parametros para configurar el juego
void Director::loadParams(const std::string &file_path)
{
loadParamsFromFile(file_path);
}
// Comprueba los parametros del programa // Comprueba los parametros del programa
void Director::checkProgramArguments(int argc, const char *argv[]) void Director::checkProgramArguments(int argc, const char *argv[])
{ {
const std::vector<std::string> argument_list = {"--h", "--320x240", "--clear_score"};
// Establece la ruta del programa // Establece la ruta del programa
executable_path_ = argv[0]; executable_path_ = argv[0];
// Comprueba el resto de parámetros // Comprueba el resto de parámetros
for (int i = 1; i < argc; ++i) for (int i = 1; i < argc; ++i)
{ {
if (strcmp(argv[i], "--h") == 0) std::string arg = argv[i];
{
for (const auto &argument : argument_list)
{
std::cout << argument << std::endl;
}
// std::exit(EXIT_SUCCESS);
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
}
if (strcmp(argv[i], "--320x240") == 0) if (arg == "--320x240")
{ {
overrides.param_file = argv[i]; overrides.param_file = arg;
} }
else if (arg == "--clear_score")
if (strcmp(argv[i], "--clear_score") == 0)
{ {
overrides.clear_hi_score_table = true; overrides.clear_hi_score_table = true;
} }
@@ -673,54 +656,57 @@ int Director::run()
case section::Name::INIT: case section::Name::INIT:
section::name = section::Name::LOGO; section::name = section::Name::LOGO;
break; break;
case section::Name::LOGO: case section::Name::LOGO:
runLogo(); runLogo();
break; break;
case section::Name::INTRO: case section::Name::INTRO:
runIntro(); runIntro();
break; break;
case section::Name::TITLE: case section::Name::TITLE:
runTitle(); runTitle();
break; break;
case section::Name::GAME: case section::Name::GAME:
runGame(); runGame();
break; break;
case section::Name::HI_SCORE_TABLE: case section::Name::HI_SCORE_TABLE:
runHiScoreTable(); runHiScoreTable();
break; break;
case section::Name::GAME_DEMO: case section::Name::GAME_DEMO:
runDemoGame(); runDemoGame();
break; break;
case section::Name::INSTRUCTIONS: case section::Name::INSTRUCTIONS:
runInstructions(); runInstructions();
break; break;
default: default:
break; break;
} }
} }
#ifdef ARCADE std::string return_code;
// Comprueba si ha de apagar el sistema switch (section::options)
if (section::options == section::Options::QUIT_WITH_CONTROLLER) {
shutdownSystem(); case section::Options::QUIT_WITH_KEYBOARD:
#endif return_code = "with keyboard";
break;
case section::Options::QUIT_WITH_CONTROLLER:
return_code = "with controller";
break;
default:
return_code = "from event";
break;
}
const auto return_code = (section::options == section::Options::QUIT_WITH_KEYBOARD) ? "with keyboard" : (section::options == section::Options::QUIT_WITH_CONTROLLER) ? "with controller"
: "from event";
std::cout << "\nGame end " << return_code << std::endl; std::cout << "\nGame end " << return_code << std::endl;
#ifndef VERBOSE #ifndef VERBOSE
// Habilita de nuevo los std::cout // Habilita de nuevo los std::cout
std::cout.rdbuf(orig_buf); std::cout.rdbuf(orig_buf);
#endif #endif
#ifdef ARCADE
// Comprueba si ha de apagar el sistema
if (section::options == section::Options::QUIT_WITH_CONTROLLER)
shutdownSystem();
#endif
return (section::options == section::Options::QUIT_WITH_CONTROLLER) ? 1 : 0; return (section::options == section::Options::QUIT_WITH_CONTROLLER) ? 1 : 0;
} }
@@ -733,15 +719,12 @@ std::string Director::getLangFile(lang::Code code)
case lang::Code::ba_BA: case lang::Code::ba_BA:
return Asset::get()->get("ba_BA.txt"); return Asset::get()->get("ba_BA.txt");
break; break;
case lang::Code::es_ES: case lang::Code::es_ES:
return Asset::get()->get("es_ES.txt"); return Asset::get()->get("es_ES.txt");
break; break;
case lang::Code::en_UK: case lang::Code::en_UK:
return Asset::get()->get("en_UK.txt"); return Asset::get()->get("en_UK.txt");
break; break;
default: default:
break; break;
} }

View File

@@ -34,9 +34,6 @@ private:
// Asigna los botones y teclas al objeto Input // Asigna los botones y teclas al objeto Input
void bindInputs(); void bindInputs();
// Carga los parametros para configurar el juego
void loadParams(const std::string &file_path);
// Crea el indice de ficheros // Crea el indice de ficheros
void setFileList(); void setFileList();

View File

@@ -1,39 +1,39 @@
#include "game.h" #include "game.h"
#include "asset.h" // for Asset #include "asset.h" // Para Asset
#include "background.h" // for Background #include "background.h" // Para Background
#include "balloon.h" // for Balloon, BALLOON_SCORE, BALLOON_VE... #include "balloon.h" // Para Balloon, BALLOON_SCORE, BALLOON_VE...
#include "balloon_formations.h" // for BalloonFormations, BalloonFormatio... #include "balloon_formations.h" // Para BalloonFormations, BalloonFormatio...
#include "bullet.h" // for Bullet, BulletType, BulletMoveStatus #include "bullet.h" // Para Bullet, BulletType, BulletMoveStatus
#include "explosions.h" // for Explosions #include "explosions.h" // Para Explosions
#include "fade.h" // for Fade, FadeType #include "fade.h" // Para Fade, FadeType
#include "global_inputs.h" // for check #include "global_inputs.h" // Para check
#include "input.h" // for InputType, Input, INPUT_DO_NOT_ALL... #include "input.h" // Para InputType, Input, INPUT_DO_NOT_ALL...
#include "item.h" // for Item, ItemType #include "item.h" // Para Item, ItemType
#include "jail_audio.h" // for JA_PlaySound, JA_GetMusicState #include "jail_audio.h" // Para JA_PlaySound, JA_GetMusicState
#include "lang.h" // for getText #include "lang.h" // Para getText
#include "manage_hiscore_table.h" // for ManageHiScoreTable, HiScoreEntry #include "manage_hiscore_table.h" // Para ManageHiScoreTable, HiScoreEntry
#include "notifier.h" // for Notifier #include "notifier.h" // Para Notifier
#include "param.h" // for Param, param, ParamGame, ParamFade #include "param.h" // Para Param, param, ParamGame, ParamFade
#include "path_sprite.h" // for Path, PathSprite, createPath, Path... #include "path_sprite.h" // Para Path, PathSprite, createPath, Path...
#include "player.h" // for Player, PlayerStatus #include "player.h" // Para Player, PlayerStatus
#include "resource.h" // for Resource #include "resource.h" // Para Resource
#include "scoreboard.h" // for Scoreboard, ScoreboardMode, SCOREB... #include "scoreboard.h" // Para Scoreboard, ScoreboardMode, SCOREB...
#include "screen.h" // for Screen #include "screen.h" // Para Screen
#include "section.h" // for Name, name, Options, options #include "section.h" // Para Name, name, Options, options
#include "smart_sprite.h" // for SmartSprite #include "smart_sprite.h" // Para SmartSprite
#include "text.h" // for Text #include "text.h" // Para Text
#include "texture.h" // for Texture #include "texture.h" // Para Texture
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND #include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_KEYDOWN #include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_KEYDOWN
#include <SDL2/SDL_keycode.h> // for SDLK_1, SDLK_2, SDLK_3, SDLK_4 #include <SDL2/SDL_keycode.h> // Para SDLK_1, SDLK_2, SDLK_3, SDLK_4
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888 #include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_timer.h> // for SDL_GetTicks #include <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_FOCUS_GAINED, SDL_... #include <SDL2/SDL_video.h> // Para SDL_WINDOWEVENT_FOCUS_GAINED, SDL_...
#include <algorithm> // for find_if, clamp, min, remove_if #include <algorithm> // Para find_if, clamp, min, remove_if
#include <functional> // for function #include <functional> // Para function
#include <iterator> // for distance, size #include <iterator> // Para distance, size
#include <numeric> // for accumulate #include <numeric> // Para accumulate
#include <stdlib.h> // for rand, size_t #include <stdlib.h> // Para rand, size_t
struct JA_Sound_t; // lines 36-36 struct JA_Sound_t; // lines 36-36
@@ -85,6 +85,15 @@ Game::Game(int player_id, int current_stage, bool demo)
initPaths(); initPaths();
setTotalPower(); setTotalPower();
#ifdef DEBUG
// Si se empieza en una fase que no es la primera
if (!demo_.enabled)
for (int i = 0; i < current_stage_; ++i)
{
balloons_popped_ += balloon_formations_->getStage(i).power_to_complete;
}
#endif
// Crea los primeros globos y el mensaje de inicio // Crea los primeros globos y el mensaje de inicio
if (!demo_.enabled) if (!demo_.enabled)
{ {
@@ -319,6 +328,8 @@ void Game::renderPlayers()
// Comprueba si hay cambio de fase y actualiza las variables // Comprueba si hay cambio de fase y actualiza las variables
void Game::updateStage() void Game::updateStage()
{
if (state_ == GameState::PLAYING)
{ {
if (current_power_ >= balloon_formations_->getStage(current_stage_).power_to_complete) if (current_power_ >= balloon_formations_->getStage(current_stage_).power_to_complete)
{ {
@@ -331,32 +342,8 @@ void Game::updateStage()
screen_->flash(flash_color, 100); screen_->flash(flash_color, 100);
screen_->shake(); screen_->shake();
// Ha llegado al final el juego
if (status_ == GameStatus::PLAYING && current_stage_ == 10)
{
status_ = GameStatus::COMPLETED;
stopMusic();
current_stage_ = 9; // Deja el valor dentro de los limites
destroyAllBalloons(); // Destruye a todos los globos
destroyAllItems(); // Destruye todos los items
current_power_ = 0; // Vuelve a dejar el poder a cero, por lo que hubiera podido subir al destruir todos los globos
for (auto &player : players_)
if (player->isPlaying())
{
player->addScore(1000000);
player->setStatusPlaying(player->IsEligibleForHighScore() ? PlayerStatus::ENTERING_NAME_GAME_COMPLETED : PlayerStatus::GAME_COMPLETED);
}
else
{
player->setStatusPlaying(PlayerStatus::GAME_OVER);
}
updateHiScore();
}
// Escribe el texto por pantalla // Escribe el texto por pantalla
if (status_ == GameStatus::PLAYING) if (current_stage_ < 10)
{ {
const auto stage_number = balloon_formations_->getStage(current_stage_).number; const auto stage_number = balloon_formations_->getStage(current_stage_).number;
std::vector<Path> paths = {paths_.at(2), paths_.at(3)}; std::vector<Path> paths = {paths_.at(2), paths_.at(3)};
@@ -369,19 +356,14 @@ void Game::updateStage()
createMessage(paths, text->writeToTexture(caption, 2, -2)); createMessage(paths, text->writeToTexture(caption, 2, -2));
} }
} }
else
{
createMessage({paths_.at(4), paths_.at(5)}, Resource::get()->getTexture("congratulations"));
createMessage({paths_.at(6), paths_.at(7)}, Resource::get()->getTexture("1000000_points"));
} }
} }
} }
// Actualiza el estado de fin de la partida // Actualiza el estado de fin de la partida
void Game::updateGameOver() void Game::updateGameOverState()
{ {
// Si todos estan en estado de Game Over y no hay mensajes por pantalla if (state_ == GameState::GAME_OVER)
if (allPlayersAreGameOver() && path_sprites_.empty())
{ {
if (game_over_counter_ > 0) if (game_over_counter_ > 0)
{ {
@@ -411,6 +393,71 @@ void Game::updateGameOver()
} }
} }
// Gestiona eventos para el estado del final del juego
void Game::updateCompletedState()
{
if (state_ == GameState::COMPLETED)
{
// Para la música y elimina todos los globos e items
if (game_completed_counter_ == 0)
{
stopMusic();
current_stage_ = 9; // Deja el valor dentro de los limites
destroyAllBalloons(); // Destruye a todos los globos
destroyAllItems(); // Destruye todos los items
current_power_ = 0; // Vuelve a dejar el poder a cero, por lo que hubiera podido subir al destruir todos los globos
}
// Comienza las celebraciones
// Muestra el mensaje de felicitación y da los puntos a los jugadores
if (game_completed_counter_ == 200)
{
createMessage({paths_.at(4), paths_.at(5)}, Resource::get()->getTexture("congratulations"));
createMessage({paths_.at(6), paths_.at(7)}, Resource::get()->getTexture("1000000_points"));
for (auto &player : players_)
if (player->isPlaying())
{
player->addScore(1000000);
player->setPlayingState(PlayerState::CELEBRATING);
}
else
{
player->setPlayingState(PlayerState::GAME_OVER);
}
updateHiScore();
}
// Termina las celebraciones
if (game_completed_counter_ == 500)
{
for (auto &player : players_)
if (player->isCelebrating())
{
player->setPlayingState(player->IsEligibleForHighScore() ? PlayerState::ENTERING_NAME_GAME_COMPLETED : PlayerState::GAME_COMPLETED);
}
}
// Incrementa el contador al final
++game_completed_counter_;
}
}
// Comprueba el estado del juego
void Game::checkState()
{
if (state_ != GameState::COMPLETED && current_stage_ == 10)
{
state_ = GameState::COMPLETED;
}
if (state_ != GameState::GAME_OVER && allPlayersAreGameOver())
{
state_ = GameState::GAME_OVER;
}
}
// Actualiza los globos // Actualiza los globos
void Game::updateBalloons() void Game::updateBalloons()
{ {
@@ -1036,7 +1083,7 @@ void Game::killPlayer(std::shared_ptr<Player> &player)
JA_PlaySound(Resource::get()->getSound("player_collision.wav")); JA_PlaySound(Resource::get()->getSound("player_collision.wav"));
screen_->shake(); screen_->shake();
JA_PlaySound(Resource::get()->getSound("coffeeout.wav")); JA_PlaySound(Resource::get()->getSound("coffeeout.wav"));
player->setStatusPlaying(PlayerStatus::DYING); player->setPlayingState(PlayerState::DYING);
allPlayersAreNotPlaying() ? stopMusic() : resumeMusic(); allPlayersAreNotPlaying() ? stopMusic() : resumeMusic();
} }
} }
@@ -1096,8 +1143,7 @@ void Game::update()
#ifdef RECORDING #ifdef RECORDING
updateRecording(); updateRecording();
#endif #endif
updateNormalGame(); updateGame();
updateCompletedGame();
checkMusicStatus(); checkMusicStatus();
screen_->update(); screen_->update();
@@ -1109,7 +1155,7 @@ void Game::update()
void Game::updateBackground() void Game::updateBackground()
{ {
// Si el juego está completado, se reduce la velocidad de las nubes // Si el juego está completado, se reduce la velocidad de las nubes
if (status_ == GameStatus::COMPLETED) if (state_ == GameState::COMPLETED)
balloons_popped_ = (balloons_popped_ > 400) ? (balloons_popped_ - 25) : 200; balloons_popped_ = (balloons_popped_ > 400) ? (balloons_popped_ - 25) : 200;
// Calcula la velocidad en función de los globos explotados y el total de globos a explotar para acabar el juego // Calcula la velocidad en función de los globos explotados y el total de globos a explotar para acabar el juego
@@ -1212,7 +1258,7 @@ void Game::checkMusicStatus()
if (JA_GetMusicState() == JA_MUSIC_INVALID || if (JA_GetMusicState() == JA_MUSIC_INVALID ||
JA_GetMusicState() == JA_MUSIC_STOPPED) JA_GetMusicState() == JA_MUSIC_STOPPED)
// Si se ha completado el juego o los jugadores han terminado, detiene la música // Si se ha completado el juego o los jugadores han terminado, detiene la música
status_ == GameStatus::COMPLETED || allPlayersAreGameOver() ? JA_StopMusic() : JA_PlayMusic(Resource::get()->getMusic("playing.ogg")); state_ == GameState::COMPLETED || allPlayersAreGameOver() ? JA_StopMusic() : JA_PlayMusic(Resource::get()->getMusic("playing.ogg"));
} }
// Bucle para el juego // Bucle para el juego
@@ -1405,7 +1451,7 @@ void Game::checkEvents()
case SDLK_3: // Activa el modo para pasar el juego automaticamente case SDLK_3: // Activa el modo para pasar el juego automaticamente
{ {
auto_pop_balloons_ = !auto_pop_balloons_; auto_pop_balloons_ = !auto_pop_balloons_;
Notifier::get()->showText("auto_pop_balloons_ " + boolToString(auto_pop_balloons_)); Notifier::get()->showText({"auto_pop_balloons_ " + boolToString(auto_pop_balloons_)});
break; break;
} }
case SDLK_4: // Suelta un item case SDLK_4: // Suelta un item
@@ -1432,7 +1478,7 @@ void Game::checkEvents()
} }
case SDLK_8: case SDLK_8:
{ {
players_.at(0)->setStatusPlaying(PlayerStatus::GAME_COMPLETED); players_.at(0)->setPlayingState(PlayerState::GAME_COMPLETED);
} }
default: default:
break; break;
@@ -1502,7 +1548,7 @@ void Game::checkAndUpdatePlayerStatus(int activePlayerIndex, int inactivePlayerI
{ {
if (players_[activePlayerIndex]->isGameOver() && !players_[inactivePlayerIndex]->isGameOver() && !players_[inactivePlayerIndex]->isWaiting()) if (players_[activePlayerIndex]->isGameOver() && !players_[inactivePlayerIndex]->isGameOver() && !players_[inactivePlayerIndex]->isWaiting())
{ {
players_[activePlayerIndex]->setStatusPlaying(PlayerStatus::WAITING); players_[activePlayerIndex]->setPlayingState(PlayerState::WAITING);
} }
} }
@@ -1520,7 +1566,7 @@ void Game::checkPlayersStatusPlaying()
// Entonces los pone en estado de Game Over // Entonces los pone en estado de Game Over
for (auto &player : players_) for (auto &player : players_)
{ {
player->setStatusPlaying(PlayerStatus::GAME_OVER); player->setPlayingState(PlayerState::GAME_OVER);
} }
} }
@@ -1545,12 +1591,12 @@ std::shared_ptr<Player> Game::getPlayer(int id)
// Obtiene un controlador a partir del "id" del jugador // Obtiene un controlador a partir del "id" del jugador
int Game::getController(int player_id) int Game::getController(int player_id)
{ {
auto it = std::find_if(options.controller.begin(), options.controller.end(), [player_id](const auto &controller) auto it = std::find_if(options.controllers.begin(), options.controllers.end(), [player_id](const auto &controller)
{ return controller.player_id == player_id; }); { return controller.player_id == player_id; });
if (it != options.controller.end()) if (it != options.controllers.end())
{ {
return std::distance(options.controller.begin(), it); return std::distance(options.controllers.begin(), it);
} }
return -1; return -1;
@@ -1559,19 +1605,13 @@ int Game::getController(int player_id)
// Gestiona la entrada durante el juego // Gestiona la entrada durante el juego
void Game::checkInput() void Game::checkInput()
{ {
checkPauseInput(); // Verifica si se debe pausar el juego. // Verifica si se debe pausar el juego.
checkPauseInput();
if (demo_.enabled) demo_.enabled ? handleDemoMode() : handlePlayersInput();
{ // Controla el comportamiento de los jugadores en modo demo.
handleDemoMode();
}
else
{ // Gestiona el input normal de los jugadores.
handlePlayersInput();
}
screen_->checkInput(); // Verifica el input en la pantalla del juego. // Verifica los inputs globales.
globalInputs::check(); // Verifica los inputs globales. globalInputs::check();
} }
// Verifica si alguno de los controladores ha solicitado una pausa y actualiza el estado de pausa del juego. // Verifica si alguno de los controladores ha solicitado una pausa y actualiza el estado de pausa del juego.
@@ -1579,16 +1619,17 @@ void Game::checkPauseInput()
{ {
// Comprueba los mandos // Comprueba los mandos
for (int i = 0; i < input_->getNumControllers(); ++i) for (int i = 0; i < input_->getNumControllers(); ++i)
if (input_->checkModInput(InputType::SERVICE, InputType::PAUSE, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (input_->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
input_->checkInput(InputType::PAUSE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{ {
pause(!paused_); // Alterna entre pausado y no pausado. pause(!paused_);
return; return;
} }
// Comprueba el teclado // Comprueba el teclado
if (input_->checkInput(InputType::PAUSE, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) if (input_->checkInput(InputType::PAUSE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{ {
pause(!paused_); // Alterna entre pausado y no pausado. pause(!paused_);
return; return;
} }
} }
@@ -1682,17 +1723,17 @@ void Game::handlePlayersInput()
// Maneja las entradas de movimiento y disparo para un jugador en modo normal. // Maneja las entradas de movimiento y disparo para un jugador en modo normal.
void Game::handleNormalPlayerInput(const std::shared_ptr<Player> &player) void Game::handleNormalPlayerInput(const std::shared_ptr<Player> &player)
{ {
const auto controllerIndex = player->getController(); const auto &controller = options.controllers.at(player->getController());
const bool autofire = player->isPowerUp() || options.game.autofire; const bool autofire = player->isPowerUp() || options.game.autofire;
if (input_->checkInput(InputType::LEFT, INPUT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) if (input_->checkInput(InputType::LEFT, INPUT_ALLOW_REPEAT, controller.type, controller.index))
{ {
player->setInput(InputType::LEFT); player->setInput(InputType::LEFT);
#ifdef RECORDING #ifdef RECORDING
demo_.keys.left = 1; demo_.keys.left = 1;
#endif #endif
} }
else if (input_->checkInput(InputType::RIGHT, INPUT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) else if (input_->checkInput(InputType::RIGHT, INPUT_ALLOW_REPEAT, controller.type, controller.index))
{ {
player->setInput(InputType::RIGHT); player->setInput(InputType::RIGHT);
#ifdef RECORDING #ifdef RECORDING
@@ -1707,27 +1748,27 @@ void Game::handleNormalPlayerInput(const std::shared_ptr<Player> &player)
#endif #endif
} }
handleFireInputs(player, autofire, controllerIndex); // Verifica y maneja todas las posibles entradas de disparo. handleFireInputs(player, autofire, player->getController()); // Verifica y maneja todas las posibles entradas de disparo.
} }
// Procesa las entradas de disparo del jugador, permitiendo disparos automáticos si está habilitado. // Procesa las entradas de disparo del jugador, permitiendo disparos automáticos si está habilitado.
void Game::handleFireInputs(const std::shared_ptr<Player> &player, bool autofire, int controllerIndex) void Game::handleFireInputs(const std::shared_ptr<Player> &player, bool autofire, int controllerIndex)
{ {
if (input_->checkInput(InputType::FIRE_CENTER, autofire, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) if (input_->checkInput(InputType::FIRE_CENTER, autofire, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
{ {
handleFireInput(player, BulletType::UP); handleFireInput(player, BulletType::UP);
#ifdef RECORDING #ifdef RECORDING
demo_.keys.fire = 1; demo_.keys.fire = 1;
#endif #endif
} }
else if (input_->checkInput(InputType::FIRE_LEFT, autofire, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) else if (input_->checkInput(InputType::FIRE_LEFT, autofire, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
{ {
handleFireInput(player, BulletType::LEFT); handleFireInput(player, BulletType::LEFT);
#ifdef RECORDING #ifdef RECORDING
demo_.keys.fire_left = 1; demo_.keys.fire_left = 1;
#endif #endif
} }
else if (input_->checkInput(InputType::FIRE_RIGHT, autofire, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) else if (input_->checkInput(InputType::FIRE_RIGHT, autofire, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
{ {
handleFireInput(player, BulletType::RIGHT); handleFireInput(player, BulletType::RIGHT);
#ifdef RECORDING #ifdef RECORDING
@@ -1740,15 +1781,15 @@ void Game::handleFireInputs(const std::shared_ptr<Player> &player, bool autofire
void Game::handlePlayerContinue(const std::shared_ptr<Player> &player) void Game::handlePlayerContinue(const std::shared_ptr<Player> &player)
{ {
const auto controllerIndex = player->getController(); const auto controllerIndex = player->getController();
if (input_->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) if (input_->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
{ {
player->setStatusPlaying(PlayerStatus::PLAYING); player->setPlayingState(PlayerState::PLAYING);
} }
// Disminuye el contador de continuación si se presiona cualquier botón de disparo. // Disminuye el contador de continuación si se presiona cualquier botón de disparo.
if (input_->checkInput(InputType::FIRE_LEFT, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index) || if (input_->checkInput(InputType::FIRE_LEFT, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index) ||
input_->checkInput(InputType::FIRE_CENTER, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index) || input_->checkInput(InputType::FIRE_CENTER, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index) ||
input_->checkInput(InputType::FIRE_RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) input_->checkInput(InputType::FIRE_RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
{ {
player->decContinueCounter(); player->decContinueCounter();
} }
@@ -1758,31 +1799,31 @@ void Game::handlePlayerContinue(const std::shared_ptr<Player> &player)
void Game::handleNameInput(const std::shared_ptr<Player> &player) void Game::handleNameInput(const std::shared_ptr<Player> &player)
{ {
const auto controllerIndex = player->getController(); const auto controllerIndex = player->getController();
if (input_->checkInput(InputType::FIRE_LEFT, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index) || if (input_->checkInput(InputType::FIRE_LEFT, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index) ||
input_->checkInput(InputType::FIRE_CENTER, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index) || input_->checkInput(InputType::FIRE_CENTER, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index) ||
input_->checkInput(InputType::FIRE_RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) input_->checkInput(InputType::FIRE_RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
{ {
if (player->getRecordNamePos() == 7) if (player->getRecordNamePos() == 7)
{ {
player->setInput(InputType::START); player->setInput(InputType::START);
addScoreToScoreBoard(player->getRecordName(), player->getScore()); addScoreToScoreBoard(player->getRecordName(), player->getScore());
const auto status = player->getStatusPlaying(); const auto status = player->getPlayingState();
player->setStatusPlaying(status == PlayerStatus::ENTERING_NAME ? PlayerStatus::CONTINUE : PlayerStatus::GAME_COMPLETED); player->setPlayingState(status == PlayerState::ENTERING_NAME ? PlayerState::CONTINUE : PlayerState::GAME_COMPLETED);
} }
else else
{ {
player->setInput(InputType::RIGHT); player->setInput(InputType::RIGHT);
} }
} }
else if (input_->checkInput(InputType::UP, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) else if (input_->checkInput(InputType::UP, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
{ {
player->setInput(InputType::UP); player->setInput(InputType::UP);
} }
else if (input_->checkInput(InputType::DOWN, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) else if (input_->checkInput(InputType::DOWN, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
{ {
player->setInput(InputType::DOWN); player->setInput(InputType::DOWN);
} }
else if (input_->checkInput(InputType::LEFT, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) else if (input_->checkInput(InputType::LEFT, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
{ {
player->setInput(InputType::LEFT); player->setInput(InputType::LEFT);
} }
@@ -1792,12 +1833,12 @@ void Game::handleNameInput(const std::shared_ptr<Player> &player)
player->setInput(InputType::RIGHT); player->setInput(InputType::RIGHT);
} }
*/ */
else if (input_->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index)) else if (input_->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
{ {
player->setInput(InputType::START); player->setInput(InputType::START);
addScoreToScoreBoard(player->getRecordName(), player->getScore()); addScoreToScoreBoard(player->getRecordName(), player->getScore());
const auto status = player->getStatusPlaying(); const auto status = player->getPlayingState();
player->setStatusPlaying(status == PlayerStatus::ENTERING_NAME ? PlayerStatus::CONTINUE : PlayerStatus::GAME_COMPLETED); player->setPlayingState(status == PlayerState::ENTERING_NAME ? PlayerState::CONTINUE : PlayerState::GAME_COMPLETED);
} }
} }
@@ -1820,8 +1861,7 @@ void Game::initDemo(int player_id)
current_stage_ = stages[demo]; current_stage_ = stages[demo];
} }
// Actualiza el numero de globos explotados según la fase del modo // Actualiza el numero de globos explotados según la fase del modo demostración
// demostración
for (int i = 0; i < current_stage_; ++i) for (int i = 0; i < current_stage_; ++i)
{ {
balloons_popped_ += balloon_formations_->getStage(i).power_to_complete; balloons_popped_ += balloon_formations_->getStage(i).power_to_complete;
@@ -1832,7 +1872,7 @@ void Game::initDemo(int player_id)
{ {
const auto other_player_id = player_id == 1 ? 2 : 1; const auto other_player_id = player_id == 1 ? 2 : 1;
auto other_player = getPlayer(other_player_id); auto other_player = getPlayer(other_player_id);
other_player->setStatusPlaying(PlayerStatus::PLAYING); other_player->setPlayingState(PlayerState::PLAYING);
} }
// Asigna cafes a los jugadores // Asigna cafes a los jugadores
@@ -1939,7 +1979,7 @@ void Game::initPlayers(int player_id)
// Activa el jugador que coincide con el "player_id" // Activa el jugador que coincide con el "player_id"
auto player = getPlayer(player_id); auto player = getPlayer(player_id);
player->setStatusPlaying(PlayerStatus::PLAYING); player->setPlayingState(PlayerState::PLAYING);
player->setInvulnerable(false); player->setInvulnerable(false);
} }
@@ -2023,15 +2063,15 @@ void Game::updateRecording()
#endif #endif
// Actualiza las variables durante el transcurso normal del juego // Actualiza las variables durante el transcurso normal del juego
void Game::updateNormalGame() void Game::updateGame()
{ {
if (status_ == GameStatus::PLAYING && !paused_) if (!paused_)
{ {
#ifdef DEBUG #ifdef DEBUG
if (auto_pop_balloons_) if (auto_pop_balloons_ && state_ == GameState::PLAYING)
{ {
balloons_popped_++; balloons_popped_ += 5;
increaseStageCurrentPower(1); increaseStageCurrentPower(5);
} }
#endif #endif
fade_->update(); fade_->update();
@@ -2044,7 +2084,8 @@ void Game::updateNormalGame()
moveBullets(); moveBullets();
updateItems(); updateItems();
updateStage(); updateStage();
updateGameOver(); updateGameOverState();
updateCompletedState();
updateSmartSprites(); updateSmartSprites();
updatePathSprites(); updatePathSprites();
updateTimeStopped(); updateTimeStopped();
@@ -2053,36 +2094,17 @@ void Game::updateNormalGame()
checkBulletBalloonCollision(); checkBulletBalloonCollision();
updateMenace(); updateMenace();
checkAndUpdateBalloonSpeed(); checkAndUpdateBalloonSpeed();
freeBullets(); checkState();
freeBalloons(); cleanVectors();
freeItems();
freeSmartSprites();
freePathSprites();
} }
} }
// Actualiza las variables durante el transcurso normal del juego // Vacía los vectores de elementos deshabilitados
void Game::updateCompletedGame() void Game::cleanVectors()
{ {
if (status_ == GameStatus::COMPLETED && !paused_)
{
fade_->update();
updatePlayers();
checkPlayersStatusPlaying();
updateScoreboard();
updateBackground();
updateBalloons();
explosions_->update();
moveBullets();
updateItems();
updateGameOver();
updateSmartSprites();
updatePathSprites();
checkBulletBalloonCollision();
freeBullets(); freeBullets();
freeBalloons(); freeBalloons();
freeItems(); freeItems();
freeSmartSprites(); freeSmartSprites();
freePathSprites(); freePathSprites();
} }
}

View File

@@ -1,15 +1,15 @@
#pragma once #pragma once
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture #include <SDL2/SDL_render.h> // Para SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // for Uint32, Uint8 #include <SDL2/SDL_stdinc.h> // Para Uint32, Uint8
#include <memory> // for shared_ptr, unique_ptr #include <memory> // Para shared_ptr, unique_ptr
#include <string> // for string #include <string> // Para string
#include <vector> // for vector #include <vector> // Para vector
#include "balloon.h" // for Balloon #include "balloon.h" // Para Balloon
#include "manage_hiscore_table.h" // for HiScoreEntry #include "manage_hiscore_table.h" // Para HiScoreEntry
#include "options.h" // for Options, OptionsGame, options #include "options.h" // Para Options, OptionsGame, options
#include "player.h" // for Player #include "player.h" // Para Player
#include "utils.h" // for Demo #include "utils.h" // Para Demo
class Asset; // lines 14-14 class Asset; // lines 14-14
class Background; // lines 15-15 class Background; // lines 15-15
class BalloonFormations; // lines 16-16 class BalloonFormations; // lines 16-16
@@ -65,10 +65,11 @@ class Game
{ {
private: private:
// Enum // Enum
enum class GameStatus enum class GameState
{ {
PLAYING, PLAYING,
COMPLETED, COMPLETED,
GAME_OVER,
}; };
// Contadores // Contadores
@@ -180,7 +181,7 @@ private:
int power_ball_counter_ = 0; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra int power_ball_counter_ = 0; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra
int time_stopped_counter_ = 0; // Temporizador para llevar la cuenta del tiempo detenido int time_stopped_counter_ = 0; // Temporizador para llevar la cuenta del tiempo detenido
int total_power_to_complete_game_; // La suma del poder necesario para completar todas las fases int total_power_to_complete_game_; // La suma del poder necesario para completar todas las fases
GameStatus status_ = GameStatus::PLAYING; // Estado GameState state_ = GameState::PLAYING; // Estado
#ifdef DEBUG #ifdef DEBUG
bool auto_pop_balloons_ = false; // Si es true, incrementa automaticamente los globos explotados bool auto_pop_balloons_ = false; // Si es true, incrementa automaticamente los globos explotados
#endif #endif
@@ -216,7 +217,7 @@ private:
void updateStage(); void updateStage();
// Actualiza el estado de fin de la partida // Actualiza el estado de fin de la partida
void updateGameOver(); void updateGameOverState();
// Actualiza los globos // Actualiza los globos
void updateBalloons(); void updateBalloons();
@@ -350,9 +351,6 @@ private:
// Inicializa las variables que contienen puntos de ruta para mover objetos // Inicializa las variables que contienen puntos de ruta para mover objetos
void initPaths(); void initPaths();
// Pinta diferentes mensajes en la pantalla
void renderMessages();
// Habilita el efecto del item de detener el tiempo // Habilita el efecto del item de detener el tiempo
void enableTimeStopItem(); void enableTimeStopItem();
@@ -471,11 +469,20 @@ private:
void updateRecording(); void updateRecording();
#endif #endif
// Actualiza las variables durante el transcurso normal del juego // Actualiza las variables durante el transcurso normal del juego
void updateNormalGame(); void updateGame();
// Actualiza las variables durante el transcurso del final del juego // Actualiza las variables durante el transcurso del final del juego
void updateCompletedGame(); void updateCompletedGame();
// Gestiona eventos para el estado del final del juego
void updateCompletedState();
// Comprueba el estado del juego
void checkState();
// Vacía los vectores de elementos deshabilitados
void cleanVectors();
public: public:
// Constructor // Constructor
Game(int playerID, int current_stage, bool demo); Game(int playerID, int current_stage, bool demo);

View File

@@ -8,6 +8,7 @@
#include "options.h" // Para Options, OptionsAudio, options, OptionsM... #include "options.h" // Para Options, OptionsAudio, options, OptionsM...
#include "section.h" // Para Name, Options, name, options #include "section.h" // Para Name, Options, name, options
#include "utils.h" // Para boolToOnOff, stringInVector #include "utils.h" // Para boolToOnOff, stringInVector
#include "screen.h"
namespace globalInputs namespace globalInputs
{ {
@@ -39,9 +40,9 @@ namespace globalInputs
{ {
#ifdef ARCADE #ifdef ARCADE
const int index = code == section::Options::QUIT_WITH_CONTROLLER ? 116 : 94; const int index = code == section::Options::QUIT_WITH_CONTROLLER ? 116 : 94;
Notifier::get()->showText(lang::getText(index), std::string(), -1, exit_code); Notifier::get()->showText({lang::getText(index), std::string()}, -1, exit_code);
#else #else
Notifier::get()->showText(lang::getText(94), std::string(), -1, exit_code); Notifier::get()->showText({lang::getText(94), std::string()}, -1, exit_code);
#endif #endif
} }
} }
@@ -50,11 +51,11 @@ namespace globalInputs
void reset() void reset()
{ {
section::name = section::Name::INIT; section::name = section::Name::INIT;
Notifier::get()->showText("Reset"); Notifier::get()->showText({"Reset"});
} }
// Activa o desactiva el audio // Activa o desactiva el audio
void switchAudio() void toggleAudio()
{ {
options.audio.enabled = !options.audio.enabled; options.audio.enabled = !options.audio.enabled;
if (options.audio.enabled) if (options.audio.enabled)
@@ -67,33 +68,80 @@ namespace globalInputs
JA_SetMusicVolume(0); JA_SetMusicVolume(0);
JA_SetSoundVolume(0); JA_SetSoundVolume(0);
} }
Notifier::get()->showText("Audio " + boolToOnOff(options.audio.enabled)); Notifier::get()->showText({"Audio " + boolToOnOff(options.audio.enabled)});
} }
// Comprueba los inputs que se pueden introducir en cualquier sección del juego // Comprueba los inputs que se pueden introducir en cualquier sección del juego
void check() void check()
{ {
// Comprueba si se sale con el teclado // Teclado
if (Input::get()->checkInput(InputType::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) {
#ifndef ARCADE
// Comprueba el teclado para cambiar entre pantalla completa y ventana
if (Input::get()->checkInput(InputType::WINDOW_FULLSCREEN, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
Screen::get()->toggleVideoMode();
const std::string mode = options.video.mode == ScreenVideoMode::WINDOW ? "Window" : "Fullscreen";
Notifier::get()->showText({mode + " mode"});
return;
}
// Comprueba el teclado para decrementar el tamaño de la ventana
if (Input::get()->checkInput(InputType::WINDOW_DEC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
Screen::get()->decWindowSize();
const std::string size = std::to_string(options.video.window.size);
Notifier::get()->showText({"Window size x" + size});
return;
}
// Comprueba el teclado para incrementar el tamaño de la ventana
if (Input::get()->checkInput(InputType::WINDOW_INC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
Screen::get()->incWindowSize();
const std::string size = std::to_string(options.video.window.size);
Notifier::get()->showText({"Window size x" + size});
return;
}
#endif
// Salir
if (Input::get()->checkInput(InputType::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{ {
quit(section::Options::QUIT_WITH_KEYBOARD); quit(section::Options::QUIT_WITH_KEYBOARD);
return; return;
} }
// Comprueba si se va a resetear el juego // Reset
else if (Input::get()->checkInput(InputType::RESET, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) if (Input::get()->checkInput(InputType::RESET, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{ {
reset(); reset();
return; return;
} }
else if (Input::get()->checkInput(InputType::MUTE, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) // Audio
if (Input::get()->checkInput(InputType::MUTE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{ {
switchAudio(); toggleAudio();
return; return;
} }
else if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) // Shaders
if (Input::get()->checkInput(InputType::VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
Screen::get()->toggleShaders();
return;
}
#ifdef DEBUG
// Comprueba el teclado para mostrar la información de debug
if (Input::get()->checkInput(InputType::SHOWINFO, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
Screen::get()->toggleDebugInfo();
return;
}
#endif
// OnScreenHelp
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{ {
service_pressed_counter[0]++; service_pressed_counter[0]++;
@@ -104,35 +152,56 @@ namespace globalInputs
} }
return; return;
} }
else
{
service_pressed_counter[0] = 0; service_pressed_counter[0] = 0;
} }
// Mandos
{
for (int i = 0; i < Input::get()->getNumControllers(); ++i) for (int i = 0; i < Input::get()->getNumControllers(); ++i)
{ {
// Comprueba si se sale con el mando // Salir
if (Input::get()->checkModInput(InputType::SERVICE, InputType::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputType::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{ {
quit(section::Options::QUIT_WITH_CONTROLLER); quit(section::Options::QUIT_WITH_CONTROLLER);
return; return;
} }
// Comprueba si se va a resetear el juego // Reset
else if (Input::get()->checkModInput(InputType::SERVICE, InputType::RESET, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputType::RESET, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{ {
reset(); reset();
return; return;
} }
// Comprueba si se va a activar o desactivar el audio // Audio
else if (Input::get()->checkModInput(InputType::SERVICE, InputType::MUTE, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputType::MUTE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{ {
switchAudio(); toggleAudio();
return; return;
} }
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) // Shaders
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputType::VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
Screen::get()->toggleShaders();
return;
}
#ifdef DEBUG
// Debug Info
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputType::SHOWINFO, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
Screen::get()->toggleDebugInfo();
return;
}
#endif
// OnScreenHelp
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{ {
service_pressed_counter[i + 1]++; service_pressed_counter[i + 1]++;
@@ -143,8 +212,7 @@ namespace globalInputs
} }
return; return;
} }
else
{
service_pressed_counter[i + 1] = 0; service_pressed_counter[i + 1] = 0;
} }
} }

View File

@@ -208,9 +208,6 @@ void HiScoreTable::checkInput()
return; return;
} }
// Comprueba el input para el resto de objetos
Screen::get()->checkInput();
// Comprueba los inputs que se pueden introducir en cualquier sección del juego // Comprueba los inputs que se pueden introducir en cualquier sección del juego
globalInputs::check(); globalInputs::check();
} }

View File

@@ -1,9 +1,13 @@
#include "input.h" #include "input.h"
#include <SDL2/SDL.h> // para SDL_INIT_GAMECONTROLLER, SDL_InitSubS... #include <SDL2/SDL.h> // Para SDL_INIT_GAMECONTROLLER, SDL_InitSubS...
#include <SDL2/SDL_error.h> // para SDL_GetError #include <SDL2/SDL_error.h> // Para SDL_GetError
#include <SDL2/SDL_events.h> // para SDL_ENABLE #include <SDL2/SDL_events.h> // Para SDL_ENABLE
#include <SDL2/SDL_keyboard.h> // para SDL_GetKeyboardState #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] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado // [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
Input *Input::input_ = nullptr; Input *Input::input_ = nullptr;
@@ -28,49 +32,23 @@ Input *Input::get()
// Constructor // Constructor
Input::Input(const std::string &game_controller_db_path) Input::Input(const std::string &game_controller_db_path)
: game_controller_db_path_(game_controller_db_path), : game_controller_db_path_(game_controller_db_path)
enabled_(true)
{ {
// Busca si hay mandos conectados // Busca si hay mandos conectados
discoverGameControllers(); discoverGameControllers();
// Inicializa las vectores // Inicializa los vectores
KeyBindings kb; key_bindings_.resize(static_cast<int>(InputType::NUMBER_OF_INPUTS), KeyBindings());
kb.scancode = 0; controller_bindings_.resize(num_gamepads_, std::vector<ControllerBindings>(static_cast<int>(InputType::NUMBER_OF_INPUTS), ControllerBindings()));
kb.active = false;
key_bindings_.resize(static_cast<int>(InputType::NUMBER_OF_INPUTS), kb);
ControllerBindings gcb;
gcb.button = SDL_CONTROLLER_BUTTON_INVALID;
gcb.active = false;
controller_bindings_.resize(num_gamepads_);
for (int i = 0; i < num_gamepads_; ++i)
{
controller_bindings_[i].resize(static_cast<int>(InputType::NUMBER_OF_INPUTS), gcb);
}
// Listado de los inputs usados para jugar, excluyendo botones para la interfaz
game_inputs_.clear();
game_inputs_.push_back(InputType::FIRE_LEFT);
game_inputs_.push_back(InputType::FIRE_CENTER);
game_inputs_.push_back(InputType::FIRE_RIGHT);
game_inputs_.push_back(InputType::UP);
game_inputs_.push_back(InputType::DOWN);
game_inputs_.push_back(InputType::LEFT);
game_inputs_.push_back(InputType::RIGHT);
// Listado de los inputs para jugar que utilizan botones, ni palancas ni crucetas // Listado de los inputs para jugar que utilizan botones, ni palancas ni crucetas
button_inputs_.clear(); button_inputs_ = {InputType::FIRE_LEFT, InputType::FIRE_CENTER, InputType::FIRE_RIGHT, InputType::START};
button_inputs_.push_back(InputType::FIRE_LEFT);
button_inputs_.push_back(InputType::FIRE_CENTER);
button_inputs_.push_back(InputType::FIRE_RIGHT);
button_inputs_.push_back(InputType::START);
} }
// Asigna inputs a teclas // Asigna inputs a teclas
void Input::bindKey(InputType input, SDL_Scancode code) void Input::bindKey(InputType input, SDL_Scancode code)
{ {
key_bindings_[static_cast<int>(input)].scancode = code; key_bindings_.at(static_cast<int>(input)).scancode = code;
} }
// Asigna inputs a botones del mando // Asigna inputs a botones del mando
@@ -78,7 +56,7 @@ void Input::bindGameControllerButton(int controller_index, InputType input, SDL_
{ {
if (controller_index < num_gamepads_) if (controller_index < num_gamepads_)
{ {
controller_bindings_[controller_index][static_cast<int>(input)].button = button; controller_bindings_.at(controller_index).at(static_cast<int>(input)).button = button;
} }
} }
@@ -87,41 +65,24 @@ void Input::bindGameControllerButton(int controller_index, InputType input_targe
{ {
if (controller_index < num_gamepads_) if (controller_index < num_gamepads_)
{ {
controller_bindings_[controller_index][static_cast<int>(input_target)].button = controller_bindings_[controller_index][static_cast<int>(input_source)].button; 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 // Comprueba si un input esta activo
bool Input::checkInput(InputType input, bool repeat, int device, int controller_index) bool Input::checkInput(InputType input, bool repeat, InputDeviceToUse device, int controller_index)
{ {
if (!enabled_)
{
return false;
}
bool success_keyboard = false; bool success_keyboard = false;
bool success_controller = false; bool success_controller = false;
const int input_index = static_cast<int>(input); const int input_index = static_cast<int>(input);
if (device == INPUT_USE_ANY) if (device == InputDeviceToUse::KEYBOARD || device == InputDeviceToUse::ANY)
{
controller_index = 0;
}
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY)
{ {
const Uint8 *keyStates = SDL_GetKeyboardState(nullptr); const Uint8 *keyStates = SDL_GetKeyboardState(nullptr);
if (repeat) if (repeat)
{ {
if (keyStates[key_bindings_[input_index].scancode] != 0) success_keyboard = keyStates[key_bindings_[input_index].scancode] != 0;
{
success_keyboard = true;
}
else
{
success_keyboard = false;
}
} }
else else
{ {
@@ -142,26 +103,29 @@ bool Input::checkInput(InputType input, bool repeat, int device, int controller_
if (keyStates[key_bindings_[input_index].scancode] == 0) if (keyStates[key_bindings_[input_index].scancode] == 0)
{ {
key_bindings_[input_index].active = false; key_bindings_[input_index].active = false;
success_keyboard = false;
} }
else
{
success_keyboard = false; success_keyboard = false;
} }
} }
} }
}
if (gameControllerFound() && controller_index < num_gamepads_) if (gameControllerFound() && controller_index >= 0 && controller_index < num_gamepads_)
if ((device == INPUT_USE_GAMECONTROLLER) || (device == INPUT_USE_ANY)) if ((device == InputDeviceToUse::CONTROLLER) || (device == InputDeviceToUse::ANY))
{ {
success_controller = checkAxisInput(input, controller_index); success_controller = checkAxisInput(input, controller_index);
if (!success_controller) if (!success_controller)
{ {
if (repeat) if (repeat)
{ {
if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) != 0) success_controller = SDL_GameControllerGetButton(connected_controllers_.at(controller_index), controller_bindings_.at(controller_index).at(input_index).button) != 0;
}
else
{ {
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; success_controller = true;
} }
else else
@@ -171,142 +135,13 @@ bool Input::checkInput(InputType input, bool repeat, int device, int controller_
} }
else else
{ {
if (!controller_bindings_[controller_index][input_index].active) if (SDL_GameControllerGetButton(connected_controllers_.at(controller_index), controller_bindings_.at(controller_index).at(input_index).button) == 0)
{ {
if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) != 0) controller_bindings_.at(controller_index).at(input_index).active = false;
{
controller_bindings_[controller_index][input_index].active = true;
success_controller = true;
} }
else
{
success_controller = false; success_controller = false;
} }
} }
else
{
if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) == 0)
{
controller_bindings_[controller_index][input_index].active = false;
success_controller = false;
}
else
{
success_controller = false;
}
}
}
}
}
return (success_keyboard || success_controller);
}
// Comprueba si un input con modificador esta activo
bool Input::checkModInput(InputType input_mod, InputType input, bool repeat, int device, int controller_index)
{
if (!enabled_ || controller_index >= num_gamepads_ || !checkInput(input_mod, INPUT_ALLOW_REPEAT, device, controller_index))
{
return false;
}
bool success_keyboard = false;
bool success_controller = false;
const int input_index = static_cast<int>(input);
if (device == INPUT_USE_ANY)
{
controller_index = 0;
}
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY)
{
const Uint8 *keyStates = SDL_GetKeyboardState(nullptr);
if (repeat)
{
if (keyStates[key_bindings_[input_index].scancode] != 0)
{
success_keyboard = true;
}
else
{
success_keyboard = false;
}
}
else
{
if (!key_bindings_[input_index].active)
{
if (keyStates[key_bindings_[input_index].scancode] != 0)
{
key_bindings_[input_index].active = true;
success_keyboard = true;
}
else
{
success_keyboard = false;
}
}
else
{
if (keyStates[key_bindings_[input_index].scancode] == 0)
{
key_bindings_[input_index].active = false;
success_keyboard = false;
}
else
{
success_keyboard = false;
}
}
}
}
if (gameControllerFound() && controller_index < num_gamepads_)
if ((device == INPUT_USE_GAMECONTROLLER) || (device == INPUT_USE_ANY))
{
success_controller = checkAxisInput(input, controller_index);
if (!success_controller)
{
if (repeat)
{
if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) != 0)
{
success_controller = true;
}
else
{
success_controller = false;
}
}
else
{
if (!controller_bindings_[controller_index][input_index].active)
{
if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) != 0)
{
controller_bindings_[controller_index][input_index].active = true;
success_controller = true;
}
else
{
success_controller = false;
}
}
else
{
if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) == 0)
{
controller_bindings_[controller_index][input_index].active = false;
success_controller = false;
}
else
{
success_controller = false;
}
}
}
} }
} }
@@ -314,14 +149,9 @@ bool Input::checkModInput(InputType input_mod, InputType input, bool repeat, int
} }
// Comprueba si hay almenos un input activo // Comprueba si hay almenos un input activo
bool Input::checkAnyInput(int device, int controller_index) bool Input::checkAnyInput(InputDeviceToUse device, int controller_index)
{ {
if (device == INPUT_USE_ANY) if (device == InputDeviceToUse::KEYBOARD || device == InputDeviceToUse::ANY)
{
controller_index = 0;
}
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY)
{ {
const Uint8 *mKeystates = SDL_GetKeyboardState(nullptr); const Uint8 *mKeystates = SDL_GetKeyboardState(nullptr);
@@ -337,7 +167,7 @@ bool Input::checkAnyInput(int device, int controller_index)
if (gameControllerFound()) if (gameControllerFound())
{ {
if (device == INPUT_USE_GAMECONTROLLER || device == INPUT_USE_ANY) if (device == InputDeviceToUse::CONTROLLER || device == InputDeviceToUse::ANY)
{ {
for (int i = 0; i < (int)controller_bindings_.size(); ++i) for (int i = 0; i < (int)controller_bindings_.size(); ++i)
{ {
@@ -357,7 +187,7 @@ bool Input::checkAnyInput(int device, int controller_index)
int Input::checkAnyButtonPressed(bool repeat) int Input::checkAnyButtonPressed(bool repeat)
{ {
// Si está pulsado el botón de servicio, ningún botón se puede considerar pulsado // Si está pulsado el botón de servicio, ningún botón se puede considerar pulsado
if (checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, INPUT_USE_ANY)) if (checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::ANY))
{ {
return 0; return 0;
} }
@@ -366,7 +196,7 @@ int Input::checkAnyButtonPressed(bool repeat)
for (auto bi : button_inputs_) for (auto bi : button_inputs_)
{ {
// Comprueba el teclado // Comprueba el teclado
if (checkInput(bi, repeat, INPUT_USE_KEYBOARD)) if (checkInput(bi, repeat, InputDeviceToUse::KEYBOARD))
{ {
return 1; return 1;
} }
@@ -374,7 +204,7 @@ int Input::checkAnyButtonPressed(bool repeat)
// Comprueba los mandos // Comprueba los mandos
for (int i = 0; i < num_gamepads_; ++i) for (int i = 0; i < num_gamepads_; ++i)
{ {
if (checkInput(bi, repeat, INPUT_USE_GAMECONTROLLER, i)) if (checkInput(bi, repeat, InputDeviceToUse::CONTROLLER, i))
{ {
return i + 1; return i + 1;
} }
@@ -395,11 +225,9 @@ bool Input::discoverGameControllers()
} }
if (SDL_GameControllerAddMappingsFromFile(game_controller_db_path_.c_str()) < 0) if (SDL_GameControllerAddMappingsFromFile(game_controller_db_path_.c_str()) < 0)
{
{ {
std::cout << "Error, could not load " << game_controller_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;
} }
}
num_joysticks_ = SDL_NumJoysticks(); num_joysticks_ = SDL_NumJoysticks();
num_gamepads_ = 0; num_gamepads_ = 0;
@@ -408,7 +236,7 @@ bool Input::discoverGameControllers()
joysticks_.clear(); joysticks_.clear();
for (int i = 0; i < num_joysticks_; ++i) for (int i = 0; i < num_joysticks_; ++i)
{ {
SDL_Joystick *joy = SDL_JoystickOpen(i); auto joy = SDL_JoystickOpen(i);
joysticks_.push_back(joy); joysticks_.push_back(joy);
if (SDL_IsGameController(i)) if (SDL_IsGameController(i))
{ {
@@ -417,7 +245,6 @@ bool Input::discoverGameControllers()
} }
std::cout << "\n** LOOKING FOR GAME CONTROLLERS" << std::endl; std::cout << "\n** LOOKING FOR GAME CONTROLLERS" << std::endl;
// std::cout << " " << num_joysticks_ << " joysticks found" << std::endl;
std::cout << "Gamepads found: " << num_gamepads_ << std::endl; std::cout << "Gamepads found: " << num_gamepads_ << std::endl;
if (num_gamepads_ > 0) if (num_gamepads_ > 0)
@@ -432,44 +259,30 @@ bool Input::discoverGameControllers()
{ {
connected_controllers_.push_back(pad); connected_controllers_.push_back(pad);
const std::string name = SDL_GameControllerNameForIndex(i); const std::string name = SDL_GameControllerNameForIndex(i);
{
std::cout << "#" << i << ": " << name << std::endl; std::cout << "#" << i << ": " << name << std::endl;
}
controller_names_.push_back(name); controller_names_.push_back(name);
} }
else else
{
{ {
std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl; std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl;
} }
} }
}
SDL_GameControllerEventState(SDL_ENABLE); SDL_GameControllerEventState(SDL_ENABLE);
} }
std::cout << "\n** FINISHED LOOKING FOR GAME CONTROLLERS" << std::endl; std::cout << "\n** FINISHED LOOKING FOR GAME CONTROLLERS" << std::endl;
return found; return found;
} }
// Comprueba si hay algun mando conectado // Comprueba si hay algun mando conectado
bool Input::gameControllerFound() bool Input::gameControllerFound() { return num_gamepads_ > 0 ? true : false; }
{
return num_gamepads_ > 0 ? true : false;
}
// Obten el nombre de un mando de juego // Obten el nombre de un mando de juego
std::string Input::getControllerName(int controller_index) const std::string Input::getControllerName(int controller_index) const { return num_gamepads_ > 0 ? controller_names_.at(controller_index) : std::string(); }
{
return num_gamepads_ > 0 ? controller_names_[controller_index] : "";
}
// Obten el número de mandos conectados // Obten el número de mandos conectados
int Input::getNumControllers() const int Input::getNumControllers() const { return num_gamepads_; }
{
return num_gamepads_;
}
// Obtiene el indice del controlador a partir de un event.id // Obtiene el indice del controlador a partir de un event.id
int Input::getJoyIndex(int id) const int Input::getJoyIndex(int id) const
@@ -485,14 +298,14 @@ int Input::getJoyIndex(int id) const
} }
// Muestra por consola los controles asignados // Muestra por consola los controles asignados
void Input::printBindings(int device, int controller_index) const void Input::printBindings(InputDeviceToUse device, int controller_index) const
{ {
if (device == INPUT_USE_ANY || device == INPUT_USE_KEYBOARD) if (device == InputDeviceToUse::ANY || device == InputDeviceToUse::KEYBOARD)
{ {
return; return;
} }
if (device == INPUT_USE_GAMECONTROLLER) if (device == InputDeviceToUse::CONTROLLER)
{ {
if (controller_index >= num_gamepads_) if (controller_index >= num_gamepads_)
{ {
@@ -500,13 +313,12 @@ void Input::printBindings(int device, int controller_index) const
} }
// Muestra el nombre del mando // Muestra el nombre del mando
std::cout << "\n" std::cout << "\n" + controller_names_.at(controller_index) << std::endl;
<< controller_names_[controller_index] << std::endl;
// Muestra los botones asignados // Muestra los botones asignados
for (auto bi : button_inputs_) for (auto bi : button_inputs_)
{ {
std::cout << to_string(bi) << " : " << controller_bindings_[controller_index][static_cast<int>(bi)].button << std::endl; std::cout << to_string(bi) << " : " << controller_bindings_.at(controller_index).at(static_cast<int>(bi)).button << std::endl;
} }
} }
} }
@@ -520,116 +332,58 @@ SDL_GameControllerButton Input::getControllerBinding(int controller_index, Input
// Obtiene el indice a partir del nombre del mando // Obtiene el indice a partir del nombre del mando
int Input::getIndexByName(const std::string &name) const int Input::getIndexByName(const std::string &name) const
{ {
for (int i = 0; i < num_gamepads_; ++i) auto it = std::find(controller_names_.begin(), controller_names_.end(), name);
{ return it != controller_names_.end() ? std::distance(controller_names_.begin(), it) : -1;
if (controller_names_[i] == name)
{
return i;
}
}
return -1;
} }
// Convierte un InputType a std::string // Convierte un InputType a std::string
std::string Input::to_string(InputType input) const std::string Input::to_string(InputType input) const
{ {
if (input == InputType::FIRE_LEFT) switch (input)
{ {
case InputType::FIRE_LEFT:
return "input_fire_left"; return "input_fire_left";
} case InputType::FIRE_CENTER:
if (input == InputType::FIRE_CENTER)
{
return "input_fire_center"; return "input_fire_center";
} case InputType::FIRE_RIGHT:
if (input == InputType::FIRE_RIGHT)
{
return "input_fire_right"; return "input_fire_right";
} case InputType::START:
if (input == InputType::START)
{
return "input_start"; return "input_start";
} case InputType::SERVICE:
if (input == InputType::SERVICE)
{
return "input_service"; return "input_service";
} default:
return ""; return "";
} }
}
// Convierte un std::string a InputType // Convierte un std::string a InputType
InputType Input::to_inputs_e(const std::string &name) const InputType Input::to_inputs_e(const std::string &name) const
{ {
if (name == "input_fire_left") static const std::unordered_map<std::string, InputType> inputMap = {
{ {"input_fire_left", InputType::FIRE_LEFT},
return InputType::FIRE_LEFT; {"input_fire_center", InputType::FIRE_CENTER},
} {"input_fire_right", InputType::FIRE_RIGHT},
{"input_start", InputType::START},
{"input_service", InputType::SERVICE}};
if (name == "input_fire_center") auto it = inputMap.find(name);
{ return it != inputMap.end() ? it->second : InputType::NONE;
return InputType::FIRE_CENTER;
}
if (name == "input_fire_right")
{
return InputType::FIRE_RIGHT;
}
if (name == "input_start")
{
return InputType::START;
}
if (name == "input_service")
{
return InputType::SERVICE;
}
return InputType::NONE;
} }
// Comprueba el eje del mando // Comprueba el eje del mando
bool Input::checkAxisInput(InputType input, int controller_index) const bool Input::checkAxisInput(InputType input, int controller_index) const
{ {
bool success = false;
switch (input) switch (input)
{ {
case InputType::LEFT: case InputType::LEFT:
if (SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) < -30000) return SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) < -30000;
{
success = true;
}
break;
case InputType::RIGHT: case InputType::RIGHT:
if (SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) > 30000) return SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) > 30000;
{
success = true;
}
break;
case InputType::UP: case InputType::UP:
if (SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) < -30000) return SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) < -30000;
{
success = true;
}
break;
case InputType::DOWN: case InputType::DOWN:
if (SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) > 30000) return SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) > 30000;
{
success = true;
}
break;
default: default:
break; return false;
} }
return success;
} }

View File

@@ -11,9 +11,9 @@
connectedControllers es un vector donde estan todos los mandos encontrados [0 .. n] connectedControllers es un vector donde estan todos los mandos encontrados [0 .. n]
checkInput requiere de un indice para comprobar las pulsaciónes de un controlador en concreto [0 .. n] checkInput requiere de un indice para comprobar las pulsaciónes de un controlador en concreto [0 .. n]
device contiene el tipo de dispositivo a comprobar: device contiene el tipo de dispositivo a comprobar:
INPUT_USE_KEYBOARD solo mirará el teclado InputDeviceToUse::KEYBOARD solo mirará el teclado
INPUT_USE_GAMECONTROLLER solo mirará el controlador especificado (Si no se especifica, el primero) InputDeviceToUse::CONTROLLER solo mirará el controlador especificado (Si no se especifica, el primero)
INPUT_USE_ANY mirará tanto el teclado como el PRIMER controlador InputDeviceToUse::ANY mirará tanto el teclado como el PRIMER controlador
*/ */
enum class InputType : int enum class InputType : int
@@ -52,9 +52,12 @@ enum class InputType : int
constexpr bool INPUT_ALLOW_REPEAT = true; constexpr bool INPUT_ALLOW_REPEAT = true;
constexpr bool INPUT_DO_NOT_ALLOW_REPEAT = false; constexpr bool INPUT_DO_NOT_ALLOW_REPEAT = false;
constexpr int INPUT_USE_KEYBOARD = 0; enum class InputDeviceToUse : int
constexpr int INPUT_USE_GAMECONTROLLER = 1; {
constexpr int INPUT_USE_ANY = 2; KEYBOARD = 0,
CONTROLLER = 1,
ANY = 2,
};
class Input class Input
{ {
@@ -66,12 +69,20 @@ private:
{ {
Uint8 scancode; // Scancode asociado Uint8 scancode; // Scancode asociado
bool active; // Indica si está activo bool active; // Indica si está activo
// Constructor
explicit KeyBindings(Uint8 sc = 0, bool act = false)
: scancode(sc), active(act) {}
}; };
struct ControllerBindings struct ControllerBindings
{ {
SDL_GameControllerButton button; // GameControllerButton asociado SDL_GameControllerButton button; // GameControllerButton asociado
bool active; // Indica si está activo bool active; // Indica si está activo
// Constructor
explicit ControllerBindings(SDL_GameControllerButton btn = SDL_CONTROLLER_BUTTON_INVALID, bool act = false)
: button(btn), active(act) {}
}; };
// Variables // Variables
@@ -80,12 +91,10 @@ private:
std::vector<KeyBindings> key_bindings_; // Vector con las teclas asociadas a los inputs predefinidos 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::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<std::string> controller_names_; // Vector con los nombres de los mandos
std::vector<InputType> game_inputs_; // Inputs usados para jugar, normalmente direcciones y botones
std::vector<InputType> button_inputs_; // Inputs asignados al jugador y a botones, excluyendo direcciones std::vector<InputType> button_inputs_; // Inputs asignados al jugador y a botones, excluyendo direcciones
int num_joysticks_; // Número de joysticks conectados int num_joysticks_ = 0; // Número de joysticks conectados
int num_gamepads_; // Número de mandos conectados int num_gamepads_ = 0; // Número de mandos conectados
std::string game_controller_db_path_; // Ruta al archivo gamecontrollerdb.txt std::string game_controller_db_path_; // Ruta al archivo gamecontrollerdb.txt
bool enabled_; // Indica si está habilitado
// Comprueba el eje del mando // Comprueba el eje del mando
bool checkAxisInput(InputType input, int controller_index = 0) const; bool checkAxisInput(InputType input, int controller_index = 0) const;
@@ -114,13 +123,10 @@ public:
void bindGameControllerButton(int controller_index, InputType inputTarget, InputType inputSource); void bindGameControllerButton(int controller_index, InputType inputTarget, InputType inputSource);
// Comprueba si un input esta activo // Comprueba si un input esta activo
bool checkInput(InputType input, bool repeat = true, int device = INPUT_USE_ANY, int controller_index = 0); bool checkInput(InputType input, bool repeat = true, InputDeviceToUse device = InputDeviceToUse::ANY, int controller_index = 0);
// Comprueba si un input con modificador esta activo
bool checkModInput(InputType input_mod, InputType input, bool repeat = true, int device = INPUT_USE_ANY, int controller_index = 0);
// Comprueba si hay almenos un input activo // Comprueba si hay almenos un input activo
bool checkAnyInput(int device = INPUT_USE_ANY, int controller_index = 0); bool checkAnyInput(InputDeviceToUse device = InputDeviceToUse::ANY, int controller_index = 0);
// Comprueba si hay algún botón pulsado // Comprueba si hay algún botón pulsado
int checkAnyButtonPressed(bool repeat = INPUT_DO_NOT_ALLOW_REPEAT); int checkAnyButtonPressed(bool repeat = INPUT_DO_NOT_ALLOW_REPEAT);
@@ -141,7 +147,7 @@ public:
int getJoyIndex(int id) const; int getJoyIndex(int id) const;
// Muestra por consola los controles asignados // Muestra por consola los controles asignados
void printBindings(int device = INPUT_USE_KEYBOARD, int controller_index = 0) const; void printBindings(InputDeviceToUse device = InputDeviceToUse::KEYBOARD, int controller_index = 0) const;
// Obtiene el SDL_GameControllerButton asignado a un input // Obtiene el SDL_GameControllerButton asignado a un input
SDL_GameControllerButton getControllerBinding(int controller_index, InputType input) const; SDL_GameControllerButton getControllerBinding(int controller_index, InputType input) const;

View File

@@ -313,9 +313,6 @@ void Instructions::checkInput()
return; return;
} }
// Comprueba el input para el resto de objetos
Screen::get()->checkInput();
// Comprueba los inputs que se pueden introducir en cualquier sección del juego // Comprueba los inputs que se pueden introducir en cualquier sección del juego
globalInputs::check(); globalInputs::check();
} }

View File

@@ -191,9 +191,6 @@ void Intro::checkInput()
return; return;
} }
// Comprueba el input para el resto de objetos
Screen::get()->checkInput();
// Comprueba los inputs que se pueden introducir en cualquier sección del juego // Comprueba los inputs que se pueden introducir en cualquier sección del juego
globalInputs::check(); globalInputs::check();
} }

View File

@@ -12,6 +12,7 @@
#include "section.h" // Para Name, name, Options, options #include "section.h" // Para Name, name, Options, options
#include "sprite.h" // Para Sprite #include "sprite.h" // Para Sprite
#include "texture.h" // Para Texture #include "texture.h" // Para Texture
#include "utils.h" // Para Color, Zone
// Constructor // Constructor
Logo::Logo() Logo::Logo()
@@ -105,9 +106,6 @@ void Logo::checkInput()
return; return;
} }
// Comprueba el input para el resto de objetos
Screen::get()->checkInput();
// Comprueba los inputs que se pueden introducir en cualquier sección del juego // Comprueba los inputs que se pueden introducir en cualquier sección del juego
globalInputs::check(); globalInputs::check();
} }

View File

@@ -1,12 +1,12 @@
#pragma once #pragma once
#include <SDL2/SDL_rect.h> // para SDL_Point #include <SDL2/SDL_rect.h> // Para SDL_Point
#include <SDL2/SDL_stdinc.h> // para Uint32 #include <SDL2/SDL_stdinc.h> // Para Uint32
#include <memory> // para unique_ptr, shared_ptr #include <memory> // Para shared_ptr, unique_ptr
#include <vector> // para vector #include <vector> // Para vector
#include "sprite.h" // para Sprite class Sprite;
#include "utils.h" // para Color class Texture; // lines 9-9
class Texture; struct Color;
/* /*
Esta clase gestiona un estado del programa. Se encarga de dibujar por pantalla el Esta clase gestiona un estado del programa. Se encarga de dibujar por pantalla el

View File

@@ -2,6 +2,8 @@
#include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND #include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND
#include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888 #include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
#include <string> // Para string #include <string> // Para string
#include <algorithm>
#include <vector>
#include "jail_audio.h" // Para JA_DeleteSound, JA_LoadSound, JA_Pla... #include "jail_audio.h" // Para JA_DeleteSound, JA_LoadSound, JA_Pla...
#include "param.h" // Para Param, param, ParamNotification, Par... #include "param.h" // Para Param, param, ParamNotification, Par...
#include "screen.h" // Para Screen #include "screen.h" // Para Screen
@@ -51,8 +53,10 @@ Notifier::~Notifier()
void Notifier::render() void Notifier::render()
{ {
for (int i = (int)notifications_.size() - 1; i >= 0; --i) for (int i = (int)notifications_.size() - 1; i >= 0; --i)
{
notifications_[i].sprite->render(); notifications_[i].sprite->render();
} }
}
// Actualiza el estado de las notificaiones // Actualiza el estado de las notificaiones
void Notifier::update() void Notifier::update()
@@ -154,39 +158,41 @@ void Notifier::clearFinishedNotifications()
} }
} }
void Notifier::showText(std::string text1, std::string text2, int icon, const std::string &code) void Notifier::showText(std::vector<std::string> texts, int icon, const std::string &code)
{ {
// Cuenta el número de textos a mostrar
const int num_texts = !text1.empty() + !text2.empty();
// Si no hay texto, acaba // Si no hay texto, acaba
if (num_texts == 0) if (texts.empty())
{ {
return; return;
} }
// Si solo hay un texto, lo coloca en la primera variable
if (num_texts == 1)
{
text1 += text2;
text2.clear();
}
// Si las notificaciones no se apilan, elimina las anteriores // Si las notificaciones no se apilan, elimina las anteriores
if (!stack_) if (!stack_)
{ {
clearNotifications(); clearNotifications();
} }
// Elimina las cadenas vacías
texts.erase(std::remove_if(texts.begin(), texts.end(), [](const std::string &s)
{ return s.empty(); }),
texts.end());
// Encuentra la cadena más larga
std::string longest;
for (const auto &text : texts)
{
if (text.length() > longest.length())
longest = text;
}
// Inicializa variables // Inicializa variables
constexpr auto icon_size = 16; constexpr int icon_size = 16;
constexpr auto padding_out = 1; constexpr int padding_out = 1;
const auto padding_in_h = text_->getCharacterSize(); const auto padding_in_h = text_->getCharacterSize();
const auto padding_in_v = text_->getCharacterSize() / 2; const auto padding_in_v = text_->getCharacterSize() / 2;
const auto icon_space = icon >= 0 ? icon_size + padding_in_h : 0; const int icon_space = icon >= 0 ? icon_size + padding_in_h : 0;
const std::string txt = text1.length() > text2.length() ? text1 : text2; const int width = text_->lenght(longest) + (padding_in_h * 2) + icon_space;
const auto width = text_->lenght(txt) + (padding_in_h * 2) + icon_space; const int height = (text_->getCharacterSize() * texts.size()) + (padding_in_v * 2);
const auto height = (text_->getCharacterSize() * num_texts) + (padding_in_v * 2);
const auto shape = NotificationShape::SQUARED; const auto shape = NotificationShape::SQUARED;
// Posición horizontal // Posición horizontal
@@ -212,11 +218,11 @@ void Notifier::showText(std::string text1, std::string text2, int icon, const st
auto offset = 0; auto offset = 0;
if (param.notification.pos_v == NotifyPosition::TOP) if (param.notification.pos_v == NotifyPosition::TOP)
{ {
offset = (int)notifications_.size() > 0 ? notifications_.back().y + travel_dist : desp_v; offset = !notifications_.empty() ? notifications_.back().y + travel_dist : desp_v;
} }
else else
{ {
offset = (int)notifications_.size() > 0 ? notifications_.back().y - travel_dist : desp_v; offset = !notifications_.empty() ? notifications_.back().y - travel_dist : desp_v;
} }
// Crea la notificacion // Crea la notificacion
@@ -226,8 +232,7 @@ void Notifier::showText(std::string text1, std::string text2, int icon, const st
n.code = code; n.code = code;
n.y = offset; n.y = offset;
n.travel_dist = travel_dist; n.travel_dist = travel_dist;
n.text1 = text1; n.texts = texts;
n.text2 = text2;
n.shape = shape; n.shape = shape;
auto y_pos = offset + (param.notification.pos_v == NotifyPosition::TOP ? -travel_dist : travel_dist); auto y_pos = offset + (param.notification.pos_v == NotifyPosition::TOP ? -travel_dist : travel_dist);
n.rect = {desp_h, y_pos, width, height}; n.rect = {desp_h, y_pos, width, height};
@@ -264,7 +269,7 @@ void Notifier::showText(std::string text1, std::string text2, int icon, const st
} }
// Dibuja el icono de la notificación // Dibuja el icono de la notificación
if (has_icons_ && icon >= 0 && num_texts == 2) if (has_icons_ && icon >= 0 && texts.size() >= 2)
{ {
auto sp = std::make_unique<Sprite>(icon_texture_, (SDL_Rect){0, 0, icon_size, icon_size}); auto sp = std::make_unique<Sprite>(icon_texture_, (SDL_Rect){0, 0, icon_size, icon_size});
sp->setPosition({padding_in_h, padding_in_v, icon_size, icon_size}); sp->setPosition({padding_in_h, padding_in_v, icon_size, icon_size});
@@ -273,15 +278,12 @@ void Notifier::showText(std::string text1, std::string text2, int icon, const st
} }
// Escribe el texto de la notificación // Escribe el texto de la notificación
Color color{255, 255, 255}; const Color color{255, 255, 255};
if (num_texts == 2) int iterator = 0;
{ // Dos lineas de texto for (const auto &text : texts)
text_->writeColored(padding_in_h + icon_space, padding_in_v, text1, color); {
text_->writeColored(padding_in_h + icon_space, padding_in_v + text_->getCharacterSize() + 1, text2, color); text_->writeColored(padding_in_h + icon_space, padding_in_v + iterator * (text_->getCharacterSize() + 1), text, color);
} ++iterator;
else
{ // Una linea de texto
text_->writeColored(padding_in_h + icon_space, padding_in_v, text1, color);
} }
// Deja de dibujar en la textura // Deja de dibujar en la textura
@@ -294,26 +296,18 @@ void Notifier::showText(std::string text1, std::string text2, int icon, const st
n.texture->setAlpha(0); n.texture->setAlpha(0);
// Añade la notificación a la lista // Añade la notificación a la lista
notifications_.push_back(n); notifications_.emplace_back(n);
} }
// Indica si hay notificaciones activas // Indica si hay notificaciones activas
bool Notifier::isActive() bool Notifier::isActive() { return !notifications_.empty(); }
{
if ((int)notifications_.size() > 0)
{
return true;
}
return false;
}
// Finaliza y elimnina todas las notificaciones activas // Finaliza y elimnina todas las notificaciones activas
void Notifier::clearNotifications() void Notifier::clearNotifications()
{ {
for (int i = 0; i < (int)notifications_.size(); ++i) for (auto &notification : notifications_)
{ {
notifications_[i].status = NotificationStatus::FINISHED; notification.status = NotificationStatus::FINISHED;
} }
clearFinishedNotifications(); clearFinishedNotifications();
@@ -323,9 +317,9 @@ void Notifier::clearNotifications()
std::vector<std::string> Notifier::getCodes() std::vector<std::string> Notifier::getCodes()
{ {
std::vector<std::string> codes; std::vector<std::string> codes;
for (int i = 0; i < (int)notifications_.size(); ++i) for (const auto &notification : notifications_)
{ {
codes.push_back(notifications_[i].code); codes.emplace_back(notification.code);
} }
return codes; return codes;
} }

View File

@@ -35,8 +35,7 @@ private:
{ {
std::shared_ptr<Texture> texture; std::shared_ptr<Texture> texture;
std::shared_ptr<Sprite> sprite; std::shared_ptr<Sprite> sprite;
std::string text1; std::vector<std::string> texts;
std::string text2;
int counter; int counter;
NotificationStatus status; NotificationStatus status;
NotificationShape shape; NotificationShape shape;
@@ -47,7 +46,7 @@ private:
// Constructor // Constructor
explicit Notification() explicit Notification()
: texture(nullptr), sprite(nullptr), text1(""), text2(""), counter(0), status(NotificationStatus::RISING), : texture(nullptr), sprite(nullptr), texts(), counter(0), status(NotificationStatus::RISING),
shape(NotificationShape::SQUARED), rect{0, 0, 0, 0}, y(0), travel_dist(0), code("") {} shape(NotificationShape::SQUARED), rect{0, 0, 0, 0}, y(0), travel_dist(0), code("") {}
}; };
@@ -95,15 +94,8 @@ public:
// Actualiza el estado de las notificaiones // Actualiza el estado de las notificaiones
void update(); void update();
/** // Muestra una notificación de texto por pantalla
* @brief Muestra una notificación de texto por pantalla. void showText(std::vector<std::string> texts, int icon = -1, const std::string &code = std::string());
*
* @param text1 Primer texto opcional para mostrar (valor predeterminado: cadena vacía).
* @param text2 Segundo texto opcional para mostrar (valor predeterminado: cadena vacía).
* @param icon Icono opcional para mostrar (valor predeterminado: -1).
* @param code Permite asignar un código a la notificación (valor predeterminado: cadena vacía).
*/
void showText(std::string text1 = std::string(), std::string text2 = std::string(), int icon = -1, const std::string &code = std::string());
// Indica si hay notificaciones activas // Indica si hay notificaciones activas
bool isActive(); bool isActive();

View File

@@ -1,13 +1,14 @@
#include "options.h" #include "options.h"
#include <SDL2/SDL_gamecontroller.h> // para SDL_GameControllerButton, SDL_C... #include <SDL2/SDL_gamecontroller.h> // Para SDL_GameControllerButton
#include <algorithm> // para max, min #include <algorithm> // Para clamp
#include <fstream> // para basic_ostream, operator<<, basi... #include <fstream> // Para basic_ostream, operator<<, basi...
#include <iostream> // para cout #include <iostream> // Para cout
#include <vector> // para vector #include <utility> // Para swap
#include "input.h" // para inputs_e, INPUT_USE_ANY, INPUT_... #include <vector> // Para vector
#include "lang.h" // para lang_e #include "input.h" // Para InputDeviceToUse
#include "screen.h" // para ScreenVideoMode, ScreenFilter #include "lang.h" // Para Code
#include "utils.h" // para OptionsController, Options, op_... #include "screen.h" // Para ScreenVideoMode, ScreenFilter
#include "utils.h" // Para boolToString, stringToBool, get...
// Variables // Variables
Options options; Options options;
@@ -45,37 +46,11 @@ void initOptions()
options.game.autofire = true; options.game.autofire = true;
// Opciones de control // Opciones de control
options.controller.clear(); options.controllers.clear();
OptionsController c; options.controllers.resize(2);
options.controllers.at(0).player_id = 1;
constexpr int num_players = 2; options.controllers.at(1).player_id = 2;
for (int index = 0; index < num_players; ++index) setKeyboardToPlayer(1);
{
c.index = index;
c.player_id = index + 1;
c.device_type = INPUT_USE_GAMECONTROLLER;
c.name = "NO NAME";
c.plugged = false;
// Inputs que se guardan en las opciones y, por tanto, a disco
c.inputs.clear();
c.inputs.push_back(InputType::FIRE_LEFT);
c.inputs.push_back(InputType::FIRE_CENTER);
c.inputs.push_back(InputType::FIRE_RIGHT);
c.inputs.push_back(InputType::START);
c.inputs.push_back(InputType::SERVICE);
// Botones asociados a los inputs anteriores
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_B);
c.buttons.push_back(SDL_CONTROLLER_BUTTON_START);
c.buttons.push_back(SDL_CONTROLLER_BUTTON_BACK);
options.controller.push_back(c);
}
options.controller[0].device_type = INPUT_USE_ANY; // El primer jugador puede usar tanto el teclado como el primer mando
} }
// Carga el fichero de configuración // Carga el fichero de configuración
@@ -129,12 +104,11 @@ bool loadOptionsFile(std::string file_path)
options.video.mode = ScreenVideoMode::WINDOW; options.video.mode = ScreenVideoMode::WINDOW;
} }
if (options.video.window.size < 1 || options.video.window.size > 4) options.video.window.size = std::clamp(options.video.window.size, 1, 4);
{
options.video.window.size = 3;
}
if (options.game.language != lang::Code::en_UK && options.game.language != lang::Code::ba_BA && options.game.language != lang::Code::es_ES) if (options.game.language != lang::Code::en_UK &&
options.game.language != lang::Code::ba_BA &&
options.game.language != lang::Code::es_ES)
{ {
options.game.language = lang::Code::en_UK; options.game.language = lang::Code::en_UK;
} }
@@ -156,73 +130,58 @@ bool saveOptionsFile(std::string file_path)
std::cout << "Writing file: " << getFileName(file_path) << std::endl; std::cout << "Writing file: " << getFileName(file_path) << std::endl;
// Opciones de video // Opciones de video
const auto value_video_mode_winow = std::to_string(static_cast<int>(ScreenVideoMode::WINDOW));
const auto value_video_mode_fullscreen = std::to_string(static_cast<int>(ScreenVideoMode::FULLSCREEN));
const auto value_filter_nearest = std::to_string(static_cast<int>(ScreenFilter::NEAREST));
const auto value_filter_lineal = std::to_string(static_cast<int>(ScreenFilter::LINEAL));
file << "## VIDEO\n"; file << "## VIDEO\n";
file << "## video.mode [" << value_video_mode_winow << ": window, " << value_video_mode_fullscreen << ": fullscreen]\n"; file << "## video.mode [" << static_cast<int>(ScreenVideoMode::WINDOW) << ": window, " << static_cast<int>(ScreenVideoMode::FULLSCREEN) << ": fullscreen]\n";
file << "## video.filter [" << value_filter_nearest << ": nearest, " << value_filter_lineal << ": lineal]\n"; file << "## video.filter [" << static_cast<int>(ScreenFilter::NEAREST) << ": nearest, " << static_cast<int>(ScreenFilter::LINEAL) << ": lineal]\n";
file << "\n"; file << "\n";
const auto valueVideoMode = std::to_string(static_cast<int>(options.video.mode)); file << "video.mode=" << static_cast<int>(options.video.mode) << "\n";
file << "video.mode=" << valueVideoMode << "\n"; file << "video.window.size=" << options.video.window.size << "\n";
file << "video.filter=" << static_cast<int>(options.video.filter) << "\n";
file << "video.window.size=" + std::to_string(options.video.window.size) + "\n"; file << "video.v_sync=" << boolToString(options.video.v_sync) << "\n";
file << "video.integer_scale=" << boolToString(options.video.integer_scale) << "\n";
const auto valueFilter = std::to_string(static_cast<int>(options.video.filter)); file << "video.shaders=" << boolToString(options.video.shaders) << "\n";
file << "video.filter=" << valueFilter << "\n";
file << "video.v_sync=" + boolToString(options.video.v_sync) + "\n";
file << "video.integer_scale=" + boolToString(options.video.integer_scale) + "\n";
file << "video.shaders=" + boolToString(options.video.shaders) + "\n";
// Opciones de audio // Opciones de audio
file << "\n\n## AUDIO\n"; file << "\n\n## AUDIO\n";
file << "## volume [0 .. 100]\n"; file << "## volume [0 .. 100]\n";
file << "\n"; file << "\n";
file << "audio.enabled=" + boolToString(options.audio.enabled) + "\n"; file << "audio.enabled=" << boolToString(options.audio.enabled) << "\n";
file << "audio.volume=" + std::to_string(options.audio.volume) + "\n"; file << "audio.volume=" << options.audio.volume << "\n";
file << "audio.music.enabled=" + boolToString(options.audio.music.enabled) + "\n"; file << "audio.music.enabled=" << boolToString(options.audio.music.enabled) << "\n";
file << "audio.music.volume=" + std::to_string(options.audio.music.volume) + "\n"; file << "audio.music.volume=" << options.audio.music.volume << "\n";
file << "audio.sound.enabled=" + boolToString(options.audio.sound.enabled) + "\n"; file << "audio.sound.enabled=" << boolToString(options.audio.sound.enabled) << "\n";
file << "audio.sound.volume=" + std::to_string(options.audio.sound.volume) + "\n"; file << "audio.sound.volume=" << options.audio.sound.volume << "\n";
// Opciones del juego // Opciones del juego
const auto value_difficulty_easy = std::to_string(static_cast<int>(GameDifficulty::EASY));
const auto value_difficulty_normal = std::to_string(static_cast<int>(GameDifficulty::NORMAL));
const auto value_difficulty_hard = std::to_string(static_cast<int>(GameDifficulty::HARD));
file << "\n\n## GAME\n"; file << "\n\n## GAME\n";
file << "## game.language [0: spanish, 1: valencian, 2: english]\n"; file << "## game.language [0: spanish, 1: valencian, 2: english]\n";
file << "## game.difficulty [" << value_difficulty_easy << ": easy, " << value_difficulty_normal << ": normal, " << value_difficulty_hard << ": hard]\n"; file << "## game.difficulty [" << static_cast<int>(GameDifficulty::EASY) << ": easy, " << static_cast<int>(GameDifficulty::NORMAL) << ": normal, " << static_cast<int>(GameDifficulty::HARD) << ": hard]\n";
file << "\n"; file << "\n";
file << "game.language=" + std::to_string(static_cast<int>(options.game.language)) + "\n"; file << "game.language=" << static_cast<int>(options.game.language) << "\n";
file << "game.difficulty=" + std::to_string(static_cast<int>(options.game.difficulty)) + "\n"; file << "game.difficulty=" << static_cast<int>(options.game.difficulty) << "\n";
file << "game.autofire=" + boolToString(options.game.autofire) + "\n"; file << "game.autofire=" << boolToString(options.game.autofire) << "\n";
// Opciones de mandos // Opciones de mandos
file << "\n\n## CONTROLLERS\n"; file << "\n\n## CONTROLLERS\n";
file << "\n";
const int num_players = 2; int controller_index = 0;
for (int index = 0; index < num_players; ++index) for (const auto &controller : options.controllers)
{
const std::string joyIndex = std::to_string(index + 1);
file << "controller" + joyIndex + ".name=" + options.controller[index].name + "\n";
file << "controller" + joyIndex + ".player=" + std::to_string(options.controller[index].player_id) + "\n";
file << "controller" + joyIndex + ".button.fire_left=" + std::to_string((int)options.controller[index].buttons[0]) + "\n";
file << "controller" + joyIndex + ".button.fire_center=" + std::to_string((int)options.controller[index].buttons[1]) + "\n";
file << "controller" + joyIndex + ".button.fire_right=" + std::to_string((int)options.controller[index].buttons[2]) + "\n";
file << "controller" + joyIndex + ".button.start=" + std::to_string((int)options.controller[index].buttons[3]) + "\n";
file << "controller" + joyIndex + ".button.service=" + std::to_string((int)options.controller[index].buttons[4]) + "\n";
if (index < num_players - 1)
{ {
file << "\n"; file << "\n";
} file << "controller." << controller_index << ".name=" << controller.name << "\n";
file << "controller." << controller_index << ".player=" << controller.player_id << "\n";
file << "controller." << controller_index << ".type=" << static_cast<int>(controller.type) << "\n";
file << "controller." << controller_index << ".button.fire_left=" << controller.buttons.at(0) << "\n";
file << "controller." << controller_index << ".button.fire_center=" << controller.buttons.at(1) << "\n";
file << "controller." << controller_index << ".button.fire_right=" << controller.buttons.at(2) << "\n";
file << "controller." << controller_index << ".button.start=" << controller.buttons.at(3) << "\n";
file << "controller." << controller_index << ".button.service=" << controller.buttons.at(4) << "\n";
// Incrementa el índice
++controller_index;
} }
// Cierra el fichero // Cierra el fichero
@@ -242,7 +201,6 @@ bool setOptions(const std::string &var, const std::string &value)
{ {
options.video.mode = static_cast<ScreenVideoMode>(std::stoi(value)); options.video.mode = static_cast<ScreenVideoMode>(std::stoi(value));
} }
else if (var == "video.window.size") else if (var == "video.window.size")
{ {
options.video.window.size = std::stoi(value); options.video.window.size = std::stoi(value);
@@ -251,22 +209,18 @@ bool setOptions(const std::string &var, const std::string &value)
options.video.window.size = 3; options.video.window.size = 3;
} }
} }
else if (var == "video.filter") else if (var == "video.filter")
{ {
options.video.filter = static_cast<ScreenFilter>(std::stoi(value)); options.video.filter = static_cast<ScreenFilter>(std::stoi(value));
} }
else if (var == "video.shaders") else if (var == "video.shaders")
{ {
options.video.shaders = stringToBool(value); options.video.shaders = stringToBool(value);
} }
else if (var == "video.integer_scale") else if (var == "video.integer_scale")
{ {
options.video.integer_scale = stringToBool(value); options.video.integer_scale = stringToBool(value);
} }
else if (var == "video.v_sync") else if (var == "video.v_sync")
{ {
options.video.v_sync = stringToBool(value); options.video.v_sync = stringToBool(value);
@@ -277,7 +231,6 @@ bool setOptions(const std::string &var, const std::string &value)
{ {
options.audio.enabled = stringToBool(value); options.audio.enabled = stringToBool(value);
} }
else if (var == "audio.volume") else if (var == "audio.volume")
{ {
options.audio.volume = std::stoi(value); options.audio.volume = std::stoi(value);
@@ -286,17 +239,14 @@ bool setOptions(const std::string &var, const std::string &value)
{ {
options.audio.music.enabled = stringToBool(value); options.audio.music.enabled = stringToBool(value);
} }
else if (var == "audio.music.volume") else if (var == "audio.music.volume")
{ {
options.audio.music.volume = std::stoi(value); options.audio.music.volume = std::stoi(value);
} }
else if (var == "audio.sound.enabled") else if (var == "audio.sound.enabled")
{ {
options.audio.sound.enabled = stringToBool(value); options.audio.sound.enabled = stringToBool(value);
} }
else if (var == "audio.sound.volume") else if (var == "audio.sound.volume")
{ {
options.audio.sound.volume = std::stoi(value); options.audio.sound.volume = std::stoi(value);
@@ -307,93 +257,85 @@ bool setOptions(const std::string &var, const std::string &value)
{ {
options.game.language = static_cast<lang::Code>(std::stoi(value)); options.game.language = static_cast<lang::Code>(std::stoi(value));
} }
else if (var == "game.difficulty") else if (var == "game.difficulty")
{ {
options.game.difficulty = static_cast<GameDifficulty>(std::stoi(value)); options.game.difficulty = static_cast<GameDifficulty>(std::stoi(value));
} }
else if (var == "game.autofire") else if (var == "game.autofire")
{ {
options.game.autofire = stringToBool(value); options.game.autofire = stringToBool(value);
} }
// Opciones de mandos // Opciones de mandos
else if (var == "controller1.name") else if (var == "controller.0.name")
{ {
options.controller[0].name = value; options.controllers.at(0).name = value;
} }
else if (var == "controller.0.player")
else if (var == "controller1.player")
{ {
options.controller[0].player_id = std::max(1, std::min(2, std::stoi(value))); options.controllers.at(0).player_id = std::clamp(std::stoi(value), 1, 2);
} }
else if (var == "controller.0.type")
else if (var == "controller1.button.fire_left")
{ {
options.controller[0].buttons[0] = (SDL_GameControllerButton)std::stoi(value); options.controllers.at(0).type = static_cast<InputDeviceToUse>(std::stoi(value));
} }
else if (var == "controller.0.button.fire_left")
else if (var == "controller1.button.fire_center")
{ {
options.controller[0].buttons[1] = (SDL_GameControllerButton)std::stoi(value); options.controllers.at(0).buttons.at(0) = static_cast<SDL_GameControllerButton>(std::stoi(value));
} }
else if (var == "controller.0.button.fire_center")
else if (var == "controller1.button.fire_right")
{ {
options.controller[0].buttons[2] = (SDL_GameControllerButton)std::stoi(value); options.controllers.at(0).buttons.at(1) = static_cast<SDL_GameControllerButton>(std::stoi(value));
} }
else if (var == "controller.0.button.fire_right")
else if (var == "controller1.button.start")
{ {
options.controller[0].buttons[3] = (SDL_GameControllerButton)std::stoi(value); options.controllers.at(0).buttons.at(2) = static_cast<SDL_GameControllerButton>(std::stoi(value));
} }
else if (var == "controller.0.button.start")
else if (var == "controller1.button.service")
{ {
options.controller[0].buttons[4] = (SDL_GameControllerButton)std::stoi(value); options.controllers.at(0).buttons.at(3) = static_cast<SDL_GameControllerButton>(std::stoi(value));
} }
else if (var == "controller.0.button.service")
else if (var == "controller2.name")
{ {
options.controller[1].name = value; options.controllers.at(0).buttons.at(4) = static_cast<SDL_GameControllerButton>(std::stoi(value));
} }
else if (var == "controller.1.name")
else if (var == "controller2.player")
{ {
options.controller[1].player_id = std::max(1, std::min(2, std::stoi(value))); options.controllers.at(1).name = value;
} }
else if (var == "controller.1.player")
else if (var == "controller2.button.fire_left")
{ {
options.controller[1].buttons[0] = (SDL_GameControllerButton)std::stoi(value); options.controllers.at(1).player_id = std::clamp(std::stoi(value), 1, 2);
} }
else if (var == "controller.1.type")
else if (var == "controller2.button.fire_center")
{ {
options.controller[1].buttons[1] = (SDL_GameControllerButton)std::stoi(value); options.controllers.at(1).type = static_cast<InputDeviceToUse>(std::stoi(value));
} }
else if (var == "controller.1.button.fire_left")
else if (var == "controller2.button.fire_right")
{ {
options.controller[1].buttons[2] = (SDL_GameControllerButton)std::stoi(value); options.controllers.at(1).buttons.at(0) = static_cast<SDL_GameControllerButton>(std::stoi(value));
} }
else if (var == "controller.1.button.fire_center")
else if (var == "controller2.button.start")
{ {
options.controller[1].buttons[3] = (SDL_GameControllerButton)std::stoi(value); options.controllers.at(1).buttons.at(1) = static_cast<SDL_GameControllerButton>(std::stoi(value));
} }
else if (var == "controller.1.button.fire_right")
else if (var == "controller2.button.service")
{ {
options.controller[1].buttons[4] = (SDL_GameControllerButton)std::stoi(value); options.controllers.at(1).buttons.at(2) = static_cast<SDL_GameControllerButton>(std::stoi(value));
}
else if (var == "controller.1.button.start")
{
options.controllers.at(1).buttons.at(3) = static_cast<SDL_GameControllerButton>(std::stoi(value));
}
else if (var == "controller.1.button.service")
{
options.controllers.at(1).buttons.at(4) = static_cast<SDL_GameControllerButton>(std::stoi(value));
} }
// Lineas vacias o que empiezan por comentario // Lineas vacias o que empiezan por comentario
else if (var.empty() || var.starts_with("#")) else if (var.empty() || var.starts_with("#"))
{ {
} }
else else
{ {
success = false; success = false;
@@ -408,3 +350,45 @@ int to_JA_volume(int vol)
vol = vol * 1.28f; vol = vol * 1.28f;
return std::clamp(vol, 0, 128); return std::clamp(vol, 0, 128);
} }
// Asigna el teclado al jugador
void setKeyboardToPlayer(int player_id)
{
for (auto &controller : options.controllers)
{
if (controller.player_id == player_id)
{
controller.type = InputDeviceToUse::ANY;
}
else
{
controller.type = InputDeviceToUse::CONTROLLER;
}
}
}
// Intercambia el teclado de jugador
void swapOptionsKeyboard()
{
std::swap(options.controllers.at(0).type, options.controllers.at(1).type);
}
// Intercambia los jugadores asignados a los dos primeros mandos
void swapOptionsControllers()
{
std::swap(options.controllers.at(0).player_id, options.controllers.at(1).player_id);
std::swap(options.controllers.at(0).type, options.controllers.at(1).type);
}
// Averigua quien está usando el teclado
int getPlayerWhoUsesKeyboard()
{
for (const auto &controller : options.controllers)
{
if (controller.type == InputDeviceToUse::ANY)
{
return controller.player_id;
}
}
return 0;
}

View File

@@ -1,17 +1,16 @@
#pragma once #pragma once
#include <SDL2/SDL_gamecontroller.h> // Para SDL_GameControllerButton #include <SDL2/SDL_gamecontroller.h> // Para SDL_CONTROLLER_BUTTON_B, SDL_CO...
#include <SDL2/SDL_stdinc.h> // Para Uint8 #include <string> // Para string
#include "manage_hiscore_table.h"
#include <vector> // Para vector #include <vector> // Para vector
#include <string> #include "input.h" // Para InputType, InputDeviceToUse
enum class InputType : int; #include "manage_hiscore_table.h" // Para HiScoreEntry
enum class ScreenFilter : int; enum class ScreenFilter : int; // lines 10-10
enum class ScreenVideoMode : int; enum class ScreenVideoMode : int; // lines 11-11
namespace lang namespace lang
{ {
enum class Code : int; enum class Code : int;
} } // lines 14-14
// Dificultad del juego // Dificultad del juego
enum class GameDifficulty enum class GameDifficulty
@@ -75,11 +74,17 @@ struct OptionsController
{ {
int index; // Indice en el vector de mandos int index; // Indice en el vector de mandos
int player_id; // Jugador asociado al mando int player_id; // Jugador asociado al mando
Uint8 device_type; // Indica si se utilizará teclado o mando o ambos InputDeviceToUse type; // Indica si se utilizará teclado o mando o ambos
std::string name; // Nombre del dispositivo std::string name; // Nombre del dispositivo
bool plugged; // Indica si el mando se encuentra conectado bool plugged; // Indica si el mando se encuentra conectado
std::vector<InputType> inputs; // Listado de inputs std::vector<InputType> inputs; // Listado de inputs
std::vector<SDL_GameControllerButton> buttons; // Listado de botones asignados a cada input std::vector<SDL_GameControllerButton> buttons; // Listado de botones asignados a cada input
// Constructor por defecto
OptionsController()
: index(-1), player_id(-1), type(InputDeviceToUse::CONTROLLER), name(""), plugged(false),
inputs{InputType::FIRE_LEFT, InputType::FIRE_CENTER, InputType::FIRE_RIGHT, InputType::START, InputType::SERVICE},
buttons{SDL_CONTROLLER_BUTTON_X, SDL_CONTROLLER_BUTTON_Y, SDL_CONTROLLER_BUTTON_B, SDL_CONTROLLER_BUTTON_START, SDL_CONTROLLER_BUTTON_BACK} {}
}; };
// Estructura con todas las opciones de configuración del programa // Estructura con todas las opciones de configuración del programa
@@ -88,12 +93,14 @@ struct Options
OptionsGame game; // Opciones para el propio juego OptionsGame game; // Opciones para el propio juego
OptionsVideo video; // Opciones relativas a la clase screen OptionsVideo video; // Opciones relativas a la clase screen
OptionsAudio audio; // Opciones para el audio OptionsAudio audio; // Opciones para el audio
std::vector<OptionsController> controller; // Opciones con las asignaciones del mando para cada jugador std::vector<OptionsController> controllers; // Opciones con las asignaciones del mando para cada jugador
}; };
// Variables // Variables
extern Options options; extern Options options;
void initOptions();
// Carga el fichero de configuración // Carga el fichero de configuración
bool loadOptionsFile(std::string file_path); bool loadOptionsFile(std::string file_path);
@@ -102,3 +109,15 @@ bool saveOptionsFile(std::string file_path);
// Convierte valores de 0 a 100 en valores de 0 a 128 // Convierte valores de 0 a 100 en valores de 0 a 128
int to_JA_volume(int vol); int to_JA_volume(int vol);
// Asigna el teclado al jugador
void setKeyboardToPlayer(int player_id);
// Intercambia el teclado de jugador
void swapOptionsKeyboard();
// Intercambia los jugadores asignados a los dos primeros mandos
void swapOptionsControllers();
// Averigua quien está usando el teclado
int getPlayerWhoUsesKeyboard();

View File

@@ -23,6 +23,7 @@ void initParam()
param.game.item_size = 20; param.game.item_size = 20;
param.game.game_area.rect = {0, 0, param.game.width, param.game.height}; param.game.game_area.rect = {0, 0, param.game.width, param.game.height};
param.game.play_area.rect = {0, 0, param.game.width, 216}; param.game.play_area.rect = {0, 0, param.game.width, 216};
param.game.enter_name_seconds = 30;
precalculateZones(); precalculateZones();
// SCOREBOARD // SCOREBOARD

View File

@@ -1,8 +1,8 @@
#include "path_sprite.h" #include "path_sprite.h"
#include <cmath> // for abs #include <cmath> // Para abs
#include <stdlib.h> // for abs #include <stdlib.h> // Para abs
#include <functional> // for function #include <functional> // Para function
#include <utility> // for move #include <utility> // Para move
// Devuelve un vector con los puntos que conforman la ruta // Devuelve un vector con los puntos que conforman la ruta
std::vector<SDL_Point> createPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function<double(double)> &easingFunction) std::vector<SDL_Point> createPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function<double(double)> &easingFunction)

View File

@@ -1,10 +1,10 @@
#pragma once #pragma once
#include <SDL2/SDL_rect.h> // for SDL_Point #include <SDL2/SDL_rect.h> // Para SDL_Point
#include <functional> // for function #include <functional> // Para function
#include <memory> // for shared_ptr #include <memory> // Para shared_ptr
#include <vector> // for vector #include <vector> // Para vector
#include "sprite.h" // for Sprite #include "sprite.h" // Para Sprite
class Texture; // lines 8-8 class Texture; // lines 8-8
enum class PathType enum class PathType

View File

@@ -39,9 +39,9 @@ void Player::init()
// Inicializa variables de estado // Inicializa variables de estado
pos_x_ = default_pos_x_; pos_x_ = default_pos_x_;
pos_y_ = default_pos_y_; pos_y_ = default_pos_y_;
status_walking_ = PlayerStatus::WALKING_STOP; walking_state_ = PlayerState::WALKING_STOP;
status_firing_ = PlayerStatus::FIRING_NONE; firing_state_ = PlayerState::FIRING_NONE;
status_playing_ = PlayerStatus::WAITING; playing_state_ = PlayerState::WAITING;
invulnerable_ = true; invulnerable_ = true;
invulnerable_counter_ = INVULNERABLE_COUNTER_; invulnerable_counter_ = INVULNERABLE_COUNTER_;
power_up_ = false; power_up_ = false;
@@ -70,19 +70,15 @@ void Player::init()
// Actua en consecuencia de la entrada recibida // Actua en consecuencia de la entrada recibida
void Player::setInput(InputType input) void Player::setInput(InputType input)
{ {
switch (status_playing_) switch (playing_state_)
{ {
case PlayerStatus::PLAYING: case PlayerState::PLAYING:
{ {
setInputPlaying(input); setInputPlaying(input);
break; break;
} }
case PlayerStatus::ENTERING_NAME: case PlayerState::ENTERING_NAME:
{ case PlayerState::ENTERING_NAME_GAME_COMPLETED:
setInputEnteringName(input);
break;
}
case PlayerStatus::ENTERING_NAME_GAME_COMPLETED:
{ {
setInputEnteringName(input); setInputEnteringName(input);
break; break;
@@ -100,34 +96,34 @@ void Player::setInputPlaying(InputType input)
case InputType::LEFT: case InputType::LEFT:
{ {
vel_x_ = -BASE_SPEED_; vel_x_ = -BASE_SPEED_;
setWalkingStatus(PlayerStatus::WALKING_LEFT); setWalkingState(PlayerState::WALKING_LEFT);
break; break;
} }
case InputType::RIGHT: case InputType::RIGHT:
{ {
vel_x_ = BASE_SPEED_; vel_x_ = BASE_SPEED_;
setWalkingStatus(PlayerStatus::WALKING_RIGHT); setWalkingState(PlayerState::WALKING_RIGHT);
break; break;
} }
case InputType::FIRE_CENTER: case InputType::FIRE_CENTER:
{ {
setFiringStatus(PlayerStatus::FIRING_UP); setFiringState(PlayerState::FIRING_UP);
break; break;
} }
case InputType::FIRE_LEFT: case InputType::FIRE_LEFT:
{ {
setFiringStatus(PlayerStatus::FIRING_LEFT); setFiringState(PlayerState::FIRING_LEFT);
break; break;
} }
case InputType::FIRE_RIGHT: case InputType::FIRE_RIGHT:
{ {
setFiringStatus(PlayerStatus::FIRING_RIGHT); setFiringState(PlayerState::FIRING_RIGHT);
break; break;
} }
default: default:
{ {
vel_x_ = 0; vel_x_ = 0;
setWalkingStatus(PlayerStatus::WALKING_STOP); setWalkingState(PlayerState::WALKING_STOP);
break; break;
} }
} }
@@ -162,9 +158,9 @@ void Player::setInputEnteringName(InputType input)
// Mueve el jugador a la posición y animación que le corresponde // Mueve el jugador a la posición y animación que le corresponde
void Player::move() void Player::move()
{ {
switch (status_playing_) switch (playing_state_)
{ {
case PlayerStatus::PLAYING: case PlayerState::PLAYING:
{ {
// Mueve el jugador a derecha o izquierda // Mueve el jugador a derecha o izquierda
pos_x_ += vel_x_; pos_x_ += vel_x_;
@@ -177,7 +173,7 @@ void Player::move()
shiftSprite(); shiftSprite();
break; break;
} }
case PlayerStatus::DYING: case PlayerState::DYING:
{ {
// Si el cadaver abandona el area de juego por los laterales lo hace rebotar // Si el cadaver abandona el area de juego por los laterales lo hace rebotar
if ((player_sprite_->getPosX() < param.game.play_area.rect.x) || (player_sprite_->getPosX() + WIDTH_ > play_area_.w)) if ((player_sprite_->getPosX() < param.game.play_area.rect.x) || (player_sprite_->getPosX() + WIDTH_ > play_area_.w))
@@ -185,10 +181,10 @@ void Player::move()
// Si el cadaver abandona el area de juego por abajo // Si el cadaver abandona el area de juego por abajo
if (player_sprite_->getPosY() > param.game.play_area.rect.h) if (player_sprite_->getPosY() > param.game.play_area.rect.h)
setStatusPlaying(PlayerStatus::DIED); setPlayingState(PlayerState::DIED);
break; break;
} }
case PlayerStatus::GAME_COMPLETED: case PlayerState::GAME_COMPLETED:
{ {
switch (id_) switch (id_)
{ {
@@ -208,7 +204,7 @@ void Player::move()
shiftSprite(); shiftSprite();
if (pos_x_ == min_x || pos_x_ == max_x) if (pos_x_ == min_x || pos_x_ == max_x)
setStatusPlaying(PlayerStatus::GAME_OVER); setPlayingState(PlayerState::GAME_OVER);
break; break;
} }
default: default:
@@ -227,28 +223,22 @@ void Player::render()
player_sprite_->render(); player_sprite_->render();
} }
// Establece el estado del jugador cuando camina
void Player::setWalkingStatus(PlayerStatus status) { status_walking_ = status; }
// Establece el estado del jugador cuando dispara
void Player::setFiringStatus(PlayerStatus status) { status_firing_ = status; }
// Establece la animación correspondiente al estado // Establece la animación correspondiente al estado
void Player::setAnimation() void Player::setAnimation()
{ {
// Crea cadenas de texto para componer el nombre de la animación // Crea cadenas de texto para componer el nombre de la animación
const std::string a_walking = status_walking_ == PlayerStatus::WALKING_STOP ? "stand" : "walk"; const std::string a_walking = walking_state_ == PlayerState::WALKING_STOP ? "stand" : "walk";
const std::string a_firing = status_firing_ == PlayerStatus::FIRING_UP ? "centershoot" : "sideshoot"; const std::string a_firing = firing_state_ == PlayerState::FIRING_UP ? "centershoot" : "sideshoot";
const std::string a_cooling = status_firing_ == PlayerStatus::COOLING_UP ? "centershoot" : "sideshoot"; const std::string a_cooling = firing_state_ == PlayerState::COOLING_UP ? "centershoot" : "sideshoot";
const SDL_RendererFlip flip_walk = status_walking_ == PlayerStatus::WALKING_RIGHT ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE; const SDL_RendererFlip flip_walk = walking_state_ == PlayerState::WALKING_RIGHT ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE;
const SDL_RendererFlip flip_fire = status_firing_ == PlayerStatus::FIRING_RIGHT ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE; const SDL_RendererFlip flip_fire = firing_state_ == PlayerState::FIRING_RIGHT ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE;
const SDL_RendererFlip flip_cooling = status_firing_ == PlayerStatus::COOLING_RIGHT ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE; const SDL_RendererFlip flip_cooling = firing_state_ == PlayerState::COOLING_RIGHT ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE;
// Establece la animación a partir de las cadenas // Establece la animación a partir de las cadenas
if (isPlaying() || isEnteringNameGameCompleted() || isGameCompleted()) if (isPlaying() || isEnteringNameGameCompleted() || isGameCompleted())
{ {
if (status_firing_ == PlayerStatus::FIRING_NONE) if (firing_state_ == PlayerState::FIRING_NONE)
{ // No esta disparando { // No esta disparando
player_sprite_->setCurrentAnimation(a_walking); player_sprite_->setCurrentAnimation(a_walking);
player_sprite_->setFlip(flip_walk); player_sprite_->setFlip(flip_walk);
@@ -266,34 +256,20 @@ void Player::setAnimation()
player_sprite_->setFlip(a_firing == "centershoot" ? flip_walk : flip_fire); player_sprite_->setFlip(a_firing == "centershoot" ? flip_walk : flip_fire);
} }
} }
else else if (isDying() || hasDied())
{ {
player_sprite_->setCurrentAnimation("death"); player_sprite_->setCurrentAnimation("death");
} }
else if (isCelebrating())
{
player_sprite_->setCurrentAnimation("celebration");
}
// Actualiza las animaciones de los sprites // Actualiza las animaciones de los sprites
player_sprite_->update(); // Hace avanzar las animaciones y mueve el cadaver del jugador player_sprite_->update(); // Hace avanzar las animaciones y mueve el cadaver del jugador
power_sprite_->update(); power_sprite_->update();
} }
// Obtiene el valor de la variable
int Player::getPosX() const { return static_cast<int>(pos_x_); }
// Obtiene el valor de la variable
int Player::getPosY() const { return pos_y_; }
// Obtiene el valor de la variable
int Player::getWidth() const { return WIDTH_; }
// Obtiene el valor de la variable
int Player::getHeight() const { return HEIGHT_; }
// Indica si el jugador puede disparar
bool Player::canFire() const { return cooldown_ > 0 ? false : true; }
// Establece el valor de la variable
void Player::setFireCooldown(int time) { cooldown_ = time; }
// Actualiza el valor de la variable // Actualiza el valor de la variable
void Player::updateCooldown() void Player::updateCooldown()
{ {
@@ -306,16 +282,16 @@ void Player::updateCooldown()
if (!isCooling()) if (!isCooling())
{ {
cooling_status_counter_ = 40; cooling_status_counter_ = 40;
switch (status_firing_) switch (firing_state_)
{ {
case PlayerStatus::FIRING_LEFT: case PlayerState::FIRING_LEFT:
status_firing_ = PlayerStatus::COOLING_LEFT; firing_state_ = PlayerState::COOLING_LEFT;
break; break;
case PlayerStatus::FIRING_RIGHT: case PlayerState::FIRING_RIGHT:
status_firing_ = PlayerStatus::COOLING_RIGHT; firing_state_ = PlayerState::COOLING_RIGHT;
break; break;
case PlayerStatus::FIRING_UP: case PlayerState::FIRING_UP:
status_firing_ = PlayerStatus::COOLING_UP; firing_state_ = PlayerState::COOLING_UP;
break; break;
default: default:
break; break;
@@ -327,7 +303,7 @@ void Player::updateCooldown()
} }
else else
{ {
setFiringStatus(PlayerStatus::FIRING_NONE); setFiringState(PlayerState::FIRING_NONE);
} }
} }
} }
@@ -346,12 +322,6 @@ void Player::update()
updateScoreboard(); updateScoreboard();
} }
// Obtiene la puntuación del jugador
int Player::getScore() const { return score_; }
// Asigna un valor a la puntuación del jugador
void Player::setScore(int score) { score_ = score; }
// Incrementa la puntuación del jugador // Incrementa la puntuación del jugador
void Player::addScore(int score) void Player::addScore(int score)
{ {
@@ -361,50 +331,18 @@ void Player::addScore(int score)
} }
} }
// Indica si el jugador está jugando
bool Player::isPlaying() const { return status_playing_ == PlayerStatus::PLAYING; }
// Indica si el jugador está continuando
bool Player::isContinue() const { return status_playing_ == PlayerStatus::CONTINUE; }
// Indica si el jugador está esperando
bool Player::isWaiting() const { return status_playing_ == PlayerStatus::WAITING; }
// Indica si el jugador está introduciendo su nombre
bool Player::isEnteringName() const { return status_playing_ == PlayerStatus::ENTERING_NAME; }
// Indica si el jugador está muriendose
bool Player::isDying() const { return status_playing_ == PlayerStatus::DYING; }
// Indica si el jugador ha terminado de morir
bool Player::hasDied() const { return status_playing_ == PlayerStatus::DIED; }
// Indica si el jugador ya ha terminado de jugar
bool Player::isGameOver() const { return status_playing_ == PlayerStatus::GAME_OVER; }
// Indica si el jugador está introduciendo su nombre una vez ha completado el juego
bool Player::isEnteringNameGameCompleted() const { return status_playing_ == PlayerStatus::ENTERING_NAME_GAME_COMPLETED; }
// Indica si el jugador ha completado el juego
bool Player::isGameCompleted() const { return status_playing_ == PlayerStatus::GAME_COMPLETED; }
// Actualiza el panel del marcador // Actualiza el panel del marcador
void Player::updateScoreboard() void Player::updateScoreboard()
{ {
switch (status_playing_) switch (playing_state_)
{ {
case PlayerStatus::CONTINUE: case PlayerState::CONTINUE:
{ {
Scoreboard::get()->setContinue(getScoreBoardPanel(), getContinueCounter()); Scoreboard::get()->setContinue(getScoreBoardPanel(), getContinueCounter());
break; break;
} }
case PlayerStatus::ENTERING_NAME: case PlayerState::ENTERING_NAME:
{ case PlayerState::ENTERING_NAME_GAME_COMPLETED:
Scoreboard::get()->setRecordName(getScoreBoardPanel(), getRecordName());
Scoreboard::get()->setSelectorPos(getScoreBoardPanel(), getRecordNamePos());
break;
}
case PlayerStatus::ENTERING_NAME_GAME_COMPLETED:
{ {
Scoreboard::get()->setRecordName(getScoreBoardPanel(), getRecordName()); Scoreboard::get()->setRecordName(getScoreBoardPanel(), getRecordName());
Scoreboard::get()->setSelectorPos(getScoreBoardPanel(), getRecordNamePos()); Scoreboard::get()->setSelectorPos(getScoreBoardPanel(), getRecordNamePos());
@@ -425,20 +363,20 @@ void Player::setScoreboardMode(ScoreboardMode mode)
} }
// Establece el estado del jugador en el juego // Establece el estado del jugador en el juego
void Player::setStatusPlaying(PlayerStatus value) void Player::setPlayingState(PlayerState state)
{ {
status_playing_ = value; playing_state_ = state;
switch (status_playing_) switch (playing_state_)
{ {
case PlayerStatus::PLAYING: case PlayerState::PLAYING:
{ {
init(); init();
status_playing_ = PlayerStatus::PLAYING; playing_state_ = PlayerState::PLAYING;
setScoreboardMode(ScoreboardMode::SCORE); setScoreboardMode(ScoreboardMode::SCORE);
break; break;
} }
case PlayerStatus::CONTINUE: case PlayerState::CONTINUE:
{ {
// Inicializa el contador de continuar // Inicializa el contador de continuar
continue_ticks_ = SDL_GetTicks(); continue_ticks_ = SDL_GetTicks();
@@ -447,17 +385,17 @@ void Player::setStatusPlaying(PlayerStatus value)
setScoreboardMode(ScoreboardMode::CONTINUE); setScoreboardMode(ScoreboardMode::CONTINUE);
break; break;
} }
case PlayerStatus::WAITING: case PlayerState::WAITING:
{ {
setScoreboardMode(ScoreboardMode::WAITING); setScoreboardMode(ScoreboardMode::WAITING);
break; break;
} }
case PlayerStatus::ENTERING_NAME: case PlayerState::ENTERING_NAME:
{ {
setScoreboardMode(ScoreboardMode::ENTER_NAME); setScoreboardMode(ScoreboardMode::ENTER_NAME);
break; break;
} }
case PlayerStatus::DYING: case PlayerState::DYING:
{ {
// Activa la animación de morir // Activa la animación de morir
player_sprite_->setAccelY(0.2f); player_sprite_->setAccelY(0.2f);
@@ -465,27 +403,32 @@ void Player::setStatusPlaying(PlayerStatus value)
rand() % 2 == 0 ? player_sprite_->setVelX(3.3f) : player_sprite_->setVelX(-3.3f); rand() % 2 == 0 ? player_sprite_->setVelX(3.3f) : player_sprite_->setVelX(-3.3f);
break; break;
} }
case PlayerStatus::DIED: case PlayerState::DIED:
{ {
const auto nextPlayerStatus = IsEligibleForHighScore() ? PlayerStatus::ENTERING_NAME : PlayerStatus::CONTINUE; const auto nextPlayerStatus = IsEligibleForHighScore() ? PlayerState::ENTERING_NAME : PlayerState::CONTINUE;
demo_ ? setStatusPlaying(PlayerStatus::WAITING) : setStatusPlaying(nextPlayerStatus); demo_ ? setPlayingState(PlayerState::WAITING) : setPlayingState(nextPlayerStatus);
break; break;
} }
case PlayerStatus::GAME_OVER: case PlayerState::GAME_OVER:
{ {
setScoreboardMode(ScoreboardMode::GAME_OVER); setScoreboardMode(ScoreboardMode::GAME_OVER);
break; break;
} }
case PlayerStatus::ENTERING_NAME_GAME_COMPLETED: case PlayerState::CELEBRATING:
{ {
setWalkingStatus(PlayerStatus::WALKING_STOP); setScoreboardMode(ScoreboardMode::SCORE);
setFiringStatus(PlayerStatus::FIRING_NONE); break;
}
case PlayerState::ENTERING_NAME_GAME_COMPLETED:
{
setWalkingState(PlayerState::WALKING_STOP);
setFiringState(PlayerState::FIRING_NONE);
setScoreboardMode(ScoreboardMode::ENTER_NAME); setScoreboardMode(ScoreboardMode::ENTER_NAME);
break; break;
} }
case PlayerStatus::GAME_COMPLETED: case PlayerState::GAME_COMPLETED:
{ {
setScoreboardMode(ScoreboardMode::GAME_OVER); setScoreboardMode(ScoreboardMode::GAME_COMPLETED);
break; break;
} }
default: default:
@@ -493,15 +436,6 @@ void Player::setStatusPlaying(PlayerStatus value)
} }
} }
// Obtiene el estado del jugador en el juego
PlayerStatus Player::getStatusPlaying() const { return status_playing_; }
// Obtiene el valor de la variable
float Player::getScoreMultiplier() const { return score_multiplier_; }
// Establece el valor de la variable
void Player::setScoreMultiplier(float value) { score_multiplier_ = value; }
// Aumenta el valor de la variable hasta un máximo // Aumenta el valor de la variable hasta un máximo
void Player::incScoreMultiplier() void Player::incScoreMultiplier()
{ {
@@ -516,9 +450,6 @@ void Player::decScoreMultiplier()
score_multiplier_ = std::max(score_multiplier_, 1.0f); score_multiplier_ = std::max(score_multiplier_, 1.0f);
} }
// Obtiene el valor de la variable
bool Player::isInvulnerable() const { return invulnerable_; }
// Establece el valor del estado // Establece el valor del estado
void Player::setInvulnerable(bool value) void Player::setInvulnerable(bool value)
{ {
@@ -526,12 +457,6 @@ void Player::setInvulnerable(bool value)
invulnerable_counter_ = invulnerable_ ? INVULNERABLE_COUNTER_ : 0; invulnerable_counter_ = invulnerable_ ? INVULNERABLE_COUNTER_ : 0;
} }
// Obtiene el valor de la variable
int Player::getInvulnerableCounter() const { return invulnerable_counter_; }
// Establece el valor de la variable
void Player::setInvulnerableCounter(int value) { invulnerable_counter_ = value; }
// Monitoriza el estado // Monitoriza el estado
void Player::updateInvulnerable() void Player::updateInvulnerable()
{ {
@@ -550,9 +475,6 @@ void Player::updateInvulnerable()
} }
} }
// Obtiene el valor de la variable
bool Player::isPowerUp() const { return power_up_; }
// Establece el valor de la variable // Establece el valor de la variable
void Player::setPowerUp() void Player::setPowerUp()
{ {
@@ -560,12 +482,6 @@ void Player::setPowerUp()
power_up_counter_ = POWERUP_COUNTER_; power_up_counter_ = POWERUP_COUNTER_;
} }
// Obtiene el valor de la variable
int Player::getPowerUpCounter() const { return power_up_counter_; }
// Establece el valor de la variable
void Player::setPowerUpCounter(int value) { power_up_counter_ = value; }
// Actualiza el valor de la variable // Actualiza el valor de la variable
void Player::updatePowerUp() void Player::updatePowerUp()
{ {
@@ -576,9 +492,6 @@ void Player::updatePowerUp()
} }
} }
// Obtiene el valor de la variable
bool Player::hasExtraHit() const { return extra_hit_; }
// Concede un toque extra al jugador // Concede un toque extra al jugador
void Player::giveExtraHit() void Player::giveExtraHit()
{ {
@@ -603,12 +516,6 @@ void Player::removeExtraHit()
extra_hit_ = coffees_ == 0 ? false : true; extra_hit_ = coffees_ == 0 ? false : true;
} }
// Devuelve el número de cafes actuales
int Player::getCoffees() const { return coffees_; }
// Obtiene el circulo de colisión
Circle &Player::getCollider() { return collider_; }
// Actualiza el circulo de colisión a la posición del jugador // Actualiza el circulo de colisión a la posición del jugador
void Player::shiftColliders() void Player::shiftColliders()
{ {
@@ -623,13 +530,10 @@ void Player::setPlayerTextures(const std::vector<std::shared_ptr<Texture>> &text
power_sprite_->setTexture(texture[1]); power_sprite_->setTexture(texture[1]);
} }
// Obtiene el valor de la variable
int Player::getContinueCounter() const { return continue_counter_; }
// Actualiza el contador de continue // Actualiza el contador de continue
void Player::updateContinueCounter() void Player::updateContinueCounter()
{ {
if (status_playing_ == PlayerStatus::CONTINUE) if (playing_state_ == PlayerState::CONTINUE)
{ {
constexpr int TICKS_SPEED = 1000; constexpr int TICKS_SPEED = 1000;
if (SDL_GetTicks() - continue_ticks_ > TICKS_SPEED) if (SDL_GetTicks() - continue_ticks_ > TICKS_SPEED)
@@ -642,7 +546,7 @@ void Player::updateContinueCounter()
// Actualiza el contador de entrar nombre // Actualiza el contador de entrar nombre
void Player::updateEnterNameCounter() void Player::updateEnterNameCounter()
{ {
if (status_playing_ == PlayerStatus::ENTERING_NAME || status_playing_ == PlayerStatus::ENTERING_NAME_GAME_COMPLETED) if (playing_state_ == PlayerState::ENTERING_NAME || playing_state_ == PlayerState::ENTERING_NAME_GAME_COMPLETED)
{ {
constexpr int TICKS_SPEED = 1000; constexpr int TICKS_SPEED = 1000;
if (SDL_GetTicks() - enter_name_ticks_ > TICKS_SPEED) if (SDL_GetTicks() - enter_name_ticks_ > TICKS_SPEED)
@@ -652,12 +556,6 @@ void Player::updateEnterNameCounter()
} }
} }
// Le asigna un panel en el marcador al jugador
void Player::setScoreBoardPanel(int panel) { scoreboard_panel_ = panel; }
// Obtiene el valor de la variable
int Player::getScoreBoardPanel() const { return scoreboard_panel_; }
// Decrementa el contador de continuar // Decrementa el contador de continuar
void Player::decContinueCounter() void Player::decContinueCounter()
{ {
@@ -665,7 +563,7 @@ void Player::decContinueCounter()
--continue_counter_; --continue_counter_;
if (continue_counter_ < 0) if (continue_counter_ < 0)
{ {
setStatusPlaying(PlayerStatus::GAME_OVER); setPlayingState(PlayerState::GAME_OVER);
} }
} }
@@ -677,23 +575,14 @@ void Player::decEnterNameCounter()
if (enter_name_counter_ < 0) if (enter_name_counter_ < 0)
{ {
enter_name_counter_ = param.game.enter_name_seconds; enter_name_counter_ = param.game.enter_name_seconds;
setStatusPlaying(PlayerStatus::CONTINUE); if (playing_state_ == PlayerState::ENTERING_NAME)
setPlayingState(PlayerState::CONTINUE);
else
setPlayingState(PlayerState::GAME_COMPLETED);
} }
} }
// Establece el nombre del jugador // Obtiene la posición que se está editando del nombre del jugador para la tabla de mejores puntuaciones
void Player::setName(const std::string &name) { name_ = name; }
// Establece el nombre del jugador para la tabla de mejores puntuaciones
void Player::setRecordName(const std::string &record_name) { record_name_ = record_name.substr(0, 8); }
// Obtiene el nombre del jugador
std::string Player::getName() const { return name_; }
// Obtiene el nombre del jugador para la tabla de mejores puntuaciones
std::string Player::getRecordName() const { return record_name_; }
// Obtiene la posici´´on que se está editando del nombre del jugador para la tabla de mejores puntuaciones
int Player::getRecordNamePos() const int Player::getRecordNamePos() const
{ {
if (enter_name_) if (enter_name_)
@@ -702,21 +591,6 @@ int Player::getRecordNamePos() const
return 0; return 0;
} }
// Establece el mando que usará para ser controlado
void Player::setController(int index) { controller_index_ = index; }
// Obtiene el mando que usa para ser controlado
int Player::getController() const { return controller_index_; }
// Obtiene el "id" del jugador
int Player::getId() const { return id_; }
// Indica si el jugador se puede dibujar
bool Player::isRenderable() const { return isPlaying() || isDying() || isEnteringNameGameCompleted() || isGameCompleted(); }
// Comprueba si la puntuación entra en la tabla de mejores puntuaciones
bool Player::IsEligibleForHighScore() { return score_ > options.game.hi_score_table.back().score; }
// Recoloca los sprites // Recoloca los sprites
void Player::shiftSprite() void Player::shiftSprite()
{ {
@@ -725,4 +599,48 @@ void Player::shiftSprite()
power_sprite_->setPosX(getPosX() - power_up_desp_x_); power_sprite_->setPosX(getPosX() - power_up_desp_x_);
} }
bool Player::isCooling() { return status_firing_ == PlayerStatus::COOLING_LEFT || status_firing_ == PlayerStatus::COOLING_UP || status_firing_ == PlayerStatus::COOLING_RIGHT; } int Player::getScore() const { return score_; }
void Player::setScore(int score) { score_ = score; }
PlayerState Player::getPlayingState() const { return playing_state_; }
float Player::getScoreMultiplier() const { return score_multiplier_; }
void Player::setScoreMultiplier(float value) { score_multiplier_ = value; }
bool Player::isInvulnerable() const { return invulnerable_; }
int Player::getInvulnerableCounter() const { return invulnerable_counter_; }
void Player::setInvulnerableCounter(int value) { invulnerable_counter_ = value; }
bool Player::isPowerUp() const { return power_up_; }
int Player::getPowerUpCounter() const { return power_up_counter_; }
void Player::setPowerUpCounter(int value) { power_up_counter_ = value; }
bool Player::hasExtraHit() const { return extra_hit_; }
void Player::setScoreBoardPanel(int panel) { scoreboard_panel_ = panel; }
int Player::getScoreBoardPanel() const { return scoreboard_panel_; }
int Player::getCoffees() const { return coffees_; }
Circle &Player::getCollider() { return collider_; }
int Player::getContinueCounter() const { return continue_counter_; }
void Player::setName(const std::string &name) { name_ = name; }
void Player::setRecordName(const std::string &record_name) { record_name_ = record_name.substr(0, 8); }
std::string Player::getName() const { return name_; }
std::string Player::getRecordName() const { return record_name_; }
void Player::setController(int index) { controller_index_ = index; }
int Player::getController() const { return controller_index_; }
int Player::getId() const { return id_; }
bool Player::isRenderable() const { return isPlaying() || isDying() || isCelebrating() || isEnteringNameGameCompleted() || isGameCompleted(); }
bool Player::IsEligibleForHighScore() { return score_ > options.game.hi_score_table.back().score; }
bool Player::isCooling() { return firing_state_ == PlayerState::COOLING_LEFT || firing_state_ == PlayerState::COOLING_UP || firing_state_ == PlayerState::COOLING_RIGHT; }
int Player::getPosX() const { return static_cast<int>(pos_x_); }
int Player::getPosY() const { return pos_y_; }
int Player::getWidth() const { return WIDTH_; }
int Player::getHeight() const { return HEIGHT_; }
bool Player::canFire() const { return cooldown_ > 0 ? false : true; }
void Player::setFireCooldown(int time) { cooldown_ = time; }
void Player::setWalkingState(PlayerState state) { walking_state_ = state; }
void Player::setFiringState(PlayerState state) { firing_state_ = state; }
bool Player::isPlaying() const { return playing_state_ == PlayerState::PLAYING; }
bool Player::isContinue() const { return playing_state_ == PlayerState::CONTINUE; }
bool Player::isWaiting() const { return playing_state_ == PlayerState::WAITING; }
bool Player::isEnteringName() const { return playing_state_ == PlayerState::ENTERING_NAME; }
bool Player::isDying() const { return playing_state_ == PlayerState::DYING; }
bool Player::hasDied() const { return playing_state_ == PlayerState::DIED; }
bool Player::isGameOver() const { return playing_state_ == PlayerState::GAME_OVER; }
bool Player::isEnteringNameGameCompleted() const { return playing_state_ == PlayerState::ENTERING_NAME_GAME_COMPLETED; }
bool Player::isGameCompleted() const { return playing_state_ == PlayerState::GAME_COMPLETED; }
bool Player::isCelebrating() const { return playing_state_ == PlayerState::CELEBRATING; }

View File

@@ -14,7 +14,7 @@ enum class InputType : int; // lines 13-13
enum class ScoreboardMode; // lines 14-14 enum class ScoreboardMode; // lines 14-14
// Estados del jugador // Estados del jugador
enum class PlayerStatus enum class PlayerState
{ {
WALKING_LEFT, WALKING_LEFT,
WALKING_RIGHT, WALKING_RIGHT,
@@ -29,15 +29,16 @@ enum class PlayerStatus
COOLING_LEFT, COOLING_LEFT,
COOLING_RIGHT, COOLING_RIGHT,
PLAYING, PLAYING, // Está jugando
CONTINUE, CONTINUE, // Está con la cuenta atras para continuar
WAITING, WAITING, // No está jugando pero puede entrar a jugar
ENTERING_NAME, ENTERING_NAME, // Introduciendo nombre
DYING, DYING, // El cadaver está volando por ahi
DIED, DIED, // El cadaver ha desaparecido por el fondo
GAME_OVER, GAME_OVER, // No está jugando y no puede entrar a jugar
ENTERING_NAME_GAME_COMPLETED, CELEBRATING, // Poniendo pose de victoria
GAME_COMPLETED, ENTERING_NAME_GAME_COMPLETED, // Poniendo nombre en el tramo final del juego
GAME_COMPLETED, // Moviendose fuera de la pantalla
}; };
// Clase Player // Clase Player
@@ -69,9 +70,9 @@ private:
int cooling_status_counter_ = 0; // Contador para la animación del estado cooling int cooling_status_counter_ = 0; // Contador para la animación del estado cooling
int score_ = 0; // Puntos del jugador int score_ = 0; // Puntos del jugador
float score_multiplier_ = 1.0f; // Multiplicador de puntos float score_multiplier_ = 1.0f; // Multiplicador de puntos
PlayerStatus status_walking_ = PlayerStatus::WALKING_STOP; // Estado del jugador al moverse PlayerState walking_state_ = PlayerState::WALKING_STOP; // Estado del jugador al moverse
PlayerStatus status_firing_ = PlayerStatus::FIRING_NONE; // Estado del jugador al disparar PlayerState firing_state_ = PlayerState::FIRING_NONE; // Estado del jugador al disparar
PlayerStatus status_playing_ = PlayerStatus::WAITING; // Estado del jugador en el juego PlayerState playing_state_ = PlayerState::WAITING; // Estado del jugador en el juego
bool invulnerable_ = true; // Indica si el jugador es invulnerable bool invulnerable_ = true; // Indica si el jugador es invulnerable
int invulnerable_counter_ = INVULNERABLE_COUNTER_; // Contador para la invulnerabilidad int invulnerable_counter_ = INVULNERABLE_COUNTER_; // Contador para la invulnerabilidad
bool extra_hit_ = false; // Indica si el jugador tiene un toque extra bool extra_hit_ = false; // Indica si el jugador tiene un toque extra
@@ -117,6 +118,7 @@ private:
// Cambia el modo del marcador // Cambia el modo del marcador
void setScoreboardMode(ScoreboardMode mode); void setScoreboardMode(ScoreboardMode mode);
// Se encuentra en alguno de los estados "COOLING"
bool isCooling(); bool isCooling();
public: public:
@@ -151,10 +153,10 @@ public:
void move(); void move();
// Establece el estado del jugador // Establece el estado del jugador
void setWalkingStatus(PlayerStatus status); void setWalkingState(PlayerState state);
// Establece el estado del jugador // Establece el estado del jugador
void setFiringStatus(PlayerStatus status); void setFiringState(PlayerState state);
// Establece la animación correspondiente al estado // Establece la animación correspondiente al estado
void setAnimation(); void setAnimation();
@@ -189,38 +191,23 @@ public:
// Incrementa la puntuación del jugador // Incrementa la puntuación del jugador
void addScore(int score); void addScore(int score);
// Indica si el jugador está jugando // Indica si el jugador se encuentra en ese estado
bool isPlaying() const; bool isPlaying() const;
// Indica si el jugador está continuando
bool isContinue() const; bool isContinue() const;
// Indica si el jugador está esperando
bool isWaiting() const; bool isWaiting() const;
// Indica si el jugador está introduciendo su nombre
bool isEnteringName() const; bool isEnteringName() const;
// Indica si el jugador está muriendose
bool isDying() const; bool isDying() const;
// Indica si el jugador ha terminado de morir
bool hasDied() const; bool hasDied() const;
// Indica si el jugador ya ha terminado de jugar
bool isGameOver() const; bool isGameOver() const;
// Indica si el jugador está introduciendo su nombre una vez ha completado el juego
bool isEnteringNameGameCompleted() const; bool isEnteringNameGameCompleted() const;
// Indica si el jugador ha completado el juego
bool isGameCompleted() const; bool isGameCompleted() const;
bool isCelebrating() const;
// Establece el estado del jugador en el juego // Establece el estado del jugador en el juego
void setStatusPlaying(PlayerStatus value); void setPlayingState(PlayerState state);
// Obtiene el estado del jugador en el juego // Obtiene el estado del jugador en el juego
PlayerStatus getStatusPlaying() const; PlayerState getPlayingState() const;
// Obtiene el valor de la variable // Obtiene el valor de la variable
float getScoreMultiplier() const; float getScoreMultiplier() const;

View File

@@ -118,77 +118,28 @@ void Scoreboard::render()
SDL_RenderCopy(renderer_, background_, nullptr, &rect_); SDL_RenderCopy(renderer_, background_, nullptr, &rect_);
} }
// Establece el valor de la variable void Scoreboard::setName(int panel, const std::string &name) { name_[panel] = name; }
void Scoreboard::setName(int panel_, const std::string &name_) void Scoreboard::setRecordName(int panel, const std::string &record_name) { record_name_[panel] = record_name; }
{ void Scoreboard::setSelectorPos(int panel, int pos) { selector_pos_[panel] = pos; }
this->name_[panel_] = name_; void Scoreboard::setScore(int panel, int score) { score_[panel] = score; }
} void Scoreboard::setMult(int panel, float mult) { mult_[panel] = mult; }
void Scoreboard::setContinue(int panel, int continue_counter) { continue_counter_[panel] = continue_counter; }
void Scoreboard::setStage(int stage) { stage_ = stage; }
void Scoreboard::setHiScore(int hi_score) { hi_score_ = hi_score; }
void Scoreboard::setPower(float power) { power_ = power; }
void Scoreboard::setHiScoreName(const std::string &name) { hi_score_name_ = name; }
// Establece el valor de la variable // Establece el valor de la variable
void Scoreboard::setRecordName(int panel_, const std::string &record_name_) void Scoreboard::setColor(Color color)
{ {
this->record_name_[panel_] = record_name_; color_ = color;
}
// Establece el valor de la variable
void Scoreboard::setSelectorPos(int panel_, int pos)
{
selector_pos_[panel_] = pos;
}
// Establece el valor de la variable
void Scoreboard::setScore(int panel_, int score_)
{
this->score_[panel_] = score_;
}
// Establece el valor de la variable
void Scoreboard::setMult(int panel_, float mult_)
{
this->mult_[panel_] = mult_;
}
// Establece el valor de la variable
void Scoreboard::setContinue(int panel_, int value)
{
continue_counter_[panel_] = value;
}
// Establece el valor de la variable
void Scoreboard::setStage(int stage_)
{
this->stage_ = stage_;
}
// Establece el valor de la variable
void Scoreboard::setHiScore(int hi_score_)
{
this->hi_score_ = hi_score_;
}
// Establece el valor de la variable
void Scoreboard::setPower(float power_)
{
this->power_ = power_;
}
// Establece el valor de la variable
void Scoreboard::setHiScoreName(const std::string &name_)
{
hi_score_name_ = name_;
}
// Establece el valor de la variable
void Scoreboard::setColor(Color color_)
{
this->color_ = color_;
fillBackgroundTexture(); fillBackgroundTexture();
} }
// Establece el valor de la variable // Establece el valor de la variable
void Scoreboard::setPos(SDL_Rect rect_) void Scoreboard::setPos(SDL_Rect rect)
{ {
this->rect_ = rect_; rect_ = rect;
// Recalcula las anclas de los elementos // Recalcula las anclas de los elementos
recalculateAnchors(); recalculateAnchors();
@@ -207,10 +158,10 @@ void Scoreboard::setPos(SDL_Rect rect_)
void Scoreboard::fillPanelTextures() void Scoreboard::fillPanelTextures()
{ {
// Guarda a donde apunta actualmente el renderizador // Guarda a donde apunta actualmente el renderizador
SDL_Texture *temp = SDL_GetRenderTarget(renderer_); auto temp = SDL_GetRenderTarget(renderer_);
// Genera el contenidoi de cada panel_ // Genera el contenidoi de cada panel_
for (int i = 0; i < SCOREBOARD_MAX_PANELS; ++i) for (size_t i = 0; i < SCOREBOARD_MAX_PANELS; ++i)
{ {
// Cambia el destino del renderizador // Cambia el destino del renderizador
SDL_SetRenderTarget(renderer_, panel_texture_[i]); SDL_SetRenderTarget(renderer_, panel_texture_[i]);
@@ -314,8 +265,9 @@ void Scoreboard::fillPanelTextures()
text_scoreboard_->writeCentered(slot4_3_.x, slot4_3_.y, lang::getText(106)); text_scoreboard_->writeCentered(slot4_3_.x, slot4_3_.y, lang::getText(106));
SDL_Rect rect = {enter_name_pos_.x, enter_name_pos_.y, 5, 7}; SDL_Rect rect = {enter_name_pos_.x, enter_name_pos_.y, 5, 7};
SDL_SetRenderDrawColor(renderer_, 0xFF, 0xFF, 0xEB, 255); SDL_SetRenderDrawColor(renderer_, 0xFF, 0xFF, 0xEB, 255);
for (int j = 0; j < (int)record_name_[i].size(); ++j) for (size_t j = 0; j < record_name_[i].size(); ++j)
{ {
/*
if (j == selector_pos_[i]) if (j == selector_pos_[i])
{ // La letra seleccionada se pinta de forma intermitente { // La letra seleccionada se pinta de forma intermitente
if (counter_ % 3 > 0) if (counter_ % 3 > 0)
@@ -329,11 +281,28 @@ void Scoreboard::fillPanelTextures()
SDL_RenderDrawLine(renderer_, rect.x, rect.y + rect.h, rect.x + rect.w, rect.y + rect.h); SDL_RenderDrawLine(renderer_, rect.x, rect.y + rect.h, rect.x + rect.w, rect.y + rect.h);
text_scoreboard_->write(rect.x, rect.y, record_name_[i].substr(j, 1)); text_scoreboard_->write(rect.x, rect.y, record_name_[i].substr(j, 1));
} }
*/
if (j != selector_pos_[i] || counter_ % 3 == 0)
{
SDL_RenderDrawLine(renderer_, rect.x, rect.y + rect.h, rect.x + rect.w, rect.y + rect.h);
text_scoreboard_->write(rect.x, rect.y, record_name_[i].substr(j, 1));
}
rect.x += 7; rect.x += 7;
} }
break; break;
} }
case ScoreboardMode::GAME_COMPLETED:
{
// GAME OVER
text_scoreboard_->writeCentered(slot4_1_.x, slot4_1_.y + 4, lang::getText(102));
// SCORE
if (counter_ % 10 < 8)
{
text_scoreboard_->writeCentered(slot4_3_.x, slot4_3_.y - 2, lang::getText(120));
text_scoreboard_->writeCentered(slot4_4_.x, slot4_4_.y - 2, updateScoreText(score_[i]));
}
}
default: default:
break; break;
} }
@@ -416,10 +385,7 @@ void Scoreboard::recalculateAnchors()
} }
// Establece el modo del marcador // Establece el modo del marcador
void Scoreboard::setMode(int index, ScoreboardMode mode) void Scoreboard::setMode(int index, ScoreboardMode mode) { panel_[index].mode = mode; }
{
panel_[index].mode = mode;
}
// Crea la textura de fondo // Crea la textura de fondo
void Scoreboard::createBackgroundTexture() void Scoreboard::createBackgroundTexture()

View File

@@ -1,16 +1,17 @@
#pragma once #pragma once
#include <SDL2/SDL_rect.h> // para SDL_Point, SDL_Rect #include <SDL2/SDL_rect.h> // Para SDL_Point, SDL_Rect
#include <SDL2/SDL_render.h> // para SDL_Renderer, SDL_Texture #include <SDL2/SDL_render.h> // Para SDL_Texture, SDL_Renderer
#include <SDL2/SDL_stdinc.h> // para Uint32 #include <SDL2/SDL_stdinc.h> // Para Uint32
#include <SDL2/SDL_timer.h> // para SDL_GetTicks #include <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <memory> // para unique_ptr, shared_ptr #include <stddef.h> // Para size_t
#include <string> // para string #include <memory> // Para unique_ptr, shared_ptr
#include <vector> // para vector #include <string> // Para string
#include "utils.h" // para Color #include <vector> // Para vector
class Sprite; #include "utils.h" // Para Color
class Text; class Sprite; // lines 11-11
class Texture; class Text; // lines 12-12
class Texture; // lines 13-13
// Defines // Defines
constexpr int SCOREBOARD_LEFT_PANEL = 0; constexpr int SCOREBOARD_LEFT_PANEL = 0;
@@ -28,6 +29,7 @@ enum class ScoreboardMode : int
GAME_OVER, GAME_OVER,
DEMO, DEMO,
ENTER_NAME, ENTER_NAME,
GAME_COMPLETED,
NUM_MODES, NUM_MODES,
}; };
@@ -58,7 +60,7 @@ private:
// Variables // Variables
std::string name_[SCOREBOARD_MAX_PANELS] = {}; // Nom de cada jugador std::string name_[SCOREBOARD_MAX_PANELS] = {}; // Nom de cada jugador
std::string record_name_[SCOREBOARD_MAX_PANELS] = {}; // Nombre introducido para la tabla de records std::string record_name_[SCOREBOARD_MAX_PANELS] = {}; // Nombre introducido para la tabla de records
int selector_pos_[SCOREBOARD_MAX_PANELS] = {}; // Posición del selector de letra para introducir el nombre size_t selector_pos_[SCOREBOARD_MAX_PANELS] = {}; // Posición del selector de letra para introducir el nombre
int score_[SCOREBOARD_MAX_PANELS] = {}; // Puntuación de los jugadores int score_[SCOREBOARD_MAX_PANELS] = {}; // Puntuación de los jugadores
float mult_[SCOREBOARD_MAX_PANELS] = {}; // Multiplicador de los jugadores float mult_[SCOREBOARD_MAX_PANELS] = {}; // Multiplicador de los jugadores
int continue_counter_[SCOREBOARD_MAX_PANELS] = {}; // Tiempo para continuar de los jugadores int continue_counter_[SCOREBOARD_MAX_PANELS] = {}; // Tiempo para continuar de los jugadores

View File

@@ -6,12 +6,12 @@
#include <algorithm> // Para clamp, max, min #include <algorithm> // Para clamp, max, min
#include <fstream> // Para basic_ifstream, ifstream #include <fstream> // Para basic_ifstream, ifstream
#include <iterator> // Para istreambuf_iterator, operator== #include <iterator> // Para istreambuf_iterator, operator==
#include <string> // Para allocator, operator+, to_string, char_t... #include <string> // Para allocator, operator+, char_traits, to_s...
#include <vector> // Para vector #include <vector> // Para vector
#include "asset.h" // Para Asset #include "asset.h" // Para Asset
#include "dbgtxt.h" // Para dbg_print #include "dbgtxt.h" // Para dbg_print
#include "global_inputs.h" // Para service_pressed_counter #include "global_inputs.h" // Para service_pressed_counter
#include "input.h" // Para Input, InputType, INPUT_DO_NOT_ALLOW_RE... #include "jail_shader.h" // Para init, render
#include "notifier.h" // Para Notifier #include "notifier.h" // Para Notifier
#include "on_screen_help.h" // Para OnScreenHelp #include "on_screen_help.h" // Para OnScreenHelp
#include "options.h" // Para Options, OptionsVideo, options, Options... #include "options.h" // Para Options, OptionsVideo, options, Options...
@@ -98,7 +98,7 @@ void Screen::blit()
OnScreenHelp::get()->render(); OnScreenHelp::get()->render();
// Muestra información por pantalla // Muestra información por pantalla
displayInfo(); renderInfo();
// Muestra las notificaciones // Muestra las notificaciones
Notifier::get()->render(); Notifier::get()->render();
@@ -210,7 +210,7 @@ void Screen::setVideoMode(ScreenVideoMode videoMode)
} }
// Camibia entre pantalla completa y ventana // Camibia entre pantalla completa y ventana
void Screen::switchVideoMode() void Screen::toggleVideoMode()
{ {
options.video.mode = options.video.mode == ScreenVideoMode::WINDOW ? ScreenVideoMode::FULLSCREEN : ScreenVideoMode::WINDOW; options.video.mode = options.video.mode == ScreenVideoMode::WINDOW ? ScreenVideoMode::FULLSCREEN : ScreenVideoMode::WINDOW;
setVideoMode(options.video.mode); setVideoMode(options.video.mode);
@@ -260,72 +260,6 @@ void Screen::update()
OnScreenHelp::get()->update(); OnScreenHelp::get()->update();
} }
// Comprueba las entradas
void Screen::checkInput()
{
#ifndef ARCADE
// Comprueba el teclado para cambiar entre pantalla completa y ventana
if (Input::get()->checkInput(InputType::WINDOW_FULLSCREEN, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{
switchVideoMode();
const std::string mode = options.video.mode == ScreenVideoMode::WINDOW ? "Window" : "Fullscreen";
Notifier::get()->showText(mode + " mode");
return;
}
// Comprueba el teclado para decrementar el tamaño de la ventana
if (Input::get()->checkInput(InputType::WINDOW_DEC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{
decWindowSize();
const std::string size = std::to_string(options.video.window.size);
Notifier::get()->showText("Window size x" + size);
return;
}
// Comprueba el teclado para incrementar el tamaño de la ventana
if (Input::get()->checkInput(InputType::WINDOW_INC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{
incWindowSize();
const std::string size = std::to_string(options.video.window.size);
Notifier::get()->showText("Window size x" + size);
return;
}
#endif
// Comprueba el teclado para activar o desactivar los shaders
if (Input::get()->checkInput(InputType::VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{
switchShaders();
return;
}
#ifdef DEBUG
// Comprueba el teclado para mostrar la información de debug
if (Input::get()->checkInput(InputType::SHOWINFO, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{
show_info_ = !show_info_;
return;
}
#endif
for (int i = 0; i < Input::get()->getNumControllers(); ++i)
{
// Comprueba los mandos para activar o desactivar los shaders
if (Input::get()->checkModInput(InputType::SERVICE, InputType::VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{
switchShaders();
return;
}
// Comprueba los mandos para mostrar la información de debug
if (Input::get()->checkModInput(InputType::SERVICE, InputType::SHOWINFO, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{
show_info_ = !show_info_;
return;
}
}
}
// Agita la pantalla // Agita la pantalla
void Screen::shake() void Screen::shake()
{ {
@@ -384,11 +318,8 @@ void Screen::doFlash()
if (flash_effect_.enabled) if (flash_effect_.enabled)
{ {
// Dibuja el color del flash en la textura // Dibuja el color del flash en la textura
//auto temp = SDL_GetRenderTarget(renderer_);
//SDL_SetRenderTarget(renderer_, game_canvas_);
SDL_SetRenderDrawColor(renderer_, flash_effect_.color.r, flash_effect_.color.g, flash_effect_.color.b, 0xFF); SDL_SetRenderDrawColor(renderer_, flash_effect_.color.r, flash_effect_.color.g, flash_effect_.color.b, 0xFF);
SDL_RenderClear(renderer_); SDL_RenderClear(renderer_);
//SDL_SetRenderTarget(renderer_, temp);
// Actualiza la lógica del efecto // Actualiza la lógica del efecto
flash_effect_.counter > 0 ? flash_effect_.counter-- : flash_effect_.enabled = false; flash_effect_.counter > 0 ? flash_effect_.counter-- : flash_effect_.enabled = false;
@@ -400,21 +331,24 @@ void Screen::doAttenuate()
{ {
if (attenuate_effect_) if (attenuate_effect_)
{ {
//auto temp = SDL_GetRenderTarget(renderer_);
//SDL_SetRenderTarget(renderer_, game_canvas_);
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 64); SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 64);
SDL_RenderFillRect(renderer_, nullptr); SDL_RenderFillRect(renderer_, nullptr);
//SDL_SetRenderTarget(renderer_, temp);
} }
} }
// Activa / desactiva los shaders // Activa / desactiva los shaders
void Screen::switchShaders() void Screen::toggleShaders()
{ {
options.video.shaders = !options.video.shaders; options.video.shaders = !options.video.shaders;
setVideoMode(options.video.mode); setVideoMode(options.video.mode);
const std::string value = options.video.shaders ? "on" : "off"; const std::string value = options.video.shaders ? "on" : "off";
Notifier::get()->showText("Shaders " + value); Notifier::get()->showText({"Shaders " + value});
}
// Activa / desactiva la información de debug
void Screen::toggleDebugInfo()
{
show_info_ = !show_info_;
} }
// Atenua la pantalla // Atenua la pantalla
@@ -441,7 +375,7 @@ void Screen::updateFPS()
} }
// Muestra información por pantalla // Muestra información por pantalla
void Screen::displayInfo() void Screen::renderInfo()
{ {
if (show_info_) if (show_info_)
{ {

View File

@@ -92,7 +92,7 @@ private:
void updateFPS(); void updateFPS();
// Muestra información por pantalla // Muestra información por pantalla
void displayInfo(); void renderInfo();
// Calcula la nueva posición de la ventana a partir de la antigua al cambiarla de tamaño // Calcula la nueva posición de la ventana a partir de la antigua al cambiarla de tamaño
SDL_Point getNewPosition(); SDL_Point getNewPosition();
@@ -118,9 +118,6 @@ public:
// Actualiza la lógica de la clase // Actualiza la lógica de la clase
void update(); void update();
// Comprueba las entradas
void checkInput();
// Limpia la pantalla // Limpia la pantalla
void clean(Color color = Color(0x00, 0x00, 0x00)); void clean(Color color = Color(0x00, 0x00, 0x00));
@@ -133,8 +130,8 @@ public:
// Establece el modo de video // Establece el modo de video
void setVideoMode(ScreenVideoMode video_mode); void setVideoMode(ScreenVideoMode video_mode);
// Camibia entre pantalla completa y ventana // Cambia entre pantalla completa y ventana
void switchVideoMode(); void toggleVideoMode();
// Cambia el tamaño de la ventana // Cambia el tamaño de la ventana
void setWindowSize(int size); void setWindowSize(int size);
@@ -158,7 +155,10 @@ public:
void flash(Color color, int lenght); void flash(Color color, int lenght);
// Activa / desactiva los shaders // Activa / desactiva los shaders
void switchShaders(); void toggleShaders();
// Activa / desactiva la información de debug
void toggleDebugInfo();
// Atenua la pantalla // Atenua la pantalla
void attenuate(bool value); void attenuate(bool value);

View File

@@ -1,16 +1,16 @@
#include "text.h" #include "text.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND #include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888 #include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // Para SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_TEXTUREACCESS_TARGET #include <SDL2/SDL_render.h> // Para SDL_TEXTUREACCESS_TARGET
#include <stddef.h> // for size_t #include <stddef.h> // Para size_t
#include <fstream> // for basic_ifstream, basic_istream, basic... #include <fstream> // Para basic_ifstream, basic_istream, basic...
#include <iostream> // for cerr #include <iostream> // Para cerr
#include <stdexcept> // for runtime_error #include <stdexcept> // Para runtime_error
#include "screen.h" // for Screen #include "screen.h" // Para Screen
#include "sprite.h" // for Sprite #include "sprite.h" // Para Sprite
#include "texture.h" // for Texture #include "texture.h" // Para Texture
#include "utils.h" // for Color, getFileName, printWithDots #include "utils.h" // Para Color, getFileName, printWithDots
// Llena una estructuta TextFile desde un fichero // Llena una estructuta TextFile desde un fichero
std::shared_ptr<TextFile> loadTextFile(const std::string &file_path) std::shared_ptr<TextFile> loadTextFile(const std::string &file_path)

View File

@@ -2,13 +2,13 @@
#include "texture.h" #include "texture.h"
#include <SDL2/SDL_error.h> // Para SDL_GetError #include <SDL2/SDL_error.h> // Para SDL_GetError
#include <SDL2/SDL_surface.h> // Para SDL_CreateRGBSurfaceWithFormatFrom #include <SDL2/SDL_surface.h> // Para SDL_CreateRGBSurfaceWithFormatFrom
#include <fcntl.h> // Para SEEK_END, SEEK_SET
#include <stdio.h> // Para fseek, fclose, fopen, fread, ftell, FILE
#include <stdlib.h> // Para free, malloc
#include <fstream> // Para basic_ostream, operator<<, basic_ifstream #include <fstream> // Para basic_ostream, operator<<, basic_ifstream
#include <iostream> // Para cerr, cout #include <iostream> // Para cerr, cout
#include <stdexcept> // Para runtime_error #include <stdexcept> // Para runtime_error
#include <string> // Para char_traits, operator<<, operator+
#include <vector> // Para vector
#include "gif.c" // Para LoadGif, LoadPalette #include "gif.c" // Para LoadGif, LoadPalette
#include "stb_image.h" // Para stbi_image_free, stbi_load, STBI_rgb_a...
#include "utils.h" // Para getFileName, printWithDots #include "utils.h" // Para getFileName, printWithDots
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
@@ -315,8 +315,8 @@ std::vector<Uint32> Texture::loadPaletteFromFile(const std::string &file_path)
{ {
std::vector<Uint32> palette; std::vector<Uint32> palette;
FILE *f = fopen(file_path.c_str(), "rb"); std::ifstream file(file_path, std::ios::binary | std::ios::ate);
if (!f) if (!file)
{ {
std::cerr << "Error: Fichero no encontrado " << getFileName(file_path) << std::endl; std::cerr << "Error: Fichero no encontrado " << getFileName(file_path) << std::endl;
throw std::runtime_error("Fichero no encontrado: " + getFileName(file_path)); throw std::runtime_error("Fichero no encontrado: " + getFileName(file_path));
@@ -326,21 +326,22 @@ std::vector<Uint32> Texture::loadPaletteFromFile(const std::string &file_path)
printWithDots("Image : ", getFileName(file_path), "[ LOADED ]"); printWithDots("Image : ", getFileName(file_path), "[ LOADED ]");
} }
fseek(f, 0, SEEK_END); auto size = file.tellg();
long size = ftell(f); file.seekg(0, std::ios::beg);
fseek(f, 0, SEEK_SET);
Uint8 *buffer = static_cast<Uint8 *>(malloc(size));
fread(buffer, size, 1, f);
fclose(f);
const auto *pal = LoadPalette(buffer); std::vector<Uint8> buffer(size);
if (!file.read(reinterpret_cast<char *>(buffer.data()), size))
{
std::cerr << "Error: No se pudo leer completamente el fichero " << getFileName(file_path) << std::endl;
throw std::runtime_error("Error al leer el fichero: " + getFileName(file_path));
}
const auto pal = LoadPalette(buffer.data());
if (!pal) if (!pal)
{ {
return palette; return palette;
} }
free(buffer);
for (int i = 0; i < 256; ++i) for (int i = 0; i < 256; ++i)
{ {
palette.push_back((pal[i] << 8) + 255); palette.push_back((pal[i] << 8) + 255);

View File

@@ -1,9 +1,10 @@
#include "title.h" #include "title.h"
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_KEYDOWN #include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_KEYDOWN
#include <SDL2/SDL_keycode.h> // Para SDLK_1, SDLK_2, SDLK_3 #include <SDL2/SDL_keycode.h> // Para SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_5
#include <SDL2/SDL_rect.h> // Para SDL_Rect #include <SDL2/SDL_rect.h> // Para SDL_Rect
#include <SDL2/SDL_timer.h> // Para SDL_GetTicks #include <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <string> // Para char_traits, operator+, to_string, bas... #include <stddef.h> // Para size_t
#include <string> // Para char_traits, operator+, basic_string
#include <utility> // Para move #include <utility> // Para move
#include <vector> // Para vector #include <vector> // Para vector
#include "define_buttons.h" // Para DefineButtons #include "define_buttons.h" // Para DefineButtons
@@ -18,7 +19,7 @@
#include "param.h" // Para Param, param, ParamGame, ParamTitle #include "param.h" // Para Param, param, ParamGame, ParamTitle
#include "resource.h" // Para Resource #include "resource.h" // Para Resource
#include "screen.h" // Para Screen #include "screen.h" // Para Screen
#include "section.h" // Para Options, options, name, Name #include "section.h" // Para Options, options, Name, name, AttractMode
#include "sprite.h" // Para Sprite #include "sprite.h" // Para Sprite
#include "text.h" // Para Text, TEXT_CENTER, TEXT_SHADOW #include "text.h" // Para Text, TEXT_CENTER, TEXT_SHADOW
#include "texture.h" // Para Texture #include "texture.h" // Para Texture
@@ -171,11 +172,13 @@ void Title::render()
// Comprueba los eventos // Comprueba los eventos
void Title::checkEvents() void Title::checkEvents()
{ {
// Comprueba el input para el resto de objetos
define_buttons_->checkEvents();
// Si define_buttons_ está habilitado, es él quien gestiona los eventos // Si define_buttons_ está habilitado, es él quien gestiona los eventos
if (!define_buttons_->isEnabled()) if (!define_buttons_->isEnabled())
{ {
SDL_Event event; SDL_Event event;
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(&event)) while (SDL_PollEvent(&event))
{ {
// Evento de salida de la aplicación // Evento de salida de la aplicación
@@ -196,26 +199,36 @@ void Title::checkEvents()
{ {
switch (event.key.keysym.sym) switch (event.key.keysym.sym)
{ {
case SDLK_1: case SDLK_1: // Redefine los botones del mando #0
{ {
if (define_buttons_->enable(0)) if (define_buttons_->enable(0))
resetCounter(); resetCounter();
break; break;
} }
case SDLK_2: // Redefine los botones del mando #1
case SDLK_2:
{ {
if (define_buttons_->enable(1)) if (define_buttons_->enable(1))
resetCounter(); resetCounter();
break; break;
} }
case SDLK_3: // Intercambia los mandos entre los dos jugadores
case SDLK_3:
{ {
swapControllers(); swapControllers();
resetCounter();
break;
}
case SDLK_4: // Intercambia la asignación del teclado
{
swapKeyboard();
resetCounter();
break;
}
case SDLK_5: // Muestra la asignacion de mandos y teclado
{
showControllers();
resetCounter();
break; break;
} }
default: default:
break; break;
} }
@@ -230,53 +243,37 @@ void Title::checkInput()
// Comprueba los controladores solo si no se estan definiendo los botones // Comprueba los controladores solo si no se estan definiendo los botones
if (!define_buttons_->isEnabled()) if (!define_buttons_->isEnabled())
{ {
// Comprueba el teclado para empezar a jugar // Comprueba los métodos de control
if (Input::get()->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) for (const auto &controller : options.controllers)
{
if (Input::get()->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, controller.type, controller.index) &&
!Input::get()->checkInput(InputType::SERVICE, INPUT_DO_NOT_ALLOW_REPEAT, controller.type, controller.index))
{ {
if (section::options == section::Options::TITLE_2 || ALLOW_TITLE_ANIMATION_SKIP) if (section::options == section::Options::TITLE_2 || ALLOW_TITLE_ANIMATION_SKIP)
{ {
fade_->activate(); fade_->activate();
post_fade_ = options.controller[0].player_id; post_fade_ = controller.player_id;
return;
} }
} }
// Comprueba los mandos
for (int i = 0; i < Input::get()->getNumControllers(); ++i)
{
// Comprueba si se va a intercambiar la asignación de mandos a jugadores // Comprueba si se va a intercambiar la asignación de mandos a jugadores
if (Input::get()->checkModInput(InputType::SERVICE, InputType::SWAP_CONTROLLERS, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, controller.type, controller.index) &&
Input::get()->checkInput(InputType::SWAP_CONTROLLERS, INPUT_DO_NOT_ALLOW_REPEAT, controller.type, controller.index))
{ {
swapControllers(); swapControllers();
return; return;
} }
// Comprueba si algun mando quiere ser configurado // Comprueba si algun mando quiere ser configurado
if (Input::get()->checkModInput(InputType::SERVICE, InputType::CONFIG, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, controller.type, controller.index) &&
Input::get()->checkInput(InputType::CONFIG, INPUT_DO_NOT_ALLOW_REPEAT, controller.type, controller.index))
{ {
define_buttons_->enable(i); define_buttons_->enable(controller.index);
return;
}
// Comprueba el botón de START de los mandos
if (Input::get()->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{
// Si no está el botón de servicio activo
if (!Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{
if (section::options == section::Options::TITLE_2 || ALLOW_TITLE_ANIMATION_SKIP)
{
fade_->activate();
post_fade_ = options.controller[i].player_id;
return; return;
} }
} }
} }
}
}
// Comprueba el input para el resto de objetos
Screen::get()->checkInput();
define_buttons_->checkInput();
// Comprueba los inputs que se pueden introducir en cualquier sección del juego // Comprueba los inputs que se pueden introducir en cualquier sección del juego
globalInputs::check(); globalInputs::check();
@@ -302,50 +299,52 @@ void Title::reLoadTextures()
} }
// Reinicia el contador interno // Reinicia el contador interno
void Title::resetCounter() void Title::resetCounter() { counter_ = 0; }
{
counter_ = 0;
}
// Intercambia la asignación de mandos a los jugadores // Intercambia la asignación de mandos a los jugadores
void Title::swapControllers() void Title::swapControllers()
{ {
const auto num_controllers = Input::get()->getNumControllers(); if (Input::get()->getNumControllers() == 0)
if (num_controllers == 0)
{
return; return;
swapOptionsControllers();
showControllers();
} }
define_buttons_->swapControllers(); // Intercambia el teclado de jugador
void Title::swapKeyboard()
// Crea cadenas de texto vacias para un numero máximo de mandos
constexpr int MAX_CONTROLLERS = 2;
std::string text[MAX_CONTROLLERS];
int playerControllerIndex[MAX_CONTROLLERS];
for (int i = 0; i < MAX_CONTROLLERS; ++i)
{ {
text[i].clear(); swapOptionsKeyboard();
playerControllerIndex[i] = -1; std::string text = lang::getText(100) + std::to_string(getPlayerWhoUsesKeyboard()) + ": " + lang::getText(69);
Notifier::get()->showText({text});
} }
// Obtiene para cada jugador el índice del mando correspondiente // Muestra información sobre los controles y los jugadores
for (int i = 0; i < MAX_CONTROLLERS; ++i) void Title::showControllers()
{ {
playerControllerIndex[options.controller[i].player_id - 1] = i; // Crea vectores de texto vacíos para un número máximo de mandos
constexpr size_t NUM_CONTROLLERS = 2;
std::vector<std::string> text(NUM_CONTROLLERS);
std::vector<int> playerControllerIndex(NUM_CONTROLLERS, -1);
// Obtiene de cada jugador el índice del mando que tiene asignado
for (size_t i = 0; i < NUM_CONTROLLERS; ++i)
{
// Ejemplo: el jugador 1 tiene el mando 2
playerControllerIndex.at(options.controllers.at(i).player_id - 1) = i;
} }
// Genera el texto correspondiente // Genera el texto correspondiente
for (int i = 0; i < MAX_CONTROLLERS; ++i) for (size_t i = 0; i < NUM_CONTROLLERS; ++i)
{ {
const int index = playerControllerIndex[i]; const size_t index = playerControllerIndex.at(i);
if (options.controller[index].plugged) if (options.controllers.at(index).plugged)
{ {
text[i] = lang::getText(101) + std::to_string(i + 1) + ": " + options.controller[index].name; text.at(i) = lang::getText(100) + std::to_string(i + 1) + ": " + options.controllers.at(index).name;
} }
} }
Notifier::get()->showText(text[0], text[1]); // std::string spaces(lang::getText(100).length() + 3, ' ');
// std::string kb_text = spaces + lang::getText(69);
resetCounter(); Notifier::get()->showText({text.at(0), text.at(1)});
} }

View File

@@ -2,14 +2,17 @@
#include <SDL2/SDL_stdinc.h> // Para Uint32 #include <SDL2/SDL_stdinc.h> // Para Uint32
#include <memory> // Para unique_ptr, shared_ptr #include <memory> // Para unique_ptr, shared_ptr
#include "section.h" // Para Name class DefineButtons; // lines 6-6
class DefineButtons; class Fade; // lines 7-7
class Fade; class GameLogo; // lines 8-8
class GameLogo; class Sprite; // lines 9-9
class Sprite; class Text; // lines 10-10
class Text; class Texture; // lines 11-11
class Texture; // lines 14-14 class TiledBG; // lines 12-12
class TiledBG; namespace section
{
enum class Name;
}
// Textos // Textos
constexpr const char TEXT_COPYRIGHT[] = "@2020,2024 JailDesigner"; constexpr const char TEXT_COPYRIGHT[] = "@2020,2024 JailDesigner";
@@ -74,6 +77,12 @@ private:
// Intercambia la asignación de mandos a los jugadores // Intercambia la asignación de mandos a los jugadores
void swapControllers(); void swapControllers();
// Intercambia el teclado de jugador
void swapKeyboard();
// Muestra información sobre los controles y los jugadores
void showControllers();
public: public:
// Constructor // Constructor
Title(); Title();