#include "hiscore_table.h" #include "service.h" #include // Constructor HiScoreTable::HiScoreTable(Screen *screen, Asset *asset, Input *input, Lang *lang, options_t *options, param_t *param, section_t *section, JA_Music_t *music) { // Copia punteros this->screen = screen; this->asset = asset; this->input = input; this->lang = lang; this->section = section; this->options = options; this->param = param; this->music = music; renderer = screen->getRenderer(); // Objetos eventHandler = new SDL_Event(); fade = new Fade(renderer, param); background = new Background(renderer, asset, param); text = new Text(asset->get("smb2.gif"), asset->get("smb2.txt"), renderer); // Crea un backbuffer para el renderizador backbuffer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param->game.width, param->game.height); SDL_SetTextureBlendMode(backbuffer, SDL_BLENDMODE_BLEND); // Inicializa variables section->name = SECTION_PROG_HI_SCORE_TABLE; ticks = 0; ticksSpeed = 15; counter = 0; counterEnd = 800; viewArea = {0, 0, param->game.width, param->game.height}; fadeMode = FADE_IN; // Inicializa objetos background->setPos(param->game.gameArea.rect); background->setCloudsSpeed(-0.1f); background->setGradientNumber(1); background->setTransition(0.8f); fade->setColor(fadeColor.r, fadeColor.g, fadeColor.b); fade->setType(FADE_RANDOM_SQUARE); fade->setPost(param->fade.postDuration); fade->setMode(fadeMode); fade->activate(); // Crea el contenido de la textura con la lista de puntuaciones fillTexture(); } // Destructor HiScoreTable::~HiScoreTable() { delete text; delete eventHandler; delete background; SDL_DestroyTexture(backbuffer); } // Actualiza las variables void HiScoreTable::update() { // Actualiza las variables if (SDL_GetTicks() - ticks > ticksSpeed) { // 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(music); // Actualiza el objeto screen screen->update(); // Actualiza el fondo background->update(); // Gestiona el fade updateFade(); // Gestiona el contador y sus eventos counter++; if (counter == 150) { background->setColor({0, 0, 0}); background->setAlpha(96); } if (counter == counterEnd) { fade->activate(); } } } // Crea el contenido de la textura con la lista de puntuaciones void HiScoreTable::fillTexture() { // hay 27 letras - 7 de puntos quedan 20 caracteres 20 - nameLenght 0 numDots const int maxNames = 10; const int spaceBetweenHeader = 32; const int spaceBetweenLines = text->getCharacterSize() * 2.0f; const int size = spaceBetweenHeader + spaceBetweenLines * (maxNames - 1) + text->getCharacterSize(); const int firstLine = (param->game.height - size) / 2; // Pinta en el backbuffer el texto y los sprites SDL_Texture *temp = SDL_GetRenderTarget(renderer); SDL_SetRenderTarget(renderer, backbuffer); SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); SDL_RenderClear(renderer); // Escribe el texto: Mejores puntuaciones text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, param->game.gameArea.centerX, firstLine, lang->getText(42), 1, orangeColor, 1, shdwTxtColor); // Escribe los nombres de la tabla de puntuaciones for (int i = 0; i < maxNames; ++i) { const int nameLenght = options->game.hiScoreTable[i].name.length(); const std::string score = format(options->game.hiScoreTable[i].score); const int scoreLenght = score.size(); const int numDots = 25 - nameLenght - scoreLenght; std::string dots = ""; for (int j = 0; j < numDots; ++j) { dots = dots + "."; } const std::string line = options->game.hiScoreTable[i].name + dots + score; text->writeDX(TXT_CENTER | TXT_SHADOW, param->game.gameArea.centerX, (i * spaceBetweenLines) + firstLine + spaceBetweenHeader, line, 1, orangeColor, 1, shdwTxtColor); } // 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->start(); // Limpia la pantalla screen->clean(bgColor); // Pinta el fondo background->render(); // Establece la ventana del backbuffer viewArea.y = std::max(0, param->game.height - counter + 100); // Copia el backbuffer al renderizador SDL_RenderCopy(renderer, backbuffer, nullptr, &viewArea); fade->render(); // Vuelca el contenido del renderizador en pantalla screen->blit(); } // Recarga todas las texturas void HiScoreTable::reloadTextures() { text->reLoadTexture(); fillTexture(); } // Comprueba los eventos void HiScoreTable::checkEvents() { // Comprueba los eventos que hay en la cola while (SDL_PollEvent(eventHandler) != 0) { // Evento de salida de la aplicación if (eventHandler->type == SDL_QUIT) { section->name = SECTION_PROG_QUIT; break; } // Comprueba si se ha cambiado el tamaño de la ventana else if (eventHandler->type == SDL_WINDOWEVENT) { if (eventHandler->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { reloadTextures(); } } } } // Comprueba las entradas void HiScoreTable::checkInput() { if (input->checkInput(input_exit, INPUT_DO_NOT_ALLOW_REPEAT)) { section->name = SECTION_PROG_QUIT; section->options = SECTION_OPTIONS_QUIT_NORMAL; } else if (input->checkAnyButtonPressed()) { JA_StopMusic(); section->name = SECTION_PROG_TITLE; section->options = SECTION_OPTIONS_TITLE_1; } // Comprueba el botón de SERVICE switch (checkServiceButton(input)) { case SERVICE_RESET: { section->name = SECTION_PROG_LOGO; screen->showNotification("Reset"); break; } case SERVICE_MUTE: { const bool value = !options->audio.music.enabled; options->audio.music.enabled = value; options->audio.sound.enabled = value; JA_EnableMusic(value); JA_EnableSound(value); const std::string text = value ? "on" : "off"; screen->showNotification("Audio " + text); break; } default: { break; } } // Comprueba el input para el resto de objetos screen->checkInput(); } // Bucle para la pantalla de instrucciones void HiScoreTable::run() { while (section->name == SECTION_PROG_HI_SCORE_TABLE) { checkInput(); update(); checkEvents(); // Tiene que ir antes del render render(); } } // Transforma un valor numérico en una cadena de 6 cifras std::string HiScoreTable::scoreToString(int num) { if ((num >= 0) && (num <= 9)) { return ("000000" + std::to_string(num)); } if ((num >= 10) && (num <= 99)) { return ("00000" + std::to_string(num)); } if ((num >= 100) && (num <= 999)) { return ("0000" + std::to_string(num)); } if ((num >= 1000) && (num <= 9999)) { return ("000" + std::to_string(num)); } if ((num >= 010000) && (num <= 99999)) { return ("00" + std::to_string(num)); } if ((num >= 100000) && (num <= 999999)) { return ("0" + std::to_string(num)); } if ((num >= 1000000) && (num <= 9999999)) { return (std::to_string(num)); } return (std::to_string(num)); } // Gestiona el fade void HiScoreTable::updateFade() { fade->update(); if (fade->hasEnded() && fadeMode == FADE_IN) { fade->reset(); fadeMode = FADE_OUT; fade->setMode(fadeMode); } if (fade->hasEnded() && fadeMode == FADE_OUT) { section->name = SECTION_PROG_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); int index = (int)score.size() - 1; std::string result = ""; int i = 0; while (index >= 0) { result = score.at(index) + result; index--; i++; if (i == 3) { i = 0; result = separator + result; } } return result; }