Files
jaildoctors_dilemma/source/game/scenes/loading_screen.cpp

199 lines
7.0 KiB
C++

#include "game/scenes/loading_screen.hpp"
#include <SDL3/SDL.h>
#include <stdlib.h> // Para rand
#include "utils/defines.hpp" // Para GAME_SPEED
#include "external/jail_audio.h" // Para JA_PlayMusic, JA_SetVolume, JA_StopMusic
#include "utils/global_events.hpp" // Para check
#include "core/input/global_inputs.hpp" // Para check
#include "game/gameplay/options.hpp" // Para Options, options, SectionState, Options...
#include "core/resources/resource.hpp" // Para Resource
#include "core/rendering/screen.hpp" // Para Screen
#include "core/rendering/surface_sprite.hpp" // Para SSprite
#include "core/rendering/surface.hpp" // Para Surface
#include "utils/utils.hpp" // Para stringToColor, PaletteColor
// Constructor
LoadingScreen::LoadingScreen()
: mono_loading_screen_surface_(Resource::get()->getSurface("loading_screen_bn.gif")),
color_loading_screen_surface_(Resource::get()->getSurface("loading_screen_color.gif")),
mono_loading_screen_sprite_(std::make_shared<SSprite>(mono_loading_screen_surface_, 0, 0, mono_loading_screen_surface_->getWidth(), mono_loading_screen_surface_->getHeight())),
color_loading_screen_sprite_(std::make_shared<SSprite>(color_loading_screen_surface_, 0, 0, color_loading_screen_surface_->getWidth(), color_loading_screen_surface_->getHeight())),
screen_surface_(std::make_shared<Surface>(options.game.width, options.game.height)) {
// Configura la superficie donde se van a pintar los sprites
screen_surface_->clear(static_cast<Uint8>(PaletteColor::WHITE));
// Inicializa variables
options.section.section = Section::LOADING_SCREEN;
options.section.subsection = Subsection::NONE;
// Establece el orden de las lineas para imitar el direccionamiento de memoria del spectrum
for (int i = 0; i < 192; ++i) {
if (i < 64) { // Primer bloque de 2K
line_index_[i] = ((i % 8) * 8) + (i / 8);
} else if (i < 128) { // Segundo bloque de 2K
line_index_[i] = 64 + ((i % 8) * 8) + ((i - 64) / 8);
} else { // Tercer bloque de 2K
line_index_[i] = 128 + ((i % 8) * 8) + ((i - 128) / 8);
}
}
// Cambia el color del borde
Screen::get()->setBorderColor(stringToColor("black"));
}
// Destructor
LoadingScreen::~LoadingScreen() {
JA_StopMusic();
}
// Comprueba el manejador de eventos
void LoadingScreen::checkEvents() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
globalEvents::check(event);
}
}
// Comprueba las entradas
void LoadingScreen::checkInput() {
globalInputs::check();
}
// Gestiona el contador de carga
void LoadingScreen::updateLoad() {
// Primera parte de la carga, la parte en blanco y negro
if (loading_first_part_) {
// Cada 5 pasos el load_counter_ se incrementa en uno
constexpr int NUM_STEPS = 5;
constexpr int STEPS = 51;
load_counter_ = counter_ / NUM_STEPS;
if (load_counter_ < 192) {
load_rect_.x = STEPS * (counter_ % NUM_STEPS);
load_rect_.y = line_index_[load_counter_];
mono_loading_screen_sprite_->setClip(load_rect_);
mono_loading_screen_sprite_->setPosition(load_rect_);
}
// Una vez actualizadas las 192 lineas, pasa a la segunda fase de la carga
else if (load_counter_ == 192) {
loading_first_part_ = false;
load_counter_ = 0;
load_rect_ = {0, 0, 16, 8};
color_loading_screen_sprite_->setClip(load_rect_);
color_loading_screen_sprite_->setPosition(load_rect_);
JA_PlayMusic(Resource::get()->getMusic("loading_sound3.ogg"));
}
}
// Segunda parte de la carga, la parte de los bloques en color
else {
load_counter_ += 2;
load_rect_.x = (load_counter_ * 8) % 256;
load_rect_.y = (load_counter_ / 32) * 8;
color_loading_screen_sprite_->setClip(load_rect_);
color_loading_screen_sprite_->setPosition(load_rect_);
// Comprueba si ha terminado la intro
if (load_counter_ >= 768) {
options.section.section = Section::TITLE;
options.section.subsection = Subsection::TITLE_WITH_LOADING_SCREEN;
JA_StopMusic();
}
}
}
// Gestiona el contador interno
void LoadingScreen::updateCounter() {
(pre_counter_ >= 50) ? counter_++ : pre_counter_++;
if (counter_ == 1) {
JA_PlayMusic(Resource::get()->getMusic("loading_sound2.ogg"));
}
}
// Dibuja la pantalla de carga
void LoadingScreen::renderLoad() {
auto previuos_renderer = Screen::get()->getRendererSurface();
Screen::get()->setRendererSurface(screen_surface_);
loading_first_part_ ? mono_loading_screen_sprite_->render(1, stringToColor("black")) : color_loading_screen_sprite_->render();
Screen::get()->setRendererSurface(previuos_renderer);
}
// Dibuja el efecto de carga en el borde
void LoadingScreen::renderBorder() {
// Obtiene la Surface del borde
auto border = Screen::get()->getBorderSurface();
// Pinta el borde de color azul
border->clear(static_cast<Uint8>(PaletteColor::BLUE));
// Añade lineas amarillas
const Uint8 COLOR = static_cast<Uint8>(PaletteColor::YELLOW);
const int WIDTH = options.game.width + (options.video.border.width * 2);
const int HEIGHT = options.game.height + (options.video.border.height * 2);
bool draw_enabled = rand() % 2 == 0 ? true : false;
int row = 0;
while (row < HEIGHT) {
const int ROW_HEIGHT = (rand() % 4) + 3;
if (draw_enabled) {
for (int i = row; i < row + ROW_HEIGHT; ++i) {
border->drawLine(0, i, WIDTH, i, COLOR);
}
}
row += ROW_HEIGHT;
draw_enabled = !draw_enabled;
}
}
// Actualiza las variables
void LoadingScreen::update() {
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
if (SDL_GetTicks() - ticks_ > GAME_SPEED) {
ticks_ = SDL_GetTicks();
checkInput();
updateCounter();
updateLoad();
renderLoad();
Screen::get()->update();
}
}
// Dibuja en pantalla
void LoadingScreen::render() {
if (options.video.border.enabled) {
// Dibuja el efecto de carga en el borde
renderBorder();
}
// Prepara para empezar a dibujar en la textura de juego
Screen::get()->start();
Screen::get()->clearSurface(stringToColor("white"));
// Copia la surface a la surface de Screen
screen_surface_->render(0, 0);
// Vuelca el contenido del renderizador en pantalla
Screen::get()->render();
}
// Bucle para el logo del juego
void LoadingScreen::run() {
// Inicia el sonido de carga
JA_SetVolume(64);
JA_PlayMusic(Resource::get()->getMusic("loading_sound1.ogg"));
// Limpia la pantalla
Screen::get()->start();
Screen::get()->clearRenderer();
Screen::get()->render();
while (options.section.section == Section::LOADING_SCREEN) {
update();
checkEvents();
render();
}
JA_SetVolume(128);
}