553 lines
16 KiB
C++
553 lines
16 KiB
C++
#include "ending2.h"
|
|
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
|
|
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event
|
|
#include <SDL2/SDL_rect.h> // for SDL_Rect
|
|
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
|
|
#include <algorithm> // for max, min, replace
|
|
#include "animated_sprite.h" // for AnimatedSprite
|
|
#include "asset.h" // for Asset
|
|
#include "defines.h" // for GAMECANVAS_HEIGHT, GAMECANVAS_CENTER_X
|
|
#include "global_events.h" // for check
|
|
#include "global_inputs.h" // for check
|
|
#include "input.h" // for Input
|
|
#include "jail_audio.h" // for JA_SetVolume, JA_PlayMusic, JA_StopM...
|
|
#include "moving_sprite.h" // for MovingSprite
|
|
#include "options.h" // for Options, options, OptionsVideo, Sect...
|
|
#include "resource.h" // for Resource
|
|
#include "screen.h" // for Screen
|
|
#include "text.h" // for Text
|
|
#include "texture.h" // for Texture
|
|
#include "utils.h" // for Color, stringToColor
|
|
|
|
// Constructor
|
|
Ending2::Ending2()
|
|
: screen_(Screen::get()),
|
|
renderer_(Screen::get()->getRenderer()),
|
|
resource_(Resource::get()),
|
|
asset_(Asset::get()),
|
|
input_(Input::get())
|
|
{
|
|
// Reserva memoria para los punteros a objetos
|
|
text_ = resource_->getText("smb2");
|
|
music_ = resource_->getMusic("ending2.ogg");
|
|
|
|
// Inicializa variables
|
|
counter_enabled_ = false;
|
|
pre_counter_ = 0;
|
|
post_counter_ = 0;
|
|
post_counter_enabled_ = false;
|
|
options.section.section = Section::ENDING2;
|
|
options.section.subsection = Subsection::NONE;
|
|
ticks_ = 0;
|
|
dist_sprite_text_ = 8;
|
|
dist_sprite_sprite_ = 0;
|
|
sprite_desp_speed_ = -0.2f;
|
|
|
|
// Inicializa el vector de colores
|
|
const std::vector<std::string> color_list = {"white", "yellow", "cyan", "green", "magenta", "red", "blue", "black"};
|
|
for (auto color : color_list)
|
|
{
|
|
colors_.push_back(stringToColor(options.video.palette, color));
|
|
}
|
|
|
|
// Cambia el color del borde
|
|
screen_->setBorderColor(stringToColor(options.video.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();
|
|
}
|
|
|
|
// Actualiza el objeto
|
|
void Ending2::update()
|
|
{
|
|
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
|
|
if (SDL_GetTicks() - ticks_ > GAME_SPEED)
|
|
{
|
|
// Actualiza el contador de ticks
|
|
ticks_ = SDL_GetTicks();
|
|
|
|
// Comprueba las entradas
|
|
checkInput();
|
|
|
|
// Actualiza los contadores
|
|
updateCounters();
|
|
|
|
if (counter_enabled_)
|
|
{
|
|
// 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();
|
|
|
|
screen_->update();
|
|
}
|
|
}
|
|
|
|
// 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.video.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(post_counter_);
|
|
// 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_->render();
|
|
}
|
|
|
|
// Comprueba el manejador de eventos
|
|
void Ending2::checkEvents()
|
|
{
|
|
SDL_Event event;
|
|
while (SDL_PollEvent(&event))
|
|
{
|
|
globalEvents::check(event);
|
|
}
|
|
}
|
|
|
|
// Comprueba las entradas
|
|
void Ending2::checkInput()
|
|
{
|
|
globalInputs::check();
|
|
}
|
|
|
|
// Bucle principal
|
|
void Ending2::run()
|
|
{
|
|
JA_PlayMusic(music_);
|
|
|
|
while (options.section.section == Section::ENDING2)
|
|
{
|
|
update();
|
|
checkEvents();
|
|
render();
|
|
}
|
|
|
|
JA_StopMusic();
|
|
JA_SetVolume(128);
|
|
}
|
|
|
|
// Actualiza los contadores
|
|
void Ending2::updateCounters()
|
|
{
|
|
// Incrementa el contador
|
|
if (pre_counter_ < 200)
|
|
{
|
|
pre_counter_++;
|
|
}
|
|
else
|
|
{
|
|
counter_enabled_ = true;
|
|
}
|
|
|
|
if (post_counter_enabled_)
|
|
{
|
|
post_counter_++;
|
|
}
|
|
|
|
if (post_counter_ > 600)
|
|
{
|
|
options.section.section = Section::LOGO;
|
|
options.section.subsection = Subsection::LOGO_TO_INTRO;
|
|
}
|
|
}
|
|
|
|
// Inicializa la lista de sprites
|
|
void Ending2::iniSpriteList()
|
|
{
|
|
// Reinicia el vector
|
|
sprite_list_.clear();
|
|
|
|
// Añade los valores
|
|
sprite_list_.push_back("bin");
|
|
sprite_list_.push_back("floppy");
|
|
sprite_list_.push_back("bird");
|
|
sprite_list_.push_back("chip");
|
|
sprite_list_.push_back("jeannine");
|
|
sprite_list_.push_back("spark");
|
|
sprite_list_.push_back("code");
|
|
sprite_list_.push_back("paco");
|
|
sprite_list_.push_back("elsa");
|
|
sprite_list_.push_back("z80");
|
|
|
|
sprite_list_.push_back("bell");
|
|
sprite_list_.push_back("dong");
|
|
|
|
sprite_list_.push_back("amstrad_cs");
|
|
sprite_list_.push_back("breakout");
|
|
|
|
sprite_list_.push_back("flying_arounder");
|
|
sprite_list_.push_back("stopped_arounder");
|
|
sprite_list_.push_back("walking_arounder");
|
|
sprite_list_.push_back("arounders_door");
|
|
sprite_list_.push_back("arounders_machine");
|
|
|
|
sprite_list_.push_back("abad");
|
|
sprite_list_.push_back("abad_bell");
|
|
sprite_list_.push_back("lord_abad");
|
|
|
|
sprite_list_.push_back("bat");
|
|
sprite_list_.push_back("batman_bell");
|
|
sprite_list_.push_back("batman_fire");
|
|
sprite_list_.push_back("batman");
|
|
|
|
sprite_list_.push_back("demon");
|
|
sprite_list_.push_back("heavy");
|
|
sprite_list_.push_back("dimallas");
|
|
sprite_list_.push_back("guitar");
|
|
|
|
sprite_list_.push_back("jailbattle_alien");
|
|
sprite_list_.push_back("jailbattle_human");
|
|
|
|
sprite_list_.push_back("jailer_#1");
|
|
sprite_list_.push_back("jailer_#2");
|
|
sprite_list_.push_back("jailer_#3");
|
|
sprite_list_.push_back("bry");
|
|
sprite_list_.push_back("upv_student");
|
|
|
|
sprite_list_.push_back("lamp");
|
|
sprite_list_.push_back("robot");
|
|
sprite_list_.push_back("congo");
|
|
sprite_list_.push_back("crosshair");
|
|
sprite_list_.push_back("tree_thing");
|
|
|
|
sprite_list_.push_back("matatunos");
|
|
sprite_list_.push_back("tuno");
|
|
|
|
sprite_list_.push_back("mummy");
|
|
sprite_list_.push_back("sam");
|
|
|
|
sprite_list_.push_back("qvoid");
|
|
sprite_list_.push_back("sigmasua");
|
|
|
|
sprite_list_.push_back("tv_panel");
|
|
sprite_list_.push_back("tv");
|
|
|
|
sprite_list_.push_back("spider");
|
|
sprite_list_.push_back("shock");
|
|
sprite_list_.push_back("wave");
|
|
|
|
sprite_list_.push_back("player");
|
|
}
|
|
|
|
// Carga todos los sprites desde una lista
|
|
void Ending2::loadSprites()
|
|
{
|
|
// Inicializa variables
|
|
sprite_max_width_ = 0;
|
|
sprite_max_height_ = 0;
|
|
|
|
// Carga los sprites
|
|
for (auto sl : sprite_list_)
|
|
{
|
|
sprites_.emplace_back(std::make_shared<AnimatedSprite>(resource_->getTexture(sl + ".png"), resource_->getAnimations(sl + ".ani")));
|
|
sprite_max_width_ = std::max(sprites_.back()->getWidth(), sprite_max_width_);
|
|
sprite_max_height_ = std::max(sprites_.back()->getHeight(), sprite_max_height_);
|
|
}
|
|
}
|
|
|
|
// Actualiza los sprites
|
|
void Ending2::updateSprites()
|
|
{
|
|
for (auto sprite : sprites_)
|
|
{
|
|
sprite->update();
|
|
}
|
|
}
|
|
|
|
// Actualiza los sprites de texto
|
|
void Ending2::updateTextSprites()
|
|
{
|
|
for (auto sprite : sprite_texts_)
|
|
{
|
|
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
|
|
{
|
|
post_counter_enabled_ = true;
|
|
}
|
|
}
|
|
|
|
// Dibuja los sprites
|
|
void Ending2::renderSprites()
|
|
{
|
|
const Color color = stringToColor(options.video.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 c = stringToColor(options.video.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 color = stringToColor(options.video.palette, "white");
|
|
for (auto sprite : 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();
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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 ? FIRST_COL_ : SECOND_COL_;
|
|
const int y = (i / 1) * (sprite_max_height_ + dist_sprite_text_ + text_->getCharacterSize() + dist_sprite_sprite_) + GAMECANVAS_HEIGHT + 40;
|
|
const int w = sprites_[i]->getWidth();
|
|
const int h = sprites_[i]->getHeight();
|
|
const int dx = -(w / 2);
|
|
const int dy = i % 1 == 0 ? sprite_max_height_ - h : (int)(sprite_max_height_ * 1.5f) - h;
|
|
|
|
sprites_[i]->setPosition({x + dx, y + dy, w, h});
|
|
sprites_[i]->setVelY(sprite_desp_speed_);
|
|
}
|
|
|
|
// Recoloca el último sprite, que es el del jugador
|
|
const int w = sprites_.back()->getWidth();
|
|
const int x = GAMECANVAS_CENTER_X - (w / 2);
|
|
const int y = sprites_.back()->getPosY() + sprite_max_height_ * 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()
|
|
{
|
|
// Crea los sprites de texto a partir de la lista
|
|
for (int i = 0; i < (int)sprite_list_.size(); ++i)
|
|
{
|
|
// Calcula constantes
|
|
std::string txt = sprite_list_[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 ? FIRST_COL_ : SECOND_COL_;
|
|
const int dx = -(w / 2);
|
|
const int y = sprites_[i]->getPosY() + sprites_[i]->getHeight() + dist_sprite_text_;
|
|
|
|
// Cambia la posición del último sprite
|
|
const int X = (i == (int)sprite_list_.size() - 1) ? GAMECANVAS_CENTER_X - (w / 2) : x + dx;
|
|
|
|
// Crea la textura
|
|
auto texture = std::make_shared<Texture>(renderer_);
|
|
texture->createBlank(w, h);
|
|
texture->setAsRenderTarget(renderer_);
|
|
texture->setBlendMode(SDL_BLENDMODE_BLEND);
|
|
text_->write(0, 0, txt);
|
|
|
|
// Crea el sprite
|
|
SDL_Rect pos = {X, y, w, h};
|
|
sprite_texts_.emplace_back(std::make_shared<MovingSprite>(texture, pos));
|
|
sprite_texts_.back()->setVelY(sprite_desp_speed_);
|
|
}
|
|
}
|
|
|
|
// Crea los sprites con las texturas con los textos del final
|
|
void Ending2::createTexts()
|
|
{
|
|
// 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[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
|
|
auto texture = std::make_shared<Texture>(renderer_);
|
|
texture->createBlank(w, h);
|
|
texture->setAsRenderTarget(renderer_);
|
|
texture->setBlendMode(SDL_BLENDMODE_BLEND);
|
|
text_->write(0, 0, list[i]);
|
|
|
|
// Crea el sprite
|
|
SDL_Rect pos = {x + dx, y, w, h};
|
|
texts_.emplace_back(std::make_shared<MovingSprite>(texture, pos));
|
|
texts_.back()->setVelY(sprite_desp_speed_);
|
|
}
|
|
|
|
// Crea los últimos textos
|
|
// El primer texto va a continuación del ultimo spriteText
|
|
const int start = sprite_texts_.back()->getPosY() + text_->getCharacterSize() * 15;
|
|
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[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
|
|
auto texture = std::make_shared<Texture>(renderer_);
|
|
texture->createBlank(w, h);
|
|
texture->setAsRenderTarget(renderer_);
|
|
texture->setBlendMode(SDL_BLENDMODE_BLEND);
|
|
text_->write(0, 0, list[i]);
|
|
|
|
// Crea el sprite
|
|
SDL_Rect pos = {x + dx, y, w, h};
|
|
texts_.emplace_back(std::make_shared<MovingSprite>(texture, pos));
|
|
texts_.back()->setVelY(sprite_desp_speed_);
|
|
}
|
|
}
|
|
|
|
// 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(post_counter_, 500) - 500, 40) / 40.0f;
|
|
const int index = (colors_.size() - 1) * step;
|
|
|
|
for (auto t : texts_)
|
|
{
|
|
t->getTexture()->setColor(colors_[index].r, colors_[index].g, colors_[index].b);
|
|
}
|
|
}
|
|
|
|
// Actualiza el volumen de la musica
|
|
void Ending2::updateMusicVolume()
|
|
{
|
|
if (post_counter_ > 0)
|
|
{
|
|
const float step = (600.0f - post_counter_) / 600.0f;
|
|
const int volume = 128 * step;
|
|
JA_SetVolume(volume);
|
|
}
|
|
} |