#include "scoreboard.h" #include // for SDL_Rect #include // for SDL_GetTicks #include "animated_sprite.h" // for AnimatedSprite #include "asset.h" // for Asset #include "defines.h" // for BLOCK, GAMECANVAS_HEIGHT, PLAY_AREA_HEIGHT #include "options.h" // for Options, options, OptionsVideo, Cheat #include "resource.h" // for Resource #include "screen.h" // for Screen #include "text.h" // for Text #include "texture.h" // for Texture #include // Constructor Scoreboard::Scoreboard(std::shared_ptr data) : renderer_(Screen::get()->getRenderer()), resource_(Resource::get()), asset_(Asset::get()), data_(data) { const int TEXTURE_WIDTH_ = options.game.width; constexpr int TEXTURE_HEIGHT_ = 6 * BLOCK; // Reserva memoria para los objetos item_texture_ = resource_->getTexture("items.png"); auto player_texture = resource_->getTexture(options.cheats.alternate_skin == Cheat::CheatState::ENABLED ? "player2.png" : "player.png"); auto player_animations = resource_->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"); text_ = resource_->getText("smb2"); texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, TEXTURE_WIDTH_, TEXTURE_HEIGHT_); if (texture_ == nullptr) { if (options.console) { std::cout << "Scorebard::texture_ could not be created!\nSDL Error: " << SDL_GetError() << std::endl; } } texture_dest_ = {0, options.game.height - TEXTURE_HEIGHT_, TEXTURE_WIDTH_, TEXTURE_HEIGHT_}; // Inicializa las variables counter_ = 0; change_color_speed_ = 4; is_paused_ = false; paused_time_ = 0; paused_time_elapsed_ = 0; items_color_ = stringToColor(options.video.palette, "white"); // Inicializa el vector de colores const std::vector vColors = {"blue", "magenta", "green", "cyan", "yellow", "white", "bright_blue", "bright_magenta", "bright_green", "bright_cyan", "bright_yellow", "bright_white"}; for (auto v : vColors) { color_.push_back(stringToColor(options.video.palette, v)); } } // Destructor Scoreboard::~Scoreboard() { SDL_DestroyTexture(texture_); } // Pinta el objeto en pantalla void Scoreboard::render() { SDL_RenderCopy(renderer_, texture_, nullptr, &texture_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; } // Recarga la textura void Scoreboard::reLoadTexture() { player_sprite_->getTexture()->reLoad(); // playerTexture->reLoad(); item_texture_->reLoad(); text_->reLoadTexture(); } // Recarga la paleta void Scoreboard::reLoadPalette() { // Reinicia el vector de colores const std::vector vColors = {"blue", "magenta", "green", "cyan", "yellow", "white", "bright_blue", "bright_magenta", "bright_green", "bright_cyan", "bright_yellow", "bright_white"}; color_.clear(); for (auto v : vColors) { color_.push_back(stringToColor(options.video.palette, v)); } } // 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(options.video.palette, "white"); } else { items_color_ = stringToColor(options.video.palette, "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 temp = SDL_GetRenderTarget(renderer_); SDL_SetRenderTarget(renderer_, texture_); // Limpia la textura SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 255); SDL_RenderFillRect(renderer_, nullptr); // 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_->getTexture()->setColor(color_[index].r, color_[index].g, color_[index].b); player_sprite_->render(); } // Muestra si suena la música if (data_->music) { const Color c = data_->color; SDL_Rect clip = {0, 8, 8, 8}; item_texture_->setColor(c.r, c.g, c.b); item_texture_->render(20 * BLOCK, LINE2, &clip); } // Escribe los textos const std::string timeTxt = 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 itemsTxt = 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, itemsTxt, items_color_); text_->writeColored(20 * BLOCK, LINE1, " Time ", data_->color); text_->writeColored(26 * BLOCK, LINE1, timeTxt, stringToColor(options.video.palette, "white")); const std::string roomsTxt = 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(options.video.palette, "white")); text_->writeColored(28 * BLOCK, LINE2, roomsTxt, stringToColor(options.video.palette, "white")); // Deja el renderizador como estaba SDL_SetRenderTarget(renderer_, temp); }