338 lines
11 KiB
C++
338 lines
11 KiB
C++
#include "instructions.h"
|
|
#include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND
|
|
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_QUIT
|
|
#include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
|
|
#include <SDL2/SDL_timer.h> // Para SDL_GetTicks
|
|
#include <SDL2/SDL_video.h> // Para SDL_WINDOWEVENT_SIZE_CHANGED
|
|
#include <algorithm> // Para max
|
|
#include <utility> // Para move
|
|
#include "fade.h" // Para Fade, FadeMode, FadeType
|
|
#include "global_inputs.h" // Para check
|
|
#include "input.h" // Para Input
|
|
#include "jail_audio.h" // Para JA_GetMusicState, JA_Music_state
|
|
#include "lang.h" // Para getText
|
|
#include "param.h" // Para Param, param, ParamGame, ParamFade
|
|
#include "resource.h" // Para Resource
|
|
#include "screen.h" // Para Screen
|
|
#include "section.h" // Para Name, name, Options, options
|
|
#include "sprite.h" // Para Sprite
|
|
#include "text.h" // Para Text, TEXT_CENTER, TEXT_COLOR, TEXT_...
|
|
#include "texture.h" // Para Texture
|
|
#include "tiled_bg.h" // Para TiledBG, TiledBGMode
|
|
#include "utils.h" // Para Color, shdw_txt_color, Zone, no_color
|
|
#include "mouse.h"
|
|
|
|
// Constructor
|
|
Instructions::Instructions()
|
|
: renderer_(Screen::get()->getRenderer()),
|
|
texture_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
|
|
backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
|
|
text_(Resource::get()->getText("smb2")),
|
|
tiled_bg_(std::make_unique<TiledBG>(param.game.game_area.rect, TiledBGMode::STATIC)),
|
|
fade_(std::make_unique<Fade>())
|
|
{
|
|
// Configura las texturas
|
|
SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
|
|
SDL_SetTextureBlendMode(texture_, SDL_BLENDMODE_BLEND);
|
|
|
|
// Inicializa variables
|
|
section::name = section::Name::INSTRUCTIONS;
|
|
view_ = param.game.game_area.rect;
|
|
|
|
// Inicializa objetos
|
|
fade_->setColor(fade_color.r, fade_color.g, fade_color.b);
|
|
fade_->setType(FadeType::FULLSCREEN);
|
|
fade_->setPostDuration(param.fade.post_duration);
|
|
fade_->setMode(FadeMode::IN);
|
|
fade_->activate();
|
|
|
|
// Rellena la textura de texto
|
|
fillTexture();
|
|
|
|
// Inicializa los sprites de los items
|
|
iniSprites();
|
|
}
|
|
|
|
// Destructor
|
|
Instructions::~Instructions()
|
|
{
|
|
item_textures_.clear();
|
|
sprites_.clear();
|
|
|
|
SDL_DestroyTexture(backbuffer_);
|
|
SDL_DestroyTexture(texture_);
|
|
}
|
|
|
|
// Inicializa los sprites de los items
|
|
void Instructions::iniSprites()
|
|
{
|
|
// Inicializa las texturas
|
|
item_textures_.emplace_back(Resource::get()->getTexture("item_points1_disk.png"));
|
|
item_textures_.emplace_back(Resource::get()->getTexture("item_points2_gavina.png"));
|
|
item_textures_.emplace_back(Resource::get()->getTexture("item_points3_pacmar.png"));
|
|
item_textures_.emplace_back(Resource::get()->getTexture("item_clock.png"));
|
|
item_textures_.emplace_back(Resource::get()->getTexture("item_coffee.png"));
|
|
|
|
// Inicializa los sprites
|
|
for (int i = 0; i < (int)item_textures_.size(); ++i)
|
|
{
|
|
auto sprite = std::make_unique<Sprite>(item_textures_[i], 0, 0, param.game.item_size, param.game.item_size);
|
|
sprite->setPosition((SDL_Point){sprite_pos_.x, sprite_pos_.y + ((param.game.item_size + item_space_) * i)});
|
|
sprites_.push_back(std::move(sprite));
|
|
}
|
|
}
|
|
|
|
// Actualiza los sprites
|
|
void Instructions::updateSprites()
|
|
{
|
|
SDL_Rect src_rect = {0, 0, param.game.item_size, param.game.item_size};
|
|
|
|
// Disquito
|
|
src_rect.y = param.game.item_size * (((counter_ + 12) / 36) % 2);
|
|
sprites_[0]->setSpriteClip(src_rect);
|
|
|
|
// Gavina
|
|
src_rect.y = param.game.item_size * (((counter_ + 9) / 36) % 2);
|
|
sprites_[1]->setSpriteClip(src_rect);
|
|
|
|
// Pacmar
|
|
src_rect.y = param.game.item_size * (((counter_ + 6) / 36) % 2);
|
|
sprites_[2]->setSpriteClip(src_rect);
|
|
|
|
// Time Stopper
|
|
src_rect.y = param.game.item_size * (((counter_ + 3) / 36) % 2);
|
|
sprites_[3]->setSpriteClip(src_rect);
|
|
|
|
// Coffee
|
|
src_rect.y = param.game.item_size * (((counter_ + 0) / 36) % 2);
|
|
sprites_[4]->setSpriteClip(src_rect);
|
|
}
|
|
|
|
// Rellena la textura de texto
|
|
void Instructions::fillTexture()
|
|
{
|
|
const int desp_x = param.game.item_size + 8;
|
|
|
|
// Modifica el renderizador para pintar en la textura
|
|
auto temp = SDL_GetRenderTarget(renderer_);
|
|
SDL_SetRenderTarget(renderer_, texture_);
|
|
|
|
// Limpia la textura
|
|
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
|
|
SDL_RenderClear(renderer_);
|
|
|
|
// Constantes
|
|
constexpr int num_lines = 4;
|
|
constexpr int num_item_lines = 4;
|
|
constexpr int num_post_headers = 2;
|
|
constexpr int num_pre_headers = 1;
|
|
|
|
constexpr int space_post_header = 20;
|
|
constexpr int space_pre_header = 28;
|
|
const int space_between_lines = text_->getCharacterSize() * 1.5f;
|
|
const int space_between_item_lines = param.game.item_size + item_space_;
|
|
const int space_new_paragraph = space_between_lines * 0.5f;
|
|
|
|
const int size = (num_lines * space_between_lines) + (num_item_lines * space_between_item_lines) + (num_post_headers * space_post_header) + (num_pre_headers * space_pre_header) + (space_new_paragraph);
|
|
const int first_line = (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 anchor_item = (param.game.width - (lenght + desp_x)) / 2;
|
|
|
|
// Escribe el texto de las instrucciones
|
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, first_line, lang::getText(11), 1, orange_color, 1, shdw_txt_color);
|
|
|
|
const int anchor1 = first_line + space_post_header;
|
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, anchor1 + space_between_lines * 0, lang::getText(12), 1, no_color, 1, shdw_txt_color);
|
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, anchor1 + space_between_lines * 1, lang::getText(13), 1, no_color, 1, shdw_txt_color);
|
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, anchor1 + space_new_paragraph + space_between_lines * 2, lang::getText(14), 1, no_color, 1, shdw_txt_color);
|
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, anchor1 + space_new_paragraph + space_between_lines * 3, lang::getText(15), 1, no_color, 1, shdw_txt_color);
|
|
|
|
// Escribe el texto de los objetos y sus puntos
|
|
const int anchor2 = anchor1 + space_pre_header + space_new_paragraph + space_between_lines * 3;
|
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, anchor2, lang::getText(16), 1, orange_color, 1, shdw_txt_color);
|
|
|
|
const int anchor3 = anchor2 + space_post_header;
|
|
// const int anchor4 = anchor3 + ((param.game.item_size + text->getCharacterSize()) / 2);
|
|
text_->writeShadowed(anchor_item + desp_x, anchor3 + space_between_item_lines * 0, lang::getText(17), shdw_txt_color);
|
|
text_->writeShadowed(anchor_item + desp_x, anchor3 + space_between_item_lines * 1, lang::getText(18), shdw_txt_color);
|
|
text_->writeShadowed(anchor_item + desp_x, anchor3 + space_between_item_lines * 2, lang::getText(19), shdw_txt_color);
|
|
text_->writeShadowed(anchor_item + desp_x, anchor3 + space_between_item_lines * 3, lang::getText(20), shdw_txt_color);
|
|
text_->writeShadowed(anchor_item + desp_x, anchor3 + space_between_item_lines * 4, lang::getText(21), shdw_txt_color);
|
|
|
|
// Deja el renderizador como estaba
|
|
SDL_SetRenderTarget(renderer_, temp);
|
|
|
|
// Da valor a la variable
|
|
sprite_pos_.x = anchor_item;
|
|
sprite_pos_.y = anchor3 - ((param.game.item_size - text_->getCharacterSize()) / 2);
|
|
}
|
|
|
|
// Rellena el backbuffer
|
|
void Instructions::fillBackbuffer()
|
|
{
|
|
// Modifica el renderizador para pintar en la textura
|
|
auto 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()
|
|
{
|
|
constexpr int TICKS_SPEED = 15;
|
|
|
|
if (SDL_GetTicks() - ticks_ > TICKS_SPEED)
|
|
{
|
|
// 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(Resource::get()->getMusic("title.ogg"));
|
|
}
|
|
|
|
// Actualiza el objeto screen
|
|
Screen::get()->update();
|
|
|
|
// Actualiza las variables de globalInputs
|
|
globalInputs::update();
|
|
|
|
// Incrementa el contador
|
|
counter_++;
|
|
|
|
// Actualiza los sprites
|
|
updateSprites();
|
|
|
|
// Actualiza el mosaico de fondo
|
|
tiled_bg_->update();
|
|
|
|
// Actualiza el objeto "fade"
|
|
fade_->update();
|
|
|
|
// Comprueba si el contador ha llegado al final
|
|
if (counter_ == counter_end_)
|
|
{
|
|
section::name = section::Name::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::get()->start();
|
|
|
|
// Limpia la pantalla
|
|
Screen::get()->clean(bg_color);
|
|
|
|
// Dibuja el mosacico de fondo
|
|
tiled_bg_->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::get()->blit();
|
|
}
|
|
|
|
// Recarga todas las texturas
|
|
void Instructions::reloadTextures()
|
|
{
|
|
for (auto &texture : item_textures_)
|
|
{
|
|
texture->reLoad();
|
|
}
|
|
text_->reLoadTexture();
|
|
fillTexture();
|
|
}
|
|
|
|
// Comprueba los eventos
|
|
void Instructions::checkEvents()
|
|
{
|
|
// Comprueba los eventos que hay en la cola
|
|
SDL_Event event;
|
|
while (SDL_PollEvent(&event))
|
|
{
|
|
// Evento de salida de la aplicación
|
|
if (event.type == SDL_QUIT)
|
|
{
|
|
section::name = section::Name::QUIT;
|
|
section::options = section::Options::QUIT_FROM_EVENT;
|
|
break;
|
|
}
|
|
|
|
// Comprueba si se ha cambiado el tamaño de la ventana
|
|
else if (event.type == SDL_WINDOWEVENT)
|
|
{
|
|
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
|
|
{
|
|
reloadTextures();
|
|
}
|
|
}
|
|
|
|
// Comprueba el cursor
|
|
Mouse::handleEvent(event);
|
|
}
|
|
}
|
|
|
|
// Comprueba las entradas
|
|
void Instructions::checkInput()
|
|
{
|
|
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
|
|
if (Input::get()->checkAnyButtonPressed())
|
|
{
|
|
// JA_StopMusic();
|
|
section::name = section::Name::TITLE;
|
|
section::options = section::Options::TITLE_1;
|
|
section::attract_mode = section::AttractMode::TITLE_TO_DEMO;
|
|
return;
|
|
}
|
|
|
|
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
|
|
globalInputs::check();
|
|
}
|
|
|
|
// Bucle para la pantalla de instrucciones
|
|
void Instructions::run()
|
|
{
|
|
while (section::name == section::Name::INSTRUCTIONS)
|
|
{
|
|
checkInput();
|
|
update();
|
|
checkEvents(); // Tiene que ir antes del render
|
|
render();
|
|
}
|
|
} |