step B.1: fades de ModuleGame tick-based amb scenes::PaletteFade (fases FadingIn/FadingOut sense redibuixar, per no perdre el frame final)
This commit is contained in:
@@ -37,11 +37,11 @@ Director* Director::instance_ = nullptr;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Entry del fiber del joc. Alterna entre la capa `scenes::` (cinemàtiques
|
// Entry del fiber del joc. Dispatcha a una escena segons l'estat actual:
|
||||||
// i menús, triats per `info::ctx.num_piramide` via el SceneRegistry) i
|
// `gameState == 0` → ModuleGame (gameplay), `gameState == 1` → una
|
||||||
// ModuleGame (gameplay) fins que el joc demana eixir. Quan el codi de
|
// `scenes::Scene` del registry triada per `info::ctx.num_piramide`. Cada
|
||||||
// gameplay o una escena crida JD8_Flip(), el control torna automàticament
|
// escena és tick-based; el JD8_Flip() entre ticks cedeix al Director
|
||||||
// al Director via `GameFiber::yield()`.
|
// via `GameFiber::yield()`.
|
||||||
void gameFiberEntry() {
|
void gameFiberEntry() {
|
||||||
info::ctx.num_habitacio = Options::game.habitacio_inicial;
|
info::ctx.num_habitacio = Options::game.habitacio_inicial;
|
||||||
info::ctx.num_piramide = Options::game.piramide_inicial;
|
info::ctx.num_piramide = Options::game.piramide_inicial;
|
||||||
@@ -60,31 +60,29 @@ void gameFiberEntry() {
|
|||||||
|
|
||||||
int gameState = 1;
|
int gameState = 1;
|
||||||
while (gameState != -1 && !JG_Quitting()) {
|
while (gameState != -1 && !JG_Quitting()) {
|
||||||
|
std::unique_ptr<scenes::Scene> scene;
|
||||||
|
|
||||||
if (gameState == 0) {
|
if (gameState == 0) {
|
||||||
// Gameplay pur (ModuleGame encara és cooperatiu-clàssic: conté
|
// Gameplay. ModuleGame és una scenes::Scene des de Phase A de
|
||||||
// el seu while intern i crida JD8_Flip manualment). Fora
|
// la migració — mateix mini-loop tick+flip que la resta.
|
||||||
// d'abast de la migració scenes:: — es tractarà en una fase
|
scene = std::make_unique<ModuleGame>();
|
||||||
// posterior quan el fiber es puga eliminar.
|
} else {
|
||||||
auto* mg = new ModuleGame();
|
// gameState == 1: dispatch al registry per num_piramide. El
|
||||||
gameState = mg->Go();
|
// vell ModuleSequence::Go() feia aquest redirect al principi:
|
||||||
delete mg;
|
// si el jugador arriba a la Secreta (6) sense prou diners,
|
||||||
continue;
|
// salta als slides de fracàs (7) abans de buscar l'escena.
|
||||||
|
if (info::ctx.num_piramide == 6 && info::ctx.diners < 200) {
|
||||||
|
info::ctx.num_piramide = 7;
|
||||||
|
}
|
||||||
|
scene = scenes::SceneRegistry::instance().tryCreate(info::ctx.num_piramide);
|
||||||
}
|
}
|
||||||
|
|
||||||
// gameState == 1: dispatch a la capa scenes::.
|
|
||||||
// El vell `ModuleSequence::Go()` feia aquest redirect al principi:
|
|
||||||
// si el jugador arriba a la Secreta (6) sense prou diners, salta
|
|
||||||
// als slides de fracàs (7) abans de buscar l'escena al registry.
|
|
||||||
if (info::ctx.num_piramide == 6 && info::ctx.diners < 200) {
|
|
||||||
info::ctx.num_piramide = 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto scene = scenes::SceneRegistry::instance().tryCreate(info::ctx.num_piramide);
|
|
||||||
if (!scene) {
|
if (!scene) {
|
||||||
// State no registrat — indica un bug del dispatcher o del
|
// State no registrat — indica un bug del dispatcher o del
|
||||||
// registre d'escenes. Eixim ordenadament en lloc de cremar CPU.
|
// registre d'escenes. Eixim ordenadament en lloc de cremar CPU.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
scene->onEnter();
|
scene->onEnter();
|
||||||
Uint32 last = SDL_GetTicks();
|
Uint32 last = SDL_GetTicks();
|
||||||
while (!scene->done() && !JG_Quitting()) {
|
while (!scene->done() && !JG_Quitting()) {
|
||||||
|
|||||||
@@ -1,165 +1,204 @@
|
|||||||
#include "game/modulegame.hpp"
|
#include "game/modulegame.hpp"
|
||||||
|
|
||||||
#include "core/jail/jail_audio.hpp"
|
#include "core/jail/jail_audio.hpp"
|
||||||
#include "core/jail/jdraw8.hpp"
|
#include "core/jail/jdraw8.hpp"
|
||||||
#include "core/jail/jfile.hpp"
|
#include "core/jail/jfile.hpp"
|
||||||
#include "core/jail/jgame.hpp"
|
#include "core/jail/jgame.hpp"
|
||||||
#include "core/jail/jinput.hpp"
|
#include "core/jail/jinput.hpp"
|
||||||
|
|
||||||
ModuleGame::ModuleGame() {
|
ModuleGame::ModuleGame() {
|
||||||
this->gfx = JD8_LoadSurface(info::ctx.pepe_activat ? "frames2.gif" : "frames.gif");
|
this->gfx = JD8_LoadSurface(info::ctx.pepe_activat ? "frames2.gif" : "frames.gif");
|
||||||
JG_SetUpdateTicks(10);
|
JG_SetUpdateTicks(10);
|
||||||
|
|
||||||
this->sam = new Prota(this->gfx);
|
this->sam = new Prota(this->gfx);
|
||||||
this->mapa = new Mapa(this->gfx, this->sam);
|
this->mapa = new Mapa(this->gfx, this->sam);
|
||||||
this->marcador = new Marcador(this->gfx, this->sam);
|
this->marcador = new Marcador(this->gfx, this->sam);
|
||||||
if (info::ctx.num_piramide == 2) {
|
if (info::ctx.num_piramide == 2) {
|
||||||
this->bola = new Bola(this->gfx, this->sam);
|
this->bola = new Bola(this->gfx, this->sam);
|
||||||
} else {
|
} else {
|
||||||
this->bola = NULL;
|
this->bola = nullptr;
|
||||||
}
|
}
|
||||||
this->momies = NULL;
|
this->momies = nullptr;
|
||||||
|
|
||||||
this->final = 0;
|
this->iniciarMomies();
|
||||||
this->iniciarMomies();
|
}
|
||||||
}
|
|
||||||
|
ModuleGame::~ModuleGame() {
|
||||||
ModuleGame::~ModuleGame(void) {
|
if (this->bola != nullptr) delete this->bola;
|
||||||
JD8_FadeOut();
|
if (this->momies != nullptr) {
|
||||||
|
this->momies->clear();
|
||||||
if (this->bola != NULL) delete this->bola;
|
delete this->momies;
|
||||||
if (this->momies != NULL) {
|
}
|
||||||
this->momies->clear();
|
delete this->marcador;
|
||||||
delete this->momies;
|
delete this->mapa;
|
||||||
}
|
delete this->sam;
|
||||||
delete this->marcador;
|
|
||||||
delete this->mapa;
|
JD8_FreeSurface(this->gfx);
|
||||||
delete this->sam;
|
}
|
||||||
|
|
||||||
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
|
||||||
int ModuleGame::Go() {
|
// fade interpolarien cap a una paleta amb pantalla buida.
|
||||||
this->Draw();
|
this->Draw();
|
||||||
|
|
||||||
const char* music = info::ctx.num_piramide == 3 ? "00000008.ogg" : (info::ctx.num_piramide == 2 ? "00000007.ogg" : (info::ctx.num_piramide == 6 ? "00000002.ogg" : "00000006.ogg"));
|
const char* music = info::ctx.num_piramide == 3 ? "00000008.ogg"
|
||||||
const char* current_music = JA_GetMusicFilename();
|
: info::ctx.num_piramide == 2 ? "00000007.ogg"
|
||||||
if ((JA_GetMusicState() != JA_MUSIC_PLAYING) || !(strcmp(music, current_music) == 0)) {
|
: info::ctx.num_piramide == 6 ? "00000002.ogg"
|
||||||
auto buffer = file_readfile(music);
|
: "00000006.ogg";
|
||||||
JA_PlayMusic(JA_LoadMusic(reinterpret_cast<Uint8*>(buffer.data()),
|
const char* current_music = JA_GetMusicFilename();
|
||||||
static_cast<Uint32>(buffer.size()), music));
|
if ((JA_GetMusicState() != JA_MUSIC_PLAYING) || !current_music ||
|
||||||
}
|
strcmp(music, current_music) != 0) {
|
||||||
|
auto buffer = file_readfile(music);
|
||||||
JD8_FadeToPal(JD8_LoadPalette(info::ctx.pepe_activat ? "frames2.gif" : "frames.gif"));
|
JA_PlayMusic(JA_LoadMusic(reinterpret_cast<Uint8*>(buffer.data()),
|
||||||
|
static_cast<Uint32>(buffer.size()), music));
|
||||||
while (this->final == 0 && !JG_Quitting()) {
|
}
|
||||||
this->Draw();
|
|
||||||
this->Update();
|
// 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`.
|
||||||
// JS_FadeOutMusic();
|
fade_.startFadeTo(JD8_LoadPalette(info::ctx.pepe_activat ? "frames2.gif" : "frames.gif"));
|
||||||
|
phase_ = Phase::FadingIn;
|
||||||
if (this->final == 1) {
|
}
|
||||||
info::ctx.num_habitacio++;
|
|
||||||
if (info::ctx.num_habitacio == 6) {
|
void ModuleGame::tick(int delta_ms) {
|
||||||
info::ctx.num_habitacio = 1;
|
switch (phase_) {
|
||||||
info::ctx.num_piramide++;
|
case Phase::FadingIn:
|
||||||
}
|
// No redibuixem durant el fade: el `screen` ja va ser omplit
|
||||||
if (info::ctx.num_piramide == 6 && info::ctx.num_habitacio == 2) info::ctx.num_piramide++;
|
// per la Draw() d'onEnter. Només el JD8_Flip del caller muta
|
||||||
} else if (this->final == 2) {
|
// pixel_data segons la paleta que avança pas a pas.
|
||||||
info::ctx.num_piramide = 100;
|
fade_.tick(delta_ms);
|
||||||
}
|
if (fade_.done()) phase_ = Phase::Playing;
|
||||||
|
break;
|
||||||
if (JG_Quitting()) {
|
|
||||||
return -1;
|
case Phase::Playing:
|
||||||
} else {
|
this->Draw();
|
||||||
if (info::ctx.num_habitacio == 1 || info::ctx.num_piramide == 100 || info::ctx.num_piramide == 7) {
|
this->Update();
|
||||||
return 1;
|
if (this->final_ != 0) {
|
||||||
} else {
|
this->applyFinalTransitions();
|
||||||
return 0;
|
fade_.startFadeOut();
|
||||||
}
|
phase_ = Phase::FadingOut;
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
|
|
||||||
void ModuleGame::Draw() {
|
case Phase::FadingOut:
|
||||||
this->mapa->draw();
|
// No redibuixem: el `screen` té l'últim frame pintat per la
|
||||||
this->marcador->draw();
|
// fase Playing (just abans que Update() setegés `final_`).
|
||||||
this->sam->draw();
|
// El vell `JD8_FadeOut` feia exactament això — flips amb
|
||||||
if (this->momies != NULL) this->momies->draw();
|
// paleta fading però sense tocar el buffer. Redibuixar ací
|
||||||
if (this->bola != NULL) this->bola->draw();
|
// mostraria l'estat post-Update del sprite (p.ex. el prota
|
||||||
|
// "tornant" davant la porta després d'haver eixit).
|
||||||
JD8_Flip();
|
fade_.tick(delta_ms);
|
||||||
}
|
if (fade_.done()) phase_ = Phase::Done;
|
||||||
|
break;
|
||||||
void ModuleGame::Update() {
|
|
||||||
if (JG_ShouldUpdate()) {
|
case Phase::Done:
|
||||||
JI_Update();
|
break;
|
||||||
|
}
|
||||||
this->final = this->sam->update();
|
}
|
||||||
if (this->momies != NULL && this->momies->update()) {
|
|
||||||
Momia* seguent = this->momies->next;
|
int ModuleGame::nextState() const {
|
||||||
delete this->momies;
|
if (JG_Quitting()) return -1;
|
||||||
this->momies = seguent;
|
if (info::ctx.num_habitacio == 1 ||
|
||||||
info::ctx.momies--;
|
info::ctx.num_piramide == 100 ||
|
||||||
}
|
info::ctx.num_piramide == 7) {
|
||||||
if (this->bola != NULL) this->bola->update();
|
return 1;
|
||||||
this->mapa->update();
|
}
|
||||||
if (this->mapa->novaMomia()) {
|
return 0;
|
||||||
if (this->momies != NULL) {
|
}
|
||||||
this->momies->insertar(new Momia(this->gfx, true, 0, 0, this->sam));
|
|
||||||
info::ctx.momies++;
|
void ModuleGame::applyFinalTransitions() {
|
||||||
} else {
|
if (this->final_ == 1) {
|
||||||
this->momies = new Momia(this->gfx, true, 0, 0, this->sam);
|
info::ctx.num_habitacio++;
|
||||||
info::ctx.momies++;
|
if (info::ctx.num_habitacio == 6) {
|
||||||
}
|
info::ctx.num_habitacio = 1;
|
||||||
}
|
info::ctx.num_piramide++;
|
||||||
|
}
|
||||||
if (JI_CheatActivated("reviu")) info::ctx.vida = 5;
|
if (info::ctx.num_piramide == 6 && info::ctx.num_habitacio == 2) info::ctx.num_piramide++;
|
||||||
if (JI_CheatActivated("alone")) {
|
} else if (this->final_ == 2) {
|
||||||
if (this->momies != NULL) {
|
info::ctx.num_piramide = 100;
|
||||||
this->momies->clear();
|
}
|
||||||
delete this->momies;
|
}
|
||||||
this->momies = NULL;
|
|
||||||
info::ctx.momies = 0;
|
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.
|
||||||
if (JI_CheatActivated("obert")) {
|
this->mapa->draw();
|
||||||
for (int i = 0; i < 16; i++) {
|
this->marcador->draw();
|
||||||
this->mapa->tombes[i].costat[0] = true;
|
this->sam->draw();
|
||||||
this->mapa->tombes[i].costat[1] = true;
|
if (this->momies != nullptr) this->momies->draw();
|
||||||
this->mapa->tombes[i].costat[2] = true;
|
if (this->bola != nullptr) this->bola->draw();
|
||||||
this->mapa->tombes[i].costat[3] = true;
|
}
|
||||||
this->mapa->comprovaCaixa(i);
|
|
||||||
}
|
void ModuleGame::Update() {
|
||||||
}
|
if (JG_ShouldUpdate()) {
|
||||||
|
JI_Update();
|
||||||
if (JI_KeyPressed(SDL_SCANCODE_ESCAPE)) {
|
|
||||||
JG_QuitSignal();
|
this->final_ = this->sam->update();
|
||||||
}
|
if (this->momies != nullptr && this->momies->update()) {
|
||||||
}
|
Momia* seguent = this->momies->next;
|
||||||
}
|
delete this->momies;
|
||||||
|
this->momies = seguent;
|
||||||
void ModuleGame::iniciarMomies() {
|
info::ctx.momies--;
|
||||||
if (info::ctx.num_habitacio == 1) {
|
}
|
||||||
info::ctx.momies = 1;
|
if (this->bola != nullptr) this->bola->update();
|
||||||
} else {
|
this->mapa->update();
|
||||||
info::ctx.momies++;
|
if (this->mapa->novaMomia()) {
|
||||||
}
|
if (this->momies != nullptr) {
|
||||||
if (info::ctx.num_piramide == 6) info::ctx.momies = 8;
|
this->momies->insertar(new Momia(this->gfx, true, 0, 0, this->sam));
|
||||||
|
info::ctx.momies++;
|
||||||
int x = 20;
|
} else {
|
||||||
int y = 170;
|
this->momies = new Momia(this->gfx, true, 0, 0, this->sam);
|
||||||
bool dimonis = info::ctx.num_piramide == 6;
|
info::ctx.momies++;
|
||||||
for (int i = 0; i < info::ctx.momies; i++) {
|
}
|
||||||
if (this->momies == NULL) {
|
}
|
||||||
this->momies = new Momia(this->gfx, dimonis, x, y, this->sam);
|
|
||||||
} else {
|
if (JI_CheatActivated("reviu")) info::ctx.vida = 5;
|
||||||
this->momies->insertar(new Momia(this->gfx, dimonis, x, y, this->sam));
|
if (JI_CheatActivated("alone")) {
|
||||||
}
|
if (this->momies != nullptr) {
|
||||||
x += 65;
|
this->momies->clear();
|
||||||
if (x == 345) {
|
delete this->momies;
|
||||||
x = 20;
|
this->momies = nullptr;
|
||||||
y -= 35;
|
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);
|
||||||
|
} else {
|
||||||
|
this->momies->insertar(new Momia(this->gfx, dimonis, x, y, this->sam));
|
||||||
|
}
|
||||||
|
x += 65;
|
||||||
|
if (x == 345) {
|
||||||
|
x = 20;
|
||||||
|
y -= 35;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,31 +1,60 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "game/bola.hpp"
|
#include "game/bola.hpp"
|
||||||
#include "game/info.hpp"
|
#include "game/info.hpp"
|
||||||
#include "game/mapa.hpp"
|
#include "game/mapa.hpp"
|
||||||
#include "game/marcador.hpp"
|
#include "game/marcador.hpp"
|
||||||
#include "game/momia.hpp"
|
#include "game/momia.hpp"
|
||||||
#include "game/prota.hpp"
|
#include "game/prota.hpp"
|
||||||
|
#include "scenes/palette_fade.hpp"
|
||||||
class ModuleGame {
|
#include "scenes/scene.hpp"
|
||||||
public:
|
|
||||||
ModuleGame();
|
// Escena de gameplay pur. Reemplaça el vell `Go()` bloquejant amb
|
||||||
~ModuleGame(void);
|
// l'interfície `scenes::Scene` tick-based: `onEnter()` arranca la
|
||||||
|
// música i un fade-in, el `tick()` avança un frame (Draw + Update
|
||||||
int Go();
|
// gated per JG_ShouldUpdate), i quan la partida acaba fa un fade-out
|
||||||
|
// abans de retornar el next state.
|
||||||
private:
|
//
|
||||||
void Draw();
|
// Tres fases internes:
|
||||||
void Update();
|
// 1. FadingIn — fade-in 32 passos mentre el render segueix viu.
|
||||||
|
// 2. Playing — gameplay normal; `final_` es setja quan el prota mor
|
||||||
void iniciarMomies();
|
// o canvia de sala. `Update()` només avança cada 10 ms
|
||||||
|
// via `JG_ShouldUpdate` (ticker fix del jail).
|
||||||
Uint8 final;
|
// 3. FadingOut — fade-out 32 passos mantenint l'últim frame visible
|
||||||
JD8_Surface gfx;
|
// (substituïx el `JD8_FadeOut` bloquejant que feia el
|
||||||
|
// destructor legacy).
|
||||||
Mapa* mapa;
|
class ModuleGame : public scenes::Scene {
|
||||||
Prota* sam;
|
public:
|
||||||
Marcador* marcador;
|
ModuleGame();
|
||||||
Momia* momies;
|
~ModuleGame() override;
|
||||||
Bola* bola;
|
|
||||||
};
|
void onEnter() override;
|
||||||
|
void tick(int delta_ms) override;
|
||||||
|
bool done() const override { return phase_ == Phase::Done; }
|
||||||
|
int nextState() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class Phase {
|
||||||
|
FadingIn,
|
||||||
|
Playing,
|
||||||
|
FadingOut,
|
||||||
|
Done,
|
||||||
|
};
|
||||||
|
|
||||||
|
void Draw(); // render a `screen`; no crida JD8_Flip (ho fa el caller)
|
||||||
|
void Update(); // gated per JG_ShouldUpdate
|
||||||
|
|
||||||
|
void iniciarMomies();
|
||||||
|
void applyFinalTransitions(); // muta info::ctx quan final_ passa a !=0
|
||||||
|
|
||||||
|
Phase phase_{Phase::FadingIn};
|
||||||
|
scenes::PaletteFade fade_;
|
||||||
|
Uint8 final_{0};
|
||||||
|
JD8_Surface gfx{nullptr};
|
||||||
|
|
||||||
|
Mapa* mapa{nullptr};
|
||||||
|
Prota* sam{nullptr};
|
||||||
|
Marcador* marcador{nullptr};
|
||||||
|
Momia* momies{nullptr};
|
||||||
|
Bola* bola{nullptr};
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user