#pragma once #include #include #include #include #include #include // El Director és el thread principal que controla la presentació i els inputs. // Executa el joc en un thread secundari (game thread) com si fos una "fibra emulada": // el joc produeix un frame, es bloqueja a JD8_Flip(), i el director el presenta // abans de donar-li via per produir el següent. class Director { public: static void init(); static void destroy(); static auto get() -> Director*; // Bucle principal del director. Crida des de main(). void run(); // Invocat pel game thread des de JD8_Flip(). Bloqueja fins que el director // consumeix el frame i dona via per produir el següent. void publishFrame(Uint32* pixels); // Demana l'eixida (ex: segona pulsació d'ESC o SDL_QUIT) void requestQuit(); // Consumeix el flag de "tecla polsada" (com l'antic JI_AnyKey) auto consumeKeyPressed() -> bool; // Indica si ESC està bloquejada (el joc no l'ha de veure) auto isEscBlocked() const -> bool { return esc_blocked_ || esc_swallow_until_release_; } // Pausa: bloqueja el consum de frames del game thread + pausa la música void togglePause(); auto isPaused() const -> bool { return paused_; } private: Director() = default; ~Director() = default; static Director* instance_; void gameThreadFunc(); void handleEvents(); std::thread game_thread_; std::mutex mutex_; std::condition_variable frame_produced_cv_; std::condition_variable frame_consumed_cv_; Uint32* latest_frame_{nullptr}; bool frame_ready_{false}; bool frame_consumed_{true}; std::atomic quit_requested_{false}; std::atomic game_thread_done_{false}; std::atomic key_pressed_{false}; std::atomic esc_blocked_{false}; std::atomic paused_{false}; // Quan el menú tanca amb ESC, empassem-nos l'ESC fins que l'usuari la deixe anar, // per no fer eixir el joc al proper poll de JI_KeyPressed. std::atomic esc_swallow_until_release_{false}; // Tecles consumides pel menú (KEY_DOWN): el KEY_UP associat cal empassar-lo // per evitar que el joc (JI_AnyKey / JI_moveCheats) les veja quan el menú tanca. bool menu_keys_held_[SDL_SCANCODE_COUNT]{}; };