#include "scoreboard.h" #include // for SDL_GetError #include // for SDL_PIXELFORMAT_RGBA8888 #include // for SDL_Rect #include // for SDL_GetTicks #include // for basic_ostream, operator<<, cout, endl #include "s_animated_sprite.h" // for SAnimatedSprite #include "defines.h" // for BLOCK #include "options.h" // for Options, options, OptionsVideo, Cheat #include "resource.h" // for Resource #include "screen.h" // for Screen #include "text.h" // for Text #include "surface.h" // for Texture // Constructor Scoreboard::Scoreboard(std::shared_ptr data) : data_(data), clock_(ClockData()) { const int SURFACE_WIDTH_ = options.game.width; constexpr int SURFACE_HEIGHT_ = 6 * BLOCK; // Reserva memoria para los objetos item_surface_ = Resource::get()->getSurface("items.gif"); 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(player_texture, player_animations); player_sprite_->setCurrentAnimation("walk_menu"); surface_ = std::make_shared(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 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 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(nullptr); }