Files
jaildoctors_dilemma/source/ending2.cpp

615 lines
17 KiB
C++

#include "ending2.h"
#include <algorithm>
// Constructor
Ending2::Ending2(SDL_Renderer *renderer, Screen *screen, Resource *resource, Asset *asset, options_t *options)
{
// Copia los punteros
this->renderer = renderer;
this->screen = screen;
this->resource = resource;
this->asset = asset;
this->options = options;
// Reserva memoria para los punteros a objetos
eventHandler = new SDL_Event();
text = new Text(resource->getOffset("smb2.txt"), resource->getTexture("smb2.png"), renderer);
music = JA_LoadMusic(asset->get("ending2.ogg").c_str());
// Inicializa variables
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 = -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<std::string> 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"));
// Inicializa la lista de sprites
iniSpriteList();
// Carga todos los sprites desde una lista
loadSprites();
// Coloca los sprites en su sito
placeSprites();
// Crea los sprites con las texturas con los textos
createSpriteTexts();
// Crea los sprites con las texturas con los textos del final
createTexts();
}
// Destructor
Ending2::~Ending2()
{
// Libera la memoria de los objetos
delete eventHandler;
delete text;
JA_DeleteMusic(music);
deleteSprites();
deleteSpriteTexts();
deleteTexts();
}
// Actualiza el objeto
void Ending2::update()
{
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
if (SDL_GetTicks() - ticks > ticksSpeed)
{
// Actualiza el contador de ticks
ticks = SDL_GetTicks();
// Comprueba el manejador de eventos
checkEventHandler();
// Actualiza los contadores
updateCounters();
if (counterEnabled)
{
// Actualiza los sprites
updateSprites();
// Actualiza los sprites de texto
updateTextSprites();
// Actualiza los sprites de texto del final
updateTexts();
}
// Actualiza el fade final
updateFinalFade();
// Actualiza el volumen de la musica
updateMusicVolume();
}
}
// Dibuja el final en pantalla
void Ending2::render()
{
// Prepara para empezar a dibujar en la textura de juego
screen->start();
// Limpia la pantalla
screen->clean(stringToColor(options->palette, "black"));
// Dibuja los sprites
renderSprites();
// Dibuja los sprites con el texto
renderSpriteTexts();
// Dibuja los sprites con el texto del final
renderTexts();
const std::string txt = std::to_string(postCounter);
// text->write(0, 192 - 8, txt);
// Dibuja la cuadricula
/*{
SDL_SetRenderDrawColor(renderer, 128, 128, 128, 255);
const int sw = maxSpriteWidth + 6;
const int sh = maxSpriteHeight + 6;
for (int i = 0; i < 256; i += sw)
{
SDL_RenderDrawLine(renderer, i, 0, i, 192);
}
for (int i = 0; i < 192; i += sh)
{
SDL_RenderDrawLine(renderer, 0, i, 255, i);
}
}*/
{
// Dibuja una trama arriba y abajo
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0xFF);
for (int i = 0; i < 256; i += 2)
{
SDL_RenderDrawPoint(renderer, i + 0, 0);
SDL_RenderDrawPoint(renderer, i + 1, 1);
SDL_RenderDrawPoint(renderer, i + 0, 2);
SDL_RenderDrawPoint(renderer, i + 1, 3);
SDL_RenderDrawPoint(renderer, i, 4);
SDL_RenderDrawPoint(renderer, i, 6);
SDL_RenderDrawPoint(renderer, i + 0, 191);
SDL_RenderDrawPoint(renderer, i + 1, 190);
SDL_RenderDrawPoint(renderer, i + 0, 189);
SDL_RenderDrawPoint(renderer, i + 1, 188);
SDL_RenderDrawPoint(renderer, i, 187);
SDL_RenderDrawPoint(renderer, i, 185);
}
// SDL_RenderDrawLine(renderer, 0, 1, 255, 1);
// SDL_RenderDrawLine(renderer, 0, 3, 255, 3);
// SDL_RenderDrawLine(renderer, 0, 188, 255, 188);
// SDL_RenderDrawLine(renderer, 0, 190, 255, 190);
}
// Vuelca el contenido del renderizador en pantalla
screen->blit();
}
// Comprueba el manejador de eventos
void Ending2::checkEventHandler()
{
// 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 las teclas que se han pulsado
if ((eventHandler->type == SDL_KEYDOWN && eventHandler->key.repeat == 0) || (eventHandler->type == SDL_JOYBUTTONDOWN))
{
switch (eventHandler->key.keysym.scancode)
{
case SDL_SCANCODE_ESCAPE:
section.name = SECTION_PROG_QUIT;
break;
case SDL_SCANCODE_B:
screen->switchBorder();
resource->reLoadTextures();
break;
case SDL_SCANCODE_F:
screen->switchVideoMode();
resource->reLoadTextures();
break;
case SDL_SCANCODE_F1:
screen->setWindowSize(1);
resource->reLoadTextures();
break;
case SDL_SCANCODE_F2:
screen->setWindowSize(2);
resource->reLoadTextures();
break;
case SDL_SCANCODE_F3:
screen->setWindowSize(3);
resource->reLoadTextures();
break;
case SDL_SCANCODE_F4:
screen->setWindowSize(4);
resource->reLoadTextures();
break;
case SDL_SCANCODE_F5:
// switchPalette();
break;
default:
break;
}
}
}
}
// Bucle principal
section_t Ending2::run()
{
JA_PlayMusic(music);
while (section.name == SECTION_PROG_ENDING2)
{
update();
render();
}
JA_StopMusic();
JA_SetVolume(128);
return section;
}
// Actualiza los contadores
void Ending2::updateCounters()
{
// Incrementa el contador
if (preCounter < 200)
{
preCounter++;
}
else
{
counterEnabled = true;
}
if (postCounterEnabled)
{
postCounter++;
}
if (postCounter > 600)
{
section.name = SECTION_PROG_LOGO;
section.subsection = SUBSECTION_LOGO_TO_INTRO;
}
}
// Inicializa la lista de sprites
void Ending2::iniSpriteList()
{
// Reinicia el vector
spriteList.clear();
// Añade los valores
spriteList.push_back("abad");
spriteList.push_back("abad_bell");
spriteList.push_back("amstrad_cs");
spriteList.push_back("arounder_fly");
spriteList.push_back("arounder_stop");
spriteList.push_back("arounder_walk");
spriteList.push_back("arounders_door");
spriteList.push_back("arounders_machine");
spriteList.push_back("bat");
spriteList.push_back("batman_bell");
spriteList.push_back("batman_fire");
spriteList.push_back("batman");
spriteList.push_back("bell");
spriteList.push_back("bin");
spriteList.push_back("bird");
spriteList.push_back("breakout");
spriteList.push_back("bry");
spriteList.push_back("chip");
spriteList.push_back("code");
spriteList.push_back("demon");
spriteList.push_back("heavy");
spriteList.push_back("dimallas");
spriteList.push_back("diskette");
spriteList.push_back("dong");
spriteList.push_back("guitar");
spriteList.push_back("jb_alien");
spriteList.push_back("jb_human");
spriteList.push_back("jailer");
spriteList.push_back("jailer2");
spriteList.push_back("jailer3");
spriteList.push_back("lamp");
spriteList.push_back("macaronni_ted");
spriteList.push_back("matatunos");
spriteList.push_back("mummy");
spriteList.push_back("paco");
spriteList.push_back("printer");
spriteList.push_back("qvoid");
spriteList.push_back("sam");
spriteList.push_back("sigmasua");
spriteList.push_back("spider");
spriteList.push_back("tuno");
spriteList.push_back("tv_panel");
spriteList.push_back("tv");
spriteList.push_back("shock");
spriteList.push_back("wave");
spriteList.push_back("player");
}
// Carga todos los sprites desde una lista
void Ending2::loadSprites()
{
// Borra la memoria ocupada por los sprites
deleteSprites();
// Inicializa variables
maxSpriteWidth = 0;
maxSpriteHeight = 0;
// Carga los sprites
for (auto sl : spriteList)
{
sprites.push_back(new AnimatedSprite(renderer, resource->getAnimation(sl + ".ani")));
maxSpriteWidth = std::max(sprites.back()->getAnimationClip(0, 0).w, maxSpriteWidth);
maxSpriteHeight = std::max(sprites.back()->getAnimationClip(0, 0).h, maxSpriteHeight);
}
}
// Actualiza los sprites
void Ending2::updateSprites()
{
for (auto sprite : sprites)
{
sprite->update();
}
}
// Actualiza los sprites de texto
void Ending2::updateTextSprites()
{
for (auto sprite : spriteTexts)
{
sprite->update();
}
}
// Actualiza los sprites de texto del final
void Ending2::updateTexts()
{
if (texts.back()->getPosY() > GAMECANVAS_CENTER_Y)
{
for (auto sprite : texts)
{
sprite->update();
}
}
else
{
postCounterEnabled = true;
}
}
// Dibuja los sprites
void Ending2::renderSprites()
{
const color_t color = stringToColor(options->palette, "red");
for (auto sprite : sprites)
{
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();
}
}
// Pinta el ultimo elemento de otro color
const color_t c = stringToColor(options->palette, "white");
sprites.back()->getTexture()->setColor(c.r, c.g, c.b);
sprites.back()->render();
}
// Dibuja los sprites con el texto
void Ending2::renderSpriteTexts()
{
const color_t color = stringToColor(options->palette, "white");
for (auto sprite : spriteTexts)
{
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();
}
}
}
// Dibuja los sprites con el texto del final
void Ending2::renderTexts()
{
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->render();
}
}
}
// Coloca los sprites en su sito
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 + 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);
const int dy = i % 1 == 0 ? maxSpriteHeight - h : (int)(maxSpriteHeight * 1.5f) - h;
sprites.at(i)->setRect({x + dx, y + dy, w, h});
sprites.at(i)->setVelY(despSpeed);
}
// Recoloca el último sprite, que es el del jugador
const int w = sprites.back()->getAnimationClip(0, 0).w;
const int x = GAMECANVAS_CENTER_X - (w / 2);
const int y = sprites.back()->getPosY() + maxSpriteHeight * 2;
sprites.back()->setPosX(x);
sprites.back()->setPosY(y);
sprites.back()->setCurrentAnimation("walk");
}
// Crea los sprites con las texturas con los textos
void Ending2::createSpriteTexts()
{
// Borra la memoria ocupada por los sprites con las texturas de los textos
deleteSpriteTexts();
// Crea los sprites de texto a partir de la lista
for (int i = 0; i < (int)spriteList.size(); ++i)
{
// Calcula constantes
std::string txt = spriteList.at(i);
std::replace(txt.begin(), txt.end(), '_', ' ');
txt = txt == "player" ? "JAILDOCTOR" : txt; // Reemplaza el texto
const int w = text->lenght(txt, 1);
const int h = text->getCharacterSize();
const int x = i % 2 == 0 ? firstCol : secondCol;
const int dx = -(w / 2);
const int y = sprites.at(i)->getPosY() + sprites.at(i)->getHeight() + distSpriteText;
// Cambia la posición del último sprite
const int X = (i == (int)spriteList.size() - 1) ? GAMECANVAS_CENTER_X - (w / 2) : x + dx;
// 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, txt);
// Crea el sprite
MovingSprite *sprite = new MovingSprite(X, y, w, h, 0.0f, despSpeed, 0.0f, 0.0f, texture, renderer);
spriteTexts.push_back(sprite);
}
}
// Crea los sprites con las texturas con los textos del final
void Ending2::createTexts()
{
// Borra la memoria ocupada por los sprites con las texturas de los textos del final
deleteTexts();
// Crea los primeros textos
std::vector<std::string> 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!");
// 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 = start + (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);
}
}
// Borra la memoria ocupada por los sprites con las texturas de los textos
void Ending2::deleteSpriteTexts()
{
for (auto sprite : spriteTexts)
{
delete sprite->getTexture();
delete sprite;
}
spriteTexts.clear();
}
// Borra la memoria ocupada por los sprites
void Ending2::deleteSprites()
{
for (auto sprite : sprites)
{
delete sprite;
}
sprites.clear();
}
// Borra la memoria ocupada por los sprites con las texturas de los textos del final
void Ending2::deleteTexts()
{
for (auto text : texts)
{
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);
}
}