canvi d'skin en la consola

This commit is contained in:
2026-03-29 17:21:05 +02:00
parent 2fe79de1d8
commit 77b844065e
10 changed files with 58 additions and 9 deletions

View File

@@ -249,7 +249,7 @@ auto Director::checkProgramArguments(std::vector<std::string> 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;
}
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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) { 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

View File

@@ -5,6 +5,8 @@
namespace GameControl {
// Disponible en todos los builds — refresca el color del jugador según cheats
inline std::function<void()> refresh_player_color;
// Disponible en todos los builds — cambia la skin del jugador (1=normal, 2=alternativa)
inline std::function<void(int)> change_player_skin;
} // namespace GameControl
#ifdef _DEBUG

View File

@@ -22,7 +22,7 @@ Scoreboard::Scoreboard(std::shared_ptr<Data> 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<AnimatedSprite>(player_animation_data);
player_sprite_->setCurrentAnimation("walk_menu");

View File

@@ -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<int>();
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";

View File

@@ -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

View File

@@ -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> 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>(PLAYER);
}

View File

@@ -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<ConsoleCommand> 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 [<nombre>] — disponible desde cualquier escena
if (args.size() >= 2 && args[0] == "INITIAL" && args[1] == "SCENE") {
@@ -544,7 +556,7 @@ static const std::vector<ConsoleCommand> 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<ConsoleCommand> COMMANDS = {
}
return result;
#else
return "Usage: SET SHADER [POSTFX|CRTPI]";
return "Usage: SET SHADER [POSTFX|CRTPI] | SET PLAYER SKIN <1|2>";
#endif
}},