diff --git a/data/locale/ca.yaml b/data/locale/ca.yaml index 923979c..cc15d09 100644 --- a/data/locale/ca.yaml +++ b/data/locale/ca.yaml @@ -125,6 +125,8 @@ scoreboard: items: "TRESORS PILLATS " time: " HORA " rooms: "SALES" + cheat_infinite_lives: "vides inf" + cheat_invincibility: "inv" game: music_enabled: "MÚSICA ACTIVADA" diff --git a/data/locale/en.yaml b/data/locale/en.yaml index bb9de52..a98ef2e 100644 --- a/data/locale/en.yaml +++ b/data/locale/en.yaml @@ -125,6 +125,8 @@ scoreboard: items: "ITEMS COLLECTED " time: " TIME " rooms: "ROOMS" + cheat_infinite_lives: "inf lives" + cheat_invincibility: "inv" game: music_enabled: "MUSIC ENABLED" diff --git a/source/core/rendering/render_info.cpp b/source/core/rendering/render_info.cpp index bcc61a9..a6fee0f 100644 --- a/source/core/rendering/render_info.cpp +++ b/source/core/rendering/render_info.cpp @@ -12,9 +12,9 @@ #include "core/rendering/surface.hpp" // Para Surface #include "core/rendering/text.hpp" // Para Text #include "game/options.hpp" // Para Options -#include "utils/utils.hpp" // Para prettyName #include "game/ui/console.hpp" // Para Console #include "game/ui/notifier.hpp" // Para Notifier +#include "utils/utils.hpp" // Para prettyName // [SINGLETON] RenderInfo* RenderInfo::render_info = nullptr; diff --git a/source/game/defaults.hpp b/source/game/defaults.hpp index 49bb99b..b5af0df 100644 --- a/source/game/defaults.hpp +++ b/source/game/defaults.hpp @@ -101,6 +101,6 @@ 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 const char* SKIN = "default"; // Skin del jugador por defecto + constexpr const char* SKIN = "default"; // Skin del jugador por defecto constexpr int COLOR = -1; // Color del jugador (-1 = automático según cheats) } // namespace Defaults::Game::Player diff --git a/source/game/entities/player.cpp b/source/game/entities/player.cpp index 15f5107..1efa930 100644 --- a/source/game/entities/player.cpp +++ b/source/game/entities/player.cpp @@ -620,21 +620,16 @@ auto Player::handleKillingTiles() -> bool { return false; // No se encontró ninguna colisión } -// Establece el color del jugador (0 = automático según cheats/options) +// Establece el color del jugador (0 = automático según options) void Player::setColor(Uint8 color) { if (color != 0) { color_ = color; return; } - // Color personalizado desde opciones (prioridad sobre cheats) + // Color personalizado desde opciones if (Options::game.player_color >= 0) { color_ = static_cast(Options::game.player_color); - } else if (Options::cheats.invincible == Options::Cheat::State::ENABLED) { - // Color automático según cheats - color_ = static_cast(PaletteColor::CYAN); - } else if (Options::cheats.infinite_lives == Options::Cheat::State::ENABLED) { - color_ = static_cast(PaletteColor::YELLOW); } else { color_ = static_cast(PaletteColor::WHITE); } @@ -642,8 +637,8 @@ void Player::setColor(Uint8 color) { // Si el color coincide con el fondo de la habitación, usar fallback if (room_ != nullptr && color_ == room_->getBGColor()) { color_ = (room_->getBGColor() != static_cast(PaletteColor::WHITE)) - ? static_cast(PaletteColor::WHITE) - : static_cast(PaletteColor::BRIGHT_BLACK); + ? static_cast(PaletteColor::WHITE) + : static_cast(PaletteColor::BRIGHT_BLACK); } } diff --git a/source/game/entities/player.hpp b/source/game/entities/player.hpp index a26c773..7a6f95e 100644 --- a/source/game/entities/player.hpp +++ b/source/game/entities/player.hpp @@ -100,8 +100,8 @@ 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(const std::string& skin_name); // Cambia la skin del jugador en caliente ("default" o nombre de enemigo) - static auto skinToAnimationPath(const std::string& skin_name) -> std::string; // Resuelve nombre de skin a fichero de animación + void setSkin(const std::string& skin_name); // Cambia la skin del jugador en caliente ("default" o nombre de enemigo) + static auto skinToAnimationPath(const std::string& skin_name) -> std::string; // Resuelve nombre de skin a fichero de animación 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 a6a88fb..7d82471 100644 --- a/source/game/game_control.hpp +++ b/source/game/game_control.hpp @@ -3,8 +3,6 @@ #include 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 ("default" o nombre de enemigo) inline std::function change_player_skin; // Disponible en todos los builds — cambia el color del jugador (-1 = automático, 0-15 = color fijo) diff --git a/source/game/gameplay/scoreboard.cpp b/source/game/gameplay/scoreboard.cpp index c18720d..3dc36fa 100644 --- a/source/game/gameplay/scoreboard.cpp +++ b/source/game/gameplay/scoreboard.cpp @@ -137,19 +137,14 @@ void Scoreboard::fillTexture() { // Limpia la textura surface_->clear(stringToColor("black")); - // Anclas - constexpr int LINE1 = Tile::SIZE; - constexpr int LINE2 = 3 * Tile::SIZE; - // Dibuja las vidas - // Calcular desplazamiento basado en tiempo const int WALK_FRAMES = player_sprite_->getCurrentAnimationSize(); const int DESP = static_cast(time_accumulator_ / SPRITE_WALK_CYCLE_DURATION) % (WALK_FRAMES * 2); const int FRAME = DESP % WALK_FRAMES; player_sprite_->setCurrentAnimationFrame(FRAME); - player_sprite_->setPosY(LINE2); + player_sprite_->setPosY(LINE2_Y); for (int i = 0; i < data_->lives; ++i) { - player_sprite_->setPosX(8 + (16 * i) + DESP); + player_sprite_->setPosX(LIVES_START_X + (LIVES_SPACING * i) + DESP); const int INDEX = i % color_.size(); player_sprite_->render(1, color_.at(INDEX)); } @@ -158,21 +153,30 @@ void Scoreboard::fillTexture() { if (data_->music) { const Uint8 C = data_->color; SDL_FRect clip = {.x = 0, .y = 8, .w = 8, .h = 8}; - item_surface_->renderWithColorReplace(20 * Tile::SIZE, LINE2, 1, C, &clip); + item_surface_->renderWithColorReplace(MUSIC_ICON_X, LINE2_Y, 1, C, &clip); } // Escribe los textos auto text = Resource::Cache::get()->getText("smb2"); const std::string TIME_TEXT = std::to_string((clock_.minutes % 100) / 10) + std::to_string(clock_.minutes % 10) + clock_.separator + std::to_string((clock_.seconds % 60) / 10) + std::to_string(clock_.seconds % 10); const std::string ITEMS_TEXT = std::to_string(data_->items / 100) + std::to_string((data_->items % 100) / 10) + std::to_string(data_->items % 10); - text->writeColored(Tile::SIZE, LINE1, Locale::get()->get("scoreboard.items"), data_->color); // NOLINT(readability-static-accessed-through-instance) - text->writeColored(17 * Tile::SIZE, LINE1, ITEMS_TEXT, items_color_); - text->writeColored(20 * Tile::SIZE, LINE1, Locale::get()->get("scoreboard.time"), data_->color); // NOLINT(readability-static-accessed-through-instance) - text->writeColored(26 * Tile::SIZE, LINE1, TIME_TEXT, stringToColor("white")); + text->writeColored(ITEMS_LABEL_X, LINE1_Y, Locale::get()->get("scoreboard.items"), data_->color); // NOLINT(readability-static-accessed-through-instance) + text->writeColored(ITEMS_VALUE_X, LINE1_Y, ITEMS_TEXT, items_color_); + text->writeColored(TIME_LABEL_X, LINE1_Y, Locale::get()->get("scoreboard.time"), data_->color); // NOLINT(readability-static-accessed-through-instance) + text->writeColored(TIME_VALUE_X, LINE1_Y, TIME_TEXT, stringToColor("white")); const std::string ROOMS_TEXT = std::to_string(data_->rooms / 100) + std::to_string((data_->rooms % 100) / 10) + std::to_string(data_->rooms % 10); - text->writeColored(22 * Tile::SIZE, LINE2, Locale::get()->get("scoreboard.rooms"), stringToColor("white")); // NOLINT(readability-static-accessed-through-instance) - text->writeColored(28 * Tile::SIZE, LINE2, ROOMS_TEXT, stringToColor("white")); + text->writeColored(ROOMS_LABEL_X, LINE2_Y, Locale::get()->get("scoreboard.rooms"), stringToColor("white")); // NOLINT(readability-static-accessed-through-instance) + text->writeColored(ROOMS_VALUE_X, LINE2_Y, ROOMS_TEXT, stringToColor("white")); + + // Indicadores de trucos activos (fuente 8bithud) + auto cheat_text = Resource::Cache::get()->getText("8bithud"); + if (Options::cheats.infinite_lives == Options::Cheat::State::ENABLED) { + cheat_text->writeColored(CHEAT_INF_LIVES_X, CHEAT_INF_LIVES_Y, Locale::get()->get("scoreboard.cheat_infinite_lives"), data_->color); // NOLINT(readability-static-accessed-through-instance) + } + if (Options::cheats.invincible == Options::Cheat::State::ENABLED) { + cheat_text->writeColored(CHEAT_INVINCIBLE_X, CHEAT_INVINCIBLE_Y, Locale::get()->get("scoreboard.cheat_invincibility"), data_->color); // NOLINT(readability-static-accessed-through-instance) + } // Deja el renderizador como estaba Screen::get()->setRendererSurface(previuos_renderer); diff --git a/source/game/gameplay/scoreboard.hpp b/source/game/gameplay/scoreboard.hpp index 0277030..7036d9f 100644 --- a/source/game/gameplay/scoreboard.hpp +++ b/source/game/gameplay/scoreboard.hpp @@ -44,6 +44,23 @@ class Scoreboard { static constexpr float ITEMS_COLOR_BLINK_DURATION = 0.333F; // Duración de cada estado del parpadeo (era 10 frames @ 60fps) static constexpr float SPRITE_WALK_CYCLE_DURATION = 0.667F; // Duración del ciclo de caminar (era 40 frames @ 60fps) + // Posición de los elementos del marcador (en pixels, Tile::SIZE = 8) + static constexpr int LINE1_Y = 8; // Fila superior (1 * Tile::SIZE) + static constexpr int LINE2_Y = 24; // Fila inferior (3 * Tile::SIZE) + static constexpr int ITEMS_LABEL_X = 8; // "TRESORS PILLATS" / "ITEMS COLLECTED" + static constexpr int ITEMS_VALUE_X = 136; // Valor numérico de items + static constexpr int TIME_LABEL_X = 160; // "HORA" / "TIME" + static constexpr int TIME_VALUE_X = 208; // Valor numérico del tiempo + static constexpr int LIVES_START_X = 8; // Primera vida (sprite) + static constexpr int LIVES_SPACING = 16; // Separación entre vidas + static constexpr int MUSIC_ICON_X = 160; // Icono de música + static constexpr int ROOMS_LABEL_X = 176; // "SALES" / "ROOMS" + static constexpr int ROOMS_VALUE_X = 224; // Valor numérico de salas + static constexpr int CHEAT_INF_LIVES_X = 176; // Indicador "vides inf" / "inf lives" + static constexpr int CHEAT_INF_LIVES_Y = 34; // Posición Y del indicador de vidas infinitas + static constexpr int CHEAT_INVINCIBLE_X = 231; // Indicador "inv" + static constexpr int CHEAT_INVINCIBLE_Y = 34; // Posición Y del indicador de invencibilidad + // Métodos privados auto getTime() -> ClockData; // Obtiene el tiempo transcurrido de partida void updateItemsColor(float delta_time); // Actualiza el color de la cantidad de items recogidos diff --git a/source/game/options.hpp b/source/game/options.hpp index 87a8087..a8d98b3 100644 --- a/source/game/options.hpp +++ b/source/game/options.hpp @@ -135,10 +135,10 @@ 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 std::string player_skin{Defaults::Game::Player::SKIN}; // Skin del jugador ("default" o nombre de enemigo) - int player_color{Defaults::Game::Player::COLOR}; // Color del jugador (-1 = automático, 0-15 = color fijo) + int player_color{Defaults::Game::Player::COLOR}; // Color del jugador (-1 = automático, 0-15 = color fijo) }; // Estructura para un preset de PostFX diff --git a/source/game/scenes/game.cpp b/source/game/scenes/game.cpp index 6167920..d2cbc04 100644 --- a/source/game/scenes/game.cpp +++ b/source/game/scenes/game.cpp @@ -64,7 +64,6 @@ Game::Game(Mode mode) Cheevos::get()->enable(!Options::cheats.enabled()); // Deshabilita los logros si hay trucos activados Cheevos::get()->clearUnobtainableState(); - GameControl::refresh_player_color = [this]() -> void { player_->setColor(); }; Console::get()->on_toggle = [this](bool open) { player_->setIgnoreInput(open); }; if (Console::get()->isActive()) { player_->setIgnoreInput(true); } GameControl::change_player_skin = [this](const std::string& skin_name) -> void { @@ -129,7 +128,6 @@ Game::Game(Mode mode) Game::~Game() { ItemTracker::destroy(); - GameControl::refresh_player_color = nullptr; GameControl::change_player_skin = nullptr; GameControl::change_player_color = nullptr; Console::get()->on_toggle = nullptr; diff --git a/source/game/ui/console.cpp b/source/game/ui/console.cpp index 091620e..4bfac2b 100644 --- a/source/game/ui/console.cpp +++ b/source/game/ui/console.cpp @@ -2,11 +2,11 @@ #include -#include // Para ranges::transform -#include // Para toupper -#include // Para std::istringstream -#include // Para string -#include // Para vector +#include // Para ranges::transform +#include // Para toupper +#include // Para std::istringstream +#include // Para string +#include // Para vector #include "core/rendering/screen.hpp" // Para Screen #include "core/rendering/sprite/sprite.hpp" // Para Sprite diff --git a/source/game/ui/console.hpp b/source/game/ui/console.hpp index ba7f88e..39f5d37 100644 --- a/source/game/ui/console.hpp +++ b/source/game/ui/console.hpp @@ -2,11 +2,11 @@ #include -#include // Para deque (historial) -#include // Para function -#include // Para shared_ptr -#include // Para string -#include // Para vector +#include // Para deque (historial) +#include // Para function +#include // Para shared_ptr +#include // Para string +#include // Para vector #include "game/ui/console_commands.hpp" // Para CommandRegistry diff --git a/source/game/ui/console_commands.cpp b/source/game/ui/console_commands.cpp index 24c07c1..bdbf3c4 100644 --- a/source/game/ui/console_commands.cpp +++ b/source/game/ui/console_commands.cpp @@ -2,24 +2,24 @@ #include -#include // Para ranges::transform, ranges::find -#include // Para array -#include // Para cout -#include // Para ostringstream -#include // Para string -#include // Para vector +#include // Para ranges::transform, ranges::find +#include // Para array +#include // Para cout +#include // Para ostringstream +#include // Para string +#include // Para vector -#include "core/audio/audio.hpp" // Para Audio -#include "core/locale/locale.hpp" // Para Locale -#include "core/rendering/render_info.hpp" // Para RenderInfo -#include "core/rendering/screen.hpp" // Para Screen +#include "core/audio/audio.hpp" // Para Audio +#include "core/locale/locale.hpp" // Para Locale +#include "core/rendering/render_info.hpp" // Para RenderInfo +#include "core/rendering/screen.hpp" // Para Screen #include "core/resources/resource_helper.hpp" // Para Resource::Helper -#include "external/fkyaml_node.hpp" // Para fkyaml::node -#include "game/game_control.hpp" // Para GameControl -#include "game/options.hpp" // Para Options -#include "game/scene_manager.hpp" // Para SceneManager -#include "game/ui/notifier.hpp" // Para Notifier -#include "utils/utils.hpp" // Para toUpper, prettyName +#include "external/fkyaml_node.hpp" // Para fkyaml::node +#include "game/game_control.hpp" // Para GameControl +#include "game/options.hpp" // Para Options +#include "game/scene_manager.hpp" // Para SceneManager +#include "game/ui/notifier.hpp" // Para Notifier +#include "utils/utils.hpp" // Para toUpper, prettyName #ifdef _DEBUG #include "core/system/debug.hpp" // Para Debug @@ -159,7 +159,11 @@ static auto applyPreset(const std::vector& args) -> std::string { } } - if (IS_CRTPI) { Screen::get()->reloadCrtPi(); } else { Screen::get()->reloadPostFX(); } + if (IS_CRTPI) { + Screen::get()->reloadCrtPi(); + } else { + Screen::get()->reloadPostFX(); + } return shader_label + " preset: " + presetName(); } @@ -581,7 +585,6 @@ static auto cmd_cheat(const std::vector& args) -> std::string { } else { return "usage: cheat infinite lives [on|off]"; } - if (GameControl::refresh_player_color) { GameControl::refresh_player_color(); } return std::string("Infinite lives ") + (cheat == State::ENABLED ? "ON" : "OFF"); } @@ -600,7 +603,6 @@ static auto cmd_cheat(const std::vector& args) -> std::string { } else { return "usage: cheat invincibility [on|off]"; } - if (GameControl::refresh_player_color) { GameControl::refresh_player_color(); } return std::string("Invincibility ") + (cheat == State::ENABLED ? "ON" : "OFF"); } @@ -646,7 +648,9 @@ static auto cmd_player(const std::vector& args) -> std::string { // PLAYER COLOR <0-15> if (args.size() >= 2 && args[0] == "COLOR") { int color = -1; - try { color = std::stoi(args[1]); } catch (...) {} + try { + color = std::stoi(args[1]); + } catch (...) {} if (color < 0 || color > 15) { return "usage: player color <0-15>|default"; } if (!GameControl::change_player_color) { return "Game not initialized"; } GameControl::change_player_color(color); @@ -955,7 +959,8 @@ auto CommandRegistry::generateTerminalHelp() const -> std::string { if (cmd.category != current_category) { current_category = cmd.category; - out << '\n' << '[' << current_category << ']' << '\n'; + out << '\n' + << '[' << current_category << ']' << '\n'; } // Formatear: usage alineado a la izquierda, descripción a la derecha