398 lines
11 KiB
C++
398 lines
11 KiB
C++
#include "instructions.h"
|
|
#include "param.h"
|
|
#include <iostream>
|
|
|
|
// Constructor
|
|
Instructions::Instructions(Screen *screen, Asset *asset, Input *input, options_t *options, section_t *section, JA_Music_t *music)
|
|
{
|
|
// Copia los punteros
|
|
this->screen = screen;
|
|
this->asset = asset;
|
|
this->input = input;
|
|
this->section = section;
|
|
this->music = music;
|
|
this->options = options;
|
|
renderer = screen->getRenderer();
|
|
|
|
// Crea objetos
|
|
eventHandler = new SDL_Event();
|
|
text = new Text(asset->get("smb2.gif"), asset->get("smb2.txt"), renderer);
|
|
tiledbg = new Tiledbg(renderer, asset, {0, 0, param.game.width, param.game.height}, TILED_MODE_STATIC);
|
|
fade = new Fade(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);
|
|
|
|
// Crea una textura para el texto fijo
|
|
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height);
|
|
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
|
|
|
// Inicializa variables
|
|
section->name = SECTION_PROG_INSTRUCTIONS;
|
|
ticks = 0;
|
|
ticksSpeed = 15;
|
|
counter = 0;
|
|
counterEnd = 700;
|
|
view = {0, 0, param.game.width, param.game.height};
|
|
spritePos = {0, 0};
|
|
itemSpace = 2;
|
|
|
|
// Inicializa objetos
|
|
fade->setColor(fadeColor.r, fadeColor.g, fadeColor.b);
|
|
fade->setType(FADE_FULLSCREEN);
|
|
fade->setPost(param.fade.postDuration);
|
|
fade->setMode(FADE_IN);
|
|
fade->activate();
|
|
|
|
// Rellena la textura de texto
|
|
fillTexture();
|
|
|
|
// Inicializa los sprites de los items
|
|
iniSprites();
|
|
}
|
|
|
|
// Destructor
|
|
Instructions::~Instructions()
|
|
{
|
|
for (auto texture : itemTextures)
|
|
{
|
|
texture->unload();
|
|
delete texture;
|
|
}
|
|
itemTextures.clear();
|
|
|
|
for (auto sprite : sprites)
|
|
{
|
|
delete sprite;
|
|
}
|
|
sprites.clear();
|
|
|
|
delete eventHandler;
|
|
delete text;
|
|
delete tiledbg;
|
|
delete fade;
|
|
|
|
SDL_DestroyTexture(backbuffer);
|
|
SDL_DestroyTexture(texture);
|
|
}
|
|
|
|
// Inicializa los sprites de los items
|
|
void Instructions::iniSprites()
|
|
{
|
|
// Inicializa las texturas
|
|
Texture *item1 = new Texture(renderer, asset->get("item_points1_disk.png"));
|
|
itemTextures.push_back(item1);
|
|
|
|
Texture *item2 = new Texture(renderer, asset->get("item_points2_gavina.png"));
|
|
itemTextures.push_back(item2);
|
|
|
|
Texture *item3 = new Texture(renderer, asset->get("item_points3_pacmar.png"));
|
|
itemTextures.push_back(item3);
|
|
|
|
Texture *item4 = new Texture(renderer, asset->get("item_clock.png"));
|
|
itemTextures.push_back(item4);
|
|
|
|
Texture *item5 = new Texture(renderer, asset->get("item_coffee.png"));
|
|
itemTextures.push_back(item5);
|
|
|
|
// Inicializa los sprites
|
|
for (int i = 0; i < (int)itemTextures.size(); ++i)
|
|
{
|
|
Sprite *sprite = new Sprite(0, 0, param.game.itemSize, param.game.itemSize, itemTextures[i]);
|
|
sprite->setPos((SDL_Point){spritePos.x, spritePos.y + ((param.game.itemSize + itemSpace) * i)});
|
|
sprites.push_back(sprite);
|
|
}
|
|
}
|
|
|
|
// Actualiza los sprites
|
|
void Instructions::updateSprites()
|
|
{
|
|
SDL_Rect srcRect = {0, 0, param.game.itemSize, param.game.itemSize};
|
|
|
|
// Disquito
|
|
srcRect.y = param.game.itemSize * (((counter + 12) / 36) % 2);
|
|
sprites[0]->setSpriteClip(srcRect);
|
|
|
|
// Gavineixon
|
|
srcRect.y = param.game.itemSize * (((counter + 9) / 36) % 2);
|
|
sprites[1]->setSpriteClip(srcRect);
|
|
|
|
// Pacmar
|
|
srcRect.y = param.game.itemSize * (((counter + 6) / 36) % 2);
|
|
sprites[2]->setSpriteClip(srcRect);
|
|
|
|
// Time Stopper
|
|
srcRect.y = param.game.itemSize * (((counter + 3) / 36) % 2);
|
|
sprites[3]->setSpriteClip(srcRect);
|
|
|
|
// Coffee
|
|
srcRect.y = param.game.itemSize * (((counter + 0) / 36) % 2);
|
|
sprites[4]->setSpriteClip(srcRect);
|
|
}
|
|
|
|
// Rellena la textura de texto
|
|
void Instructions::fillTexture()
|
|
{
|
|
const int despX = param.game.itemSize + 8;
|
|
|
|
// Modifica el renderizador para pintar en la textura
|
|
SDL_Texture *temp = SDL_GetRenderTarget(renderer);
|
|
SDL_SetRenderTarget(renderer, texture);
|
|
|
|
// Limpia la textura
|
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
|
|
SDL_RenderClear(renderer);
|
|
|
|
// Constantes
|
|
const int numLines = 4;
|
|
const int numItemLines = 4;
|
|
const int numPostHeaders = 2;
|
|
const int numPreHeaders = 1;
|
|
|
|
const int spacePostHeader = 20;
|
|
const int spacePreHeader = 28;
|
|
const int spaceBetweenLines = text->getCharacterSize() * 1.5f;
|
|
const int spaceBetweenItemLines = param.game.itemSize + itemSpace;
|
|
const int spaceNewParagraph = spaceBetweenLines * 0.5f;
|
|
|
|
const int size = (numLines * spaceBetweenLines) + (numItemLines * spaceBetweenItemLines) + (numPostHeaders * spacePostHeader) + (numPreHeaders * spacePreHeader) + (spaceNewParagraph);
|
|
const int firstLine = (param.game.height - size) / 2;
|
|
|
|
// Calcula cual es el texto más largo de las descripciones de los items
|
|
int lenght = 0;
|
|
for (int i = 17; i <= 21; ++i)
|
|
{
|
|
const int l = text->lenght(lang::getText(i));
|
|
lenght = l > lenght ? l : lenght;
|
|
}
|
|
const int anchorItem = (param.game.width - (lenght + despX)) / 2;
|
|
|
|
// Escribe el texto de las instrucciones
|
|
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, param.game.gameArea.centerX, firstLine, lang::getText(11), 1, orangeColor, 1, shdwTxtColor);
|
|
|
|
const int anchor1 = firstLine + spacePostHeader;
|
|
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, param.game.gameArea.centerX, anchor1 + spaceBetweenLines * 0, lang::getText(12), 1, noColor, 1, shdwTxtColor);
|
|
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, param.game.gameArea.centerX, anchor1 + spaceBetweenLines * 1, lang::getText(13), 1, noColor, 1, shdwTxtColor);
|
|
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, param.game.gameArea.centerX, anchor1 + spaceNewParagraph + spaceBetweenLines * 2, lang::getText(14), 1, noColor, 1, shdwTxtColor);
|
|
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, param.game.gameArea.centerX, anchor1 + spaceNewParagraph + spaceBetweenLines * 3, lang::getText(15), 1, noColor, 1, shdwTxtColor);
|
|
|
|
// Escribe el texto de los objetos y sus puntos
|
|
const int anchor2 = anchor1 + spacePreHeader + spaceNewParagraph + spaceBetweenLines * 3;
|
|
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, param.game.gameArea.centerX, anchor2, lang::getText(16), 1, orangeColor, 1, shdwTxtColor);
|
|
|
|
const int anchor3 = anchor2 + spacePostHeader;
|
|
// const int anchor4 = anchor3 + ((param.game.itemSize + text->getCharacterSize()) / 2);
|
|
text->writeShadowed(anchorItem + despX, anchor3 + spaceBetweenItemLines * 0, lang::getText(17), shdwTxtColor);
|
|
text->writeShadowed(anchorItem + despX, anchor3 + spaceBetweenItemLines * 1, lang::getText(18), shdwTxtColor);
|
|
text->writeShadowed(anchorItem + despX, anchor3 + spaceBetweenItemLines * 2, lang::getText(19), shdwTxtColor);
|
|
text->writeShadowed(anchorItem + despX, anchor3 + spaceBetweenItemLines * 3, lang::getText(20), shdwTxtColor);
|
|
text->writeShadowed(anchorItem + despX, anchor3 + spaceBetweenItemLines * 4, lang::getText(21), shdwTxtColor);
|
|
|
|
// Deja el renderizador como estaba
|
|
SDL_SetRenderTarget(renderer, temp);
|
|
|
|
// Da valor a la variable
|
|
spritePos.x = anchorItem;
|
|
spritePos.y = anchor3 - ((param.game.itemSize - text->getCharacterSize()) / 2);
|
|
}
|
|
|
|
// Rellena el backbuffer
|
|
void Instructions::fillBackbuffer()
|
|
{
|
|
// Modifica el renderizador para pintar en la textura
|
|
SDL_Texture *temp = SDL_GetRenderTarget(renderer);
|
|
SDL_SetRenderTarget(renderer, backbuffer);
|
|
|
|
// Limpia la textura
|
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
|
|
SDL_RenderClear(renderer);
|
|
|
|
// Coloca el texto de fondo
|
|
SDL_RenderCopy(renderer, texture, nullptr, nullptr);
|
|
|
|
// Dibuja los sprites
|
|
for (auto sprite : sprites)
|
|
{
|
|
sprite->render();
|
|
}
|
|
|
|
// Deja el renderizador como estaba
|
|
SDL_SetRenderTarget(renderer, temp);
|
|
}
|
|
|
|
// Actualiza las variables
|
|
void Instructions::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();
|
|
|
|
// Incrementa el contador
|
|
counter++;
|
|
|
|
// Actualiza los sprites
|
|
updateSprites();
|
|
|
|
// Actualiza el mosaico de fondo
|
|
tiledbg->update();
|
|
|
|
// Actualiza el objeto "fade"
|
|
fade->update();
|
|
|
|
// Comprueba si el contador ha llegado al final
|
|
if (counter == counterEnd)
|
|
{
|
|
section->name = SECTION_PROG_TITLE;
|
|
section->options = SECTION_OPTIONS_TITLE_1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Pinta en pantalla
|
|
void Instructions::render()
|
|
{
|
|
// Rellena el backbuffer
|
|
fillBackbuffer();
|
|
|
|
// Prepara para empezar a dibujar en la textura de juego
|
|
screen->start();
|
|
|
|
// Limpia la pantalla
|
|
screen->clean(bgColor);
|
|
|
|
// Dibuja el mosacico de fondo
|
|
tiledbg->render();
|
|
|
|
// Establece la ventana del backbuffer
|
|
view.y = std::max(0, param.game.height - counter + 100);
|
|
|
|
// Copia la textura y el backbuffer al renderizador
|
|
SDL_RenderCopy(renderer, backbuffer, nullptr, &view);
|
|
|
|
fade->render();
|
|
|
|
// Vuelca el contenido del renderizador en pantalla
|
|
screen->blit();
|
|
}
|
|
|
|
// Recarga todas las texturas
|
|
void Instructions::reloadTextures()
|
|
{
|
|
for (auto tex : itemTextures)
|
|
{
|
|
tex->reLoad();
|
|
}
|
|
text->reLoadTexture();
|
|
fillTexture();
|
|
}
|
|
|
|
// Comprueba los eventos
|
|
void Instructions::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 Instructions::checkInput()
|
|
{
|
|
// Comprueba si se sale con el teclado
|
|
if (input->checkInput(input_exit, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
|
|
{
|
|
quit(SECTION_OPTIONS_QUIT_NORMAL);
|
|
return;
|
|
}
|
|
|
|
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
|
|
if (input->checkAnyButtonPressed())
|
|
{
|
|
JA_StopMusic();
|
|
section->name = SECTION_PROG_TITLE;
|
|
section->options = SECTION_OPTIONS_TITLE_1;
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < input->getNumControllers(); ++i)
|
|
{
|
|
// Comprueba si se sale con el mando
|
|
if (input->checkModInput(input_service, input_exit, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
|
|
{
|
|
quit(SECTION_OPTIONS_QUIT_SHUTDOWN);
|
|
return;
|
|
}
|
|
|
|
// Comprueba si se va a resetear el juego
|
|
if (input->checkModInput(input_service, input_reset, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
|
|
{
|
|
section->name = SECTION_PROG_LOGO;
|
|
screen->showNotification("Reset");
|
|
return;
|
|
}
|
|
|
|
// Comprueba si se va a activar o desactivar el audio
|
|
if (input->checkModInput(input_service, input_mute, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
|
|
{
|
|
options->audio.sound.enabled = options->audio.music.enabled = !options->audio.music.enabled;
|
|
JA_EnableMusic(options->audio.music.enabled);
|
|
JA_EnableSound(options->audio.sound.enabled);
|
|
screen->showNotification("Audio " + boolToOnOff(options->audio.music.enabled));
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Comprueba el input para el resto de objetos
|
|
screen->checkInput();
|
|
}
|
|
|
|
// Bucle para la pantalla de instrucciones
|
|
void Instructions::run()
|
|
{
|
|
while (section->name == SECTION_PROG_INSTRUCTIONS)
|
|
{
|
|
checkInput();
|
|
update();
|
|
checkEvents(); // Tiene que ir antes del render
|
|
render();
|
|
}
|
|
}
|
|
|
|
// Termina
|
|
void Instructions::quit(int code)
|
|
{
|
|
if (screen->notificationsAreActive())
|
|
{
|
|
section->name = SECTION_PROG_QUIT;
|
|
section->options = code;
|
|
}
|
|
else
|
|
{
|
|
screen->showNotification(lang::getText(94));
|
|
}
|
|
} |