step B.2: elimina fiber — Director posseeix l'escena, JD8_Flip sense yield, fiber.hpp/cpp esborrats
This commit is contained in:
@@ -15,7 +15,6 @@
|
||||
#include "core/rendering/menu.hpp"
|
||||
#include "core/rendering/overlay.hpp"
|
||||
#include "core/rendering/screen.hpp"
|
||||
#include "core/system/fiber.hpp"
|
||||
#include "game/info.hpp"
|
||||
#include "game/modulegame.hpp"
|
||||
#include "game/options.hpp"
|
||||
@@ -35,14 +34,9 @@ extern void JI_moveCheats(Uint8 new_key);
|
||||
|
||||
Director* Director::instance_ = nullptr;
|
||||
|
||||
namespace {
|
||||
Director::~Director() = default;
|
||||
|
||||
// Entry del fiber del joc. Dispatcha a una escena segons l'estat actual:
|
||||
// `gameState == 0` → ModuleGame (gameplay), `gameState == 1` → una
|
||||
// `scenes::Scene` del registry triada per `info::ctx.num_piramide`. Cada
|
||||
// escena és tick-based; el JD8_Flip() entre ticks cedeix al Director
|
||||
// via `GameFiber::yield()`.
|
||||
void gameFiberEntry() {
|
||||
void Director::initGameContext() {
|
||||
info::ctx.num_habitacio = Options::game.habitacio_inicial;
|
||||
info::ctx.num_piramide = Options::game.piramide_inicial;
|
||||
info::ctx.diners = Options::game.diners_inicial;
|
||||
@@ -57,55 +51,31 @@ void gameFiberEntry() {
|
||||
info::ctx.nou_personatge = true;
|
||||
fclose(ini);
|
||||
}
|
||||
|
||||
int gameState = 1;
|
||||
while (gameState != -1 && !JG_Quitting()) {
|
||||
std::unique_ptr<scenes::Scene> scene;
|
||||
|
||||
if (gameState == 0) {
|
||||
// Gameplay. ModuleGame és una scenes::Scene des de Phase A de
|
||||
// la migració — mateix mini-loop tick+flip que la resta.
|
||||
scene = std::make_unique<ModuleGame>();
|
||||
} else {
|
||||
// gameState == 1: dispatch al registry per num_piramide. 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.
|
||||
if (info::ctx.num_piramide == 6 && info::ctx.diners < 200) {
|
||||
info::ctx.num_piramide = 7;
|
||||
}
|
||||
scene = scenes::SceneRegistry::instance().tryCreate(info::ctx.num_piramide);
|
||||
}
|
||||
|
||||
if (!scene) {
|
||||
// State no registrat — indica un bug del dispatcher o del
|
||||
// registre d'escenes. Eixim ordenadament en lloc de cremar CPU.
|
||||
break;
|
||||
}
|
||||
|
||||
scene->onEnter();
|
||||
Uint32 last = SDL_GetTicks();
|
||||
while (!scene->done() && !JG_Quitting()) {
|
||||
JI_Update(); // refresca key_pressed/any_key per a les escenes
|
||||
const Uint32 now = SDL_GetTicks();
|
||||
scene->tick(static_cast<int>(now - last));
|
||||
last = now;
|
||||
JD8_Flip(); // presenta i cedix al Director
|
||||
}
|
||||
gameState = scene->nextState();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
std::unique_ptr<scenes::Scene> Director::createNextScene() {
|
||||
if (game_state_ == 0) {
|
||||
// Gameplay. ModuleGame és una scenes::Scene des de la Phase A.
|
||||
return std::make_unique<ModuleGame>();
|
||||
}
|
||||
// game_state_ == 1: dispatch al registry per num_piramide. Replica
|
||||
// del redirect que el vell ModuleSequence::Go() feia: 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;
|
||||
}
|
||||
return scenes::SceneRegistry::instance().tryCreate(info::ctx.num_piramide);
|
||||
}
|
||||
|
||||
void Director::init() {
|
||||
instance_ = new Director();
|
||||
Gamepad::init();
|
||||
|
||||
// Registre d'escenes. Cada entrada = un state_key (`num_piramide`)
|
||||
// amb una factory de `scenes::Scene`. El gameFiberEntry consulta
|
||||
// aquest registry per a tots els states de seqüència; si una clau
|
||||
// no apareix ací, el fiber eixirà del loop.
|
||||
// amb una factory de `scenes::Scene`. iterate() consulta aquest
|
||||
// registry per a tots els states de seqüència (game_state_ == 1); si
|
||||
// una clau no apareix ací, Director surt ordenadament.
|
||||
auto& registry = scenes::SceneRegistry::instance();
|
||||
registry.registerScene(0, [] { return std::make_unique<scenes::MenuScene>(); });
|
||||
registry.registerScene(100, [] { return std::make_unique<scenes::MortScene>(); });
|
||||
@@ -132,12 +102,9 @@ void Director::init() {
|
||||
}
|
||||
return std::make_unique<scenes::IntroScene>();
|
||||
});
|
||||
|
||||
GameFiber::init(gameFiberEntry);
|
||||
}
|
||||
|
||||
void Director::destroy() {
|
||||
GameFiber::destroy();
|
||||
Gamepad::destroy();
|
||||
delete instance_;
|
||||
instance_ = nullptr;
|
||||
@@ -164,17 +131,17 @@ void Director::setup() {
|
||||
}
|
||||
|
||||
bool Director::iterate() {
|
||||
if (GameFiber::is_done() || quit_requested_) {
|
||||
// Si el joc encara no ha acabat (p.ex. eixida per ESC doble-press),
|
||||
// li donem l'oportunitat de tornar net: marquem quit i reprenem el
|
||||
// fiber fins que detecte JG_Quitting() i retorne de forma natural.
|
||||
if (quit_requested_) {
|
||||
JG_QuitSignal();
|
||||
while (!GameFiber::is_done()) {
|
||||
GameFiber::resume();
|
||||
}
|
||||
current_scene_.reset(); // destrueix l'escena actual ordenadament
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!context_initialized_) {
|
||||
initGameContext();
|
||||
context_initialized_ = true;
|
||||
}
|
||||
|
||||
constexpr Uint32 FRAME_MS_VSYNC = 16; // ~60 FPS amb VSync
|
||||
constexpr Uint32 FRAME_MS_NO_VSYNC = 4; // ~250 FPS sense VSync (límit superior)
|
||||
|
||||
@@ -205,15 +172,41 @@ bool Director::iterate() {
|
||||
esc_blocked_ = false;
|
||||
}
|
||||
|
||||
// Cedeix el control al fiber del joc. Quan retorne (per un JD8_Flip()
|
||||
// dins del joc) tindrem un nou frame a pixel_data. Si estem en pausa,
|
||||
// no executem el fiber: es queda congelat al seu últim yield i
|
||||
// continuem presentant l'últim frame conegut.
|
||||
// Avança l'escena (si no estem pausats). En pausa, es manté l'escena
|
||||
// congelada i re-presentem l'últim frame amb l'overlay fresc per
|
||||
// damunt.
|
||||
if (!paused_) {
|
||||
GameFiber::resume();
|
||||
if (GameFiber::is_done()) {
|
||||
return false;
|
||||
// Transicions: si l'escena actual ha acabat (o s'ha senyalat
|
||||
// quit), llegim el seu next state i la destruïm per crear la
|
||||
// següent a continuació.
|
||||
if (current_scene_ && (current_scene_->done() || JG_Quitting())) {
|
||||
game_state_ = current_scene_->nextState();
|
||||
current_scene_.reset();
|
||||
}
|
||||
|
||||
// Si no hi ha escena activa, construeix la pròxima segons
|
||||
// game_state_ i info::ctx. Si és impossible (game_state_ == -1,
|
||||
// quit, o state no registrat), eixim del loop.
|
||||
if (!current_scene_) {
|
||||
if (game_state_ == -1 || JG_Quitting()) return false;
|
||||
current_scene_ = createNextScene();
|
||||
if (!current_scene_) return false;
|
||||
current_scene_->onEnter();
|
||||
last_tick_ms_ = SDL_GetTicks();
|
||||
}
|
||||
|
||||
// Tick de l'escena. JI_Update refresca key_pressed/any_key; el
|
||||
// delta_ms és el temps real transcorregut des de l'últim tick.
|
||||
JI_Update();
|
||||
const Uint32 now = SDL_GetTicks();
|
||||
const int delta_ms = static_cast<int>(now - last_tick_ms_);
|
||||
last_tick_ms_ = now;
|
||||
current_scene_->tick(delta_ms);
|
||||
|
||||
// Converteix `screen` indexat → `pixel_data` ARGB amb la paleta
|
||||
// actual. JD8_Flip ja no fa yield (Phase B.2 eliminà els fibers);
|
||||
// ara només omple el framebuffer perquè el Director l'aprofite.
|
||||
JD8_Flip();
|
||||
std::memcpy(game_frame_, JD8_GetFramebuffer(), sizeof(game_frame_));
|
||||
has_frame_ = true;
|
||||
}
|
||||
@@ -238,12 +231,11 @@ bool Director::iterate() {
|
||||
}
|
||||
|
||||
void Director::teardown() {
|
||||
// Si el joc encara no ha acabat (p.ex. eixida per SDL_QUIT des del
|
||||
// sistema), li donem l'oportunitat de tornar net.
|
||||
// Senyal de quit i descàrrega ordenada de l'escena en curs. Els
|
||||
// destructors de cada escena són no-bloquejants — ja no fan fades
|
||||
// bloquejants. La resta de cleanup la gestiona `destroy()`.
|
||||
JG_QuitSignal();
|
||||
while (!GameFiber::is_done()) {
|
||||
GameFiber::resume();
|
||||
}
|
||||
current_scene_.reset();
|
||||
}
|
||||
|
||||
void Director::run() {
|
||||
|
||||
Reference in New Issue
Block a user