#include "core/system/director.hpp" #include #include #include #include #include #include #include "core/rendering/screen.hpp" #include "core/resources/resource_cache.hpp" #include "core/scene/scene.hpp" #include "core/system/event_buffer.hpp" #include "game/scenes/game_scene.hpp" Director::Director() { if (!SDL_Init(0)) { std::fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError()); } // Registrem SDL_Quit ABANS de tocar cap singleton: així el handler atexit // s'executa DESPRÉS dels destructors estàtics de Screen i Cache (atexit // registrat abans de la construcció d'un objecte estàtic corre després // del seu destructor). Sense açò, Screen::~Screen cridaria SDL_Destroy* // amb SDL ja apagat → caos de destrucció clàssic. std::atexit(+[] { SDL_Quit(); }); // Forcem la construcció dels singletons en l'ordre desitjat: primer // Screen (necessari per a renderitzar), després Cache. La destrucció // estàtica anirà LIFO: Cache primer, Screen últim. (void)Screen::get(); (void)Resource::Cache::get(); current_scene_ = std::make_unique(); last_ticks_ms_ = SDL_GetTicks(); } Director::~Director() { current_scene_.reset(); // SDL_Quit corre via atexit; els singletons via destrucció estàtica. } void Director::processEvents() { const bool QUIT_REQUESTED = std::ranges::any_of( EventBuffer::events, [](const SDL_Event& event) { return event.type == SDL_EVENT_QUIT; }); if (QUIT_REQUESTED) { current_scene_.reset(); } } void Director::switchSceneIfRequested() { if (!current_scene_) { return; } if (auto next = current_scene_->nextScene()) { current_scene_ = std::move(next); } } auto Director::iterate() -> SDL_AppResult { processEvents(); if (!current_scene_) { EventBuffer::events.clear(); return SDL_APP_SUCCESS; } const std::uint64_t NOW_MS = SDL_GetTicks(); int delta_ms = static_cast(NOW_MS - last_ticks_ms_); delta_ms = std::max(delta_ms, 0); last_ticks_ms_ = NOW_MS; current_scene_->update(delta_ms); current_scene_->render(); if (current_scene_->wantsQuit()) { EventBuffer::events.clear(); return SDL_APP_SUCCESS; } switchSceneIfRequested(); EventBuffer::events.clear(); return SDL_APP_CONTINUE; }