#include "game/gameplay/scoreboard.hpp" #include #include #include #include #include "core/locale/locale.hpp" #include "core/rendering/screen.hpp" #include "core/rendering/surface.hpp" #include "core/rendering/text.hpp" #include "core/resources/resource_cache.hpp" #include "game/options.hpp" #include "utils/defines.hpp" // Constructor Scoreboard::Scoreboard(std::shared_ptr data) : data_(std::move(data)), surface_(std::make_shared(Options::game.width, SURFACE_HEIGHT)), surface_dest_{.x = 0, .y = Options::game.height - SURFACE_HEIGHT, .w = Options::game.width, .h = SURFACE_HEIGHT} {} // Pinta el objeto en pantalla void Scoreboard::render() { surface_->render(nullptr, &surface_dest_); } // Actualiza las variables del objeto void Scoreboard::update(float delta_time) { fillTexture(); if (!is_paused_) { clock_ = getTime(); } } // Obtiene el tiempo transcurrido de partida auto Scoreboard::getTime() -> Scoreboard::ClockData { const Uint32 TIME_ELAPSED = SDL_GetTicks() - data_->ini_clock - paused_time_elapsed_; ClockData time; time.hours = TIME_ELAPSED / 3600000; time.minutes = TIME_ELAPSED / 60000; time.seconds = TIME_ELAPSED / 1000; time.separator = (TIME_ELAPSED % 1000 <= 500) ? ":" : " "; return time; } // Pone el marcador en modo pausa void Scoreboard::setPaused(bool value) { if (is_paused_ == value) { return; } is_paused_ = value; if (is_paused_) { paused_time_ = SDL_GetTicks(); } else { paused_time_elapsed_ += SDL_GetTicks() - paused_time_; } } // Devuelve la cantidad de minutos de juego transcurridos auto Scoreboard::getMinutes() -> int { return getTime().minutes; } // Dibuja los elementos del marcador en la surface void Scoreboard::fillTexture() { auto previous_renderer = Screen::get()->getRendererSurface(); Screen::get()->setRendererSurface(surface_); surface_->clear(0); auto text = Resource::Cache::get()->getText("8bithud"); const int CANVAS_W = static_cast(Options::game.width); const std::string SEP = " - "; const int MONO_W = 7; // Ancho fijo por carácter monoespaciado (dígitos + separador) // Valores formateados const std::string LIVES_STR = std::to_string(data_->lives); const std::string ITEMS_STR = std::to_string(data_->items); const std::string TIME_STR = 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); // --- Línea 1: vides X - objectes X - temps MM:SS (centrada) --- const std::string LIVES_LABEL = Locale::get()->get("scoreboard.lives"); const std::string ITEMS_LABEL = Locale::get()->get("scoreboard.items"); const std::string TIME_LABEL = Locale::get()->get("scoreboard.time"); // Ancho total: labels proporcionales + valores monoespaciados const int LINE1_W = text->length(LIVES_LABEL) + Text::lengthMono(LIVES_STR, MONO_W) + text->length(SEP) + text->length(ITEMS_LABEL) + Text::lengthMono(ITEMS_STR, MONO_W) + text->length(SEP) + text->length(TIME_LABEL) + Text::lengthMono(TIME_STR, MONO_W); int x = (CANVAS_W - LINE1_W) / 2; text->writeColored(x, LINE1_Y, LIVES_LABEL, LABEL_COLOR); x += text->length(LIVES_LABEL); text->writeColoredMono(x, LINE1_Y, LIVES_STR, VALUE_COLOR, MONO_W); x += Text::lengthMono(LIVES_STR, MONO_W); text->writeColored(x, LINE1_Y, SEP, LABEL_COLOR); x += text->length(SEP); text->writeColored(x, LINE1_Y, ITEMS_LABEL, LABEL_COLOR); x += text->length(ITEMS_LABEL); text->writeColoredMono(x, LINE1_Y, ITEMS_STR, VALUE_COLOR, MONO_W); x += Text::lengthMono(ITEMS_STR, MONO_W); text->writeColored(x, LINE1_Y, SEP, LABEL_COLOR); x += text->length(SEP); text->writeColored(x, LINE1_Y, TIME_LABEL, LABEL_COLOR); x += text->length(TIME_LABEL); text->writeColoredMono(x, LINE1_Y, TIME_STR, VALUE_COLOR, MONO_W); // --- Línea 2: indicadores activos (centrada) --- std::vector indicators; if (data_->music) { indicators.push_back(Locale::get()->get("scoreboard.music_on")); } if (Options::cheats.infinite_lives == Options::Cheat::State::ENABLED) { indicators.push_back(Locale::get()->get("scoreboard.cheat_infinite_lives")); } if (Options::cheats.invincible == Options::Cheat::State::ENABLED) { indicators.push_back(Locale::get()->get("scoreboard.cheat_invincibility")); } if (!indicators.empty()) { int line2_w = 0; for (size_t i = 0; i < indicators.size(); ++i) { if (i > 0) { line2_w += text->length(SEP); } line2_w += text->length(indicators[i]); } x = (CANVAS_W - line2_w) / 2; for (size_t i = 0; i < indicators.size(); ++i) { if (i > 0) { text->writeColored(x, LINE2_Y, SEP, LABEL_COLOR); x += text->length(SEP); } text->writeColored(x, LINE2_Y, indicators[i], LABEL_COLOR); x += text->length(indicators[i]); } } Screen::get()->setRendererSurface(previous_renderer); }