Files
aee/source/game/modulegame.cpp
2026-04-18 13:22:13 +02:00

194 lines
6.4 KiB
C++

#include "game/modulegame.hpp"
#include "core/audio/audio.hpp"
#include "core/jail/jdraw8.hpp"
#include "core/jail/jgame.hpp"
#include "core/jail/jinput.hpp"
ModuleGame::ModuleGame() {
this->gfx = JD8_LoadSurface(info::ctx.pepe_activat ? "gfx/frames2.gif" : "gfx/frames.gif");
JG_SetUpdateTicks(10);
this->sam = std::make_unique<Prota>(this->gfx);
this->mapa = std::make_unique<Mapa>(this->gfx, this->sam.get());
this->marcador = std::make_unique<Marcador>(this->gfx, this->sam.get());
if (info::ctx.num_piramide == 2) {
this->bola = std::make_unique<Bola>(this->gfx, this->sam.get());
}
this->iniciarMomies();
}
ModuleGame::~ModuleGame() {
if (this->momies != nullptr) {
this->momies->clear();
delete this->momies;
}
JD8_FreeSurface(this->gfx);
}
void ModuleGame::onEnter() {
// Primera Draw per omplir `screen` amb el contingut del gameplay
// abans que el fade-in arranque. Si no, les primeres iteracions del
// fade interpolarien cap a una paleta amb pantalla buida.
this->Draw();
// Audio::playMusic ja és idempotent: si la pista actual coincideix amb la
// demanada, no fa res. Per això podem cridar-lo cada onEnter sense
// desencadenar restarts indesitjats.
const char* music_name = info::ctx.num_piramide == 3 ? "piramide_3.ogg"
: info::ctx.num_piramide == 2 ? "piramide_2.ogg"
: info::ctx.num_piramide == 6 ? "secreta.ogg"
: "piramide_1_4_5.ogg";
Audio::get()->playMusic(music_name);
// Arranca el fade-in tick-based. El `PaletteFade` avança un pas (de
// 32) per cada tick; durant aquesta fase el gameplay no corre,
// només Draw+fade. Substituïx la crida bloquejant `JD8_FadeToPal`.
fade_.startFadeTo(JD8_LoadPalette(info::ctx.pepe_activat ? "gfx/frames2.gif" : "gfx/frames.gif"));
phase_ = Phase::FadingIn;
}
void ModuleGame::tick(int delta_ms) {
switch (phase_) {
case Phase::FadingIn:
// No redibuixem durant el fade: el `screen` ja va ser omplit
// per la Draw() d'onEnter. Només el JD8_Flip del caller muta
// pixel_data segons la paleta que avança pas a pas.
fade_.tick(delta_ms);
if (fade_.done()) phase_ = Phase::Playing;
break;
case Phase::Playing:
this->Draw();
this->Update();
if (this->final_ != 0) {
this->applyFinalTransitions();
fade_.startFadeOut();
phase_ = Phase::FadingOut;
}
break;
case Phase::FadingOut:
// No redibuixem: el `screen` té l'últim frame pintat per la
// fase Playing (just abans que Update() setegés `final_`).
// El vell `JD8_FadeOut` feia exactament això — flips amb
// paleta fading però sense tocar el buffer. Redibuixar ací
// mostraria l'estat post-Update del sprite (p.ex. el prota
// "tornant" davant la porta després d'haver eixit).
fade_.tick(delta_ms);
if (fade_.done()) phase_ = Phase::Done;
break;
case Phase::Done:
break;
}
}
int ModuleGame::nextState() const {
if (JG_Quitting()) return -1;
if (info::ctx.num_habitacio == 1 ||
info::ctx.num_piramide == 100 ||
info::ctx.num_piramide == 7) {
return 1;
}
return 0;
}
void ModuleGame::applyFinalTransitions() {
if (this->final_ == 1) {
info::ctx.num_habitacio++;
if (info::ctx.num_habitacio == 6) {
info::ctx.num_habitacio = 1;
info::ctx.num_piramide++;
}
if (info::ctx.num_piramide == 6 && info::ctx.num_habitacio == 2) info::ctx.num_piramide++;
} else if (this->final_ == 2) {
info::ctx.num_piramide = 100;
}
}
void ModuleGame::Draw() {
// No crida JD8_Flip — el caller (mini-loop del fiber, o Director a
// Phase B.2) ho fa després de cada tick.
this->mapa->draw();
this->marcador->draw();
this->sam->draw();
if (this->momies != nullptr) this->momies->draw();
if (this->bola) this->bola->draw();
}
void ModuleGame::Update() {
if (JG_ShouldUpdate()) {
JI_Update();
this->final_ = this->sam->update();
if (this->momies != nullptr && this->momies->update()) {
Momia* seguent = this->momies->next;
delete this->momies;
this->momies = seguent;
info::ctx.momies--;
}
if (this->bola) this->bola->update();
this->mapa->update();
if (this->mapa->novaMomia()) {
if (this->momies != nullptr) {
this->momies->insertar(new Momia(this->gfx, true, 0, 0, this->sam.get()));
info::ctx.momies++;
} else {
this->momies = new Momia(this->gfx, true, 0, 0, this->sam.get());
info::ctx.momies++;
}
}
if (JI_CheatActivated("reviu")) info::ctx.vida = 5;
if (JI_CheatActivated("alone")) {
if (this->momies != nullptr) {
this->momies->clear();
delete this->momies;
this->momies = nullptr;
info::ctx.momies = 0;
}
}
if (JI_CheatActivated("obert")) {
for (int i = 0; i < 16; i++) {
this->mapa->tombes[i].costat[0] = true;
this->mapa->tombes[i].costat[1] = true;
this->mapa->tombes[i].costat[2] = true;
this->mapa->tombes[i].costat[3] = true;
this->mapa->comprovaCaixa(i);
}
}
if (JI_KeyPressed(SDL_SCANCODE_ESCAPE)) {
JG_QuitSignal();
}
}
}
void ModuleGame::iniciarMomies() {
if (info::ctx.num_habitacio == 1) {
info::ctx.momies = 1;
} else {
info::ctx.momies++;
}
if (info::ctx.num_piramide == 6) info::ctx.momies = 8;
int x = 20;
int y = 170;
bool dimonis = info::ctx.num_piramide == 6;
for (int i = 0; i < info::ctx.momies; i++) {
if (this->momies == nullptr) {
this->momies = new Momia(this->gfx, dimonis, x, y, this->sam.get());
} else {
this->momies->insertar(new Momia(this->gfx, dimonis, x, y, this->sam.get()));
}
x += 65;
if (x == 345) {
x = 20;
y -= 35;
}
}
}