196 lines
6.0 KiB
C++
196 lines
6.0 KiB
C++
#include "game/modulegame.hpp"
|
|
|
|
#include <algorithm>
|
|
|
|
#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() {
|
|
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 = "piramide_1_4_5.ogg";
|
|
if (info::ctx.num_piramide == 3) {
|
|
music_name = "piramide_3.ogg";
|
|
} else if (info::ctx.num_piramide == 2) {
|
|
music_name = "piramide_2.ogg";
|
|
} else if (info::ctx.num_piramide == 6) {
|
|
music_name = "secreta.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::FADING_IN;
|
|
}
|
|
|
|
void ModuleGame::tick(int delta_ms) {
|
|
switch (phase_) {
|
|
case Phase::FADING_IN:
|
|
// 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::FADING_OUT;
|
|
}
|
|
break;
|
|
|
|
case Phase::FADING_OUT:
|
|
// 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;
|
|
}
|
|
}
|
|
|
|
auto ModuleGame::nextState() const -> int {
|
|
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() const {
|
|
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();
|
|
for (auto& m : this->momies_) {
|
|
m->draw();
|
|
}
|
|
if (this->bola_) {
|
|
this->bola_->draw();
|
|
}
|
|
}
|
|
|
|
void ModuleGame::update() {
|
|
if (Jg::shouldUpdate()) {
|
|
Ji::update();
|
|
|
|
this->final_ = this->sam_->update();
|
|
const auto erased = std::erase_if(this->momies_, [](auto& m) { return m->update(); });
|
|
info::ctx.momies -= static_cast<int>(erased);
|
|
if (this->bola_) {
|
|
this->bola_->update();
|
|
}
|
|
this->mapa_->update();
|
|
if (this->mapa_->novaMomia()) {
|
|
this->momies_.emplace_back(std::make_unique<Momia>(this->gfx_, true, 0, 0, this->sam_.get()));
|
|
info::ctx.momies++;
|
|
}
|
|
|
|
if (Ji::cheatActivated("reviu")) {
|
|
info::ctx.vida = 5;
|
|
}
|
|
if (Ji::cheatActivated("alone")) {
|
|
this->momies_.clear();
|
|
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++) {
|
|
this->momies_.emplace_back(std::make_unique<Momia>(this->gfx_, dimonis, x, y, this->sam_.get()));
|
|
x += 65;
|
|
if (x == 345) {
|
|
x = 20;
|
|
y -= 35;
|
|
}
|
|
}
|
|
}
|