Files
projecte_2026/source/game/gameplay/scoreboard.cpp
2026-04-11 16:25:56 +02:00

140 lines
5.1 KiB
C++

#include "game/gameplay/scoreboard.hpp"
#include <SDL3/SDL.h>
#include <string>
#include <utility>
#include <vector>
#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)
: data_(std::move(data)),
surface_(std::make_shared<Surface>(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<int>(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<std::string> 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);
}