453 lines
13 KiB
C++
453 lines
13 KiB
C++
#include "title.h"
|
|
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
|
|
#include <SDL2/SDL_error.h> // for SDL_GetError
|
|
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_KEYDOWN
|
|
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
|
|
#include <SDL2/SDL_scancode.h> // for SDL_SCANCODE_1, SDL_SCANCODE_2
|
|
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
|
|
#include <iostream> // for basic_ostream, operator<<, cout, endl
|
|
#include "asset.h" // for Asset
|
|
#include "cheevos.h" // for Achievement, Cheevos
|
|
#include "defines.h" // for PLAY_AREA_CENTER_X, GAMECANVAS_WIDTH
|
|
#include "global_events.h" // for check
|
|
#include "global_inputs.h" // for check
|
|
#include "input.h" // for Input, inputs_e, REPEAT_FALSE, REPEA...
|
|
#include "options.h" // for Options, options, OptionsVideo, Sect...
|
|
#include "resource.h" // for Resource
|
|
#include "screen.h" // for Screen
|
|
#include "sprite.h" // for Sprite
|
|
#include "text.h" // for Text, TEXT_CENTER, TEXT_COLOR
|
|
#include "texture.h" // for Texture
|
|
#include "utils.h" // for Color, stringToColor, Palette
|
|
|
|
// Constructor
|
|
Title::Title()
|
|
: screen_(Screen::get()),
|
|
renderer_(Screen::get()->getRenderer()),
|
|
resource_(Resource::get()),
|
|
input_(Input::get())
|
|
{
|
|
// Reserva memoria para los punteros
|
|
if (options.video.palette == Palette::ZXSPECTRUM)
|
|
{
|
|
texture_ = resource_->getTexture("title_logo.png");
|
|
}
|
|
else if (options.video.palette == Palette::ZXARNE)
|
|
{
|
|
texture_ = resource_->getTexture("title_logo.png");
|
|
}
|
|
sprite_ = std::make_shared<Sprite>(texture_, 0, 0, texture_->getWidth(), texture_->getHeight());
|
|
text_ = resource_->getText("smb2");
|
|
info_text_ = resource_->getText("subatomic");
|
|
|
|
// Crea la textura para los graficos que aparecen en el fondo de la pantalla de titulo
|
|
bg_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT);
|
|
if (bg_texture_ == nullptr)
|
|
{
|
|
if (options.console)
|
|
{
|
|
std::cout << "Error: bgTexture could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
|
|
}
|
|
}
|
|
SDL_SetTextureBlendMode(bg_texture_, SDL_BLENDMODE_BLEND);
|
|
|
|
// Carga la surface con los gráficos de la pantalla de carga
|
|
pInit(renderer_, 256, 128);
|
|
loading_screen_ = pLoadSurface(Asset::get()->get("loading_screen_color.gif").c_str());
|
|
pLoadPal(Asset::get()->get("loading_screen_color.gif").c_str());
|
|
pSetSource(loading_screen_);
|
|
|
|
// Inicializa variables
|
|
state_ = options.section.subsection == Subsection::TITLE_WITH_LOADING_SCREEN ? show_loading_screen : show_menu;
|
|
options.section.section = Section::TITLE;
|
|
options.section.subsection = Subsection::NONE;
|
|
initMarquee();
|
|
|
|
// Crea y rellena la textura para mostrar los logros
|
|
createCheevosTexture();
|
|
|
|
// Cambia el color del borde
|
|
screen_->setBorderColor(stringToColor(options.video.palette, "black"));
|
|
|
|
// Rellena la textura de fondo con todos los gráficos
|
|
fillTexture();
|
|
}
|
|
|
|
// Destructor
|
|
Title::~Title()
|
|
{
|
|
pDeleteSurface(loading_screen_);
|
|
SDL_DestroyTexture(bg_texture_);
|
|
}
|
|
|
|
// Inicializa la marquesina
|
|
void Title::initMarquee()
|
|
{
|
|
letters_.clear();
|
|
long_text_ = "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?";
|
|
for (int i = 0; i < (int)long_text_.length(); ++i)
|
|
{
|
|
letter_t l;
|
|
l.letter = long_text_.substr(i, 1);
|
|
l.x = 256;
|
|
l.enabled = false;
|
|
letters_.push_back(l);
|
|
}
|
|
letters_[0].enabled = true;
|
|
}
|
|
|
|
// Comprueba el manejador de eventos
|
|
void Title::checkEvents()
|
|
{
|
|
SDL_Event event;
|
|
while (SDL_PollEvent(&event))
|
|
{
|
|
globalEvents::check(event);
|
|
|
|
// Solo se comprueban estas teclas si no está activo el menu de logros
|
|
if (event.type == SDL_KEYDOWN)
|
|
{
|
|
if (!show_cheevos_)
|
|
{
|
|
switch (event.key.keysym.scancode)
|
|
{
|
|
case SDL_SCANCODE_1:
|
|
options.section.section = Section::GAME;
|
|
options.section.subsection = Subsection::NONE;
|
|
break;
|
|
|
|
case SDL_SCANCODE_2:
|
|
show_cheevos_ = true;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Comprueba las entradas
|
|
void Title::checkInput()
|
|
{
|
|
if (show_cheevos_)
|
|
{
|
|
if (input_->checkInput(input_down, REPEAT_TRUE))
|
|
{
|
|
moveCheevosList(1);
|
|
}
|
|
else if (input_->checkInput(input_up, REPEAT_TRUE))
|
|
{
|
|
moveCheevosList(0);
|
|
}
|
|
else if (input_->checkInput(input_accept, REPEAT_FALSE))
|
|
{
|
|
hideCheevosList();
|
|
counter_ = 0;
|
|
}
|
|
}
|
|
|
|
if (input_->checkInput(input_accept, REPEAT_FALSE))
|
|
{
|
|
if (state_ == show_loading_screen)
|
|
{
|
|
state_ = fade_loading_screen;
|
|
}
|
|
}
|
|
|
|
globalInputs::check();
|
|
}
|
|
|
|
// Actualiza la marquesina
|
|
void Title::updateMarquee()
|
|
{
|
|
for (int i = 0; i < (int)letters_.size(); ++i)
|
|
{
|
|
if (letters_[i].enabled)
|
|
{
|
|
letters_[i].x -= marquee_speed_;
|
|
if (letters_[i].x < -10)
|
|
{
|
|
letters_[i].enabled = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (i > 0 && letters_[i - 1].x < 256 && letters_[i - 1].enabled)
|
|
{
|
|
letters_[i].enabled = true;
|
|
letters_[i].x = letters_[i - 1].x + text_->lenght(letters_[i - 1].letter) + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Comprueba si ha terminado la marquesina y la reinicia
|
|
if (letters_[letters_.size() - 1].x < -10)
|
|
{ // Inicializa la marquesina
|
|
initMarquee();
|
|
}
|
|
}
|
|
|
|
// Dibuja la marquesina
|
|
void Title::renderMarquee()
|
|
{
|
|
for (auto l : letters_)
|
|
{
|
|
if (l.enabled)
|
|
{
|
|
text_->writeColored(l.x, 184, l.letter, stringToColor(options.video.palette, "white"));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Dibuja la linea de información inferior
|
|
void Title::renderInfo()
|
|
{
|
|
const std::string version = "v.1.09";
|
|
const int x = GAMECANVAS_WIDTH - info_text_->lenght(version) - 1;
|
|
info_text_->write(x, 1, version);
|
|
}
|
|
|
|
// Actualiza las variables
|
|
void Title::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();
|
|
|
|
screen_->update();
|
|
|
|
// Incrementa el contador
|
|
counter_++;
|
|
|
|
switch (state_)
|
|
{
|
|
case show_loading_screen:
|
|
if (counter_ == 500)
|
|
{
|
|
counter_ = 0;
|
|
state_ = fade_loading_screen;
|
|
}
|
|
break;
|
|
|
|
case fade_loading_screen:
|
|
if (counter_ % 4 == 0)
|
|
if (pFadePal())
|
|
{
|
|
counter_ = 0;
|
|
state_ = show_menu;
|
|
}
|
|
break;
|
|
|
|
case show_menu:
|
|
// Actualiza la marquesina
|
|
updateMarquee();
|
|
|
|
// Si el contador alcanza cierto valor, termina la seccion
|
|
if (counter_ == 2200)
|
|
{
|
|
if (!show_cheevos_)
|
|
{
|
|
options.section.section = Section::CREDITS;
|
|
options.section.subsection = Subsection::NONE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Dibuja en pantalla
|
|
void Title::render()
|
|
{
|
|
// Prepara para empezar a dibujar en la textura de juego
|
|
screen_->start();
|
|
screen_->clean(stringToColor(options.video.palette, "black"));
|
|
|
|
if (state_ == show_menu)
|
|
{
|
|
// Dibuja la textura de fondo
|
|
SDL_RenderCopy(renderer_, bg_texture_, nullptr, nullptr);
|
|
|
|
// Dibuja la marquesina
|
|
renderMarquee();
|
|
|
|
// Dibuja la información de logros
|
|
if (show_cheevos_)
|
|
{
|
|
cheevos_sprite_->render();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Dibuja la pantalla de carga
|
|
pCls(4);
|
|
pBlit(0, 0, 0, 0, 256, 128);
|
|
pFlip(renderer_);
|
|
|
|
// Dibuja el logo del título
|
|
sprite_->render();
|
|
}
|
|
|
|
// Vuelca el contenido del renderizador en pantalla
|
|
screen_->render();
|
|
}
|
|
|
|
// Bucle para el logo del juego
|
|
void Title::run()
|
|
{
|
|
while (options.section.section == Section::TITLE)
|
|
{
|
|
update();
|
|
checkEvents();
|
|
render();
|
|
}
|
|
}
|
|
|
|
// Recarga las texturas
|
|
void Title::reLoadTextures()
|
|
{
|
|
// Carga la textura adecuada
|
|
if (options.video.palette == Palette::ZXSPECTRUM)
|
|
{
|
|
texture_ = resource_->getTexture("loading_screen_color.png");
|
|
}
|
|
else if (options.video.palette == Palette::ZXARNE)
|
|
{
|
|
texture_ = resource_->getTexture("loading_screen_color_zxarne.png");
|
|
}
|
|
|
|
texture_->reLoad();
|
|
}
|
|
|
|
// Cambia la paleta
|
|
void Title::switchPalette()
|
|
{
|
|
if (options.video.palette == Palette::ZXSPECTRUM)
|
|
{
|
|
options.video.palette = Palette::ZXARNE;
|
|
sprite_->setTexture(resource_->getTexture("loading_screen_color_zxarne.png"));
|
|
}
|
|
else
|
|
{
|
|
options.video.palette = Palette::ZXSPECTRUM;
|
|
sprite_->setTexture(resource_->getTexture("loading_screen_color.png"));
|
|
}
|
|
|
|
// Cambia el color del borde
|
|
screen_->setBorderColor(stringToColor(options.video.palette, "bright_blue"));
|
|
}
|
|
|
|
// Desplaza la lista de logros
|
|
void Title::moveCheevosList(int direction)
|
|
{
|
|
const int speed = 2;
|
|
cheevos_texture_view_.y = direction == 0 ? cheevos_texture_view_.y - speed : cheevos_texture_view_.y + speed;
|
|
|
|
const int bottom = cheevos_texture_->getHeight() - cheevos_texture_view_.h;
|
|
if (cheevos_texture_view_.y < 0)
|
|
{
|
|
cheevos_texture_view_.y = 0;
|
|
}
|
|
else if (cheevos_texture_view_.y > bottom)
|
|
{
|
|
cheevos_texture_view_.y = bottom;
|
|
}
|
|
|
|
cheevos_sprite_->setClip(cheevos_texture_view_);
|
|
}
|
|
|
|
// Rellena la textura de fondo con todos los gráficos
|
|
void Title::fillTexture()
|
|
{
|
|
// Coloca el puntero del renderizador sobre la textura
|
|
SDL_SetRenderTarget(renderer_, bg_texture_);
|
|
|
|
// Rellena la textura de color
|
|
const Color c = stringToColor(options.video.palette, "black");
|
|
SDL_SetRenderDrawColor(renderer_, c.r, c.g, c.b, 0xFF);
|
|
SDL_RenderClear(renderer_);
|
|
|
|
// Pinta el gráfico del titulo a partir del sprite
|
|
sprite_->render();
|
|
|
|
// Escribe el texto en la textura
|
|
const Color textColor = stringToColor(options.video.palette, "green");
|
|
const int textSize = text_->getCharacterSize();
|
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, 11 * textSize, "1.PLAY", 1, textColor);
|
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, 13 * textSize, "2.ACHIEVEMENTS", 1, textColor);
|
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, 15 * textSize, "3.REDEFINE KEYS", 1, textColor);
|
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, 20 * textSize, "ESC.EXIT GAME", 1, textColor);
|
|
|
|
// Devuelve el puntero del renderizador a su sitio
|
|
SDL_SetRenderTarget(renderer_, nullptr);
|
|
}
|
|
|
|
// Crea y rellena la textura para mostrar los logros
|
|
void Title::createCheevosTexture()
|
|
{
|
|
// Crea la textura con el listado de logros
|
|
const auto cheevosList = Cheevos::get()->list();
|
|
const int cheevosTextureWidth = 200;
|
|
const int cheevosTextureViewHeight = 110;
|
|
const int cheevosTexturePosY = 73;
|
|
const int cheevosPadding = 10;
|
|
const int cheevoHeight = cheevosPadding + (info_text_->getCharacterSize() * 2) + 1;
|
|
const int cheevosTextureHeight = (cheevoHeight * cheevosList.size()) + 2 + info_text_->getCharacterSize() + 8;
|
|
cheevos_texture_ = std::make_shared<Texture>(renderer_);
|
|
cheevos_texture_->createBlank(cheevosTextureWidth, cheevosTextureHeight, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET);
|
|
cheevos_texture_->setAsRenderTarget(renderer_);
|
|
cheevos_texture_->setBlendMode(SDL_BLENDMODE_BLEND);
|
|
|
|
// Rellena la textura con color sólido
|
|
const Color cheevosBGColor = stringToColor(options.video.palette, "black");
|
|
SDL_SetRenderDrawColor(renderer_, cheevosBGColor.r, cheevosBGColor.g, cheevosBGColor.b, 0xFF);
|
|
SDL_RenderClear(renderer_);
|
|
|
|
// Escribe la lista de logros en la textura
|
|
const std::string cheevosOwner = "ACHIEVEMENTS";
|
|
const std::string cheevosListCaption = cheevosOwner + " (" + std::to_string(Cheevos::get()->unlocked()) + " / " + std::to_string(Cheevos::get()->count()) + ")";
|
|
int pos = 2;
|
|
info_text_->writeDX(TEXT_CENTER | TEXT_COLOR, cheevos_texture_->getWidth() / 2, pos, cheevosListCaption, 1, stringToColor(options.video.palette, "bright_green"));
|
|
pos += info_text_->getCharacterSize();
|
|
const Color cheevoLockedColor = stringToColor(options.video.palette, "white");
|
|
const Color cheevoUnlockedColor = stringToColor(options.video.palette, "bright_green");
|
|
Color cheevoColor;
|
|
SDL_SetRenderDrawColor(renderer_, cheevoLockedColor.r, cheevoLockedColor.g, cheevoLockedColor.b, 0xFF);
|
|
const int lineX1 = (cheevosTextureWidth / 7) * 3;
|
|
const int lineX2 = lineX1 + ((cheevosTextureWidth / 7) * 1);
|
|
|
|
for (auto cheevo : cheevosList)
|
|
{
|
|
cheevoColor = cheevo.completed ? cheevoUnlockedColor : cheevoLockedColor;
|
|
pos += cheevosPadding;
|
|
int half = cheevosPadding / 2;
|
|
SDL_RenderDrawLine(renderer_, lineX1, pos - half - 1, lineX2, pos - half - 1);
|
|
info_text_->writeDX(TEXT_CENTER | TEXT_COLOR, cheevosTextureWidth / 2, pos, cheevo.caption, 1, cheevoColor);
|
|
pos += info_text_->getCharacterSize() + 1;
|
|
info_text_->writeDX(TEXT_CENTER | TEXT_COLOR, cheevosTextureWidth / 2, pos, cheevo.description, 1, cheevoColor);
|
|
pos += info_text_->getCharacterSize();
|
|
}
|
|
|
|
// Crea el sprite para el listado de logros
|
|
cheevos_sprite_ = std::make_shared<Sprite>(cheevos_texture_, (GAMECANVAS_WIDTH - cheevos_texture_->getWidth()) / 2, cheevosTexturePosY, cheevos_texture_->getWidth(), cheevos_texture_->getHeight());
|
|
cheevos_texture_view_ = {0, 0, cheevos_texture_->getWidth(), cheevosTextureViewHeight};
|
|
cheevos_sprite_->setClip(cheevos_texture_view_);
|
|
}
|
|
|
|
// Oculta la lista de logros
|
|
void Title::hideCheevosList()
|
|
{
|
|
show_cheevos_ = false;
|
|
cheevos_texture_view_.y = 0;
|
|
cheevos_sprite_->setClip(cheevos_texture_view_);
|
|
} |