desacoplament de Player i Options
Player: canviat id de int a enum migrant input: eliminat Device, keyboard separat de la llista de mandos, llig i guarda configuracions de mandos falta: definir botons, asignar mandos a jugadors i guardar la asignació
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
#include "resource.h" // Para Resource
|
||||
|
||||
// Constructor
|
||||
Bullet::Bullet(float x, float y, BulletType bullet_type, bool powered, int owner)
|
||||
Bullet::Bullet(float x, float y, BulletType bullet_type, bool powered, Player::Id owner)
|
||||
: sprite_(std::make_unique<AnimatedSprite>(Resource::get()->getTexture("bullet.png"), Resource::get()->getAnimation("bullet.ani"))),
|
||||
pos_x_(x),
|
||||
pos_y_(y),
|
||||
@@ -94,7 +94,7 @@ void Bullet::disable() {
|
||||
bullet_type_ = BulletType::NONE;
|
||||
}
|
||||
|
||||
auto Bullet::getOwner() const -> int {
|
||||
auto Bullet::getOwner() const -> Player::Id {
|
||||
return owner_;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <string> // Para string
|
||||
|
||||
#include "animated_sprite.h" // Para AnimatedSprite
|
||||
#include "player.h" // Para Player
|
||||
#include "utils.h" // Para Circle
|
||||
|
||||
// Tipos de balas
|
||||
@@ -30,7 +31,7 @@ class Bullet {
|
||||
static constexpr float HEIGHT = 12.0F;
|
||||
|
||||
// Constructor y Destructor
|
||||
Bullet(float x, float y, BulletType bullet_type, bool powered, int owner);
|
||||
Bullet(float x, float y, BulletType bullet_type, bool powered, Player::Id owner);
|
||||
~Bullet() = default;
|
||||
|
||||
// Métodos principales
|
||||
@@ -42,8 +43,8 @@ class Bullet {
|
||||
void disable(); // Desactiva la bala
|
||||
|
||||
// Getters
|
||||
[[nodiscard]] auto getOwner() const -> int; // Devuelve el identificador del dueño
|
||||
auto getCollider() -> Circle &; // Devuelve el círculo de colisión
|
||||
[[nodiscard]] auto getOwner() const -> Player::Id; // Devuelve el identificador del dueño
|
||||
auto getCollider() -> Circle &; // Devuelve el círculo de colisión
|
||||
|
||||
private:
|
||||
// Constantes
|
||||
@@ -60,7 +61,7 @@ class Bullet {
|
||||
float vel_x_; // Velocidad en el eje X
|
||||
|
||||
BulletType bullet_type_; // Tipo de bala
|
||||
int owner_; // Identificador del dueño
|
||||
Player::Id owner_; // Identificador del dueño
|
||||
Circle collider_; // Círculo de colisión
|
||||
|
||||
// Métodos internos
|
||||
|
||||
@@ -19,8 +19,9 @@ DefineButtons::DefineButtons()
|
||||
|
||||
clearButtons();
|
||||
|
||||
for (int i = 0; i < input_->getNumControllers(); ++i) {
|
||||
// controller_names_.emplace_back(input_->getControllerName(i));
|
||||
auto gamepads = input_->getGamepads();
|
||||
for (auto gamepad : gamepads) {
|
||||
controller_names_.emplace_back(input_->getControllerName(gamepad));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,9 +29,9 @@ DefineButtons::DefineButtons()
|
||||
void DefineButtons::render() {
|
||||
static auto text = Resource::get()->getText("8bithud");
|
||||
if (enabled_) {
|
||||
// text->writeCentered(x_, y_ - 10, Lang::getText("[DEFINE_BUTTONS] PLAYER") + std::to_string(Options::controllers.at(index_controller_).player_id));
|
||||
// text->writeCentered(x_, y_, controller_names_.at(index_controller_));
|
||||
// text->writeCentered(x_, y_ + 10, buttons_.at(index_button_).label);
|
||||
text->writeCentered(x_, y_ - 10, Lang::getText("[DEFINE_BUTTONS] PLAYER") + std::to_string(static_cast<int>(gamepad_options_->player_id)));
|
||||
text->writeCentered(x_, y_, gamepad_options_->instance->name);
|
||||
text->writeCentered(x_, y_ + 10, buttons_.at(index_button_).label);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,15 +77,15 @@ void DefineButtons::checkEvents(const SDL_Event &event) {
|
||||
}
|
||||
|
||||
// Habilita el objeto
|
||||
auto DefineButtons::enable(int index) -> bool {
|
||||
if (index < input_->getNumControllers()) {
|
||||
auto DefineButtons::enable(std::shared_ptr<Options::Gamepad> gamepad_options) -> bool {
|
||||
if (gamepad_options != nullptr) {
|
||||
gamepad_options_ = gamepad_options;
|
||||
enabled_ = true;
|
||||
finished_ = false;
|
||||
index_button_ = 0;
|
||||
clearButtons();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <vector> // Para vector
|
||||
|
||||
#include "input.h"
|
||||
#include "options.h"
|
||||
|
||||
// Clase DefineButtons
|
||||
class DefineButtons {
|
||||
@@ -26,14 +27,14 @@ class DefineButtons {
|
||||
DefineButtons();
|
||||
~DefineButtons() = default;
|
||||
|
||||
void render(); // Dibuja el objeto en pantalla
|
||||
void checkEvents(const SDL_Event &event); // Procesa los eventos
|
||||
auto enable(int index_controller) -> bool; // Habilita la redefinición de botones
|
||||
[[nodiscard]] auto isEnabled() const -> bool { return enabled_; }; // Comprueba si está habilitado
|
||||
void render(); // Dibuja el objeto en pantalla
|
||||
void checkEvents(const SDL_Event &event); // Procesa los eventos
|
||||
auto enable(std::shared_ptr<Options::Gamepad> gamepad_options) -> bool; // Habilita la redefinición de botones
|
||||
[[nodiscard]] auto isEnabled() const -> bool { return enabled_; }; // Comprueba si está habilitado
|
||||
|
||||
private:
|
||||
// Objetos
|
||||
Input *input_ = nullptr; // Gestión de entrada
|
||||
Input *input_ = nullptr; // Gestión de entrada
|
||||
|
||||
// Variables
|
||||
bool enabled_ = false; // Indica si está activo
|
||||
@@ -42,11 +43,12 @@ class DefineButtons {
|
||||
size_t index_button_ = 0; // Índice del botón en proceso
|
||||
std::vector<std::string> controller_names_; // Nombres de los mandos
|
||||
bool finished_ = false;
|
||||
std::shared_ptr<Options::Gamepad> gamepad_options_;
|
||||
|
||||
// Métodos internos
|
||||
void incIndexButton(); // Incrementa el índice de botones
|
||||
void doControllerButtonDown(const SDL_GamepadButtonEvent &event); // Procesa pulsaciones
|
||||
void bindButtons(std::shared_ptr<Input::Gamepad> gamepad); // Asigna botones al sistema de entrada
|
||||
void bindButtons(std::shared_ptr<Input::Gamepad> gamepad); // Asigna botones al sistema de entrada
|
||||
void saveBindingsToOptions(); // Guarda configuraciones
|
||||
auto checkButtonNotInUse(SDL_GamepadButton button) -> bool; // Verifica uso de botones
|
||||
void clearButtons(); // Limpia asignaciones actuales
|
||||
|
||||
@@ -102,7 +102,7 @@ void Director::init() {
|
||||
|
||||
auto gamepads = Input::get()->getGamepads();
|
||||
if (!gamepads.empty())
|
||||
Options::controllers.front().gamepad = gamepads.front();
|
||||
Options::gamepads.front()->instance = gamepads.front();
|
||||
|
||||
ServiceMenu::init(); // Inicializa el menú de servicio
|
||||
Notifier::init(std::string(), Resource::get()->getText("8bithud")); // Inicialización del sistema de notificaciones
|
||||
@@ -543,23 +543,19 @@ void Director::runTitle() {
|
||||
|
||||
// Ejecuta la sección donde se juega al juego
|
||||
void Director::runGame() {
|
||||
int player_id = 1;
|
||||
Player::Id player_id = Player::Id::PLAYER1;
|
||||
|
||||
switch (Section::options) {
|
||||
case Section::Options::GAME_PLAY_1P:
|
||||
player_id = 1;
|
||||
player_id = Player::Id::PLAYER1;
|
||||
break;
|
||||
|
||||
case Section::Options::GAME_PLAY_2P:
|
||||
player_id = 2;
|
||||
player_id = Player::Id::PLAYER2;
|
||||
break;
|
||||
|
||||
case Section::Options::GAME_PLAY_BOTH:
|
||||
player_id = 0;
|
||||
player_id = Player::Id::BOTH_PLAYERS;
|
||||
break;
|
||||
|
||||
default:
|
||||
player_id = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -568,7 +564,7 @@ void Director::runGame() {
|
||||
#else
|
||||
constexpr int CURRENT_STAGE = 0;
|
||||
#endif
|
||||
auto game = std::make_unique<Game>(player_id, CURRENT_STAGE, GAME_MODE_DEMO_OFF);
|
||||
auto game = std::make_unique<Game>(player_id, CURRENT_STAGE, Game::DEMO_OFF);
|
||||
game->run();
|
||||
}
|
||||
|
||||
@@ -592,9 +588,9 @@ void Director::runHiScoreTable() {
|
||||
|
||||
// Ejecuta el juego en modo demo
|
||||
void Director::runDemoGame() {
|
||||
const auto PLAYER_ID = (rand() % 2) + 1;
|
||||
const auto PLAYER_ID = static_cast<Player::Id>((rand() % 2) + 1);
|
||||
constexpr auto CURRENT_STAGE = 0;
|
||||
auto game = std::make_unique<Game>(PLAYER_ID, CURRENT_STAGE, GAME_MODE_DEMO_ON);
|
||||
auto game = std::make_unique<Game>(PLAYER_ID, CURRENT_STAGE, Game::DEMO_ON);
|
||||
game->run();
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ auto Input::get() -> Input * { return Input::instance; }
|
||||
|
||||
// Constructor
|
||||
Input::Input(std::string game_controller_db_path, std::string gamepad_configs_file)
|
||||
: game_controller_db_path_(std::move(game_controller_db_path)),
|
||||
: gamepad_mappings_file_(std::move(game_controller_db_path)),
|
||||
gamepad_configs_file_(std::move(gamepad_configs_file)) {
|
||||
// Inicializa el subsistema SDL_INIT_GAMEPAD
|
||||
initSDLGamePad();
|
||||
@@ -139,7 +139,7 @@ auto Input::gameControllerFound() const -> bool { return !gamepads_.empty(); }
|
||||
auto Input::getControllerName(std::shared_ptr<Gamepad> gamepad) const -> std::string { return gamepad == nullptr ? std::string() : gamepad->name; }
|
||||
|
||||
// Obten el número de mandos conectados
|
||||
auto Input::getNumControllers() const -> int { return gamepads_.size(); }
|
||||
auto Input::getNumGamepads() const -> int { return gamepads_.size(); }
|
||||
|
||||
// Obtiene el indice del controlador a partir de un event.id
|
||||
auto Input::getJoyIndex(SDL_JoystickID id) const -> int {
|
||||
@@ -230,8 +230,8 @@ auto Input::checkAxisInput(Action input, std::shared_ptr<Gamepad> gamepad, bool
|
||||
}
|
||||
|
||||
void Input::addGamepadMappingsFromFile() {
|
||||
if (SDL_AddGamepadMappingsFromFile(game_controller_db_path_.c_str()) < 0) {
|
||||
std::cout << "Error, could not load " << game_controller_db_path_.c_str() << " file: " << SDL_GetError() << std::endl;
|
||||
if (SDL_AddGamepadMappingsFromFile(gamepad_mappings_file_.c_str()) < 0) {
|
||||
std::cout << "Error, could not load " << gamepad_mappings_file_.c_str() << " file: " << SDL_GetError() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,14 +362,13 @@ void Input::applyGamepadConfig(std::shared_ptr<Gamepad> gamepad) {
|
||||
}
|
||||
|
||||
// Buscar configuración por nombre del gamepad
|
||||
auto configIt = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(),
|
||||
[&gamepad](const GamepadConfig& config) {
|
||||
return config.name == gamepad->name;
|
||||
});
|
||||
auto configIt = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(), [&gamepad](const GamepadConfig &config) {
|
||||
return config.name == gamepad->name;
|
||||
});
|
||||
|
||||
if (configIt != gamepad_configs_.end()) {
|
||||
// Aplicar la configuración encontrada al gamepad
|
||||
for (const auto& [action, button] : configIt->bindings) {
|
||||
for (const auto &[action, button] : configIt->bindings) {
|
||||
if (gamepad->bindings.find(action) != gamepad->bindings.end()) {
|
||||
gamepad->bindings[action].button = button;
|
||||
}
|
||||
@@ -383,17 +382,16 @@ void Input::saveGamepadConfigFromGamepad(std::shared_ptr<Gamepad> gamepad) {
|
||||
}
|
||||
|
||||
// Buscar si ya existe una configuración con este nombre
|
||||
auto configIt = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(),
|
||||
[&gamepad](const GamepadConfig& config) {
|
||||
return config.name == gamepad->name;
|
||||
});
|
||||
auto configIt = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(), [&gamepad](const GamepadConfig &config) {
|
||||
return config.name == gamepad->name;
|
||||
});
|
||||
|
||||
// Crear nueva configuración desde el gamepad
|
||||
GamepadConfig newConfig(gamepad->name);
|
||||
newConfig.bindings.clear(); // Limpiar bindings por defecto
|
||||
|
||||
|
||||
// Copiar todos los bindings del gamepad
|
||||
for (const auto& [action, buttonState] : gamepad->bindings) {
|
||||
for (const auto &[action, buttonState] : gamepad->bindings) {
|
||||
newConfig.bindings[action] = buttonState.button;
|
||||
}
|
||||
|
||||
@@ -410,33 +408,31 @@ void Input::saveGamepadConfigFromGamepad(std::shared_ptr<Gamepad> gamepad) {
|
||||
}
|
||||
|
||||
// Método para establecer el archivo de configuración (opcional)
|
||||
void Input::setGamepadConfigsFile(const std::string& filename) {
|
||||
void Input::setGamepadConfigsFile(const std::string &filename) {
|
||||
gamepad_configs_file_ = filename;
|
||||
loadGamepadConfigs(); // Recargar con el nuevo archivo
|
||||
}
|
||||
|
||||
// Método para obtener configuración de un gamepad específico (opcional)
|
||||
GamepadConfig* Input::getGamepadConfig(const std::string& gamepadName) {
|
||||
auto configIt = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(),
|
||||
[&gamepadName](const GamepadConfig& config) {
|
||||
return config.name == gamepadName;
|
||||
});
|
||||
|
||||
GamepadConfig *Input::getGamepadConfig(const std::string &gamepadName) {
|
||||
auto configIt = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(), [&gamepadName](const GamepadConfig &config) {
|
||||
return config.name == gamepadName;
|
||||
});
|
||||
|
||||
return (configIt != gamepad_configs_.end()) ? &(*configIt) : nullptr;
|
||||
}
|
||||
|
||||
// Método para eliminar configuración de gamepad (opcional)
|
||||
bool Input::removeGamepadConfig(const std::string& gamepadName) {
|
||||
auto configIt = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(),
|
||||
[&gamepadName](const GamepadConfig& config) {
|
||||
return config.name == gamepadName;
|
||||
});
|
||||
|
||||
bool Input::removeGamepadConfig(const std::string &gamepadName) {
|
||||
auto configIt = std::find_if(gamepad_configs_.begin(), gamepad_configs_.end(), [&gamepadName](const GamepadConfig &config) {
|
||||
return config.name == gamepadName;
|
||||
});
|
||||
|
||||
if (configIt != gamepad_configs_.end()) {
|
||||
gamepad_configs_.erase(configIt);
|
||||
saveGamepadConfigs();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -49,54 +49,54 @@ class Input {
|
||||
};
|
||||
|
||||
struct Keyboard {
|
||||
std::unordered_map<InputAction, KeyState> bindings;
|
||||
std::unordered_map<Action, KeyState> bindings;
|
||||
|
||||
Keyboard()
|
||||
: bindings{
|
||||
// Teclado - Movimiento del jugador
|
||||
{InputAction::UP, KeyState(SDL_SCANCODE_UP)},
|
||||
{InputAction::DOWN, KeyState(SDL_SCANCODE_DOWN)},
|
||||
{InputAction::LEFT, KeyState(SDL_SCANCODE_LEFT)},
|
||||
{InputAction::RIGHT, KeyState(SDL_SCANCODE_RIGHT)},
|
||||
{Action::UP, KeyState(SDL_SCANCODE_UP)},
|
||||
{Action::DOWN, KeyState(SDL_SCANCODE_DOWN)},
|
||||
{Action::LEFT, KeyState(SDL_SCANCODE_LEFT)},
|
||||
{Action::RIGHT, KeyState(SDL_SCANCODE_RIGHT)},
|
||||
|
||||
// Teclado - Disparo del jugador
|
||||
{InputAction::FIRE_LEFT, KeyState(SDL_SCANCODE_Q)},
|
||||
{InputAction::FIRE_CENTER, KeyState(SDL_SCANCODE_W)},
|
||||
{InputAction::FIRE_RIGHT, KeyState(SDL_SCANCODE_E)},
|
||||
{Action::FIRE_LEFT, KeyState(SDL_SCANCODE_Q)},
|
||||
{Action::FIRE_CENTER, KeyState(SDL_SCANCODE_W)},
|
||||
{Action::FIRE_RIGHT, KeyState(SDL_SCANCODE_E)},
|
||||
|
||||
// Teclado - Interfaz
|
||||
{InputAction::START, KeyState(SDL_SCANCODE_RETURN)},
|
||||
{Action::START, KeyState(SDL_SCANCODE_RETURN)},
|
||||
|
||||
// Teclado - Menu de servicio
|
||||
{InputAction::SERVICE, KeyState(SDL_SCANCODE_0)},
|
||||
{InputAction::SM_SELECT, KeyState(SDL_SCANCODE_RETURN)},
|
||||
{InputAction::SM_BACK, KeyState(SDL_SCANCODE_BACKSPACE)},
|
||||
{Action::SERVICE, KeyState(SDL_SCANCODE_0)},
|
||||
{Action::SM_SELECT, KeyState(SDL_SCANCODE_RETURN)},
|
||||
{Action::SM_BACK, KeyState(SDL_SCANCODE_BACKSPACE)},
|
||||
|
||||
// Teclado - Control del programa
|
||||
{InputAction::EXIT, KeyState(SDL_SCANCODE_ESCAPE)},
|
||||
{InputAction::PAUSE, KeyState(SDL_SCANCODE_P)},
|
||||
{InputAction::BACK, KeyState(SDL_SCANCODE_BACKSPACE)},
|
||||
{Action::EXIT, KeyState(SDL_SCANCODE_ESCAPE)},
|
||||
{Action::PAUSE, KeyState(SDL_SCANCODE_P)},
|
||||
{Action::BACK, KeyState(SDL_SCANCODE_BACKSPACE)},
|
||||
|
||||
{InputAction::WINDOW_DEC_SIZE, KeyState(SDL_SCANCODE_F1)},
|
||||
{InputAction::WINDOW_INC_SIZE, KeyState(SDL_SCANCODE_F2)},
|
||||
{InputAction::WINDOW_FULLSCREEN, KeyState(SDL_SCANCODE_F3)},
|
||||
{InputAction::TOGGLE_VIDEO_SHADERS, KeyState(SDL_SCANCODE_F4)},
|
||||
{InputAction::TOGGLE_VIDEO_INTEGER_SCALE, KeyState(SDL_SCANCODE_F5)},
|
||||
{InputAction::TOGGLE_VIDEO_VSYNC, KeyState(SDL_SCANCODE_F6)},
|
||||
{Action::WINDOW_DEC_SIZE, KeyState(SDL_SCANCODE_F1)},
|
||||
{Action::WINDOW_INC_SIZE, KeyState(SDL_SCANCODE_F2)},
|
||||
{Action::WINDOW_FULLSCREEN, KeyState(SDL_SCANCODE_F3)},
|
||||
{Action::TOGGLE_VIDEO_SHADERS, KeyState(SDL_SCANCODE_F4)},
|
||||
{Action::TOGGLE_VIDEO_INTEGER_SCALE, KeyState(SDL_SCANCODE_F5)},
|
||||
{Action::TOGGLE_VIDEO_VSYNC, KeyState(SDL_SCANCODE_F6)},
|
||||
|
||||
{InputAction::TOGGLE_AUDIO, KeyState(SDL_SCANCODE_F7)},
|
||||
{InputAction::TOGGLE_AUTO_FIRE, KeyState(SDL_SCANCODE_F8)},
|
||||
{InputAction::CHANGE_LANG, KeyState(SDL_SCANCODE_F9)},
|
||||
{Action::TOGGLE_AUDIO, KeyState(SDL_SCANCODE_F7)},
|
||||
{Action::TOGGLE_AUTO_FIRE, KeyState(SDL_SCANCODE_F8)},
|
||||
{Action::CHANGE_LANG, KeyState(SDL_SCANCODE_F9)},
|
||||
|
||||
{InputAction::RESET, KeyState(SDL_SCANCODE_F10)},
|
||||
{InputAction::SHOW_INFO, KeyState(SDL_SCANCODE_F12)}} {}
|
||||
{Action::RESET, KeyState(SDL_SCANCODE_F10)},
|
||||
{Action::SHOW_INFO, KeyState(SDL_SCANCODE_F12)}} {}
|
||||
};
|
||||
|
||||
struct Gamepad {
|
||||
SDL_Gamepad *pad;
|
||||
SDL_JoystickID instance_id;
|
||||
std::string name;
|
||||
std::unordered_map<InputAction, ButtonState> bindings;
|
||||
std::unordered_map<Action, ButtonState> bindings;
|
||||
|
||||
Gamepad(SDL_Gamepad *gamepad)
|
||||
: pad(gamepad),
|
||||
@@ -104,19 +104,19 @@ class Input {
|
||||
name(std::string(SDL_GetGamepadName(gamepad))),
|
||||
bindings{
|
||||
// Mando - Movimiento del jugador
|
||||
{InputAction::UP, ButtonState(SDL_GAMEPAD_BUTTON_DPAD_UP)},
|
||||
{InputAction::DOWN, ButtonState(SDL_GAMEPAD_BUTTON_DPAD_DOWN)},
|
||||
{InputAction::LEFT, ButtonState(SDL_GAMEPAD_BUTTON_DPAD_LEFT)},
|
||||
{InputAction::RIGHT, ButtonState(SDL_GAMEPAD_BUTTON_DPAD_RIGHT)},
|
||||
{Action::UP, ButtonState(SDL_GAMEPAD_BUTTON_DPAD_UP)},
|
||||
{Action::DOWN, ButtonState(SDL_GAMEPAD_BUTTON_DPAD_DOWN)},
|
||||
{Action::LEFT, ButtonState(SDL_GAMEPAD_BUTTON_DPAD_LEFT)},
|
||||
{Action::RIGHT, ButtonState(SDL_GAMEPAD_BUTTON_DPAD_RIGHT)},
|
||||
|
||||
// Mando - Disparo del jugador
|
||||
{InputAction::FIRE_LEFT, ButtonState(SDL_GAMEPAD_BUTTON_WEST)},
|
||||
{InputAction::FIRE_CENTER, ButtonState(SDL_GAMEPAD_BUTTON_NORTH)},
|
||||
{InputAction::FIRE_RIGHT, ButtonState(SDL_GAMEPAD_BUTTON_EAST)},
|
||||
{Action::FIRE_LEFT, ButtonState(SDL_GAMEPAD_BUTTON_WEST)},
|
||||
{Action::FIRE_CENTER, ButtonState(SDL_GAMEPAD_BUTTON_NORTH)},
|
||||
{Action::FIRE_RIGHT, ButtonState(SDL_GAMEPAD_BUTTON_EAST)},
|
||||
|
||||
// Mando - Interfaz
|
||||
{InputAction::START, ButtonState(SDL_GAMEPAD_BUTTON_START)},
|
||||
{InputAction::SERVICE, ButtonState(SDL_GAMEPAD_BUTTON_BACK)}} {}
|
||||
{Action::START, ButtonState(SDL_GAMEPAD_BUTTON_START)},
|
||||
{Action::SERVICE, ButtonState(SDL_GAMEPAD_BUTTON_BACK)}} {}
|
||||
|
||||
~Gamepad() {
|
||||
if (pad) {
|
||||
@@ -125,7 +125,7 @@ class Input {
|
||||
}
|
||||
|
||||
// Reasigna un botón a una acción
|
||||
void rebindAction(InputAction action, SDL_GamepadButton new_button) {
|
||||
void rebindAction(Action action, SDL_GamepadButton new_button) {
|
||||
bindings[action] = new_button;
|
||||
}
|
||||
};
|
||||
@@ -149,7 +149,7 @@ class Input {
|
||||
// --- Métodos de gestión de mandos ---
|
||||
[[nodiscard]] auto gameControllerFound() const -> bool;
|
||||
auto getControllerName(std::shared_ptr<Gamepad> gamepad) const -> std::string;
|
||||
[[nodiscard]] auto getNumControllers() const -> int;
|
||||
[[nodiscard]] auto getNumGamepads() const -> int;
|
||||
[[nodiscard]] auto getJoyIndex(SDL_JoystickID id) const -> int;
|
||||
|
||||
// --- Métodos de consulta y utilidades ---
|
||||
@@ -175,7 +175,7 @@ class Input {
|
||||
std::vector<std::shared_ptr<Gamepad>> gamepads_;
|
||||
Keyboard keyboard_;
|
||||
std::vector<Action> button_inputs_;
|
||||
std::string game_controller_db_path_;
|
||||
std::string gamepad_mappings_file_;
|
||||
std::string gamepad_configs_file_;
|
||||
GamepadConfigs gamepad_configs_;
|
||||
|
||||
@@ -186,17 +186,17 @@ class Input {
|
||||
void remove_gamepad(SDL_JoystickID id);
|
||||
void addGamepadMappingsFromFile();
|
||||
void discoverGamepads();
|
||||
|
||||
|
||||
// --- Métodos para integración con GamepadConfigManager ---
|
||||
void loadGamepadConfigs();
|
||||
void saveGamepadConfigs();
|
||||
void applyGamepadConfig(std::shared_ptr<Gamepad> gamepad);
|
||||
void saveGamepadConfigFromGamepad(std::shared_ptr<Gamepad> gamepad);
|
||||
|
||||
|
||||
// Métodos auxiliares opcionales
|
||||
void setGamepadConfigsFile(const std::string& filename);
|
||||
GamepadConfig* getGamepadConfig(const std::string& gamepadName);
|
||||
bool removeGamepadConfig(const std::string& gamepadName);
|
||||
void setGamepadConfigsFile(const std::string &filename);
|
||||
GamepadConfig *getGamepadConfig(const std::string &gamepadName);
|
||||
bool removeGamepadConfig(const std::string &gamepadName);
|
||||
|
||||
// --- Constructor y destructor ---
|
||||
explicit Input(std::string game_controller_db_path, std::string gamepad_configs_file);
|
||||
|
||||
@@ -51,7 +51,7 @@ auto ManageHiScoreTable::add(const HiScoreEntry &entry) -> int {
|
||||
|
||||
// Si el nuevo elemento quedó fuera del top 10
|
||||
if (position >= 10) {
|
||||
position = -1; // No entró en el top 10
|
||||
position = NO_ENTRY; // No entró en el top 10
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,32 +22,29 @@ struct HiScoreEntry {
|
||||
: name(n.substr(0, 6)), score(s), one_credit_complete(occ) {}
|
||||
};
|
||||
|
||||
using Table = std::vector<HiScoreEntry>;
|
||||
|
||||
// --- Clase ManageHiScoreTable ---
|
||||
class ManageHiScoreTable {
|
||||
public:
|
||||
// Constructor
|
||||
explicit ManageHiScoreTable(std::vector<HiScoreEntry> &table)
|
||||
: table_(table) {}
|
||||
// --- Constantes ---
|
||||
static constexpr int NO_ENTRY = -1;
|
||||
|
||||
// Destructor
|
||||
// Constructor y destructor
|
||||
explicit ManageHiScoreTable(Table &table)
|
||||
: table_(table) {}
|
||||
~ManageHiScoreTable() = default;
|
||||
|
||||
// Resetea la tabla a los valores por defecto
|
||||
void clear();
|
||||
|
||||
// Añade un elemento a la tabla (devuelve la posición en la que se inserta)
|
||||
auto add(const HiScoreEntry &entry) -> int;
|
||||
|
||||
// Carga la tabla con los datos de un fichero
|
||||
auto loadFromFile(const std::string &file_path) -> bool;
|
||||
|
||||
// Guarda la tabla en un fichero
|
||||
auto saveToFile(const std::string &file_path) -> bool;
|
||||
// --- Métodos públicos ---
|
||||
void clear(); // Resetea la tabla a los valores por defecto
|
||||
auto add(const HiScoreEntry &entry) -> int; // Añade un elemento a la tabla (devuelve la posición en la que se inserta)
|
||||
auto loadFromFile(const std::string &file_path) -> bool; // Carga la tabla con los datos de un fichero
|
||||
auto saveToFile(const std::string &file_path) -> bool; // Guarda la tabla en un fichero
|
||||
|
||||
private:
|
||||
// Referencia a la tabla con los records
|
||||
std::vector<HiScoreEntry> &table_;
|
||||
// --- Variables privadas ---
|
||||
Table &table_; // Referencia a la tabla con los records
|
||||
|
||||
// Ordena la tabla internamente
|
||||
void sort();
|
||||
// --- Métodos privados ---
|
||||
void sort(); // Ordena la tabla
|
||||
};
|
||||
@@ -19,13 +19,13 @@
|
||||
|
||||
namespace Options {
|
||||
// --- Variables globales ---
|
||||
WindowOptions window; // Opciones de la ventana
|
||||
SettingsOptions settings; // Opciones del juego
|
||||
VideoOptions video; // Opciones de vídeo
|
||||
AudioOptions audio; // Opciones de audio
|
||||
std::vector<GamepadOptions> controllers; // Opciones de mando para cada jugador
|
||||
PendingChanges pending_changes; // Opciones que se aplican al cerrar
|
||||
// std::vector<GamepadConfig> gamepad_configs; // Lista con las configuraciones registradas para cada mando
|
||||
Window window; // Opciones de la ventana
|
||||
Settings settings; // Opciones del juego
|
||||
Video video; // Opciones de vídeo
|
||||
Audio audio; // Opciones de audio
|
||||
std::vector<std::shared_ptr<Gamepad>> gamepads; // Opciones de mando para cada jugador
|
||||
Keyboard keyboard; // Opciones para el teclado
|
||||
PendingChanges pending_changes; // Opciones que se aplican al cerrar
|
||||
|
||||
// Declaraciones
|
||||
auto set(const std::string& var, const std::string& value) -> bool;
|
||||
@@ -42,10 +42,10 @@ void init() {
|
||||
Difficulty::init();
|
||||
|
||||
// Opciones de control
|
||||
controllers.clear();
|
||||
controllers.emplace_back(GamepadOptions(1));
|
||||
controllers.emplace_back(GamepadOptions(2));
|
||||
setKeyboardToPlayer(1);
|
||||
gamepads.clear();
|
||||
gamepads.emplace_back(std::make_shared<Gamepad>(Player::Id::PLAYER1));
|
||||
gamepads.emplace_back(std::make_shared<Gamepad>(Player::Id::PLAYER2));
|
||||
setKeyboardToPlayer(Player::Id::PLAYER1);
|
||||
|
||||
// Opciones de cambios pendientes
|
||||
pending_changes.new_language = settings.language;
|
||||
@@ -154,15 +154,15 @@ auto saveToFile() -> bool {
|
||||
// Opciones de mandos
|
||||
file << "\n\n## CONTROLLERS\n";
|
||||
|
||||
int controller_index = 0;
|
||||
for (const auto& controller : controllers) {
|
||||
file << "\n";
|
||||
file << "controller." << controller_index << ".name=" << controller.name << "\n";
|
||||
file << "controller." << controller_index << ".player=" << controller.player_id << "\n";
|
||||
|
||||
// Incrementa el índice
|
||||
++controller_index;
|
||||
}
|
||||
// int controller_index = 0;
|
||||
// for (const auto& controller : gamepads) {
|
||||
// file << "\n";
|
||||
// file << "controller." << controller_index << ".name=" << controller->name << "\n";
|
||||
// file << "controller." << controller_index << ".player=" << controller->player_id << "\n";
|
||||
//
|
||||
// // Incrementa el índice
|
||||
// ++controller_index;
|
||||
// }
|
||||
|
||||
// Cierra el fichero
|
||||
file.close();
|
||||
@@ -173,19 +173,19 @@ auto saveToFile() -> bool {
|
||||
// Función auxiliar para analizar la configuración del mando y reducir duplicación
|
||||
void parseAndSetController(const std::string& var, const std::string& value) {
|
||||
// Lógica básica de análisis (puede hacerse más robusta)
|
||||
size_t first_dot = var.find('.');
|
||||
size_t second_dot = var.find('.', first_dot + 1);
|
||||
|
||||
int controller_index = std::stoi(var.substr(first_dot + 1, second_dot - first_dot - 1));
|
||||
std::string setting_key = var.substr(second_dot + 1);
|
||||
|
||||
auto& controller = controllers.at(controller_index);
|
||||
|
||||
if (setting_key == "name") {
|
||||
controller.name = value;
|
||||
} else if (setting_key == "player") {
|
||||
controller.player_id = std::clamp(std::stoi(value), 1, 2);
|
||||
}
|
||||
// size_t first_dot = var.find('.');
|
||||
// size_t second_dot = var.find('.', first_dot + 1);
|
||||
//
|
||||
// int controller_index = std::stoi(var.substr(first_dot + 1, second_dot - first_dot - 1));
|
||||
// std::string setting_key = var.substr(second_dot + 1);
|
||||
//
|
||||
// auto& controller = gamepads.at(controller_index);
|
||||
//
|
||||
// if (setting_key == "name") {
|
||||
// controller.name = value;
|
||||
// } else if (setting_key == "player") {
|
||||
// controller.player_id = std::clamp(std::stoi(value), 1, 2);
|
||||
// }
|
||||
}
|
||||
|
||||
auto set(const std::string& var, const std::string& value) -> bool {
|
||||
@@ -254,35 +254,23 @@ auto set(const std::string& var, const std::string& value) -> bool {
|
||||
}
|
||||
|
||||
// Asigna el teclado al jugador
|
||||
void setKeyboardToPlayer(int player_id) {
|
||||
for (auto& controller : controllers) {
|
||||
if (controller.player_id == player_id) {
|
||||
// controller.type = Input::Device::ANY;
|
||||
} else {
|
||||
// controller.type = Input::Device::CONTROLLER;
|
||||
}
|
||||
}
|
||||
void setKeyboardToPlayer(Player::Id player_id) {
|
||||
keyboard.player_id = player_id;
|
||||
}
|
||||
|
||||
// Intercambia el teclado de jugador
|
||||
void swapKeyboard() {
|
||||
// std::swap(controllers.at(0).type, controllers.at(1).type);
|
||||
keyboard.player_id = keyboard.player_id == Player::Id::PLAYER1 ? Player::Id::PLAYER2 : Player::Id::PLAYER1;
|
||||
}
|
||||
|
||||
// Intercambia los jugadores asignados a los dos primeros mandos
|
||||
void swapControllers() {
|
||||
std::swap(controllers.at(0).player_id, controllers.at(1).player_id);
|
||||
// std::swap(controllers.at(0).type, controllers.at(1).type);
|
||||
std::swap(gamepads.at(0)->player_id, gamepads.at(1)->player_id);
|
||||
}
|
||||
|
||||
// Averigua quien está usando el teclado
|
||||
auto getPlayerWhoUsesKeyboard() -> int {
|
||||
// for (const auto& controller : controllers) {
|
||||
// if (controller.type == Input::Device::ANY) {
|
||||
// return controller.player_id;
|
||||
// }
|
||||
//}
|
||||
return 0;
|
||||
auto getPlayerWhoUsesKeyboard() -> Player::Id {
|
||||
return keyboard.player_id;
|
||||
}
|
||||
|
||||
// Aplica los cambios pendientes copiando los valores a sus variables
|
||||
|
||||
@@ -8,28 +8,26 @@
|
||||
#include <unordered_map>
|
||||
#include <vector> // Para vector
|
||||
|
||||
#include "difficulty.h" // Para Code
|
||||
// #include "gamepad_config_manager.h"
|
||||
#include "difficulty.h" // Para Code
|
||||
#include "input.h" // Para InputAction, InputDevice
|
||||
#include "lang.h" // Para Code
|
||||
#include "manage_hiscore_table.h" // Para HiScoreEntry
|
||||
|
||||
static constexpr int INVALID_INDEX = -1;
|
||||
#include "player.h" // Para Player
|
||||
|
||||
namespace Options {
|
||||
// --- Opciones de ventana ---
|
||||
struct WindowOptions {
|
||||
struct Window {
|
||||
std::string caption; // Texto que aparece en la barra de título de la ventana
|
||||
int zoom{2}; // Valor por el que se multiplica el tamaño de la ventana
|
||||
int max_zoom{2}; // Tamaño máximo para que la ventana no sea mayor que la pantalla
|
||||
|
||||
// Constructor por defecto con valores iniciales
|
||||
WindowOptions()
|
||||
Window()
|
||||
: caption("Coffee Crisis Arcade Edition") {}
|
||||
};
|
||||
|
||||
// --- Opciones de vídeo ---
|
||||
struct VideoOptions {
|
||||
struct Video {
|
||||
SDL_ScaleMode scale_mode{SDL_ScaleMode::SDL_SCALEMODE_NEAREST}; // Filtro usado para el escalado de la imagen
|
||||
bool fullscreen{false}; // Indica si se usa pantalla completa
|
||||
bool vsync{true}; // Indica si se usa vsync
|
||||
@@ -38,69 +36,73 @@ struct VideoOptions {
|
||||
std::string info; // Información sobre el modo de vídeo
|
||||
|
||||
// Constructor por defecto con valores iniciales
|
||||
VideoOptions() = default;
|
||||
Video() = default;
|
||||
};
|
||||
|
||||
// --- Opciones de música ---
|
||||
struct MusicOptions {
|
||||
struct Music {
|
||||
bool enabled{true}; // Indica si la música suena o no
|
||||
int volume{100}; // Volumen de la música
|
||||
|
||||
// Constructor por defecto
|
||||
MusicOptions() = default;
|
||||
Music() = default;
|
||||
};
|
||||
|
||||
// --- Opciones de sonido ---
|
||||
struct SoundOptions {
|
||||
struct Sound {
|
||||
bool enabled{true}; // Indica si los sonidos suenan o no
|
||||
int volume{100}; // Volumen de los sonidos
|
||||
|
||||
// Constructor por defecto
|
||||
SoundOptions() = default;
|
||||
Sound() = default;
|
||||
};
|
||||
|
||||
// --- Opciones de audio ---
|
||||
struct AudioOptions {
|
||||
MusicOptions music; // Opciones para la música
|
||||
SoundOptions sound; // Opciones para los efectos de sonido
|
||||
struct Audio {
|
||||
Music music; // Opciones para la música
|
||||
Sound sound; // Opciones para los efectos de sonido
|
||||
bool enabled{true}; // Indica si el audio está activo o no
|
||||
int volume{100}; // Volumen general del audio
|
||||
|
||||
// Constructor por defecto
|
||||
AudioOptions() = default;
|
||||
Audio() = default;
|
||||
};
|
||||
|
||||
// --- Opciones de configuración ---
|
||||
struct SettingsOptions {
|
||||
struct Settings {
|
||||
Difficulty::Code difficulty{Difficulty::Code::NORMAL}; // Dificultad del juego
|
||||
Lang::Code language{Lang::Code::VALENCIAN}; // Idioma usado en el juego
|
||||
bool autofire{true}; // Indicador de autofire
|
||||
bool shutdown_enabled{false}; // Especifica si se puede apagar el sistema
|
||||
std::vector<HiScoreEntry> hi_score_table; // Tabla de mejores puntuaciones
|
||||
std::vector<int> last_hi_score_entry; // Últimas posiciones de entrada en la tabla
|
||||
Table hi_score_table; // Tabla de mejores puntuaciones
|
||||
std::vector<int> glowing_entries; // Últimas posiciones de entrada en la tabla
|
||||
std::string config_file; // Ruta al fichero donde guardar la configuración y las opciones del juego
|
||||
std::string controllers_file; // Ruta al fichero con las configuraciones de los mandos
|
||||
|
||||
// Constructor por defecto con valores iniciales
|
||||
SettingsOptions()
|
||||
: last_hi_score_entry({INVALID_INDEX, INVALID_INDEX}) {}
|
||||
Settings()
|
||||
: glowing_entries({ManageHiScoreTable::NO_ENTRY, ManageHiScoreTable::NO_ENTRY}) {}
|
||||
|
||||
// Reinicia las últimas entradas de puntuación
|
||||
void clearLastHiScoreEntries() {
|
||||
last_hi_score_entry.at(0) = INVALID_INDEX;
|
||||
last_hi_score_entry.at(1) = INVALID_INDEX;
|
||||
glowing_entries.at(0) = ManageHiScoreTable::NO_ENTRY;
|
||||
glowing_entries.at(1) = ManageHiScoreTable::NO_ENTRY;
|
||||
}
|
||||
};
|
||||
|
||||
struct GamepadOptions {
|
||||
std::shared_ptr<Input::Gamepad> gamepad = nullptr; // Referencia al mando
|
||||
std::string name; // Nombre del mando
|
||||
int player_id; // Jugador asociado al mando
|
||||
struct Gamepad {
|
||||
std::shared_ptr<Input::Gamepad> instance = nullptr; // Referencia al mando
|
||||
std::string name; // Nombre del mando
|
||||
Player::Id player_id; // Jugador asociado al mando
|
||||
|
||||
GamepadOptions(int custom_player_id = INVALID_INDEX)
|
||||
Gamepad(Player::Id custom_player_id = Player::Id::NO_PLAYER)
|
||||
: player_id(custom_player_id) {}
|
||||
};
|
||||
|
||||
struct Keyboard {
|
||||
Player::Id player_id = Player::Id::PLAYER1; // Jugador asociado al teclado
|
||||
};
|
||||
|
||||
// --- Opciones pendientes de aplicar ---
|
||||
struct PendingChanges {
|
||||
Lang::Code new_language{Lang::Code::VALENCIAN}; // Idioma en espera de aplicar
|
||||
@@ -112,12 +114,13 @@ struct PendingChanges {
|
||||
};
|
||||
|
||||
// --- Variables globales ---
|
||||
extern WindowOptions window; // Opciones de la ventana
|
||||
extern SettingsOptions settings; // Opciones del juego
|
||||
extern VideoOptions video; // Opciones de vídeo
|
||||
extern AudioOptions audio; // Opciones de audio
|
||||
extern std::vector<GamepadOptions> controllers; // Opciones de mando para cada jugador
|
||||
extern PendingChanges pending_changes; // Opciones que se aplican al cerrar
|
||||
extern Window window; // Opciones de la ventana
|
||||
extern Settings settings; // Opciones del juego
|
||||
extern Video video; // Opciones de vídeo
|
||||
extern Audio audio; // Opciones de audio
|
||||
extern std::vector<std::shared_ptr<Gamepad>> gamepads; // Opciones de mando para cada jugador
|
||||
extern Keyboard keyboard; // Opciones para el teclado
|
||||
extern PendingChanges pending_changes; // Opciones que se aplican al cerrar
|
||||
|
||||
// --- Funciones de configuración ---
|
||||
void init(); // Inicializa las opciones del programa
|
||||
@@ -125,10 +128,10 @@ void setConfigFile(const std::string &file_path); // Establece el fichero
|
||||
void setControllersFile(const std::string &file_path); // Establece el fichero de configuración de mandos
|
||||
auto loadFromFile() -> bool; // Carga el fichero de configuración
|
||||
auto saveToFile() -> bool; // Guarda el fichero de configuración
|
||||
void setKeyboardToPlayer(int player_id); // Asigna el teclado al jugador
|
||||
void setKeyboardToPlayer(Player::Id player_id); // Asigna el teclado al jugador
|
||||
void swapKeyboard(); // Intercambia el teclado de jugador
|
||||
void swapControllers(); // Intercambia los jugadores asignados a los dos primeros mandos
|
||||
auto getPlayerWhoUsesKeyboard() -> int; // Averigua quién está usando el teclado
|
||||
auto getPlayerWhoUsesKeyboard() -> Player::Id; // Averigua quién está usando el teclado
|
||||
void applyPendingChanges(); // Aplica los cambios pendientes copiando los valores a sus variables
|
||||
void checkPendingChanges(); // Verifica si hay cambios pendientes
|
||||
|
||||
|
||||
@@ -16,20 +16,22 @@
|
||||
#include "texture.h" // Para Texture
|
||||
|
||||
// Constructor
|
||||
Player::Player(int id, float x, int y, bool demo, SDL_FRect &play_area, std::vector<std::shared_ptr<Texture>> texture, const std::vector<std::vector<std::string>> &animations)
|
||||
: player_sprite_(std::make_unique<AnimatedSprite>(texture.at(0), animations.at(0))),
|
||||
power_sprite_(std::make_unique<AnimatedSprite>(texture.at(1), animations.at(1))),
|
||||
Player::Player(const Config& config)
|
||||
: player_sprite_(std::make_unique<AnimatedSprite>(config.texture.at(0), config.animations.at(0))),
|
||||
power_sprite_(std::make_unique<AnimatedSprite>(config.texture.at(1), config.animations.at(1))),
|
||||
enter_name_(std::make_unique<EnterName>()),
|
||||
id_(id),
|
||||
play_area_(play_area),
|
||||
default_pos_x_(x),
|
||||
default_pos_y_(y),
|
||||
demo_(demo) {
|
||||
id_(config.id),
|
||||
play_area_(*config.play_area),
|
||||
default_pos_x_(config.x),
|
||||
default_pos_y_(config.y),
|
||||
hi_score_table_(*config.hi_score_table),
|
||||
glowing_entry_(*config.glowing_entry),
|
||||
demo_(config.demo) {
|
||||
// Configura objetos
|
||||
player_sprite_->getTexture()->setPalette(coffees_);
|
||||
power_sprite_->getTexture()->setAlpha(224);
|
||||
power_up_x_offset_ = (power_sprite_->getWidth() - player_sprite_->getWidth()) / 2;
|
||||
power_sprite_->setPosY(y - (power_sprite_->getHeight() - player_sprite_->getHeight()));
|
||||
power_sprite_->setPosY(default_pos_y_ - (power_sprite_->getHeight() - player_sprite_->getHeight()));
|
||||
|
||||
// Inicializa variables
|
||||
pos_x_ = default_pos_x_;
|
||||
@@ -219,8 +221,8 @@ void Player::handleRollingGroundCollision() {
|
||||
}
|
||||
|
||||
void Player::handleRollingStop() {
|
||||
const auto NEXT_PLAYER_STATUS = isEligibleForHighScore() ? State::ENTERING_NAME : State::CONTINUE;
|
||||
const auto NEXT_STATE = demo_ ? State::LYING_ON_THE_FLOOR_FOREVER : NEXT_PLAYER_STATUS;
|
||||
const auto NEXT_PLAYER_STATE = qualifiesForHighScore() ? State::ENTERING_NAME : State::CONTINUE;
|
||||
const auto NEXT_STATE = demo_ ? State::LYING_ON_THE_FLOOR_FOREVER : NEXT_PLAYER_STATE;
|
||||
|
||||
setPlayingState(NEXT_STATE);
|
||||
pos_x_ = player_sprite_->getPosX();
|
||||
@@ -278,10 +280,15 @@ void Player::handleLeavingScreen() {
|
||||
void Player::handleEnteringScreen() {
|
||||
updateStepCounter();
|
||||
|
||||
if (id_ == 1) {
|
||||
handlePlayer1Entering();
|
||||
} else if (id_ == 2) {
|
||||
handlePlayer2Entering();
|
||||
switch (id_) {
|
||||
case Id::PLAYER1:
|
||||
handlePlayer1Entering();
|
||||
break;
|
||||
case Id::PLAYER2:
|
||||
handlePlayer2Entering();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
shiftSprite();
|
||||
@@ -350,10 +357,10 @@ void Player::updateWalkingStateForCredits() {
|
||||
|
||||
void Player::setInputBasedOnPlayerId() {
|
||||
switch (id_) {
|
||||
case 1:
|
||||
case Id::PLAYER1:
|
||||
setInputPlaying(Input::Action::LEFT);
|
||||
break;
|
||||
case 2:
|
||||
case Id::PLAYER2:
|
||||
setInputPlaying(Input::Action::RIGHT);
|
||||
break;
|
||||
default:
|
||||
@@ -552,9 +559,10 @@ void Player::update() {
|
||||
}
|
||||
|
||||
// Incrementa la puntuación del jugador
|
||||
void Player::addScore(int score) {
|
||||
void Player::addScore(int score, int last_hi_score_entry) {
|
||||
if (isPlaying()) {
|
||||
score_ += score;
|
||||
qualifies_for_high_score_ = score_ > last_hi_score_entry;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -611,10 +619,10 @@ void Player::setPlayingState(State state) {
|
||||
}
|
||||
case State::WAITING: {
|
||||
switch (id_) {
|
||||
case 1:
|
||||
case Id::PLAYER1:
|
||||
pos_x_ = param.game.game_area.rect.x;
|
||||
break;
|
||||
case 2:
|
||||
case Id::PLAYER2:
|
||||
pos_x_ = param.game.game_area.rect.w - WIDTH;
|
||||
break;
|
||||
default:
|
||||
@@ -698,11 +706,11 @@ void Player::setPlayingState(State state) {
|
||||
step_counter_ = 0;
|
||||
setScoreboardMode(Scoreboard::Mode::SCORE);
|
||||
switch (id_) {
|
||||
case 1:
|
||||
case Id::PLAYER1:
|
||||
pos_x_ = param.game.game_area.rect.x - WIDTH;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case Id::PLAYER2:
|
||||
pos_x_ = param.game.game_area.rect.x + param.game.game_area.rect.w;
|
||||
break;
|
||||
|
||||
@@ -898,7 +906,7 @@ auto Player::isRenderable() const -> bool {
|
||||
// Añade una puntuación a la tabla de records
|
||||
void Player::addScoreToScoreBoard() const {
|
||||
const auto ENTRY = HiScoreEntry(trim(getLastEnterName()), getScore(), get1CC());
|
||||
auto manager = std::make_unique<ManageHiScoreTable>(Options::settings.hi_score_table);
|
||||
Options::settings.last_hi_score_entry.at(getId() - 1) = manager->add(ENTRY);
|
||||
auto manager = std::make_unique<ManageHiScoreTable>(hi_score_table_);
|
||||
glowing_entry_ = manager->add(ENTRY);
|
||||
manager->saveToFile(Asset::get()->get("score.bin"));
|
||||
}
|
||||
@@ -10,7 +10,6 @@
|
||||
#include "enter_name.h" // Para EnterName
|
||||
#include "input.h"
|
||||
#include "manage_hiscore_table.h" // Para HiScoreEntry
|
||||
#include "options.h" // Para SettingsOptions, settings
|
||||
#include "scoreboard.h" // Para Scoreboard
|
||||
#include "utils.h" // Para Circle
|
||||
|
||||
@@ -25,6 +24,14 @@ class Player {
|
||||
static constexpr int WIDTH = 32; // Anchura
|
||||
static constexpr int HEIGHT = 32; // Altura
|
||||
|
||||
// --- Id para los jugadores ---
|
||||
enum class Id : int {
|
||||
NO_PLAYER = -1,
|
||||
BOTH_PLAYERS = 0,
|
||||
PLAYER1 = 1,
|
||||
PLAYER2 = 2
|
||||
};
|
||||
|
||||
// --- Estados posibles del jugador ---
|
||||
enum class State {
|
||||
// Estados de movimiento
|
||||
@@ -68,8 +75,20 @@ class Player {
|
||||
RESPAWNING, // Tras continuar y volver al juego
|
||||
};
|
||||
|
||||
struct Config {
|
||||
Id id;
|
||||
float x;
|
||||
int y;
|
||||
bool demo;
|
||||
SDL_FRect *play_area; // Usamos puntero para mantener la referencia
|
||||
std::vector<std::shared_ptr<Texture>> texture;
|
||||
std::vector<std::vector<std::string>> animations;
|
||||
Table *hi_score_table; // También como puntero para referencia
|
||||
int *glowing_entry; // Puntero para mantener la referencia
|
||||
};
|
||||
|
||||
// --- Constructor y destructor ---
|
||||
Player(int id, float x, int y, bool demo, SDL_FRect &play_area, std::vector<std::shared_ptr<Texture>> texture, const std::vector<std::vector<std::string>> &animations);
|
||||
Player(const Config& config);
|
||||
~Player() = default;
|
||||
|
||||
// --- Inicialización y ciclo de vida ---
|
||||
@@ -93,9 +112,9 @@ class Player {
|
||||
void updateCooldown(); // Actualiza el cooldown de disparo
|
||||
|
||||
// --- Puntuación y marcador ---
|
||||
void addScore(int score); // Añade puntos
|
||||
void incScoreMultiplier(); // Incrementa el multiplicador
|
||||
void decScoreMultiplier(); // Decrementa el multiplicador
|
||||
void addScore(int score, int last_hi_score_entry); // Añade puntos
|
||||
void incScoreMultiplier(); // Incrementa el multiplicador
|
||||
void decScoreMultiplier(); // Decrementa el multiplicador
|
||||
|
||||
// --- Estados de juego ---
|
||||
void setPlayingState(State state); // Cambia el estado de juego
|
||||
@@ -128,7 +147,7 @@ class Player {
|
||||
[[nodiscard]] auto hasExtraHit() const -> bool { return extra_hit_; }
|
||||
[[nodiscard]] auto isCooling() const -> bool { return firing_state_ == State::COOLING_LEFT || firing_state_ == State::COOLING_UP || firing_state_ == State::COOLING_RIGHT; }
|
||||
[[nodiscard]] auto isRecoiling() const -> bool { return firing_state_ == State::RECOILING_LEFT || firing_state_ == State::RECOILING_UP || firing_state_ == State::RECOILING_RIGHT; }
|
||||
[[nodiscard]] auto isEligibleForHighScore() const -> bool { return score_ > Options::settings.hi_score_table.back().score; }
|
||||
[[nodiscard]] auto qualifiesForHighScore() const -> bool { return qualifies_for_high_score_; }
|
||||
[[nodiscard]] auto isInvulnerable() const -> bool { return invulnerable_; }
|
||||
[[nodiscard]] auto isPowerUp() const -> bool { return power_up_; }
|
||||
auto getCollider() -> Circle & { return collider_; }
|
||||
@@ -137,7 +156,7 @@ class Player {
|
||||
[[nodiscard]] auto getContinueCounter() const -> int { return continue_counter_; }
|
||||
[[nodiscard]] auto getController() const -> int { return controller_index_; }
|
||||
[[nodiscard]] static auto getHeight() -> int { return HEIGHT; }
|
||||
[[nodiscard]] auto getId() const -> int { return id_; }
|
||||
[[nodiscard]] auto getId() const -> Player::Id { return id_; }
|
||||
[[nodiscard]] auto getInvulnerableCounter() const -> int { return invulnerable_counter_; }
|
||||
[[nodiscard]] auto getPosX() const -> int { return static_cast<int>(pos_x_); }
|
||||
[[nodiscard]] auto getPosY() const -> int { return pos_y_; }
|
||||
@@ -165,11 +184,13 @@ class Player {
|
||||
void setWalkingState(State state) { walking_state_ = state; }
|
||||
void addCredit() { ++credits_used_; }
|
||||
|
||||
// Setter y getter para gamepad_
|
||||
void setGamepad(std::shared_ptr<Input::Gamepad> gamepad) { gamepad_ = gamepad; }
|
||||
[[nodiscard]] std::shared_ptr<Input::Gamepad> getGamepad() const { return gamepad_; }
|
||||
void setUsesKeyboard(bool value) { uses_keyboard_ = value; }
|
||||
[[nodiscard]] bool getUsesKeyboard() const { return uses_keyboard_; }
|
||||
void setHiScoreTable(const Table &table) { hi_score_table_ = table; }
|
||||
const Table &getHiScoreTable() const { return hi_score_table_; }
|
||||
void setGlowingEntry(const int &entry) { glowing_entry_ = entry; }
|
||||
|
||||
private:
|
||||
// --- Constantes ---
|
||||
@@ -186,7 +207,7 @@ class Player {
|
||||
std::unique_ptr<EnterName> enter_name_; // Clase utilizada para introducir el nombre
|
||||
|
||||
// --- Variables de estado ---
|
||||
int id_; // Número de identificación para el jugador. Player1 = 1, Player2 = 2
|
||||
Id id_; // Identificador para el jugador
|
||||
SDL_FRect play_area_; // Rectángulo con la zona de juego
|
||||
float pos_x_ = 0.0F; // Posición en el eje X
|
||||
int pos_y_ = 0; // Posición en el eje Y
|
||||
@@ -200,6 +221,9 @@ class Player {
|
||||
int cooling_state_counter_ = 0; // Contador para la animación del estado cooling
|
||||
int score_ = 0; // Puntos del jugador
|
||||
float score_multiplier_ = 1.0F; // Multiplicador de puntos
|
||||
bool qualifies_for_high_score_ = false; // Indica si tiene una puntuación que le permite entrar en la tabla de records
|
||||
Table &hi_score_table_; // Tabla de maximas puntuaciones
|
||||
int &glowing_entry_; // Entrada de la tabla de puntuaciones para hacerla brillar
|
||||
State walking_state_ = State::WALKING_STOP; // Estado del jugador al moverse
|
||||
State firing_state_ = State::FIRING_NONE; // Estado del jugador al disparar
|
||||
State playing_state_ = State::WAITING; // Estado del jugador en el juego
|
||||
|
||||
@@ -353,11 +353,32 @@ void Credits::initPlayers() {
|
||||
const int Y = play_area_.y + play_area_.h - PLAYER_WIDTH;
|
||||
constexpr bool DEMO = false;
|
||||
constexpr int AWAY_DISTANCE = 700;
|
||||
players_.emplace_back(std::make_unique<Player>(1, play_area_.x - AWAY_DISTANCE - PLAYER_WIDTH, Y, DEMO, play_area_, player_textures.at(0), player_animations));
|
||||
|
||||
Player::Config config_player1;
|
||||
config_player1.id = Player::Id::PLAYER1;
|
||||
config_player1.x = play_area_.x - AWAY_DISTANCE - PLAYER_WIDTH;
|
||||
config_player1.y = Y;
|
||||
config_player1.demo = DEMO;
|
||||
config_player1.play_area = &play_area_;
|
||||
config_player1.texture = player_textures.at(0);
|
||||
config_player1.animations = player_animations;
|
||||
config_player1.hi_score_table = &Options::settings.hi_score_table;
|
||||
config_player1.glowing_entry = &Options::settings.glowing_entries.at(static_cast<int>(Player::Id::PLAYER1) - 1);
|
||||
players_.emplace_back(std::make_unique<Player>(config_player1));
|
||||
players_.back()->setWalkingState(Player::State::WALKING_RIGHT);
|
||||
players_.back()->setPlayingState(Player::State::CREDITS);
|
||||
|
||||
players_.emplace_back(std::make_unique<Player>(2, play_area_.x + play_area_.w + AWAY_DISTANCE, Y, DEMO, play_area_, player_textures.at(1), player_animations));
|
||||
Player::Config config_player2;
|
||||
config_player2.id = Player::Id::PLAYER2;
|
||||
config_player2.x = play_area_.x + play_area_.w + AWAY_DISTANCE;
|
||||
config_player2.y = Y;
|
||||
config_player2.demo = DEMO;
|
||||
config_player2.play_area = &play_area_;
|
||||
config_player2.texture = player_textures.at(1);
|
||||
config_player2.animations = player_animations;
|
||||
config_player2.hi_score_table = &Options::settings.hi_score_table;
|
||||
config_player2.glowing_entry = &Options::settings.glowing_entries.at(static_cast<int>(Player::Id::PLAYER2) - 1);
|
||||
players_.emplace_back(std::make_unique<Player>(config_player2));
|
||||
players_.back()->setWalkingState(Player::State::WALKING_LEFT);
|
||||
players_.back()->setPlayingState(Player::State::CREDITS);
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
#include "ui/service_menu.h" // Para ServiceMenu
|
||||
|
||||
// Constructor
|
||||
Game::Game(int player_id, int current_stage, bool demo)
|
||||
Game::Game(Player::Id player_id, int current_stage, bool demo)
|
||||
: renderer_(Screen::get()->getRenderer()),
|
||||
screen_(Screen::get()),
|
||||
input_(Input::get()),
|
||||
@@ -365,7 +365,7 @@ void Game::updateGameStateCompleted() {
|
||||
|
||||
for (auto &player : players_) {
|
||||
if (player->isPlaying()) {
|
||||
player->addScore(1000000);
|
||||
player->addScore(1000000, Options::settings.hi_score_table.back().score);
|
||||
player->setPlayingState(Player::State::CELEBRATING);
|
||||
} else {
|
||||
player->setPlayingState(Player::State::GAME_OVER);
|
||||
@@ -379,7 +379,7 @@ void Game::updateGameStateCompleted() {
|
||||
if (game_completed_counter_ == END_CELEBRATIONS) {
|
||||
for (auto &player : players_) {
|
||||
if (player->isCelebrating()) {
|
||||
player->setPlayingState(player->isEligibleForHighScore() ? Player::State::ENTERING_NAME_GAME_COMPLETED : Player::State::LEAVING_SCREEN);
|
||||
player->setPlayingState(player->qualifiesForHighScore() ? Player::State::ENTERING_NAME_GAME_COMPLETED : Player::State::LEAVING_SCREEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -435,28 +435,28 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player) {
|
||||
if (checkCollision(player->getCollider(), item->getCollider())) {
|
||||
switch (item->getType()) {
|
||||
case ItemType::DISK: {
|
||||
player->addScore(1000);
|
||||
player->addScore(1000, Options::settings.hi_score_table.back().score);
|
||||
const auto X = item->getPosX() + (item->getWidth() - game_text_textures_.at(0)->getWidth()) / 2;
|
||||
createItemText(X, game_text_textures_.at(0));
|
||||
playSound("item_pickup.wav");
|
||||
break;
|
||||
}
|
||||
case ItemType::GAVINA: {
|
||||
player->addScore(2500);
|
||||
player->addScore(2500, Options::settings.hi_score_table.back().score);
|
||||
const auto X = item->getPosX() + (item->getWidth() - game_text_textures_.at(1)->getWidth()) / 2;
|
||||
createItemText(X, game_text_textures_.at(1));
|
||||
playSound("item_pickup.wav");
|
||||
break;
|
||||
}
|
||||
case ItemType::PACMAR: {
|
||||
player->addScore(5000);
|
||||
player->addScore(5000, Options::settings.hi_score_table.back().score);
|
||||
const auto X = item->getPosX() + (item->getWidth() - game_text_textures_.at(2)->getWidth()) / 2;
|
||||
createItemText(X, game_text_textures_.at(2));
|
||||
playSound("item_pickup.wav");
|
||||
break;
|
||||
}
|
||||
case ItemType::DEBIAN: {
|
||||
player->addScore(100000);
|
||||
player->addScore(100000, Options::settings.hi_score_table.back().score);
|
||||
const auto X = item->getPosX() + (item->getWidth() - game_text_textures_.at(6)->getWidth()) / 2;
|
||||
createItemText(X, game_text_textures_.at(6));
|
||||
playSound("debian_pickup.wav");
|
||||
@@ -471,7 +471,7 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player) {
|
||||
}
|
||||
case ItemType::COFFEE: {
|
||||
if (player->getCoffees() == 2) {
|
||||
player->addScore(5000);
|
||||
player->addScore(5000, Options::settings.hi_score_table.back().score);
|
||||
const auto X = item->getPosX() + (item->getWidth() - game_text_textures_.at(2)->getWidth()) / 2;
|
||||
createItemText(X, game_text_textures_.at(2));
|
||||
} else {
|
||||
@@ -594,11 +594,11 @@ void Game::handleItemDrop(std::shared_ptr<Balloon> balloon, std::shared_ptr<Play
|
||||
|
||||
// Maneja la destrucción del globo y puntuación
|
||||
void Game::handleBalloonDestruction(std::shared_ptr<Balloon> balloon, std::shared_ptr<Player> player) {
|
||||
const auto SCORE = balloon_manager_->popBalloon(balloon);
|
||||
evaluateAndSetMenace();
|
||||
|
||||
if (player->isPlaying()) {
|
||||
player->addScore(SCORE * player->getScoreMultiplier() * difficulty_score_multiplier_);
|
||||
auto const SCORE = balloon_manager_->popBalloon(balloon) * player->getScoreMultiplier() * difficulty_score_multiplier_;
|
||||
player->addScore(SCORE, Options::settings.hi_score_table.back().score);
|
||||
player->incScoreMultiplier();
|
||||
}
|
||||
updateHiScore();
|
||||
@@ -621,7 +621,7 @@ void Game::renderBullets() {
|
||||
}
|
||||
|
||||
// Crea un objeto bala
|
||||
void Game::createBullet(int x, int y, BulletType kind, bool powered_up, int owner) {
|
||||
void Game::createBullet(int x, int y, BulletType kind, bool powered_up, Player::Id owner) {
|
||||
bullets_.emplace_back(std::make_shared<Bullet>(x, y, kind, powered_up, owner));
|
||||
}
|
||||
|
||||
@@ -1174,7 +1174,7 @@ void Game::pause(bool value) {
|
||||
void Game::addScoreToScoreBoard(const std::shared_ptr<Player> &player) {
|
||||
const auto ENTRY = HiScoreEntry(trim(player->getLastEnterName()), player->getScore(), player->get1CC());
|
||||
auto manager = std::make_unique<ManageHiScoreTable>(Options::settings.hi_score_table);
|
||||
Options::settings.last_hi_score_entry.at(player->getId() - 1) = manager->add(ENTRY);
|
||||
Options::settings.glowing_entries.at(static_cast<int>(player->getId()) - 1) = manager->add(ENTRY);
|
||||
manager->saveToFile(Asset::get()->get("score.bin"));
|
||||
hi_score_.name = Options::settings.hi_score_table.front().name;
|
||||
}
|
||||
@@ -1206,7 +1206,7 @@ void Game::checkPlayersStatusPlaying() {
|
||||
}
|
||||
|
||||
// Obtiene un jugador a partir de su "id"
|
||||
auto Game::getPlayer(int id) -> std::shared_ptr<Player> {
|
||||
auto Game::getPlayer(Player::Id id) -> std::shared_ptr<Player> {
|
||||
auto it = std::find_if(players_.begin(), players_.end(), [id](const auto &player) { return player->getId() == id; });
|
||||
|
||||
if (it != players_.end()) {
|
||||
@@ -1216,11 +1216,11 @@ auto Game::getPlayer(int id) -> std::shared_ptr<Player> {
|
||||
}
|
||||
|
||||
// Obtiene un controlador a partir del "id" del jugador
|
||||
auto Game::getController(int player_id) -> int {
|
||||
auto it = std::find_if(Options::controllers.begin(), Options::controllers.end(), [player_id](const auto &controller) { return controller.player_id == player_id; });
|
||||
auto Game::getController(Player::Id player_id) -> int {
|
||||
auto it = std::find_if(Options::gamepads.begin(), Options::gamepads.end(), [player_id](const auto &controller) { return controller->player_id == player_id; });
|
||||
|
||||
if (it != Options::controllers.end()) {
|
||||
return std::distance(Options::controllers.begin(), it);
|
||||
if (it != Options::gamepads.end()) {
|
||||
return std::distance(Options::gamepads.begin(), it);
|
||||
}
|
||||
|
||||
return -1;
|
||||
@@ -1286,7 +1286,7 @@ void Game::demoHandleInput() {
|
||||
|
||||
// Procesa las entradas para un jugador específico durante el modo demo.
|
||||
void Game::demoHandlePlayerInput(const std::shared_ptr<Player> &player, int index) {
|
||||
const auto &demo_data = demo_.data[index][demo_.counter];
|
||||
const auto &demo_data = demo_.data.at(index).at(demo_.counter);
|
||||
|
||||
if (demo_data.left == 1) {
|
||||
player->setInput(Input::Action::LEFT);
|
||||
@@ -1469,7 +1469,7 @@ void Game::handleNameInput(const std::shared_ptr<Player> &player) {
|
||||
}
|
||||
|
||||
// Inicializa las variables para el modo DEMO
|
||||
void Game::initDemo(int player_id) {
|
||||
void Game::initDemo(Player::Id player_id) {
|
||||
if (demo_.enabled) {
|
||||
// Cambia el estado del juego
|
||||
setState(State::PLAYING);
|
||||
@@ -1497,7 +1497,7 @@ void Game::initDemo(int player_id) {
|
||||
|
||||
// Activa o no al otro jugador
|
||||
if (rand() % 3 != 0) {
|
||||
const auto OTHER_PLAYER_ID = player_id == 1 ? 2 : 1;
|
||||
const auto OTHER_PLAYER_ID = player_id == Player::Id::PLAYER1 ? Player::Id::PLAYER2 : Player::Id::PLAYER1;
|
||||
auto other_player = getPlayer(OTHER_PLAYER_ID);
|
||||
other_player->setPlayingState(Player::State::PLAYING);
|
||||
}
|
||||
@@ -1581,30 +1581,54 @@ void Game::initDifficultyVars() {
|
||||
}
|
||||
|
||||
// Inicializa los jugadores
|
||||
void Game::initPlayers(int player_id) {
|
||||
void Game::initPlayers(Player::Id player_id) {
|
||||
const int Y = param.game.play_area.rect.h - Player::HEIGHT + 1; // Se hunde un pixel para esconder el outline de los pies
|
||||
|
||||
// Crea al jugador uno y lo pone en modo espera
|
||||
players_.emplace_back(std::make_unique<Player>(1, param.game.play_area.first_quarter_x - (Player::WIDTH / 2), Y, demo_.enabled, param.game.play_area.rect, player_textures_.at(0), player_animations_));
|
||||
players_.back()->setScoreBoardPanel(Scoreboard::Id::LEFT);
|
||||
players_.back()->setName(Lang::getText("[SCOREBOARD] 1"));
|
||||
//players_.back()->setController(getController(players_.back()->getId()));
|
||||
players_.back()->setGamepad(Options::controllers.front().gamepad);
|
||||
players_.back()->setUsesKeyboard(true);
|
||||
players_.back()->setPlayingState(Player::State::WAITING);
|
||||
Player::Config config_player1;
|
||||
config_player1.id = Player::Id::PLAYER1;
|
||||
config_player1.x = param.game.play_area.first_quarter_x - (Player::WIDTH / 2);
|
||||
config_player1.y = Y;
|
||||
config_player1.demo = demo_.enabled;
|
||||
config_player1.play_area = ¶m.game.play_area.rect;
|
||||
config_player1.texture = player_textures_.at(0);
|
||||
config_player1.animations = player_animations_;
|
||||
config_player1.hi_score_table = &Options::settings.hi_score_table;
|
||||
config_player1.glowing_entry = &Options::settings.glowing_entries.at(static_cast<int>(Player::Id::PLAYER1) - 1);
|
||||
|
||||
auto player1 = std::make_unique<Player>(config_player1);
|
||||
player1->setScoreBoardPanel(Scoreboard::Id::LEFT);
|
||||
player1->setName(Lang::getText("[SCOREBOARD] 1"));
|
||||
player1->setGamepad(Options::gamepads.front()->instance);
|
||||
player1->setUsesKeyboard(Player::Id::PLAYER1 == Options::keyboard.player_id);
|
||||
player1->setPlayingState(Player::State::WAITING);
|
||||
players_.push_back(std::move(player1));
|
||||
|
||||
// Crea al jugador dos y lo pone en modo espera
|
||||
players_.emplace_back(std::make_unique<Player>(2, param.game.play_area.third_quarter_x - (Player::WIDTH / 2), Y, demo_.enabled, param.game.play_area.rect, player_textures_.at(1), player_animations_));
|
||||
players_.back()->setScoreBoardPanel(Scoreboard::Id::RIGHT);
|
||||
players_.back()->setName(Lang::getText("[SCOREBOARD] 2"));
|
||||
//players_.back()->setController(getController(players_.back()->getId()));
|
||||
players_.back()->setPlayingState(Player::State::WAITING);
|
||||
Player::Config config_player2;
|
||||
config_player2.id = Player::Id::PLAYER2;
|
||||
config_player2.x = param.game.play_area.third_quarter_x - (Player::WIDTH / 2);
|
||||
config_player2.y = Y;
|
||||
config_player2.demo = demo_.enabled;
|
||||
config_player2.play_area = ¶m.game.play_area.rect;
|
||||
config_player2.texture = player_textures_.at(1);
|
||||
config_player2.animations = player_animations_;
|
||||
config_player2.hi_score_table = &Options::settings.hi_score_table;
|
||||
config_player2.glowing_entry = &Options::settings.glowing_entries.at(static_cast<int>(Player::Id::PLAYER2) - 1);
|
||||
|
||||
auto player2 = std::make_unique<Player>(config_player2);
|
||||
player2->setScoreBoardPanel(Scoreboard::Id::RIGHT);
|
||||
player2->setName(Lang::getText("[SCOREBOARD] 2"));
|
||||
player2->setGamepad(Options::gamepads.back()->instance);
|
||||
player2->setUsesKeyboard(Player::Id::PLAYER2 == Options::keyboard.player_id);
|
||||
player2->setPlayingState(Player::State::WAITING);
|
||||
players_.push_back(std::move(player2));
|
||||
|
||||
// Activa el jugador que coincide con el "player_id" o ambos si es "0"
|
||||
if (player_id == 0) {
|
||||
if (player_id == Player::Id::BOTH_PLAYERS) {
|
||||
// Activa ambos jugadores
|
||||
getPlayer(1)->setPlayingState(demo_.enabled ? Player::State::PLAYING : Player::State::ENTERING_SCREEN);
|
||||
getPlayer(2)->setPlayingState(demo_.enabled ? Player::State::PLAYING : Player::State::ENTERING_SCREEN);
|
||||
getPlayer(Player::Id::PLAYER1)->setPlayingState(demo_.enabled ? Player::State::PLAYING : Player::State::ENTERING_SCREEN);
|
||||
getPlayer(Player::Id::PLAYER2)->setPlayingState(demo_.enabled ? Player::State::PLAYING : Player::State::ENTERING_SCREEN);
|
||||
} else {
|
||||
// Activa el jugador elegido
|
||||
auto player = getPlayer(player_id);
|
||||
|
||||
@@ -30,18 +30,15 @@ namespace Difficulty {
|
||||
enum class Code;
|
||||
} // namespace Difficulty
|
||||
|
||||
// Modo demo
|
||||
constexpr bool GAME_MODE_DEMO_OFF = false;
|
||||
constexpr bool GAME_MODE_DEMO_ON = true;
|
||||
|
||||
// Cantidad de elementos a escribir en los ficheros de datos
|
||||
constexpr int TOTAL_SCORE_DATA = 3;
|
||||
|
||||
// Clase Game
|
||||
class Game {
|
||||
public:
|
||||
// --- Constantes ---
|
||||
static constexpr bool DEMO_OFF = false;
|
||||
static constexpr bool DEMO_ON = true;
|
||||
|
||||
// --- Constructor y destructor ---
|
||||
Game(int player_id, int current_stage, bool demo);
|
||||
Game(Player::Id player_id, int current_stage, bool demo);
|
||||
~Game();
|
||||
|
||||
// --- Bucle principal ---
|
||||
@@ -174,12 +171,12 @@ class Game {
|
||||
void updateGameStateGameOver(); // Gestiona el estado de fin de partida
|
||||
|
||||
// --- Gestión de jugadores ---
|
||||
void initPlayers(int player_id); // Inicializa los datos de los jugadores
|
||||
void updatePlayers(); // Actualiza las variables y estados de los jugadores
|
||||
void renderPlayers(); // Renderiza todos los jugadores en pantalla
|
||||
void sortPlayersByZOrder(); // Reorganiza el orden de dibujado de jugadores
|
||||
auto getPlayer(int id) -> std::shared_ptr<Player>; // Obtiene un jugador por su identificador
|
||||
static auto getController(int player_id) -> int; // Obtiene el controlador asignado a un jugador
|
||||
void initPlayers(Player::Id player_id); // Inicializa los datos de los jugadores
|
||||
void updatePlayers(); // Actualiza las variables y estados de los jugadores
|
||||
void renderPlayers(); // Renderiza todos los jugadores en pantalla
|
||||
void sortPlayersByZOrder(); // Reorganiza el orden de dibujado de jugadores
|
||||
auto getPlayer(Player::Id id) -> std::shared_ptr<Player>; // Obtiene un jugador por su identificador
|
||||
static auto getController(Player::Id player_id) -> int; // Obtiene el controlador asignado a un jugador
|
||||
|
||||
// --- Estado de jugadores ---
|
||||
void checkAndUpdatePlayerStatus(int active_player_index, int inactive_player_index); // Actualiza estado entre jugadores
|
||||
@@ -214,7 +211,7 @@ class Game {
|
||||
// --- Sistema de balas y proyectiles ---
|
||||
void updateBullets(); // Actualiza posición y estado de todas las balas
|
||||
void renderBullets(); // Renderiza todas las balas activas
|
||||
void createBullet(int x, int y, BulletType kind, bool powered_up, int owner); // Crea una nueva bala
|
||||
void createBullet(int x, int y, BulletType kind, bool powered_up, Player::Id owner); // Crea una nueva bala
|
||||
void checkBulletCollision(); // Verifica colisiones de todas las balas
|
||||
void freeBullets(); // Libera memoria del vector de balas
|
||||
|
||||
@@ -276,7 +273,7 @@ class Game {
|
||||
void initScoreboard(); // Inicializa el sistema de puntuación
|
||||
|
||||
// --- Modo demostración ---
|
||||
void initDemo(int player_id); // Inicializa variables para el modo demostración
|
||||
void initDemo(Player::Id player_id); // Inicializa variables para el modo demostración
|
||||
void updateDemo(); // Actualiza lógica específica del modo demo
|
||||
|
||||
// --- Recursos y renderizado ---
|
||||
|
||||
@@ -348,7 +348,7 @@ void HiScoreTable::iniEntryColors() {
|
||||
// Hace brillar los nombres de la tabla de records
|
||||
void HiScoreTable::glowEntryNames() {
|
||||
const Color ENTRY_COLOR = getEntryColor(counter_ / 5);
|
||||
for (const auto &entry_index : Options::settings.last_hi_score_entry) {
|
||||
for (const auto &entry_index : Options::settings.glowing_entries) {
|
||||
if (entry_index != -1) {
|
||||
entry_names_.at(entry_index)->getTexture()->setColor(ENTRY_COLOR);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ Title::Title()
|
||||
game_logo_(std::make_unique<GameLogo>(param.game.game_area.center_x, param.title.title_c_c_position)),
|
||||
mini_logo_sprite_(std::make_unique<Sprite>(Resource::get()->getTexture("logo_jailgames_mini.png"))),
|
||||
define_buttons_(std::make_unique<DefineButtons>()),
|
||||
num_controllers_(Input::get()->getNumControllers()),
|
||||
num_controllers_(Input::get()->getNumGamepads()),
|
||||
state_(TitleState::LOGO_ANIMATING) {
|
||||
// Configura objetos
|
||||
tiled_bg_->setColor(param.title.bg_color);
|
||||
@@ -213,12 +213,12 @@ void Title::printColorValue(const Color& color) {
|
||||
void Title::handleControlKeys(SDL_Keycode key) {
|
||||
switch (key) {
|
||||
case SDLK_1:
|
||||
define_buttons_->enable(0);
|
||||
define_buttons_->enable(Options::gamepads.at(0));
|
||||
resetCounter();
|
||||
break;
|
||||
|
||||
case SDLK_2:
|
||||
define_buttons_->enable(1);
|
||||
define_buttons_->enable(Options::gamepads.at(1));
|
||||
resetCounter();
|
||||
break;
|
||||
|
||||
@@ -262,29 +262,29 @@ auto Title::shouldSkipInputCheck() const -> bool {
|
||||
}
|
||||
|
||||
void Title::processControllerInputs() {
|
||||
for (const auto& controller : Options::controllers) {
|
||||
for (const auto& controller : Options::gamepads) {
|
||||
if (isStartButtonPressed(controller)) {
|
||||
handleStartButtonPress(controller);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto Title::isStartButtonPressed(const Options::GamepadOptions& controller) -> bool {
|
||||
auto Title::isStartButtonPressed(std::shared_ptr<Options::Gamepad> controller) -> bool {
|
||||
return Input::get()->checkAction(
|
||||
Input::Action::START,
|
||||
Input::DO_NOT_ALLOW_REPEAT,
|
||||
Input::CHECK_KEYBOARD,
|
||||
controller.gamepad);
|
||||
controller->instance);
|
||||
}
|
||||
|
||||
void Title::handleStartButtonPress(const Options::GamepadOptions& controller) {
|
||||
void Title::handleStartButtonPress(std::shared_ptr<Options::Gamepad> controller) {
|
||||
if (!canProcessStartButton()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (controller.player_id == 1) {
|
||||
if (controller->player_id == Player::Id::PLAYER1) {
|
||||
processPlayer1Start();
|
||||
} else if (controller.player_id == 2) {
|
||||
} else if (controller->player_id == Player::Id::PLAYER2) {
|
||||
processPlayer2Start();
|
||||
}
|
||||
}
|
||||
@@ -296,18 +296,18 @@ auto Title::canProcessStartButton() const -> bool {
|
||||
void Title::processPlayer1Start() {
|
||||
if (!player1_start_pressed_) {
|
||||
player1_start_pressed_ = true;
|
||||
activatePlayerAndSetState(1);
|
||||
activatePlayerAndSetState(Player::Id::PLAYER1);
|
||||
}
|
||||
}
|
||||
|
||||
void Title::processPlayer2Start() {
|
||||
if (!player2_start_pressed_) {
|
||||
player2_start_pressed_ = true;
|
||||
activatePlayerAndSetState(2);
|
||||
activatePlayerAndSetState(Player::Id::PLAYER2);
|
||||
}
|
||||
}
|
||||
|
||||
void Title::activatePlayerAndSetState(int player_id) {
|
||||
void Title::activatePlayerAndSetState(Player::Id player_id) {
|
||||
getPlayer(player_id)->setPlayingState(Player::State::TITLE_ANIMATION);
|
||||
setState(TitleState::START_HAS_BEEN_PRESSED);
|
||||
counter_ = 0;
|
||||
@@ -328,7 +328,7 @@ void Title::resetCounter() { counter_ = 0; }
|
||||
|
||||
// Intercambia la asignación de mandos a los jugadores
|
||||
void Title::swapControllers() {
|
||||
if (Input::get()->getNumControllers() == 0) {
|
||||
if (Input::get()->getNumGamepads() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -339,33 +339,34 @@ void Title::swapControllers() {
|
||||
// Intercambia el teclado de jugador
|
||||
void Title::swapKeyboard() {
|
||||
Options::swapKeyboard();
|
||||
std::string text = Lang::getText("[DEFINE_BUTTONS] PLAYER") + std::to_string(Options::getPlayerWhoUsesKeyboard()) + ": " + Lang::getText("[DEFINE_BUTTONS] KEYBOARD");
|
||||
std::string text = Lang::getText("[DEFINE_BUTTONS] PLAYER") + std::to_string(static_cast<int>(Options::getPlayerWhoUsesKeyboard())) + ": " + Lang::getText("[DEFINE_BUTTONS] KEYBOARD");
|
||||
Notifier::get()->show({text});
|
||||
}
|
||||
|
||||
// Muestra información sobre los controles y los jugadores
|
||||
void Title::showControllers() {
|
||||
// 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> player_controller_index(NUM_CONTROLLERS, -1);
|
||||
/* // 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> player_controller_index(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
|
||||
player_controller_index.at(Options::controllers.at(i).player_id - 1) = i;
|
||||
}
|
||||
// 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
|
||||
player_controller_index.at(Options::controllers.at(i)->player_id - 1) = i;
|
||||
}
|
||||
|
||||
// Genera el texto correspondiente
|
||||
//for (size_t i = 0; i < NUM_CONTROLLERS; ++i) {
|
||||
// const size_t INDEX = player_controller_index.at(i);
|
||||
// if (Options::controllers.at(INDEX).plugged) {
|
||||
// text.at(i) = Lang::getText("[DEFINE_BUTTONS] PLAYER") + std::to_string(i + 1) + ": " + Options::controllers.at(INDEX).name;
|
||||
// }
|
||||
//}
|
||||
// Genera el texto correspondiente
|
||||
for (size_t i = 0; i < NUM_CONTROLLERS; ++i) {
|
||||
const size_t INDEX = player_controller_index.at(i);
|
||||
if (Options::controllers.at(INDEX).plugged) {
|
||||
text.at(i) = Lang::getText("[DEFINE_BUTTONS] PLAYER") + std::to_string(i + 1) + ": " + Options::controllers.at(INDEX).name;
|
||||
}
|
||||
}
|
||||
|
||||
// Muestra la notificación
|
||||
Notifier::get()->show({text.at(0), text.at(1)});
|
||||
// Muestra la notificación
|
||||
Notifier::get()->show({text.at(0), text.at(1)});
|
||||
*/
|
||||
}
|
||||
|
||||
// Actualiza el fade
|
||||
@@ -558,10 +559,31 @@ void Title::initPlayers() {
|
||||
constexpr int PLAYER_HEIGHT = 32;
|
||||
const int Y = param.title.press_start_position - (PLAYER_HEIGHT / 2);
|
||||
constexpr bool DEMO = false;
|
||||
players_.emplace_back(std::make_unique<Player>(1, param.game.game_area.center_x - (PLAYER_WIDTH / 2), Y, DEMO, param.game.play_area.rect, player_textures.at(0), player_animations));
|
||||
|
||||
Player::Config config_player1;
|
||||
config_player1.id = Player::Id::PLAYER1;
|
||||
config_player1.x = param.game.game_area.center_x - (PLAYER_WIDTH / 2);
|
||||
config_player1.y = Y;
|
||||
config_player1.demo = DEMO;
|
||||
config_player1.play_area = ¶m.game.play_area.rect;
|
||||
config_player1.texture = player_textures.at(0);
|
||||
config_player1.animations = player_animations;
|
||||
config_player1.hi_score_table = &Options::settings.hi_score_table;
|
||||
config_player1.glowing_entry = &Options::settings.glowing_entries.at(static_cast<int>(Player::Id::PLAYER1) - 1);
|
||||
players_.emplace_back(std::make_unique<Player>(config_player1));
|
||||
players_.back()->setPlayingState(Player::State::TITLE_HIDDEN);
|
||||
|
||||
players_.emplace_back(std::make_unique<Player>(2, param.game.game_area.center_x - (PLAYER_WIDTH / 2), Y, DEMO, param.game.play_area.rect, player_textures.at(1), player_animations));
|
||||
Player::Config config_player2;
|
||||
config_player2.id = Player::Id::PLAYER2;
|
||||
config_player2.x = param.game.game_area.center_x - (PLAYER_WIDTH / 2);
|
||||
config_player2.y = Y;
|
||||
config_player2.demo = DEMO;
|
||||
config_player2.play_area = ¶m.game.play_area.rect;
|
||||
config_player2.texture = player_textures.at(1);
|
||||
config_player2.animations = player_animations;
|
||||
config_player2.hi_score_table = &Options::settings.hi_score_table;
|
||||
config_player2.glowing_entry = &Options::settings.glowing_entries.at(static_cast<int>(Player::Id::PLAYER2) - 1);
|
||||
players_.emplace_back(std::make_unique<Player>(config_player2));
|
||||
players_.back()->setPlayingState(Player::State::TITLE_HIDDEN);
|
||||
}
|
||||
|
||||
@@ -580,7 +602,7 @@ void Title::renderPlayers() {
|
||||
}
|
||||
|
||||
// Obtiene un jugador a partir de su "id"
|
||||
auto Title::getPlayer(int id) -> std::shared_ptr<Player> {
|
||||
auto Title::getPlayer(Player::Id id) -> std::shared_ptr<Player> {
|
||||
auto it = std::find_if(players_.begin(), players_.end(), [id](const auto& player) { return player->getId() == id; });
|
||||
|
||||
if (it != players_.end()) {
|
||||
|
||||
@@ -7,17 +7,17 @@
|
||||
#include <string_view> // Para string_view
|
||||
#include <vector> // Para vector
|
||||
|
||||
#include "player.h" // Para Player
|
||||
#include "section.hpp" // Para Options, Name (ptr only)
|
||||
|
||||
class DefineButtons;
|
||||
class Fade;
|
||||
class GameLogo;
|
||||
class Player;
|
||||
class Sprite;
|
||||
class Text;
|
||||
class TiledBG;
|
||||
namespace Options {
|
||||
struct GamepadOptions;
|
||||
struct Gamepad;
|
||||
} // namespace Options
|
||||
struct Color;
|
||||
|
||||
@@ -87,24 +87,24 @@ class Title {
|
||||
void resetCounter(); // Reinicia el contador interno
|
||||
|
||||
// --- Entrada de usuario ---
|
||||
void checkEvents(); // Comprueba los eventos
|
||||
void checkInput(); // Comprueba las entradas
|
||||
void handleKeyDownEvent(const SDL_Event& event); // Maneja el evento de tecla presionada
|
||||
void handleControlKeys(SDL_Keycode key); // Maneja las teclas de control específicas
|
||||
[[nodiscard]] auto shouldSkipInputCheck() const -> bool; // Determina si se debe omitir la comprobación de entrada
|
||||
void processControllerInputs(); // Procesa las entradas de los mandos
|
||||
[[nodiscard]] static auto isStartButtonPressed(const Options::GamepadOptions& controller) -> bool; // Comprueba si se ha pulsado el botón Start
|
||||
void handleStartButtonPress(const Options::GamepadOptions& controller); // Maneja la pulsación del botón Start
|
||||
[[nodiscard]] auto canProcessStartButton() const -> bool; // Verifica si se puede procesar la pulsación del botón Start
|
||||
void processPlayer1Start(); // Procesa el inicio del jugador 1
|
||||
void processPlayer2Start(); // Procesa el inicio del jugador 2
|
||||
void activatePlayerAndSetState(int player_id); // Activa al jugador y cambia el estado del título
|
||||
void checkEvents(); // Comprueba los eventos
|
||||
void checkInput(); // Comprueba las entradas
|
||||
void handleKeyDownEvent(const SDL_Event& event); // Maneja el evento de tecla presionada
|
||||
void handleControlKeys(SDL_Keycode key); // Maneja las teclas de control específicas
|
||||
[[nodiscard]] auto shouldSkipInputCheck() const -> bool; // Determina si se debe omitir la comprobación de entrada
|
||||
void processControllerInputs(); // Procesa las entradas de los mandos
|
||||
[[nodiscard]] static auto isStartButtonPressed(std::shared_ptr<Options::Gamepad> controller) -> bool; // Comprueba si se ha pulsado el botón Start
|
||||
void handleStartButtonPress(std::shared_ptr<Options::Gamepad> controller); // Maneja la pulsación del botón Start
|
||||
[[nodiscard]] auto canProcessStartButton() const -> bool; // Verifica si se puede procesar la pulsación del botón Start
|
||||
void processPlayer1Start(); // Procesa el inicio del jugador 1
|
||||
void processPlayer2Start(); // Procesa el inicio del jugador 2
|
||||
void activatePlayerAndSetState(Player::Id player_id); // Activa al jugador y cambia el estado del título
|
||||
|
||||
// --- Gestión de jugadores ---
|
||||
void initPlayers(); // Inicializa los jugadores
|
||||
void updatePlayers(); // Actualiza los jugadores
|
||||
void renderPlayers(); // Renderiza los jugadores
|
||||
auto getPlayer(int id) -> std::shared_ptr<Player>; // Obtiene un jugador a partir de su "id"
|
||||
void initPlayers(); // Inicializa los jugadores
|
||||
void updatePlayers(); // Actualiza los jugadores
|
||||
void renderPlayers(); // Renderiza los jugadores
|
||||
auto getPlayer(Player::Id id) -> std::shared_ptr<Player>; // Obtiene un jugador a partir de su "id"
|
||||
|
||||
// --- Visualización / Renderizado ---
|
||||
void render(); // Dibuja el objeto en pantalla
|
||||
|
||||
Reference in New Issue
Block a user