// State.h - base class and shared context for app states #pragma once #include #include #include #include #include #include // Forward declarations for frequently used types class Game; class ScoreManager; class Starfield; class Starfield3D; class FontAtlas; class LineEffect; enum class AppState; // Forward declare StateManager so StateContext can hold a pointer without // including the StateManager header here. class StateManager; // Shared context passed to states so they can access common resources struct StateContext { // Core subsystems (may be null if not available) Game* game = nullptr; ScoreManager* scores = nullptr; Starfield* starfield = nullptr; Starfield3D* starfield3D = nullptr; FontAtlas* font = nullptr; FontAtlas* pixelFont = nullptr; LineEffect* lineEffect = nullptr; // Textures SDL_Texture* logoTex = nullptr; SDL_Texture* logoSmallTex = nullptr; int logoSmallW = 0; int logoSmallH = 0; SDL_Texture* backgroundTex = nullptr; // backgroundTex is set once in `main.cpp` and passed to states via this context. // Prefer reading this field instead of relying on any `extern SDL_Texture*` globals. SDL_Texture* blocksTex = nullptr; SDL_Texture* asteroidsTex = nullptr; SDL_Texture* scorePanelTex = nullptr; SDL_Texture* statisticsPanelTex = nullptr; SDL_Texture* nextPanelTex = nullptr; SDL_Texture* holdPanelTex = nullptr; // Background for the HOLD preview SDL_Texture* mainScreenTex = nullptr; int mainScreenW = 0; int mainScreenH = 0; // Captured full-scene texture (used by menu for backdrop blur effects) SDL_Texture* sceneTex = nullptr; int sceneW = 0; int sceneH = 0; // Audio / SFX - forward declared types in main // Pointers to booleans/flags used by multiple states bool* musicEnabled = nullptr; bool* musicStarted = nullptr; bool* musicLoaded = nullptr; int* startLevelSelection = nullptr; int* hoveredButton = nullptr; // Menu popups (exposed from main) bool* showSettingsPopup = nullptr; bool* showHelpOverlay = nullptr; bool* showExitConfirmPopup = nullptr; // If true, show "Exit game?" confirmation while playing int* exitPopupSelectedButton = nullptr; // 0 = YES, 1 = NO (default) bool* gameplayCountdownActive = nullptr; // True if start-of-game countdown is running bool* menuPlayCountdownArmed = nullptr; // True if we are transitioning to play and countdown is pending std::string* playerName = nullptr; // Shared player name buffer for highscores/options bool* fullscreenFlag = nullptr; // Tracks current fullscreen state when available std::function applyFullscreen; // Allows states to request fullscreen changes std::function queryFullscreen; // Optional callback if fullscreenFlag is not reliable std::function requestQuit; // Allows menu/option states to close the app gracefully std::function startPlayTransition; // Optional fade hook when transitioning from menu to gameplay std::function requestFadeTransition; // Generic state fade requests (menu/options/level) // Pointer to the application's StateManager so states can request transitions StateManager* stateManager = nullptr; // Optional explicit per-button coordinates (logical coordinates). When // `menuButtonsExplicit` is true, MenuState will use these centers for // rendering and hit tests. Values are in logical units (LOGICAL_W/H). std::array menuButtonCX{}; std::array menuButtonCY{}; bool menuButtonsExplicit = false; }; class State { public: explicit State(StateContext& ctx) : ctx(ctx) {} virtual ~State() = default; virtual void onEnter() {} virtual void onExit() {} virtual void handleEvent(const SDL_Event& e) {} virtual void update(double frameMs) {} virtual void render(SDL_Renderer* renderer, float logicalScale, SDL_Rect logicalVP) {} protected: StateContext& ctx; };