396 lines
15 KiB
C++
396 lines
15 KiB
C++
#include "gamestates.h"
|
|
#include "../japi/game.h"
|
|
#include <SDL3/SDL.h>
|
|
#include <string>
|
|
#include "../aux/font.h"
|
|
#include "../entities/mapa.h"
|
|
#include "../entities/arounders.h"
|
|
|
|
namespace gamestate
|
|
{
|
|
namespace play
|
|
{
|
|
namespace eixir
|
|
{
|
|
const int no = 0;
|
|
const int postfase = 1;
|
|
const int mort = 2;
|
|
const int cheat = 3;
|
|
}
|
|
|
|
draw::surface *faded = nullptr;
|
|
draw::surface *fondo = nullptr;
|
|
draw::surface *cursor = nullptr;
|
|
draw::surface *aigua = nullptr;
|
|
|
|
uint32_t *original_palette = nullptr;
|
|
|
|
uint32_t arounderCount;
|
|
uint32_t startTicks;
|
|
uint32_t currentTicks;
|
|
|
|
int aigua_frame1 = 0;
|
|
int aigua_frame2 = 5;
|
|
|
|
int exit = play::eixir::no;
|
|
|
|
bool loop();
|
|
|
|
bool loop_pause();
|
|
bool loop_menu();
|
|
|
|
void backToLoop();
|
|
|
|
void draw();
|
|
void draw_aigua();
|
|
|
|
void finalize();
|
|
|
|
void init()
|
|
{
|
|
// Ara comença tot, per tant no volem eixir
|
|
play::exit = play::eixir::no;
|
|
|
|
// Carregar el fondo que toque i la seua paleta (que nomes usa els colors del 128 al 255)
|
|
char arxiuFondo[10] = "BKG00.GIF";
|
|
arxiuFondo[4] = (game::getConfig("fase") % 10) + 48;
|
|
play::fondo = draw::loadSurface(arxiuFondo, true);
|
|
|
|
// Carregar la paleta estandar (colors del 0 al 128)
|
|
uint32_t *pal = draw::loadPalette("tiles.gif");
|
|
draw::setPalette(pal, 128);
|
|
free(pal);
|
|
|
|
// Carregar els gifs auxiliars i crear la superficie per al fondo de la pausa i el menu
|
|
play::cursor = draw::loadSurface("cursor.gif");
|
|
play::aigua = draw::loadSurface("aigua.gif");
|
|
play::faded = draw::createSurface(320, 200);
|
|
|
|
arounders::init();
|
|
// [TODO] Crear el primer Arounder
|
|
// REALMENT NO. PREFEREIXC QUE PASEN UNS SEGONS ABANS QUE ARRIBE EL PRIMER
|
|
// mapa::arounders::eixits++;
|
|
// arounder_seleccionat = primerArounders
|
|
|
|
// Enxufa el arradio
|
|
audio::loadAndPlayMusic((game::getConfig("fase")+1) % 5 == 0 ? "mus6.ogg" : "mus4.ogg");
|
|
|
|
// Fiquem a contar el cronómetre de arounders
|
|
play::arounderCount = play::startTicks = game::getTicks();
|
|
|
|
// Fade in i anem al bucle principal
|
|
draw::fadein();
|
|
game::setState(gamestate::play::loop);
|
|
}
|
|
|
|
bool loop()
|
|
{
|
|
// Si ja s'ha demanat l'eixida...
|
|
if (play::exit) {
|
|
// I si ja s'ha acabat el fadeout...
|
|
if (!draw::isfading()) {
|
|
// Alliberem memòria
|
|
play::finalize();
|
|
|
|
// I anem on toque
|
|
if (play::exit==play::eixir::postfase) gamestate::postfase::init();
|
|
else if (play::exit==play::eixir::mort) gamestate::mort::init();
|
|
else if (play::exit==play::eixir::cheat) gamestate::prefase::init();
|
|
}
|
|
// En qualsevol cas, renderitzem i eixim ja del bucle (fins que acabe el fadeout)
|
|
draw::render();
|
|
return true;
|
|
}
|
|
|
|
// Pintar tot menys el cursor
|
|
play::draw();
|
|
|
|
// Si se pulsa 'P', o el botó del mig del ratolí, o si la finestra perd el foco...
|
|
if (input::keyPressed(SDL_SCANCODE_P) || input::mouseClk(input::mouse::button::middle) || !game::windowHasFocus)
|
|
{
|
|
// Parem el cronòmetre d'arounders
|
|
play::arounderCount = game::getTicks() - play::arounderCount;
|
|
|
|
// Pintem el que hi ha a la pantalla en la surface "faded", li afegim el text "PAUSA" i aixó es tot el que pintarem fins eixir de la pausa
|
|
draw::setSource(nullptr);
|
|
draw::setDestination(play::faded);
|
|
draw::draw();
|
|
font::selectFont(font::type::fade);
|
|
font::print(136, 80, "PAUSA");
|
|
draw::setDestination(nullptr);
|
|
|
|
// Reduïm tots els colors de la paleta (menys els epecials) a la meitat del seu color
|
|
play::original_palette = draw::getPalette();
|
|
for (int i=0; i<256; ++i) if ( i!=61 && i!= 62 && (i<68 || i >75) )
|
|
{
|
|
uint32_t p = play::original_palette[i];
|
|
uint8_t r = (p >> 16) & 0xff;
|
|
uint8_t g = (p >> 8) & 0xff;
|
|
uint8_t b = p & 0xff;
|
|
draw::setPaletteEntry(i, r >> 1, g >> 1, b >> 1);
|
|
}
|
|
|
|
// Canviem el bucle principal a "loop_pausa()"
|
|
game::setState(gamestate::play::loop_pause);
|
|
return true;
|
|
}
|
|
|
|
// Si se pulsa ESC...
|
|
if (input::keyPressed(SDL_SCANCODE_ESCAPE))
|
|
{
|
|
// Parem el cronòmetre d'arounders
|
|
play::arounderCount = game::getTicks() - play::arounderCount;
|
|
|
|
// Pintem el que hi ha a la pantalla en la surface "faded", li afegim el menú i aixó es tot el que pintarem fins eixir del menú
|
|
draw::setSource(nullptr);
|
|
draw::setDestination(play::faded);
|
|
draw::draw();
|
|
draw::surface *menu = draw::loadSurface("menu.gif");
|
|
draw::setSource(menu);
|
|
draw::draw(97, 52);
|
|
draw::freeSurface(menu);
|
|
font::selectFont(font::type::fade);
|
|
font::print(129, 60, "CONTINUAR");
|
|
font::print(129, 71, "REINICIAR");
|
|
font::print(112, 82, "MENU PRINCIPAL");
|
|
font::print(143, 93, "EIXIR");
|
|
draw::setDestination(nullptr);
|
|
|
|
// Reduïm tots els colors de la paleta (menys els epecials) a la meitat del seu color
|
|
play::original_palette = draw::getPalette();
|
|
for (int i=0; i<256; ++i) if ( i!=61 && i!= 62 && (i<68 || i >75) )
|
|
{
|
|
uint32_t p = play::original_palette[i];
|
|
uint8_t r = (p >> 16) & 0xff;
|
|
uint8_t g = (p >> 8) & 0xff;
|
|
uint8_t b = p & 0xff;
|
|
draw::setPaletteEntry(i, r >> 1, g >> 1, b >> 1);
|
|
}
|
|
|
|
// Canviem el bucle principal a "loop_menu()"
|
|
game::setState(gamestate::play::loop_menu);
|
|
return true;
|
|
}
|
|
|
|
// Ara ja, pintem el cursor i enviem tot a pantalla
|
|
// No ho havem fet abans perque en el fondo de la pausa o el menú no volem que aparega el cursor
|
|
draw::setSource(cursor);
|
|
draw::draw(input::mouseX(), input::mouseY());
|
|
draw::render();
|
|
|
|
// Si pulsem el botó de la dreta, el arounder seleccionat deixa de fer l'acció que està fent
|
|
if (input::mouseClk(input::mouse::button::right))
|
|
{
|
|
arounders::abortarAccio();
|
|
}
|
|
|
|
// Si pulsem el botó de l'esquerra... pos es més complicat! Anem pas per pas...
|
|
if (input::mouseClk(input::mouse::button::left))
|
|
{
|
|
// Si al pulsar no havem seleccionat cap arounder (o siga, no havem fet click sobre un arounder)...
|
|
if (!arounders::seleccionar())
|
|
{
|
|
// Si no havem pulsat en la zona de baix dels botons, i hi ha un arounder seleccionat, i està caminant...
|
|
if (input::mouseY()<165 && arounders::seleccionat != nullptr && arounders::seleccionat->accio == arounders::accions::caminar)
|
|
{
|
|
// Fem que camine en la direcció en que està el cursor
|
|
arounders::seleccionat->orientacio = input::mouseX() > arounders::seleccionat->x ? arounders::orientacions::dreta : arounders::orientacions::esquerra;
|
|
}
|
|
}
|
|
|
|
// Mirem si havem pulsat un botó... (si el botó està a 0, no conta com a pulsat)
|
|
const int botoPulsat = mapa::procesar();
|
|
// Si havem pulsat un botó i tenim un arounder seleccionat...
|
|
if (botoPulsat != -1 && arounders::seleccionat != nullptr)
|
|
{
|
|
// Si el botó pulsat se correspon en la accio encolada
|
|
if (botoPulsat == arounders::seleccionat->prevista) {
|
|
// La desencolem
|
|
arounders::seleccionat->prevista = arounders::seleccionat->accio;
|
|
} else {
|
|
// Pero si no, la encolem (atenció, moltes accions comencen instantàneament)
|
|
arounders::seleccionat->prevista = botoPulsat;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Si ha passat el temps suficient, actualitzem els arounders (i les ones)
|
|
// Açò pot ser mes tard o mes prompte depenent de si havem accelerat el temps
|
|
currentTicks = game::getTicks() - startTicks;
|
|
if( currentTicks >= mapa::velocitat ) {
|
|
startTicks = game::getTicks();
|
|
aigua_frame1 = (aigua_frame1+1)%10;
|
|
aigua_frame2 = (aigua_frame2+1)%10;
|
|
|
|
// Ací passa quasi tot lo interessant!!! No t'ho perdes!!
|
|
arounders::procesar();
|
|
}
|
|
|
|
// Si ha passat el temps suficient...
|
|
// (també depen de si havem pulsat el botó de passar rapid el temps)
|
|
if ( (game::getTicks() - arounderCount) >= mapa::velocitat*58) {
|
|
// I encara queden arounders per eixir...
|
|
if (mapa::arounders::eixits < mapa::arounders::totals) {
|
|
// Traguem un nou arounder per la porta
|
|
arounders::afegir();
|
|
mapa::arounders::eixits++;
|
|
arounderCount = game::getTicks();
|
|
}
|
|
}
|
|
|
|
// Si tots els arounders ja han arribat o han mort...
|
|
if (mapa::arounders::arrivats + mapa::arounders::morts == mapa::arounders::totals) {
|
|
// Si han arribat els necessaris...
|
|
if (mapa::arounders::arrivats >= mapa::arounders::necessaris) {
|
|
// Pujem el numero de fase en el config i anem a la postfase
|
|
game::setConfig("fase", game::getConfig("fase")+1);
|
|
draw::fadeout();
|
|
audio::fadeOutMusic();
|
|
play::exit = play::eixir::postfase;
|
|
} else {
|
|
// Sino, anem a la pantalla de mort
|
|
draw::fadeout();
|
|
audio::fadeOutMusic();
|
|
play::exit = play::eixir::mort;
|
|
}
|
|
}
|
|
|
|
if (input::keyPressed(SDL_SCANCODE_F12)) {
|
|
game::setConfig("fase", game::getConfig("fase")+1);
|
|
draw::fadeout();
|
|
audio::fadeOutMusic();
|
|
play::exit = play::eixir::cheat;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Mentres estem en pausa, este es el bucle principal
|
|
bool loop_pause()
|
|
{
|
|
// Consisteix en pintar la surface sobre la que havem pintat la foto del que hi havia en pantalla
|
|
draw::draw(faded);
|
|
// ...I el cursor...
|
|
draw::setSource(cursor);
|
|
draw::draw(input::mouseX(), input::mouseY());
|
|
|
|
draw::render();
|
|
|
|
// I mirem si s'ha polsat P o ESC, per a tornat al bucle principal del mòdul de joc
|
|
if (input::keyPressed(SDL_SCANCODE_P) || input::keyPressed(SDL_SCANCODE_ESCAPE))
|
|
{
|
|
play::backToLoop();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Mentres estem en el menú, este es el bucle principal
|
|
bool loop_menu()
|
|
{
|
|
// Si havem triat eixir...
|
|
if (play::exit) {
|
|
// esperem a que acabe el fade...
|
|
if (!draw::isfading()) {
|
|
// I quan acabe
|
|
play::finalize();
|
|
if (exit==1) {
|
|
mapa::carregar();
|
|
gamestate::play::init();
|
|
}
|
|
if (exit==2) gamestate::menu::init();
|
|
}
|
|
draw::render();
|
|
return true;
|
|
}
|
|
|
|
draw::draw(faded);
|
|
draw::setSource(cursor);
|
|
draw::draw(input::mouseX(), input::mouseY());
|
|
|
|
draw::render();
|
|
|
|
if (input::keyPressed(SDL_SCANCODE_ESCAPE))
|
|
{
|
|
play::backToLoop();
|
|
}
|
|
|
|
if (input::mouseClk(input::mouse::button::left))
|
|
{
|
|
if (input::mouseX() >= 97 && input::mouseX() <= 223) {
|
|
if (input::mouseY() >= 60 && input::mouseY() <= 65) {
|
|
play::backToLoop();
|
|
}
|
|
if (input::mouseY() >= 71 && input::mouseY() <= 76) {
|
|
free(play::original_palette);
|
|
draw::fadeout();
|
|
audio::fadeOutMusic();
|
|
play::exit = 1;
|
|
}
|
|
if (input::mouseY() >= 82 && input::mouseY() <= 87) {
|
|
free(play::original_palette);
|
|
draw::fadeout();
|
|
audio::fadeOutMusic();
|
|
play::exit = 2;
|
|
}
|
|
if (input::mouseY() >= 93 && input::mouseY() <= 98) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void backToLoop()
|
|
{
|
|
draw::setPalette(play::original_palette, 256);
|
|
free(play::original_palette);
|
|
game::setState(gamestate::play::loop);
|
|
arounderCount = game::getTicks() - arounderCount;
|
|
}
|
|
|
|
void draw()
|
|
{
|
|
draw::draw(play::fondo);
|
|
|
|
int accio = 0;
|
|
int prevista = 0;
|
|
if (arounders::seleccionat) { accio = arounders::seleccionat->accio; prevista = arounders::seleccionat->prevista; }
|
|
mapa::pintar(accio, prevista);
|
|
|
|
draw_aigua();
|
|
arounders::pintar();
|
|
|
|
// [TODO] de fet, pintar la marca en el modul "arounders"
|
|
/*
|
|
if (arounders::seleccionat) {
|
|
draw::setSource(marca);
|
|
draw::draw(arounderSeleccionat->X-3, arounderSeleccionat->Y-3);
|
|
}
|
|
*/
|
|
|
|
}
|
|
|
|
void draw_aigua()
|
|
{
|
|
static int frames1[10] = {0,1,2,1,0,3,4,5,4,3};
|
|
static int frames2[10] = {6,7,8,7,6,9,10,11,10,9};
|
|
int *frames;
|
|
frames = (game::getConfig("fase")+1) % 5 == 0 ? frames2 : frames1;
|
|
|
|
draw::setSource(aigua);
|
|
for (int i=0;i<10;i++) {
|
|
draw::draw(i*32, 150, 16, 15, frames[aigua_frame1]*16, 0);
|
|
draw::draw(16+i*32, 150, 16, 15, frames[aigua_frame2]*16, 0);
|
|
}
|
|
}
|
|
|
|
void finalize()
|
|
{
|
|
draw::freeSurface(faded);
|
|
draw::freeSurface(fondo);
|
|
draw::freeSurface(cursor);
|
|
draw::freeSurface(aigua);
|
|
}
|
|
}
|
|
} |