From 77b844065ee9f189836022561dfec745c6153816 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Sun, 29 Mar 2026 17:21:05 +0200 Subject: [PATCH] canvi d'skin en la consola --- source/core/system/director.cpp | 2 +- source/game/defaults.hpp | 2 +- source/game/entities/player.cpp | 8 ++++++++ source/game/entities/player.hpp | 1 + source/game/game_control.hpp | 2 ++ source/game/gameplay/scoreboard.cpp | 2 +- source/game/options.cpp | 21 +++++++++++++++++++++ source/game/options.hpp | 6 +++--- source/game/scenes/game.cpp | 7 ++++++- source/game/ui/console.cpp | 16 ++++++++++++++-- 10 files changed, 58 insertions(+), 9 deletions(-) diff --git a/source/core/system/director.cpp b/source/core/system/director.cpp index ca4c881..9c1aab0 100644 --- a/source/core/system/director.cpp +++ b/source/core/system/director.cpp @@ -249,7 +249,7 @@ auto Director::checkProgramArguments(std::vector const& args) -> st } else if (argument == "--jailEnabled") { Options::cheats.jail_is_open = Options::Cheat::State::ENABLED; } else if (argument == "--altSkin") { - Options::cheats.alternate_skin = Options::Cheat::State::ENABLED; + Options::game.player_skin = 2; } } diff --git a/source/game/defaults.hpp b/source/game/defaults.hpp index 744b5e0..a10afdb 100644 --- a/source/game/defaults.hpp +++ b/source/game/defaults.hpp @@ -59,7 +59,6 @@ namespace Defaults::Cheat { constexpr bool INFINITE_LIVES = false; // Vidas infinitas desactivadas por defecto constexpr bool INVINCIBLE = false; // Invencibilidad desactivada por defecto constexpr bool JAIL_IS_OPEN = false; // Jail abierta desactivada por defecto - constexpr bool ALTERNATE_SKIN = false; // Skin alternativa desactivada por defecto } // namespace Defaults::Cheat namespace Defaults::Stats { @@ -101,4 +100,5 @@ namespace Defaults::Game::Player { constexpr int SPAWN_X = 25 * Tile::SIZE; // Posición X inicial constexpr int SPAWN_Y = 13 * Tile::SIZE; // Posición Y inicial constexpr SDL_FlipMode SPAWN_FLIP = Flip::LEFT; // Orientación inicial + constexpr int SKIN = 1; // Skin del jugador por defecto (1=normal, 2=alternativa) } // namespace Defaults::Game::Player diff --git a/source/game/entities/player.cpp b/source/game/entities/player.cpp index 15340ef..4235cab 100644 --- a/source/game/entities/player.cpp +++ b/source/game/entities/player.cpp @@ -764,6 +764,14 @@ void Player::applySpawnValues(const SpawnData& spawn) { sprite_->setFlip(spawn.flip); } +// Cambia la skin del jugador en caliente preservando la orientación actual +void Player::setSkin(int skin_num) { + const auto FLIP = sprite_->getFlip(); + const std::string PATH = (skin_num == 2) ? "player2.yaml" : "player.yaml"; + initSprite(PATH); + sprite_->setFlip(FLIP); +} + // Inicializa el sprite del jugador void Player::initSprite(const std::string& animations_path) { // NOLINT(readability-convert-member-functions-to-static) const auto& animation_data = Resource::Cache::get()->getAnimationData(animations_path); diff --git a/source/game/entities/player.hpp b/source/game/entities/player.hpp index bd227f4..6cb5065 100644 --- a/source/game/entities/player.hpp +++ b/source/game/entities/player.hpp @@ -100,6 +100,7 @@ class Player { auto getCollider() -> SDL_FRect& { return collider_box_; } // Obtiene el rectangulo de colision del jugador auto getSpawnParams() -> SpawnData { return {.x = x_, .y = y_, .vx = vx_, .vy = vy_, .last_grounded_position = last_grounded_position_, .state = state_, .flip = sprite_->getFlip()}; } // Obtiene el estado de reaparición del jugador void setColor(Uint8 color = 0); // Establece el color del jugador (0 = automático según cheats) + void setSkin(int skin_num); // Cambia la skin del jugador en caliente (1=normal, 2=alternativa) void setRoom(std::shared_ptr room) { room_ = std::move(room); } // Establece la habitación en la que se encuentra el jugador //[[nodiscard]] auto isAlive() const -> bool { return is_alive_ || (Options::cheats.invincible == Options::Cheat::State::ENABLED); } // Comprueba si el jugador esta vivo [[nodiscard]] auto isAlive() const -> bool { return is_alive_; } // Comprueba si el jugador esta vivo diff --git a/source/game/game_control.hpp b/source/game/game_control.hpp index 30b167b..ea3cf92 100644 --- a/source/game/game_control.hpp +++ b/source/game/game_control.hpp @@ -5,6 +5,8 @@ namespace GameControl { // Disponible en todos los builds — refresca el color del jugador según cheats inline std::function refresh_player_color; + // Disponible en todos los builds — cambia la skin del jugador (1=normal, 2=alternativa) + inline std::function change_player_skin; } // namespace GameControl #ifdef _DEBUG diff --git a/source/game/gameplay/scoreboard.cpp b/source/game/gameplay/scoreboard.cpp index 4e267ee..6e913b1 100644 --- a/source/game/gameplay/scoreboard.cpp +++ b/source/game/gameplay/scoreboard.cpp @@ -22,7 +22,7 @@ Scoreboard::Scoreboard(std::shared_ptr data) constexpr float SURFACE_HEIGHT = 6.0F * Tile::SIZE; // Reserva memoria para los objetos - const auto& player_animation_data = Resource::Cache::get()->getAnimationData(Options::cheats.alternate_skin == Options::Cheat::State::ENABLED ? "player2.yaml" : "player.yaml"); + const auto& player_animation_data = Resource::Cache::get()->getAnimationData((Options::game.player_skin == 2) ? "player2.yaml" : "player.yaml"); player_sprite_ = std::make_shared(player_animation_data); player_sprite_->setCurrentAnimation("walk_menu"); diff --git a/source/game/options.cpp b/source/game/options.cpp index a862910..b811153 100644 --- a/source/game/options.cpp +++ b/source/game/options.cpp @@ -514,6 +514,21 @@ namespace Options { } } + // Carga configuración del jugador desde YAML + void loadPlayerConfigFromYaml(const fkyaml::node& yaml) { + if (yaml.contains("player")) { + const auto& player_node = yaml["player"]; + if (player_node.contains("skin")) { + try { + int skin = player_node["skin"].get_value(); + game.player_skin = (skin == 2) ? 2 : Defaults::Game::Player::SKIN; + } catch (...) { + game.player_skin = Defaults::Game::Player::SKIN; + } + } + } + } + // Carga configuración del modo kiosko desde YAML void loadKioskConfigFromYaml(const fkyaml::node& yaml) { if (yaml.contains("kiosk")) { @@ -666,6 +681,7 @@ namespace Options { loadAudioConfigFromYaml(yaml); loadKeyboardControlsFromYaml(yaml); loadGamepadControlsFromYaml(yaml); + loadPlayerConfigFromYaml(yaml); loadKioskConfigFromYaml(yaml); loadLocalizationFromYaml(yaml); @@ -772,6 +788,11 @@ namespace Options { // KIOSK file << "\n"; + file << "# PLAYER\n"; + file << "player:\n"; + file << " skin: " << game.player_skin << "\n"; + file << "\n"; + file << "# KIOSK MODE\n"; file << "kiosk:\n"; file << " enabled: " << (kiosk.enabled ? "true" : "false") << "\n"; diff --git a/source/game/options.hpp b/source/game/options.hpp index 4961bcc..4d1fb38 100644 --- a/source/game/options.hpp +++ b/source/game/options.hpp @@ -40,7 +40,6 @@ namespace Options { State infinite_lives{Defaults::Cheat::INFINITE_LIVES ? State::ENABLED : State::DISABLED}; // Indica si el jugador dispone de vidas infinitas State invincible{Defaults::Cheat::INVINCIBLE ? State::ENABLED : State::DISABLED}; // Indica si el jugador puede morir State jail_is_open{Defaults::Cheat::JAIL_IS_OPEN ? State::ENABLED : State::DISABLED}; // Indica si la Jail está abierta - State alternate_skin{Defaults::Cheat::ALTERNATE_SKIN ? State::ENABLED : State::DISABLED}; // Indica si se usa una skin diferente para el jugador // Método para comprobar si alguno de los tres primeros trucos está activo [[nodiscard]] auto enabled() const -> bool { @@ -115,8 +114,9 @@ namespace Options { // Estructura para las opciones de juego struct Game { - float width{Defaults::Canvas::WIDTH}; // Ancho de la resolucion del juego - float height{Defaults::Canvas::HEIGHT}; // Alto de la resolucion del juego + float width{Defaults::Canvas::WIDTH}; // Ancho de la resolucion del juego + float height{Defaults::Canvas::HEIGHT}; // Alto de la resolucion del juego + int player_skin{Defaults::Game::Player::SKIN}; // Skin del jugador (1=normal, 2=alternativa) }; // Estructura para un preset de PostFX diff --git a/source/game/scenes/game.cpp b/source/game/scenes/game.cpp index 1e0c615..3c8e67c 100644 --- a/source/game/scenes/game.cpp +++ b/source/game/scenes/game.cpp @@ -65,6 +65,10 @@ Game::Game(Mode mode) Cheevos::get()->clearUnobtainableState(); GameControl::refresh_player_color = [this]() -> void { player_->setColor(); }; + GameControl::change_player_skin = [this](int skin_num) -> void { + Options::game.player_skin = skin_num; + player_->setSkin(skin_num); + }; #ifdef _DEBUG GameControl::change_room = [this](const std::string& r) -> bool { return this->changeRoom(r); }; @@ -110,6 +114,7 @@ Game::~Game() { ItemTracker::destroy(); GameControl::refresh_player_color = nullptr; + GameControl::change_player_skin = nullptr; #ifdef _DEBUG GameControl::change_room = nullptr; @@ -875,7 +880,7 @@ void Game::checkEndGameCheevos() { // NOLINT(readability-convert-member-functio // Inicializa al jugador void Game::initPlayer(const Player::SpawnData& spawn_point, std::shared_ptr room) { // NOLINT(readability-convert-member-functions-to-static) - std::string player_animations = Options::cheats.alternate_skin == Options::Cheat::State::ENABLED ? "player2.yaml" : "player.yaml"; + std::string player_animations = (Options::game.player_skin == 2) ? "player2.yaml" : "player.yaml"; const Player::Data PLAYER{.spawn_data = spawn_point, .animations_path = player_animations, .room = std::move(room)}; player_ = std::make_shared(PLAYER); } diff --git a/source/game/ui/console.cpp b/source/game/ui/console.cpp index fdb3b32..b7038a5 100644 --- a/source/game/ui/console.cpp +++ b/source/game/ui/console.cpp @@ -77,6 +77,7 @@ static void printHelp() { SDL_Log(" SS [ON|OFF|SIZE] Supersampling"); SDL_Log(" SHADERS [ON|OFF|NEXT [PRESET]] Toggle/next shader or preset (F4/Shift+F4)"); SDL_Log(" SET SHADER [POSTFX|CRTPI] Set active shader"); + SDL_Log(" SET PLAYER SKIN <1|2> Change player skin (GAME only)"); SDL_Log(" BORDER [ON|OFF] Decorative border (B)"); SDL_Log(" FULLSCREEN [ON|OFF] Fullscreen mode (F3)"); SDL_Log(" ZOOM [UP|DOWN] Window zoom (F1/F2)"); @@ -493,6 +494,17 @@ static const std::vector COMMANDS = { } return "Usage: SET SHADER [POSTFX|CRTPI]"; } + if (args.size() >= 3 && args[0] == "PLAYER" && args[1] == "SKIN") { + if (SceneManager::current != SceneManager::Scene::GAME) { return "Only available in GAME scene"; } + int num = 0; + try { + num = std::stoi(args[2]); + } catch (...) {} + if (num < 1 || num > 2) { return "Usage: SET PLAYER SKIN <1|2>"; } + if (!GameControl::change_player_skin) { return "Game not initialized"; } + GameControl::change_player_skin(num); + return "Player skin: " + std::to_string(num); + } #ifdef _DEBUG // SET INITIAL SCENE [] — disponible desde cualquier escena if (args.size() >= 2 && args[0] == "INITIAL" && args[1] == "SCENE") { @@ -544,7 +556,7 @@ static const std::vector COMMANDS = { return "Items: " + std::to_string(count); } - if (args.empty() || args[0] != "INITIAL") { return "Usage: SET INITIAL [ROOM|POS|SCENE] | SET ITEMS <0-200> | SET SHADER [POSTFX|CRTPI]"; } + if (args.empty() || args[0] != "INITIAL") { return "Usage: SET INITIAL [ROOM|POS|SCENE] | SET ITEMS <0-200> | SET SHADER [POSTFX|CRTPI] | SET PLAYER SKIN <1|2>"; } const bool DO_ROOM = args.size() == 1 || (args.size() >= 2 && args[1] == "ROOM"); const bool DO_POS = args.size() == 1 || (args.size() >= 2 && args[1] == "POS"); @@ -560,7 +572,7 @@ static const std::vector COMMANDS = { } return result; #else - return "Usage: SET SHADER [POSTFX|CRTPI]"; + return "Usage: SET SHADER [POSTFX|CRTPI] | SET PLAYER SKIN <1|2>"; #endif }},