Files
jaildoctors_dilemma/source/scoreboard.cpp
Sergio Valor 78c5333144 Redistribuits els .cpp en carpetes
Actualitzat cmake
Modificats els include de SDL2 a SDL3
2025-10-15 08:28:57 +02:00

164 lines
5.8 KiB
C++

#include "scoreboard.h"
#include <SDL3/SDL_rect.h> // Para SDL_Rect
#include <SDL3/SDL_timer.h> // Para SDL_GetTicks
#include "defines.h" // Para BLOCK
#include "options.h" // Para Options, options, Cheat, OptionsGame
#include "resource.h" // Para Resource
#include "s_animated_sprite.h" // Para SAnimatedSprite
#include "screen.h" // Para Screen
#include "surface.h" // Para Surface
#include "text.h" // Para Text
#include "utils.h" // Para stringToColor
// Constructor
Scoreboard::Scoreboard(std::shared_ptr<ScoreboardData> data)
: item_surface_(Resource::get()->getSurface("items.gif")),
data_(data),
clock_(ClockData()) {
const int SURFACE_WIDTH_ = options.game.width;
constexpr int SURFACE_HEIGHT_ = 6 * BLOCK;
// Reserva memoria para los objetos
auto player_texture = Resource::get()->getSurface(options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.gif" : "player.gif");
auto player_animations = Resource::get()->getAnimations(options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.ani" : "player.ani");
player_sprite_ = std::make_shared<SAnimatedSprite>(player_texture, player_animations);
player_sprite_->setCurrentAnimation("walk_menu");
surface_ = std::make_shared<Surface>(SURFACE_WIDTH_, SURFACE_HEIGHT_);
surface_dest_ = {0, options.game.height - SURFACE_HEIGHT_, SURFACE_WIDTH_, SURFACE_HEIGHT_};
// Inicializa las variables
counter_ = 0;
change_color_speed_ = 4;
is_paused_ = false;
paused_time_ = 0;
paused_time_elapsed_ = 0;
items_color_ = stringToColor("white");
// Inicializa el vector de colores
const std::vector<std::string> COLORS = {"blue", "magenta", "green", "cyan", "yellow", "white", "bright_blue", "bright_magenta", "bright_green", "bright_cyan", "bright_yellow", "bright_white"};
for (const auto& color : COLORS) {
color_.push_back(stringToColor(color));
}
}
// Pinta el objeto en pantalla
void Scoreboard::render() {
surface_->render(nullptr, &surface_dest_);
}
// Actualiza las variables del objeto
void Scoreboard::update() {
counter_++;
player_sprite_->update();
// Actualiza el color de la cantidad de items recogidos
updateItemsColor();
// Dibuja la textura
fillTexture();
if (!is_paused_) {
// Si está en pausa no se actualiza el reloj
clock_ = getTime();
}
}
// Obtiene el tiempo transcurrido de partida
Scoreboard::ClockData Scoreboard::getTime() {
const Uint32 timeElapsed = SDL_GetTicks() - data_->ini_clock - paused_time_elapsed_;
ClockData time;
time.hours = timeElapsed / 3600000;
time.minutes = timeElapsed / 60000;
time.seconds = timeElapsed / 1000;
time.separator = (timeElapsed % 1000 <= 500) ? ":" : " ";
return time;
}
// Pone el marcador en modo pausa
void Scoreboard::setPaused(bool value) {
if (is_paused_ == value) {
// Evita ejecutar lógica si el estado no cambia
return;
}
is_paused_ = value;
if (is_paused_) {
// Guarda el tiempo actual al pausar
paused_time_ = SDL_GetTicks();
} else {
// Calcula el tiempo pausado acumulado al reanudar
paused_time_elapsed_ += SDL_GetTicks() - paused_time_;
}
}
// Actualiza el color de la cantidad de items recogidos
void Scoreboard::updateItemsColor() {
if (!data_->jail_is_open) {
return;
}
if (counter_ % 20 < 10) {
items_color_ = stringToColor("white");
} else {
items_color_ = stringToColor("magenta");
}
}
// Devuelve la cantidad de minutos de juego transcurridos
int Scoreboard::getMinutes() {
return getTime().minutes;
}
// Dibuja los elementos del marcador en la textura
void Scoreboard::fillTexture() {
// Empieza a dibujar en la textura
auto previuos_renderer = Screen::get()->getRendererSurface();
Screen::get()->setRendererSurface(surface_);
// Limpia la textura
surface_->clear(stringToColor("black"));
// Anclas
constexpr int LINE1 = BLOCK;
constexpr int LINE2 = 3 * BLOCK;
// Dibuja las vidas
const int desp = (counter_ / 40) % 8;
const int frame = desp % 4;
player_sprite_->setCurrentAnimationFrame(frame);
player_sprite_->setPosY(LINE2);
for (int i = 0; i < data_->lives; ++i) {
player_sprite_->setPosX(8 + (16 * i) + desp);
const int index = i % color_.size();
player_sprite_->render(1, color_.at(index));
}
// Muestra si suena la música
if (data_->music) {
const Uint8 c = data_->color;
SDL_Rect clip = {0, 8, 8, 8};
item_surface_->renderWithColorReplace(20 * BLOCK, LINE2, 1, c, &clip);
}
// Escribe los textos
auto text = Resource::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(BLOCK, LINE1, "Items collected ", data_->color);
text->writeColored(17 * BLOCK, LINE1, ITEMS_TEXT, items_color_);
text->writeColored(20 * BLOCK, LINE1, " Time ", data_->color);
text->writeColored(26 * BLOCK, LINE1, 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 * BLOCK, LINE2, "Rooms", stringToColor("white"));
text->writeColored(28 * BLOCK, LINE2, ROOMS_TEXT, stringToColor("white"));
// Deja el renderizador como estaba
Screen::get()->setRendererSurface(previuos_renderer);
}