#include "hiscore_table.h" #include // Para SDL_BLENDMODE_BLEND #include // Para SDL_PollEvent, SDL_Event, SDL_QUIT #include // Para SDL_PIXELFORMAT_RGBA8888 #include // Para SDL_GetTicks #include // Para SDL_WINDOWEVENT_SIZE_CHANGED #include // Para rand #include // Para max #include // Para function #include // Para vector #include "background.h" // Para Background #include "fade.h" // Para Fade, FadeMode, FadeType #include "global_inputs.h" // Para check, update #include "input.h" // Para Input #include "jail_audio.h" // Para JA_GetMusicState, JA_Music_state #include "lang.h" // Para getText #include "manage_hiscore_table.h" // Para HiScoreEntry #include "mouse.h" // Para handleEvent #include "options.h" // Para Options, OptionsGame, options #include "param.h" // Para Param, param, ParamGame, ParamFade #include "path_sprite.h" // Para PathSprite, Path, PathType #include "resource.h" // Para Resource #include "screen.h" // Para Screen #include "section.h" // Para Name, name, Options, options, Attr... #include "sprite.h" // Para Sprite #include "text.h" // Para Text, TEXT_COLOR, TEXT_SHADOW #include "texture.h" // Para Texture #include "utils.h" // Para Color, easeOutQuint, fade_color // Constructor HiScoreTable::HiScoreTable() : renderer_(Screen::get()->getRenderer()), backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)), fade_(std::make_unique()), background_(std::make_unique()), counter_(0), ticks_(0), view_area_({0, 0, param.game.width, param.game.height}), fade_mode_(FadeMode::IN), background_fade_color_(Color(0, 0, 0)) { // Inicializa el resto section::name = section::Name::HI_SCORE_TABLE; SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND); initFade(); initBackground(); createSprites(); } // Destructor HiScoreTable::~HiScoreTable() { SDL_DestroyTexture(backbuffer_); } // Actualiza las variables void HiScoreTable::update() { constexpr int TICKS_SPEED = 15; if (SDL_GetTicks() - ticks_ > TICKS_SPEED) { // Actualiza el contador de ticks ticks_ = SDL_GetTicks(); // Mantiene la música sonando if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED)) { JA_PlayMusic(Resource::get()->getMusic("title.ogg")); } // Actualiza las posiciones de los sprites de texto updateSprites(); // Actualiza el objeto screen Screen::get()->update(); // Actualiza las variables de globalInputs globalInputs::update(); // Actualiza el fondo background_->update(); // Gestiona el fade updateFade(); // Gestiona el contador y sus eventos counter_++; if (counter_ == 150) { background_->setColor(background_fade_color_.darken()); background_->setAlpha(96); } if (counter_ == COUNTER_END_) { fade_->activate(); } // Dibuja los sprites en la textura fillTexture(); } } // Dibuja los sprites en la textura void HiScoreTable::fillTexture() { // Pinta en el backbuffer el texto y los sprites auto temp = SDL_GetRenderTarget(renderer_); SDL_SetRenderTarget(renderer_, backbuffer_); SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0); SDL_RenderClear(renderer_); // Escribe el texto: Mejores puntuaciones header_->render(); // Escribe los nombres de la tabla de puntuaciones for (auto const &entry : entry_names_) { entry->render(); } // Cambia el destino de renderizado SDL_SetRenderTarget(renderer_, temp); } // Pinta en pantalla void HiScoreTable::render() { // Prepara para empezar a dibujar en la textura de juego Screen::get()->start(); // Limpia la pantalla Screen::get()->clean(bg_color); // Pinta el fondo background_->render(); // Establece la ventana del backbuffer view_area_.y = std::max(0, param.game.height - counter_ + 100); // Copia el backbuffer al renderizador SDL_RenderCopy(renderer_, backbuffer_, nullptr, &view_area_); // Renderiza el fade fade_->render(); // Vuelca el contenido del renderizador en pantalla Screen::get()->render(); } // Recarga todas las texturas void HiScoreTable::reloadTextures() { } // Comprueba los eventos void HiScoreTable::checkEvents() { // Comprueba los eventos que hay en la cola SDL_Event event; while (SDL_PollEvent(&event)) { // Evento de salida de la aplicación if (event.type == SDL_QUIT) { section::name = section::Name::QUIT; section::options = section::Options::QUIT_FROM_EVENT; break; } // Comprueba si se ha cambiado el tamaño de la ventana else if (event.type == SDL_WINDOWEVENT) { if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { reloadTextures(); } } // Comprueba el cursor Mouse::handleEvent(event); } } // Comprueba las entradas void HiScoreTable::checkInput() { // Comprueba si se ha pulsado cualquier botón (de los usados para jugar) if (Input::get()->checkAnyButtonPressed()) { // JA_StopMusic(); section::name = section::Name::TITLE; section::options = section::Options::TITLE_1; section::attract_mode = section::AttractMode::TITLE_TO_DEMO; return; } // Comprueba los inputs que se pueden introducir en cualquier sección del juego globalInputs::check(); } // Bucle para la pantalla de instrucciones void HiScoreTable::run() { while (section::name == section::Name::HI_SCORE_TABLE) { checkInput(); update(); checkEvents(); // Tiene que ir antes del render render(); } } // Gestiona el fade void HiScoreTable::updateFade() { fade_->update(); if (fade_->hasEnded() && fade_mode_ == FadeMode::IN) { fade_->reset(); fade_mode_ = FadeMode::OUT; fade_->setMode(fade_mode_); } if (fade_->hasEnded() && fade_mode_ == FadeMode::OUT) { section::name = section::Name::INSTRUCTIONS; } } // Convierte un entero a un string con separadores de miles std::string HiScoreTable::format(int number) { const std::string separator = "."; const std::string score = std::to_string(number); auto index = (int)score.size() - 1; std::string result; auto i = 0; while (index >= 0) { result = score.at(index) + result; index--; i++; if (i == 3) { i = 0; result = separator + result; } } return result; } // Crea los sprites con los textos void HiScoreTable::createSprites() { auto header_text = Resource::get()->getText("04b_25"); auto entry_text = Resource::get()->getText("smb2"); // Obtiene el tamaño de la textura int backbuffer_width; int backbuffer_height; SDL_QueryTexture(backbuffer_, nullptr, nullptr, &backbuffer_width, &backbuffer_height); // Hay 27 letras - 7 de puntos quedan 20 caracteres 20 - name_lenght 0 num_dots constexpr int max_names = 10; constexpr int space_between_header = 32; const int space_between_lines = entry_text->getCharacterSize() * 2; const int size = space_between_header + space_between_lines * (max_names - 1) + entry_text->getCharacterSize(); const int first_line = (param.game.height - size) / 2; // Crea el sprite para el texto de cabecera header_ = std::make_unique(header_text->writeDXToTexture(TEXT_COLOR, lang::getText(42), -2, background_fade_color_.getInverse().lighten(25))); header_->setPosition(param.game.game_area.center_x - (header_->getWidth() / 2), first_line); // Crea los sprites para las entradas en la tabla de puntuaciones const int animation = rand() % 4; for (int i = 0; i < max_names; ++i) { const auto table_position = (i + 1 >= 10) ? format(i + 1) + ". " : " " + format(i + 1) + ". "; const auto score = format(options.game.hi_score_table.at(i).score); const auto num_dots = 25 - table_position.size() - options.game.hi_score_table.at(i).name.size() - score.size(); std::string dots; for (int j = 0; j < (int)num_dots; ++j) { dots = dots + "."; } const auto line = table_position + options.game.hi_score_table.at(i).name + dots + score; entry_names_.emplace_back(std::make_shared(entry_text->writeDXToTexture(TEXT_SHADOW, line, 1, orange_color, 1, shdw_txt_color))); switch (animation) { case 0: // Ambos lados alternativamente { if (i % 2 == 0) { entry_names_.back()->addPath( -entry_names_.back()->getWidth(), (backbuffer_width - entry_names_.back()->getWidth()) / 2, PathType::HORIZONTAL, (i * space_between_lines) + first_line + space_between_header, 80, easeOutQuint, 0); entry_names_.back()->setPosition(-entry_names_.back()->getWidth(), 0); } else { entry_names_.back()->addPath( backbuffer_width, (backbuffer_width - entry_names_.back()->getWidth()) / 2, PathType::HORIZONTAL, (i * space_between_lines) + first_line + space_between_header, 80, easeOutQuint, 0); entry_names_.back()->setPosition(backbuffer_width, 0); } break; } case 1: // Entran por la izquierda { entry_names_.back()->addPath( -entry_names_.back()->getWidth(), (backbuffer_width - entry_names_.back()->getWidth()) / 2, PathType::HORIZONTAL, (i * space_between_lines) + first_line + space_between_header, 80, easeOutQuint, 0); entry_names_.back()->setPosition(-entry_names_.back()->getWidth(), 0); break; } case 2: // Entran por la derecha { entry_names_.back()->addPath( backbuffer_width, (backbuffer_width - entry_names_.back()->getWidth()) / 2, PathType::HORIZONTAL, (i * space_between_lines) + first_line + space_between_header, 80, easeOutQuint, 0); entry_names_.back()->setPosition(backbuffer_width, 0); break; } case 3: // Entran desde la parte inferior { entry_names_.back()->addPath( backbuffer_height, (i * space_between_lines) + first_line + space_between_header, PathType::VERTICAL, (backbuffer_width - entry_names_.back()->getWidth()) / 2, 80, easeOutQuint, 0); entry_names_.back()->setPosition(0, backbuffer_height); } default: break; } } } // Actualiza las posiciones de los sprites de texto void HiScoreTable::updateSprites() { constexpr int init_counter = 190; const int counter_between_entries = 16; if (counter_ >= init_counter) { const int counter2 = counter_ - init_counter; if (counter2 % counter_between_entries == 0) { int index = counter2 / counter_between_entries; if (index < static_cast(entry_names_.size())) { entry_names_.at(index)->enable(); } } } for (auto const &entry : entry_names_) { entry->update(); } } // Inicializa el fade void HiScoreTable::initFade() { fade_->setColor(fade_color.r, fade_color.g, fade_color.b); fade_->setType(FadeType::RANDOM_SQUARE); fade_->setPostDuration(param.fade.post_duration); fade_->setMode(fade_mode_); fade_->activate(); } // Inicializa el fondo void HiScoreTable::initBackground() { background_->setPos(param.game.game_area.rect); background_->setCloudsSpeed(-0.1f); const int lucky = rand() % 3; //const int lucky = 2; switch (lucky) { case 0: // Fondo verde { background_->setGradientNumber(2); background_->setTransition(0.0f); background_->setSunProgression(1.0f); background_->setMoonProgression(0.4f); background_fade_color_ = Color(0x00, 0x79, 0x6b); break; } case 1: // Fondo naranja { background_->setGradientNumber(1); background_->setTransition(0.0f); background_->setSunProgression(0.65f); background_->setMoonProgression(0.0f); background_fade_color_ = Color(0xff, 0x6b, 0x97); break; } case 2: // Fondo azul { background_->setGradientNumber(0); background_->setTransition(0.0f); background_->setSunProgression(0.0f); background_->setMoonProgression(0.0f); background_fade_color_ = Color(0x02, 0x88, 0xd1); break; } default: break; } }