/// The game manages all game systems and runs the game loop /// /// The systems managed by the game are the modules, resource handlers and the event system /// The game loop is started by calling startGame() and ended by calling endGame() /// When you start the game it will first initialize the modules, then load the first scene and then start updating all the modules. /// Modules can get access to other systems when they are initialized. /// The game can also be paused and the current scene can be both set and retrieved class Game { public: /// Constructor Game(); /// Destructor /// /// Frees all modules, resource handlers and the event system ~Game(); /// Adds a module to the game /// /// Adds a module of the given type to the game /// @tparam ModuleType The type of module to add /// @tparam ConstructionArgs [deducible] The arguments necessary to construct the module /// @param a_arguments The arguments used to construct the module, can be left empty /// @returns A reference to the added module /// @note You do not need to specify the types of construction arguments in the template list, you can simple write addModule<ExampleModule>(arg1, arg2, arg3) template <typename ModuleType, typename... ConstructionArgs> ModuleType& addModule(ConstructionArgs&&... a_arguments); /// Returns the module of the given type /// /// @tparam ModuleType The type of module to get /// @returns A reference to the requested module /// @warning The game must contain the module of the given type /// @see hasModule() template <typename ModuleType> ModuleType& getModule(); /// Returns the module of the given type /// /// @tparam ModuleType The type of module to get /// @returns A const reference to the requested module /// @warning The game must contain the module of the given type /// @see hasModule() template <typename ModuleType> const ModuleType& getModule()const; /// Returns true if the game has the module of the given type /// @tparam ModuleType The type of module to check /// @returns True if the game has the requested module /// @see addModule() template <typename ModuleType> bool hasModule()const; /// Adds a ResourceManager of the given type for the given type of resource using the given construction arguments /// /// @tparam ResourceType The type of resource the handler will handle /// @tparam ResourceHandlerType The type of resource handler to add /// @tparam ConstructionArgs [deducible] The arguments used to call the constructor of the resource handler /// @param a_arguments The arguments of the constructor of the resource handler /// @returns A reference to the added resource handler /// @see getHandlerFor() hasHandlerFor() /// @warning Any given resource type can only have one handler at once template <typename ResourceType, typename ResourceHandlerType, typename... ConstructionArgs> ResourceHandlerType& addResourceHandler(ConstructionArgs&&... a_arguments); /// Gets a reference to the current resource handler for the given type of resource /// /// @tparam ResourceType The type of resource the requested handler is for /// @returns A reference to the current resource handler for the given type of resource /// @warning The game MUST contain a handler for the given type of resource /// @see hasHandlerFor() addResourceHandler() template <typename ResourceType> IResourceHandler<ResourceType>& getHandlerFor(); /// Checks if the game contains a resource handler for the given type of resource /// /// @tparam ResourceType The type of resource the requested handler is for /// @returns True if the game contains a resource handler for the given type of resource /// @see addResourceHandler() template <typename ResourceType> bool hasHandlerFor()const; /// Registers the given module to the game loop /// /// Will make the game call the module's update method every update /// @param a_module The module that will be registered to the game loop /// @param a_priority The priority of the module within the game loop - this determines the order of systems to update /// @attention The given module must have a public method with the following signature: void update(float); the float being the elapsed time since the last update /// @warning A module can only be registered to the game loop once /// @see isInGameLoop() void registerToGameLoop(IModule& a_module, const GameLoopPriority& a_priority, bool a_updateWhilePaused); /// Checks if the given module is currently registered to the game loop /// /// @param a_module The module to test /// @returns True if the given module is currently registered to the game loop /// @see registerToGameLoop() /// @note This is a slow function and is meant mainly for debugging purposes bool isInGameLoop(const IModule& a_module)const; /// Starts the game loop /// /// Will initialize all modules, load the first scene and start updating until the game ends void startGameLoop(); /// Ends the game loop /// /// Will make the game loop end as soon as the current update finishes void endgameLoop(); /// Gets a reference to the event system /// /// @returns A reference to the event system inline EventSystem& getEventSystem(); /// Gets a const-reference to the event system /// /// @returns A const-reference to the event system inline const EventSystem& getEventSystem()const; /// @brief Checks if the game has a valid current scene /// @return True if the game has a valid current scene bool hasScene()const; /// Gets a reference to the current scene /// /// @returns A reference to the current scene Scene& getCurrentScene(); /// Gets a const-reference to the current scene /// /// @returns A const-reference to the current scene const Scene& getCurrentScene()const; /// Switches to the given scene /// /// Will switch to the given scene before the next update. /// A SceneSwitchEvent will be emitted through the EventSystem when the switching occurs. /// @param a_newScene A reference to the scene to switch to /// @attention General scene ownership and loading is not managed by the game class, it only holds a reference to the current scene /// @see getCurrentScene() void switchToScene(const UniquePtrReference<Scene>& a_newScene); /// Checks if the game is currently paused /// /// @returns True if the game is currently paused /// @see pauseGame() unpauseGame() inline bool isPaused()const; /// Pauses the game /// /// Emits a GamePauseEvent through the EventSystem owned by this game /// @note This does nothing if the game is already paused /// @see isPaused() void pauseGame(); /// Unpauses the game /// /// Emits an GameUnpauseEvent through the EventSystem owned by this game /// @note This does nothing if the game isn't paused /// @see isPaused() void unpauseGame(); }