diff --git a/source/demo.cpp b/source/demo.cpp index 69b40ba..c34f5ec 100644 --- a/source/demo.cpp +++ b/source/demo.cpp @@ -12,66 +12,66 @@ Demo::Demo(SDL_Renderer *renderer, Screen *screen, Resource *resource, Asset *as rooms.push_back("60.room"); rooms.push_back("58.room"); - //rooms.push_back("01.room"); - //rooms.push_back("02.room"); - //rooms.push_back("03.room"); - //rooms.push_back("04.room"); - //rooms.push_back("05.room"); - //rooms.push_back("06.room"); - //rooms.push_back("07.room"); - //rooms.push_back("08.room"); - //rooms.push_back("09.room"); - //rooms.push_back("10.room"); - //rooms.push_back("11.room"); - //rooms.push_back("12.room"); - //rooms.push_back("13.room"); - //rooms.push_back("14.room"); - //rooms.push_back("15.room"); - //rooms.push_back("16.room"); - //rooms.push_back("17.room"); - //rooms.push_back("18.room"); - //rooms.push_back("19.room"); - //rooms.push_back("20.room"); - //rooms.push_back("21.room"); - //rooms.push_back("22.room"); - //rooms.push_back("23.room"); - //rooms.push_back("24.room"); - //rooms.push_back("25.room"); - //rooms.push_back("26.room"); - //rooms.push_back("27.room"); - //rooms.push_back("28.room"); - //rooms.push_back("29.room"); - //rooms.push_back("30.room"); - //rooms.push_back("31.room"); - //rooms.push_back("32.room"); - //rooms.push_back("33.room"); - //rooms.push_back("34.room"); - //rooms.push_back("35.room"); - //rooms.push_back("36.room"); - //rooms.push_back("37.room"); - //rooms.push_back("38.room"); - //rooms.push_back("39.room"); - //rooms.push_back("40.room"); - //rooms.push_back("41.room"); - //rooms.push_back("42.room"); - //rooms.push_back("43.room"); - //rooms.push_back("44.room"); - //rooms.push_back("45.room"); - //rooms.push_back("46.room"); - //rooms.push_back("47.room"); - //rooms.push_back("48.room"); - //rooms.push_back("49.room"); - //rooms.push_back("50.room"); - //rooms.push_back("51.room"); - //rooms.push_back("52.room"); - //rooms.push_back("53.room"); - //rooms.push_back("54.room"); - //rooms.push_back("55.room"); - //rooms.push_back("56.room"); - //rooms.push_back("57.room"); - //rooms.push_back("58.room"); - //rooms.push_back("59.room"); - //rooms.push_back("60.room"); + // rooms.push_back("01.room"); + // rooms.push_back("02.room"); + // rooms.push_back("03.room"); + // rooms.push_back("04.room"); + // rooms.push_back("05.room"); + // rooms.push_back("06.room"); + // rooms.push_back("07.room"); + // rooms.push_back("08.room"); + // rooms.push_back("09.room"); + // rooms.push_back("10.room"); + // rooms.push_back("11.room"); + // rooms.push_back("12.room"); + // rooms.push_back("13.room"); + // rooms.push_back("14.room"); + // rooms.push_back("15.room"); + // rooms.push_back("16.room"); + // rooms.push_back("17.room"); + // rooms.push_back("18.room"); + // rooms.push_back("19.room"); + // rooms.push_back("20.room"); + // rooms.push_back("21.room"); + // rooms.push_back("22.room"); + // rooms.push_back("23.room"); + // rooms.push_back("24.room"); + // rooms.push_back("25.room"); + // rooms.push_back("26.room"); + // rooms.push_back("27.room"); + // rooms.push_back("28.room"); + // rooms.push_back("29.room"); + // rooms.push_back("30.room"); + // rooms.push_back("31.room"); + // rooms.push_back("32.room"); + // rooms.push_back("33.room"); + // rooms.push_back("34.room"); + // rooms.push_back("35.room"); + // rooms.push_back("36.room"); + // rooms.push_back("37.room"); + // rooms.push_back("38.room"); + // rooms.push_back("39.room"); + // rooms.push_back("40.room"); + // rooms.push_back("41.room"); + // rooms.push_back("42.room"); + // rooms.push_back("43.room"); + // rooms.push_back("44.room"); + // rooms.push_back("45.room"); + // rooms.push_back("46.room"); + // rooms.push_back("47.room"); + // rooms.push_back("48.room"); + // rooms.push_back("49.room"); + // rooms.push_back("50.room"); + // rooms.push_back("51.room"); + // rooms.push_back("52.room"); + // rooms.push_back("53.room"); + // rooms.push_back("54.room"); + // rooms.push_back("55.room"); + // rooms.push_back("56.room"); + // rooms.push_back("57.room"); + // rooms.push_back("58.room"); + // rooms.push_back("59.room"); + // rooms.push_back("60.room"); roomIndex = 0; currentRoom = rooms.at(roomIndex); @@ -100,8 +100,7 @@ Demo::Demo(SDL_Renderer *renderer, Screen *screen, Resource *resource, Asset *as board.lives = 9; board.items = 0; board.rooms = 1; - const color_t c = room->getBorderColor(); - board.color = (c.r + c.g + c.b == 0) ? stringToColor(options->palette, "white") : c; // Si el color es negro lo cambia a blanco + setScoreBoardColor(); board.music = !debug->getEnabled(); @@ -271,8 +270,8 @@ void Demo::switchPalette() room->reLoadPalette(); scoreboard->reLoadPalette(); - const color_t c = room->getBorderColor(); - board.color = (c.r + c.g + c.b == 0) ? stringToColor(options->palette, "white") : c; // Si el color es negro lo cambia a blanco + // Pone el color del marcador en función del color del borde de la habitación + setScoreBoardColor(); } // Cambia de habitación @@ -290,9 +289,8 @@ bool Demo::changeRoom(std::string file) // Crea un objeto habitación nuevo a partir del fichero room = new Room(resource->getRoom(file), renderer, screen, asset, options, itemTracker, &board.items, debug); - // Actualiza el marcador - const color_t c = room->getBorderColor(); // Pone el color del marcador - board.color = (c.r + c.g + c.b == 0) ? stringToColor(options->palette, "white") : c; // Si el color es negro lo cambia a blanco + // Pone el color del marcador en función del color del borde de la habitación + setScoreBoardColor(); return true; } @@ -318,4 +316,19 @@ void Demo::checkRoomChange() changeRoom(rooms.at(roomIndex)); } } +} + +// Pone el color del marcador en función del color del borde de la habitación +void Demo::setScoreBoardColor() +{ + // Obtiene el color del borde + const color_t c = room->getBorderColor(); + + // Si el color es negro lo cambia a blanco + const color_t cBlack = stringToColor(options->palette, "black"); + board.color = colorAreEqual(c, cBlack) ? stringToColor(options->palette, "white") : c; + + // Si el color es negro brillante lo cambia a blanco + const color_t cBrightBlack = stringToColor(options->palette, "bright_black"); + board.color = colorAreEqual(c, cBrightBlack) ? stringToColor(options->palette, "white") : c; } \ No newline at end of file diff --git a/source/demo.h b/source/demo.h index 4811afa..ecbac51 100644 --- a/source/demo.h +++ b/source/demo.h @@ -70,6 +70,9 @@ private: // Comprueba si se ha de cambiar de habitación void checkRoomChange(); + // Pone el color del marcador en función del color del borde de la habitación + void setScoreBoardColor(); + public: // Constructor Demo(SDL_Renderer *renderer, Screen *screen, Resource *resource, Asset *asset, options_t *options, Debug *debug); diff --git a/source/director.cpp b/source/director.cpp index b5134f4..40a43a7 100644 --- a/source/director.cpp +++ b/source/director.cpp @@ -9,7 +9,7 @@ Director::Director(int argc, char *argv[]) section.name = SECTION_PROG_LOGO; section.subsection = SUBSECTION_LOGO_TO_INTRO; - section.name = SECTION_PROG_ENDING2; + section.name = SECTION_PROG_GAME; // Crea e inicializa las opciones del programa iniOptions(); diff --git a/source/ending2.cpp b/source/ending2.cpp index 30bda78..91f42b2 100644 --- a/source/ending2.cpp +++ b/source/ending2.cpp @@ -17,18 +17,27 @@ Ending2::Ending2(SDL_Renderer *renderer, Screen *screen, Resource *resource, Ass music = JA_LoadMusic(asset->get("ending2.ogg").c_str()); // Inicializa variables - counter = -1; + counterEnabled = false; preCounter = 0; + postCounter = 0; + postCounterEnabled = false; section.name = SECTION_PROG_ENDING2; section.subsection = 0; ticks = 0; ticksSpeed = 15; distSpriteText = 8; distSpriteSprite = 0; - despSpeed = -1.6f; + despSpeed = -0.2f; firstCol = GAMECANVAS_FIRST_QUARTER_X + (GAMECANVAS_WIDTH / 16); secondCol = GAMECANVAS_THIRD_QUARTER_X - (GAMECANVAS_WIDTH / 16); + // Inicializa el vector de colores + const std::vector colorList = {"white", "yellow", "cyan", "green", "magenta", "red", "blue", "black"}; + for (auto cl : colorList) + { + colors.push_back(stringToColor(options->palette, cl)); + } + // Cambia el color del borde screen->setBorderColor(stringToColor(options->palette, "black")); @@ -76,14 +85,23 @@ void Ending2::update() // Actualiza los contadores updateCounters(); - // Actualiza los sprites - updateSprites(); + if (counterEnabled) + { + // Actualiza los sprites + updateSprites(); - // Actualiza los sprites de texto - updateTextSprites(); + // Actualiza los sprites de texto + updateTextSprites(); - // Actualiza los sprites de texto del final - updateTexts(); + // Actualiza los sprites de texto del final + updateTexts(); + } + + // Actualiza el fade final + updateFinalFade(); + + // Actualiza el volumen de la musica + updateMusicVolume(); } } @@ -105,7 +123,7 @@ void Ending2::render() // Dibuja los sprites con el texto del final renderTexts(); - const std::string txt = std::to_string(preCounter) + " - " + std::to_string(counter) + " - W:" + std::to_string(maxSpriteWidth) + " - H:" + std::to_string(maxSpriteHeight); + const std::string txt = std::to_string(postCounter); // text->write(0, 192 - 8, txt); // Dibuja la cuadricula @@ -124,6 +142,7 @@ void Ending2::render() }*/ { + // Dibuja una trama arriba y abajo SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0xFF); for (int i = 0; i < 256; i += 2) { @@ -219,7 +238,7 @@ void Ending2::checkEventHandler() // Bucle principal section_t Ending2::run() { - // JA_PlayMusic(music); + JA_PlayMusic(music); while (section.name == SECTION_PROG_ENDING2) { @@ -227,7 +246,8 @@ section_t Ending2::run() render(); } - // JA_StopMusic(); + JA_StopMusic(); + JA_SetVolume(128); return section; } @@ -236,13 +256,24 @@ section_t Ending2::run() void Ending2::updateCounters() { // Incrementa el contador - if (preCounter < 100) + if (preCounter < 200) { preCounter++; } else { - counter++; + counterEnabled = true; + } + + if (postCounterEnabled) + { + postCounter++; + } + + if (postCounter > 600) + { + section.name = SECTION_PROG_LOGO; + section.subsection = SUBSECTION_LOGO_TO_INTRO; } } @@ -342,13 +373,17 @@ void Ending2::updateTextSprites() // Actualiza los sprites de texto del final void Ending2::updateTexts() { - for (auto sprite : texts) + if (texts.back()->getPosY() > GAMECANVAS_CENTER_Y) { - if (sprite->getPosY() > GAMECANVAS_CENTER_Y) + for (auto sprite : texts) { sprite->update(); } } + else + { + postCounterEnabled = true; + } } // Dibuja los sprites @@ -363,7 +398,6 @@ void Ending2::renderSprites() { sprite->getTexture()->setColor(color.r, color.g, color.b); sprite->render(); - sprite->getTexture()->setColor(255, 255, 255); } } @@ -371,7 +405,6 @@ void Ending2::renderSprites() const color_t c = stringToColor(options->palette, "white"); sprites.back()->getTexture()->setColor(c.r, c.g, c.b); sprites.back()->render(); - sprites.back()->getTexture()->setColor(255, 255, 255); } // Dibuja los sprites con el texto @@ -386,7 +419,6 @@ void Ending2::renderSpriteTexts() { sprite->getTexture()->setColor(color.r, color.g, color.b); sprite->render(); - sprite->getTexture()->setColor(255, 255, 255); } } } @@ -394,16 +426,13 @@ void Ending2::renderSpriteTexts() // Dibuja los sprites con el texto del final void Ending2::renderTexts() { - const color_t color = stringToColor(options->palette, "white"); for (auto sprite : texts) { const bool a = sprite->getRect().y + sprite->getRect().h > 0; const bool b = sprite->getRect().y < GAMECANVAS_HEIGHT; if (a && b) { - sprite->getTexture()->setColor(color.r, color.g, color.b); sprite->render(); - sprite->getTexture()->setColor(255, 255, 255); } } } @@ -414,7 +443,7 @@ void Ending2::placeSprites() for (int i = 0; i < (int)sprites.size(); ++i) { const int x = i % 2 == 0 ? firstCol : secondCol; - const int y = (i / 1) * (maxSpriteHeight + distSpriteText + text->getCharacterSize() + distSpriteSprite) + GAMECANVAS_HEIGHT; + const int y = (i / 1) * (maxSpriteHeight + distSpriteText + text->getCharacterSize() + distSpriteSprite) + GAMECANVAS_HEIGHT + 40; const int w = sprites.at(i)->getAnimationClip(0, 0).w; const int h = sprites.at(i)->getAnimationClip(0, 0).h; const int dx = -(w / 2); @@ -474,8 +503,36 @@ void Ending2::createTexts() // Borra la memoria ocupada por los sprites con las texturas de los textos del final deleteTexts(); - const int start = spriteTexts.back()->getPosY() + text->getCharacterSize() * 6; + // Crea los primeros textos std::vector list; + list.push_back("STARRING"); + + // Crea los sprites de texto a partir de la lista + for (int i = 0; i < (int)list.size(); ++i) + { + // Calcula constantes + const int w = text->lenght(list.at(i), 1); + const int h = text->getCharacterSize(); + const int x = GAMECANVAS_CENTER_X; + const int dx = -(w / 2); + const int y = GAMECANVAS_HEIGHT + (text->getCharacterSize() * (i * 2)); + + // Crea la textura + Texture *texture = new Texture(renderer); + texture->createBlank(renderer, w, h, SDL_TEXTUREACCESS_TARGET); + texture->setAsRenderTarget(renderer); + texture->setBlendMode(SDL_BLENDMODE_BLEND); + text->write(0, 0, list.at(i)); + + // Crea el sprite + MovingSprite *sprite = new MovingSprite(x + dx, y, w, h, 0.0f, despSpeed, 0.0f, 0.0f, texture, renderer); + texts.push_back(sprite); + } + + // Crea los últimos textos + // El primer texto va a continuación del ultimo spriteText + const int start = spriteTexts.back()->getPosY() + text->getCharacterSize() * 6; + list.clear(); list.push_back("THANK YOU"); list.push_back("FOR PLAYING!"); @@ -531,4 +588,28 @@ void Ending2::deleteTexts() delete text; } texts.clear(); +} + +// Actualiza el fade final +void Ending2::updateFinalFade() +{ + // La variable step va de 0 a 40 en el tramo de postCounter que va de 500 a 540. Al dividirlo por 40, va de 0.0f a 1.0f + const float step = std::min(std::max(postCounter, 500) - 500, 40) / 40.0f; + const int index = (colors.size() - 1) * step; + + for (auto t : texts) + { + t->getTexture()->setColor(colors.at(index).r, colors.at(index).g, colors.at(index).b); + } +} + +// Actualiza el volumen de la musica +void Ending2::updateMusicVolume() +{ + if (postCounter > 0) + { + const float step = (600.0f - postCounter) / 600.0f; + const int volume = 128 * step; + JA_SetVolume(volume); + } } \ No newline at end of file diff --git a/source/ending2.h b/source/ending2.h index 4dbd198..918890e 100644 --- a/source/ending2.h +++ b/source/ending2.h @@ -32,13 +32,16 @@ private: std::vector texts; // Vector con los sprites de texto // Variables - int counter; // Contador + bool counterEnabled; // Indica si está el contador habilitado int preCounter; // Contador previo + int postCounter; // Contador posterior + bool postCounterEnabled; // Indica si está habilitado el contador section_t section; // Estado del bucle principal para saber si continua o se sale Uint32 ticks; // Contador de ticks para ajustar la velocidad del programa Uint32 ticksSpeed; // Velocidad a la que se repiten los bucles del programa JA_Music music; // Musica que suena durante el final std::vector spriteList; // Lista con todos los sprites a dibujar + std::vector colors; // Vector con los colores para el fade int maxSpriteWidth; // El valor de ancho del sprite mas ancho int maxSpriteHeight; // El valor de alto del sprite mas alto int distSpriteText; // Distancia entre el sprite y el texto que lo acompaña @@ -101,6 +104,12 @@ private: // Borra la memoria ocupada por los sprites con las texturas de los textos del final void deleteTexts(); + // Actualiza el fade final + void updateFinalFade(); + + // Actualiza el volumen de la musica + void updateMusicVolume(); + public: // Constructor Ending2(SDL_Renderer *renderer, Screen *screen, Resource *resource, Asset *asset, options_t *options); diff --git a/source/game.cpp b/source/game.cpp index 90d8e24..37286a4 100644 --- a/source/game.cpp +++ b/source/game.cpp @@ -45,16 +45,14 @@ Game::Game(SDL_Renderer *renderer, Screen *screen, Resource *resource, Asset *as board.lives = 9; board.items = 0; board.rooms = 1; - const color_t c = room->getBorderColor(); - board.color = (c.r + c.g + c.b == 0) ? stringToColor(options->palette, "white") : c; // Si el color es negro lo cambia a blanco + setScoreBoardColor(); + board.music = true; + board.jailEnabled = false; roomTracker->addRoom(currentRoom); paused = false; blackScreen = false; blackScreenCounter = 0; - // this->player->setInvincible(debug->getEnabled()); - // board.music = !debug->getEnabled(); - section.name = SECTION_PROG_GAME; section.subsection = 0; } @@ -503,10 +501,16 @@ void Game::setScoreBoardColor() // Comprueba si ha finalizado el juego bool Game::checkEndGame() { + const bool a = room->getName() == "THE JAIL"; - const bool b = board.items >= 2; + const bool b = board.items >= 5; const bool c = player->getRect().x < 152; + if (b) + { + board.jailEnabled = true; + } + if (a && b && c) { section.name = SECTION_PROG_ENDING; diff --git a/source/intro.cpp b/source/intro.cpp index a1396a4..34a462b 100644 --- a/source/intro.cpp +++ b/source/intro.cpp @@ -281,6 +281,7 @@ void Intro::render() section_t Intro::run() { // Inicia el sonido de carga + JA_SetVolume(64); JA_PlayMusic(loadingSound1); while (section.name == SECTION_PROG_INTRO) @@ -289,6 +290,7 @@ section_t Intro::run() render(); } + JA_SetVolume(128); return section; } diff --git a/source/scoreboard.cpp b/source/scoreboard.cpp index 3610d74..397af3e 100644 --- a/source/scoreboard.cpp +++ b/source/scoreboard.cpp @@ -13,7 +13,7 @@ ScoreBoard::ScoreBoard(SDL_Renderer *renderer, Resource *resource, Asset *asset, this->options = options; // Reserva memoria para los objetos - //playerTexture = resource->getTexture("player.png"); + // playerTexture = resource->getTexture("player.png"); itemTexture = resource->getTexture("items.png"); sprite = new AnimatedSprite(renderer, resource->getAnimation("player.ani")); sprite->setCurrentAnimation("walk_menu"); @@ -25,6 +25,7 @@ ScoreBoard::ScoreBoard(SDL_Renderer *renderer, Resource *resource, Asset *asset, paused = false; timePaused = 0; totalTimePaused = 0; + itemsColor = stringToColor(options->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"}; @@ -79,7 +80,7 @@ void ScoreBoard::render() const std::string timeTxt = std::to_string((clock.minutes % 60) / 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(board->items / 100) + std::to_string((board->items % 100) / 10) + std::to_string(board->items % 10); this->text->writeColored(BLOCK, line1, "Items collected ", board->color); - this->text->writeColored(17 * BLOCK, line1, itemsTxt, stringToColor(options->palette, "white")); + this->text->writeColored(17 * BLOCK, line1, itemsTxt, itemsColor); this->text->writeColored(20 * BLOCK, line1, " Time ", board->color); this->text->writeColored(26 * BLOCK, line1, timeTxt, stringToColor(options->palette, "white")); @@ -94,6 +95,9 @@ void ScoreBoard::update() counter++; sprite->update(); + // Actualiza el color de la cantidad de items recogidos + updateItemsColor(); + if (!paused) { // Si está en pausa no se actualiza el reloj clock = getTime(); @@ -118,7 +122,7 @@ ScoreBoard::clock_t ScoreBoard::getTime() void ScoreBoard::reLoadTexture() { sprite->getTexture()->reLoad(); - //playerTexture->reLoad(); + // playerTexture->reLoad(); itemTexture->reLoad(); text->reLoadTexture(); } @@ -147,4 +151,22 @@ void ScoreBoard::resume() { paused = false; totalTimePaused += SDL_GetTicks() - timePaused; +} + +// Actualiza el color de la cantidad de items recogidos +void ScoreBoard::updateItemsColor() +{ + if (!board->jailEnabled) + { + return; + } + + if (counter % 20 <10) + { + itemsColor = stringToColor(options->palette, "white"); + } + else + { + itemsColor = stringToColor(options->palette, "magenta"); + } } \ No newline at end of file diff --git a/source/scoreboard.h b/source/scoreboard.h index f994cc8..7e34c48 100644 --- a/source/scoreboard.h +++ b/source/scoreboard.h @@ -14,12 +14,13 @@ struct board_t { - int items; // Lleva la cuenta de los objetos recogidos - int lives; // Lleva la cuenta de ls vidas restantes del jugador - int rooms; // Lleva la cuenta de las habitaciones visitadas - bool music; // Indica si ha de sonar la musica durante el juego - color_t color; // Color para escribir el texto del marcador - Uint32 iniClock; + int items; // Lleva la cuenta de los objetos recogidos + int lives; // Lleva la cuenta de ls vidas restantes del jugador + int rooms; // Lleva la cuenta de las habitaciones visitadas + bool music; // Indica si ha de sonar la musica durante el juego + color_t color; // Color para escribir el texto del marcador + Uint32 iniClock; // Tiempo inicial para calcular el tiempo transcurrido + bool jailEnabled; // Indica si se puede entrar a la Jail }; class ScoreBoard @@ -34,7 +35,6 @@ private: }; // Objetos y punteros - //Texture *playerTexture; // Textura con los graficos para las vidas AnimatedSprite *sprite; // Sprite para mostrar las vidas en el marcador SDL_Renderer *renderer; // El renderizador de la ventana Resource *resource; // Objeto con los recursos @@ -52,10 +52,14 @@ private: Uint32 timePaused; // Milisegundos que ha estado el marcador en pausa Uint32 totalTimePaused; // Tiempo acumulado en pausa clock_t clock; // Contiene las horas, minutos y segundos transcurridos desde el inicio de la partida + color_t itemsColor; // Color de la cantidad de items recogidos // Obtiene el tiempo transcurrido de partida clock_t getTime(); + // Actualiza el color de la cantidad de items recogidos + void updateItemsColor(); + public: // Constructor ScoreBoard(SDL_Renderer *renderer, Resource *resource, Asset *asset, options_t *options, board_t *board); diff --git a/source/title.cpp b/source/title.cpp index 2ee9339..caaf1b9 100644 --- a/source/title.cpp +++ b/source/title.cpp @@ -29,8 +29,8 @@ Title::Title(SDL_Renderer *renderer, Screen *screen, Resource *resource, Asset * section.subsection = 0; ticks = 0; ticksSpeed = 15; - //longText = "HEY JAILERS!! IT'S 2022 AND WE'RE STILL ROCKING LIKE IT'S 1998!!! HAVE YOU HEARD IT? JAILGAMES ARE BACK!! YEEESSS BACK!! MORE THAN 10 TITLES ON JAILDOC'S KITCHEN!! THATS A LOOOOOOT OF JAILGAMES, BUT WHICH ONE WILL STRIKE FIRST? THERE IS ALSO A NEW DEVICE TO COME P.A.C.O. THAT WILL BLOW YOUR MIND WITH JAILGAMES ON THE GO. BUT WAIT! WHAT'S THAT BEAUTY I'M SEEING RIGHT OVER THERE?? OOOH THAT TINY MINIASCII IS PURE LOVE!! I WANT TO LICK EVERY BYTE OF IT!! OH SHIT! AND DON'T FORGET TO BRING BACK THOSE OLD AND FAT MS-DOS JAILGAMES TO GITHUB TO KEEP THEM ALIVE!! WHAT WILL BE THE NEXT JAILDOC RELEASE? WHAT WILL BE THE NEXT PROJECT TO COME ALIVE?? OH BABY WE DON'T KNOW BUT HERE YOU CAN FIND THE ANSWER, YOU JUST HAVE TO COMPLETE JAILDOCTOR'S DILEMMA ... COULD YOU?"; - longText = "HEY JAILERS!! IT'S 2022 AND WE'RE STILL ROCKING LIKE IT'S 1998!!!"; + longText = "HEY JAILERS!! IT'S 2022 AND WE'RE STILL ROCKING LIKE IT'S 1998!!! HAVE YOU HEARD IT? JAILGAMES ARE BACK!! YEEESSS BACK!! MORE THAN 10 TITLES ON JAILDOC'S KITCHEN!! THATS A LOOOOOOT OF JAILGAMES, BUT WHICH ONE WILL STRIKE FIRST? THERE IS ALSO A NEW DEVICE TO COME THAT WILL BLOW YOUR MIND WITH JAILGAMES ON THE GO: P. A. C. O BUT WAIT! WHAT'S THAT BEAUTY I'M SEEING RIGHT OVER THERE?? OOOH THAT TINY MINIASCII IS PURE LOVE!! I WANT TO LICK EVERY BYTE OF IT!! OH SHIT! AND DON'T FORGET TO BRING BACK THOSE OLD AND FAT MS-DOS JAILGAMES TO GITHUB TO KEEP THEM ALIVE!! WHAT WILL BE THE NEXT JAILDOC RELEASE? WHAT WILL BE THE NEXT PROJECT TO COME ALIVE?? OH BABY WE DON'T KNOW BUT HERE YOU CAN FIND THE ANSWER, YOU JUST HAVE TO COMPLETE JAILDOCTOR'S DILEMMA ... COULD YOU?"; + //longText = "HEY JAILERS!! IT'S 2022 AND WE'RE STILL ROCKING LIKE IT'S 1998!!!"; for (int i = 0; i < (int)longText.length(); ++i) { letter_t l;