el indicador de trucos ja no es el color del jugador sino que es veu al marcador

This commit is contained in:
2026-04-01 22:12:52 +02:00
parent b37b62ef1e
commit 950eeffb07
14 changed files with 86 additions and 65 deletions

View File

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

View File

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

View File

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

View File

@@ -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<Uint8>(Options::game.player_color);
} else if (Options::cheats.invincible == Options::Cheat::State::ENABLED) {
// Color automático según cheats
color_ = static_cast<Uint8>(PaletteColor::CYAN);
} else if (Options::cheats.infinite_lives == Options::Cheat::State::ENABLED) {
color_ = static_cast<Uint8>(PaletteColor::YELLOW);
} else {
color_ = static_cast<Uint8>(PaletteColor::WHITE);
}

View File

@@ -3,8 +3,6 @@
#include <string>
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 ("default" o nombre de enemigo)
inline std::function<void(const std::string&)> change_player_skin;
// Disponible en todos los builds — cambia el color del jugador (-1 = automático, 0-15 = color fijo)

View File

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

View File

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

View File

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

View File

@@ -159,7 +159,11 @@ static auto applyPreset(const std::vector<std::string>& 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<std::string>& 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<std::string>& 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<std::string>& 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