diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/crepe/api/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | src/crepe/api/IKeyListener.cpp | 19 | ||||
| -rw-r--r-- | src/crepe/api/IKeyListener.h | 50 | ||||
| -rw-r--r-- | src/crepe/api/IMouseListener.cpp | 29 | ||||
| -rw-r--r-- | src/crepe/api/IMouseListener.h | 73 | ||||
| -rw-r--r-- | src/crepe/api/LoopManager.cpp | 33 | ||||
| -rw-r--r-- | src/crepe/api/LoopManager.h | 43 | ||||
| -rw-r--r-- | src/crepe/api/LoopTimer.cpp | 79 | ||||
| -rw-r--r-- | src/crepe/manager/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/crepe/manager/EventManager.cpp | 6 | ||||
| -rw-r--r-- | src/crepe/manager/EventManager.h | 23 | ||||
| -rw-r--r-- | src/crepe/manager/LoopTimerManager.cpp | 77 | ||||
| -rw-r--r-- | src/crepe/manager/LoopTimerManager.h (renamed from src/crepe/api/LoopTimer.h) | 57 | ||||
| -rw-r--r-- | src/crepe/manager/Mediator.h | 11 | ||||
| -rw-r--r-- | src/crepe/system/AnimatorSystem.cpp | 4 | ||||
| -rw-r--r-- | src/test/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | src/test/CollisionTest.cpp | 1 | ||||
| -rw-r--r-- | src/test/EventTest.cpp | 116 | ||||
| -rw-r--r-- | src/test/InputTest.cpp | 3 | ||||
| -rw-r--r-- | src/test/LoopManagerTest.cpp | 67 | ||||
| -rw-r--r-- | src/test/LoopTimerTest.cpp | 75 | ||||
| -rw-r--r-- | src/test/ScriptTest.h | 4 | 
22 files changed, 361 insertions, 420 deletions
| diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt index 593c4e6..ca4edec 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -15,10 +15,7 @@ target_sources(crepe PUBLIC  	Animator.cpp  	BoxCollider.cpp  	CircleCollider.cpp -	IKeyListener.cpp -	IMouseListener.cpp  	LoopManager.cpp -	LoopTimer.cpp  	Asset.cpp  	EventHandler.cpp  	Script.cpp @@ -51,10 +48,7 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES  	EventHandler.h  	EventHandler.hpp  	Event.h -	IKeyListener.h -	IMouseListener.h  	LoopManager.h -	LoopTimer.h  	Asset.h  	Button.h  	UIObject.h diff --git a/src/crepe/api/IKeyListener.cpp b/src/crepe/api/IKeyListener.cpp deleted file mode 100644 index 8642655..0000000 --- a/src/crepe/api/IKeyListener.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "IKeyListener.h" - -using namespace crepe; - -// Constructor with specified channel -IKeyListener::IKeyListener(event_channel_t channel) -	: event_manager(EventManager::get_instance()) { -	this->press_id = event_manager.subscribe<KeyPressEvent>( -		[this](const KeyPressEvent & event) { return this->on_key_pressed(event); }, channel); -	this->release_id = event_manager.subscribe<KeyReleaseEvent>( -		[this](const KeyReleaseEvent & event) { return this->on_key_released(event); }, -		channel); -} - -// Destructor, unsubscribe events -IKeyListener::~IKeyListener() { -	event_manager.unsubscribe(this->press_id); -	event_manager.unsubscribe(this->release_id); -} diff --git a/src/crepe/api/IKeyListener.h b/src/crepe/api/IKeyListener.h deleted file mode 100644 index 180a0a6..0000000 --- a/src/crepe/api/IKeyListener.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include "../manager/EventManager.h" - -#include "Event.h" -#include "EventHandler.h" - -namespace crepe { - -/** - * \class IKeyListener - * \brief Interface for keyboard event handling in the application. - */ -class IKeyListener { -public: -	/** -	 * \brief Constructs an IKeyListener with a specified channel. -	 * \param channel The channel ID for event handling. -	 */ -	IKeyListener(event_channel_t channel = EventManager::CHANNEL_ALL); -	virtual ~IKeyListener(); -	IKeyListener(const IKeyListener &) = delete; -	IKeyListener & operator=(const IKeyListener &) = delete; -	IKeyListener & operator=(IKeyListener &&) = delete; -	IKeyListener(IKeyListener &&) = delete; - -	/** -	 * \brief Pure virtual function to handle key press events. -	 * \param event The key press event to handle. -	 * \return True if the event was handled, false otherwise. -	 */ -	virtual bool on_key_pressed(const KeyPressEvent & event) = 0; - -	/** -	 * \brief Pure virtual function to handle key release events. -	 * \param event The key release event to handle. -	 * \return True if the event was handled, false otherwise. -	 */ -	virtual bool on_key_released(const KeyReleaseEvent & event) = 0; - -private: -	//! Key press event id -	subscription_t press_id = -1; -	//! Key release event id -	subscription_t release_id = -1; -	//! EventManager reference -	EventManager & event_manager; -}; - -} // namespace crepe diff --git a/src/crepe/api/IMouseListener.cpp b/src/crepe/api/IMouseListener.cpp deleted file mode 100644 index 989aeb3..0000000 --- a/src/crepe/api/IMouseListener.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "IMouseListener.h" - -using namespace crepe; - -IMouseListener::IMouseListener(event_channel_t channel) -	: event_manager(EventManager::get_instance()) { -	this->click_id = event_manager.subscribe<MouseClickEvent>( -		[this](const MouseClickEvent & event) { return this->on_mouse_clicked(event); }, -		channel); - -	this->press_id = event_manager.subscribe<MousePressEvent>( -		[this](const MousePressEvent & event) { return this->on_mouse_pressed(event); }, -		channel); - -	this->release_id = event_manager.subscribe<MouseReleaseEvent>( -		[this](const MouseReleaseEvent & event) { return this->on_mouse_released(event); }, -		channel); - -	this->move_id = event_manager.subscribe<MouseMoveEvent>( -		[this](const MouseMoveEvent & event) { return this->on_mouse_moved(event); }, channel); -} - -IMouseListener::~IMouseListener() { -	// Unsubscribe event handlers -	event_manager.unsubscribe(this->click_id); -	event_manager.unsubscribe(this->press_id); -	event_manager.unsubscribe(this->release_id); -	event_manager.unsubscribe(this->move_id); -} diff --git a/src/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h deleted file mode 100644 index e19897d..0000000 --- a/src/crepe/api/IMouseListener.h +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once - -#include "../manager/EventManager.h" - -#include "Event.h" -#include "EventHandler.h" - -namespace crepe { - -/** - * \class IMouseListener - * \brief Interface for mouse event handling in the application. - */ -class IMouseListener { -public: -	/** -	 * \brief Constructs an IMouseListener with a specified channel. -	 * \param channel The channel ID for event handling. -	 */ -	IMouseListener(event_channel_t channel = EventManager::CHANNEL_ALL); -	virtual ~IMouseListener(); -	IMouseListener & operator=(const IMouseListener &) = delete; -	IMouseListener(const IMouseListener &) = delete; -	IMouseListener & operator=(const IMouseListener &&) = delete; -	IMouseListener(IMouseListener &&) = delete; - -	/** -	 * \brief Move assignment operator (deleted). -	 */ -	IMouseListener & operator=(IMouseListener &&) = delete; - -	/** -	 * \brief Handles a mouse click event. -	 * \param event The mouse click event to handle. -	 * \return True if the event was handled, false otherwise. -	 */ -	virtual bool on_mouse_clicked(const MouseClickEvent & event) = 0; - -	/** -	 * \brief Handles a mouse press event. -	 * \param event The mouse press event to handle. -	 * \return True if the event was handled, false otherwise. -	 */ -	virtual bool on_mouse_pressed(const MousePressEvent & event) = 0; - -	/** -	 * \brief Handles a mouse release event. -	 * \param event The mouse release event to handle. -	 * \return True if the event was handled, false otherwise. -	 */ -	virtual bool on_mouse_released(const MouseReleaseEvent & event) = 0; - -	/** -	 * \brief Handles a mouse move event. -	 * \param event The mouse move event to handle. -	 * \return True if the event was handled, false otherwise. -	 */ -	virtual bool on_mouse_moved(const MouseMoveEvent & event) = 0; - -private: -	//! Mouse click event id -	subscription_t click_id = -1; -	//! Mouse press event id -	subscription_t press_id = -1; -	//! Mouse release event id -	subscription_t release_id = -1; -	//! Mouse move event id -	subscription_t move_id = -1; -	//! EventManager reference -	EventManager & event_manager; -}; - -} //namespace crepe diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp index 044f096..c25e31e 100644 --- a/src/crepe/api/LoopManager.cpp +++ b/src/crepe/api/LoopManager.cpp @@ -1,3 +1,6 @@ +#include "../facade/SDLContext.h" + +#include "../manager/EventManager.h"  #include "../system/AnimatorSystem.h"  #include "../system/CollisionSystem.h"  #include "../system/InputSystem.h" @@ -20,18 +23,20 @@ LoopManager::LoopManager() {  	this->load_system<RenderSystem>();  	this->load_system<ScriptSystem>();  	this->load_system<InputSystem>(); +	this->event_manager.subscribe<ShutDownEvent>( +		[this](const ShutDownEvent & event) { return this->on_shutdown(event); });  } -void LoopManager::process_input() { this->get_system<InputSystem>().update(); } +void LoopManager::process_input() {  +	this->get_system<InputSystem>().update(); +}  void LoopManager::start() {  	this->setup();  	this->loop();  } -void LoopManager::set_running(bool running) { this->game_running = running; }  void LoopManager::fixed_update() { -	// TODO: retrieve EventManager from direct member after singleton refactor  	EventManager & ev = this->mediator.event_manager;  	ev.dispatch_events();  	this->get_system<ScriptSystem>().update(); @@ -40,31 +45,27 @@ void LoopManager::fixed_update() {  }  void LoopManager::loop() { -	LoopTimer & timer = this->loop_timer; -	timer.start(); +	  	while (game_running) { -		timer.update(); +		this->loop_timer.update(); -		while (timer.get_lag() >= timer.get_fixed_delta_time()) { +		while (this->loop_timer.get_lag() >= this->loop_timer.get_fixed_delta_time()) {  			this->process_input(); +			event_manager.dispatch_events();  			this->fixed_update(); -			timer.advance_fixed_update(); +			this->loop_timer.advance_fixed_update();  		}  		this->update();  		this->render(); - -		timer.enforce_frame_rate(); +		this->loop_timer.enforce_frame_rate();  	}  }  void LoopManager::setup() { -	LoopTimer & timer = this->loop_timer;  	this->game_running = true; -	this->scene_manager.load_next_scene(); -	timer.start(); -	timer.set_fps(200); +	this->loop_timer.start();  	this->scene_manager.load_next_scene();  } @@ -74,5 +75,9 @@ void LoopManager::render() {  	this->get_system<AnimatorSystem>().update();  	this->get_system<RenderSystem>().update();  } +bool LoopManager::on_shutdown(const ShutDownEvent & e) { +	this->game_running = false; +	return false; +}  void LoopManager::update() {} diff --git a/src/crepe/api/LoopManager.h b/src/crepe/api/LoopManager.h index d8910a0..9986aa5 100644 --- a/src/crepe/api/LoopManager.h +++ b/src/crepe/api/LoopManager.h @@ -5,12 +5,14 @@  #include "../facade/SDLContext.h"  #include "../manager/ComponentManager.h"  #include "../manager/SceneManager.h" +#include "../manager/EventManager.h" +#include "../manager/LoopTimerManager.h"  #include "../system/System.h" +#include "../manager/Mediator.h" -#include "LoopTimer.h" +#include "api/Event.h"  namespace crepe { -  /**   * \brief Main game loop manager   * @@ -18,8 +20,14 @@ namespace crepe {   */  class LoopManager {  public: -	void start();  	LoopManager(); +	/** +	 * \brief Start the gameloop +	 * +	 * This is the start of the engine where the setup is called and then the loop keeps running until the game stops running. +	 * Developers need to call this function to run the game. +	 */ +	void start();  	/**  	 * \brief Add a new concrete scene to the scene manager @@ -55,7 +63,7 @@ private:  	 *  	 * Updates the game state based on the elapsed time since the last frame.  	 */ -	void update(); +	virtual void update();  	/**  	 * \brief Late update which is called after update(). @@ -69,21 +77,13 @@ private:  	 *  	 * This function updates physics and game logic based on LoopTimer's fixed_delta_time.  	 */ -	void fixed_update(); - -	/** -	 * \brief Set game running variable -	 * -	 * \param running running (false = game shutdown, true = game running) -	 */ -	void set_running(bool running); - +	virtual void fixed_update();  	/**  	 * \brief Function for executing render-related systems.  	 *  	 * Renders the current state of the game to the screen.  	 */ -	void render(); +	virtual void render();  	bool game_running = false; @@ -95,18 +95,27 @@ private:  	ComponentManager component_manager{mediator};  	//! Scene manager instance  	SceneManager scene_manager{mediator}; +	//! LoopTimerManager instance +	LoopTimerManager loop_timer{mediator}; +	//! EventManager instance +	EventManager event_manager{mediator};  	//! SDL context \todo no more singletons!  	SDLContext & sdl_context = SDLContext::get_instance(); -	//! Loop timer \todo no more singletons! -	LoopTimer & loop_timer = LoopTimer::get_instance(); +  private:  	/** +	 * \brief Callback function for ShutDownEvent +	 * +	 * This function sets the game_running variable to false, stopping the gameloop and therefor quitting the game. +	 */ +	bool on_shutdown(const ShutDownEvent & e); +	/**  	 * \brief Collection of System instances  	 *  	 * This map holds System instances indexed by the system's class typeid. It is filled in the -	 * constructor of \c LoopManager using LoopManager::load_system. +	 * constructor of LoopManager using LoopManager::load_system.  	 */  	std::unordered_map<std::type_index, std::unique_ptr<System>> systems;  	/** diff --git a/src/crepe/api/LoopTimer.cpp b/src/crepe/api/LoopTimer.cpp deleted file mode 100644 index 15a0e3a..0000000 --- a/src/crepe/api/LoopTimer.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include <chrono> - -#include "../facade/SDLContext.h" -#include "../util/Log.h" - -#include "LoopTimer.h" - -using namespace crepe; - -LoopTimer::LoopTimer() { dbg_trace(); } - -LoopTimer & LoopTimer::get_instance() { -	static LoopTimer instance; -	return instance; -} - -void LoopTimer::start() { -	this->last_frame_time = std::chrono::steady_clock::now(); -	this->elapsed_time = std::chrono::milliseconds(0); -	this->elapsed_fixed_time = std::chrono::milliseconds(0); -	this->delta_time = std::chrono::milliseconds(0); -} - -void LoopTimer::update() { -	auto current_frame_time = std::chrono::steady_clock::now(); -	// Convert to duration in seconds for delta time -	this->delta_time = std::chrono::duration_cast<std::chrono::duration<double>>( -		current_frame_time - last_frame_time); - -	if (this->delta_time > this->maximum_delta_time) { -		this->delta_time = this->maximum_delta_time; -	} - -	this->delta_time *= this->game_scale; -	this->elapsed_time += this->delta_time; -	this->last_frame_time = current_frame_time; -} - -double LoopTimer::get_delta_time() const { return this->delta_time.count(); } - -double LoopTimer::get_current_time() const { return this->elapsed_time.count(); } - -void LoopTimer::advance_fixed_update() { this->elapsed_fixed_time += this->fixed_delta_time; } - -double LoopTimer::get_fixed_delta_time() const { return this->fixed_delta_time.count(); } - -void LoopTimer::set_fps(int fps) { -	this->fps = fps; -	// target time per frame in seconds -	this->frame_target_time = std::chrono::duration<double>(1.0) / fps; -} - -int LoopTimer::get_fps() const { return this->fps; } - -void LoopTimer::set_game_scale(double value) { this->game_scale = value; } - -double LoopTimer::get_game_scale() const { return this->game_scale; } -void LoopTimer::enforce_frame_rate() { -	std::chrono::steady_clock::time_point current_frame_time -		= std::chrono::steady_clock::now(); -	std::chrono::milliseconds frame_duration -		= std::chrono::duration_cast<std::chrono::milliseconds>(current_frame_time -																- this->last_frame_time); - -	if (frame_duration < this->frame_target_time) { -		std::chrono::milliseconds delay_time -			= std::chrono::duration_cast<std::chrono::milliseconds>(this->frame_target_time -																	- frame_duration); -		if (delay_time.count() > 0) { -			SDLContext::get_instance().delay(delay_time.count()); -		} -	} - -	this->last_frame_time = current_frame_time; -} - -double LoopTimer::get_lag() const { -	return (this->elapsed_time - this->elapsed_fixed_time).count(); -} diff --git a/src/crepe/manager/CMakeLists.txt b/src/crepe/manager/CMakeLists.txt index 517b8a2..29d6df0 100644 --- a/src/crepe/manager/CMakeLists.txt +++ b/src/crepe/manager/CMakeLists.txt @@ -4,6 +4,7 @@ target_sources(crepe PUBLIC  	Manager.cpp  	SaveManager.cpp  	SceneManager.cpp +	LoopTimerManager.cpp  )  target_sources(crepe PUBLIC FILE_SET HEADERS FILES @@ -16,5 +17,6 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES  	SaveManager.h  	SceneManager.h  	SceneManager.hpp +	LoopTimerManager.h  ) diff --git a/src/crepe/manager/EventManager.cpp b/src/crepe/manager/EventManager.cpp index 20f0dd3..9b0fa95 100644 --- a/src/crepe/manager/EventManager.cpp +++ b/src/crepe/manager/EventManager.cpp @@ -3,11 +3,9 @@  using namespace crepe;  using namespace std; -EventManager & EventManager::get_instance() { -	static EventManager instance; -	return instance; +EventManager::EventManager(Mediator & mediator) : Manager(mediator){ +	this->mediator.event_manager = *this;  } -  void EventManager::dispatch_events() {  	for (auto & event : this->events_queue) {  		this->handle_event(event.type, event.channel, *event.event.get()); diff --git a/src/crepe/manager/EventManager.h b/src/crepe/manager/EventManager.h index ba5e98b..30b929c 100644 --- a/src/crepe/manager/EventManager.h +++ b/src/crepe/manager/EventManager.h @@ -8,6 +8,8 @@  #include "../api/Event.h"  #include "../api/EventHandler.h" +#include "Manager.h" +  namespace crepe {  //! Event listener unique ID @@ -22,27 +24,16 @@ typedef size_t subscription_t;  typedef size_t event_channel_t;  /** - * \class EventManager   * \brief Manages event subscriptions, triggers, and queues, enabling decoupled event handling.   *   * The `EventManager` acts as a centralized event system. It allows for registering callbacks   * for specific event types, triggering events synchronously, queueing events for later   * processing, and managing subscriptions via unique identifiers.   */ -class EventManager { +class EventManager : public Manager {  public:  	static constexpr const event_channel_t CHANNEL_ALL = -1; - -	/** -	 * \brief Get the singleton instance of the EventManager. -	 * -	 * This method returns the unique instance of the EventManager, creating it if it -	 * doesn't already exist. Ensures only one instance is active in the program. -	 * -	 * \return Reference to the singleton instance of the EventManager. -	 */ -	static EventManager & get_instance(); - +	EventManager(Mediator & mediator);  	/**  	 * \brief Subscribe to a specific event type.  	 * @@ -107,12 +98,6 @@ public:  	void clear();  private: -	/** -	 * \brief Default constructor for the EventManager. -	 * -	 * Constructor is private to enforce the singleton pattern. -	 */ -	EventManager() = default;  	/**  	 * \struct QueueEntry diff --git a/src/crepe/manager/LoopTimerManager.cpp b/src/crepe/manager/LoopTimerManager.cpp new file mode 100644 index 0000000..2379fdd --- /dev/null +++ b/src/crepe/manager/LoopTimerManager.cpp @@ -0,0 +1,77 @@ +#include <chrono> +#include <thread> + +#include "../facade/SDLContext.h" +#include "../util/Log.h" + +#include "LoopTimerManager.h" + +using namespace crepe; + +LoopTimerManager::LoopTimerManager(Mediator & mediator) : Manager(mediator) {  +	this->mediator.loop_timer = *this; +	dbg_trace();  +	} + +void LoopTimerManager::start() { +	this->last_frame_time = std::chrono::steady_clock::now(); + +	this->elapsed_time = std::chrono::milliseconds(0); +	// by starting the elapsed_fixed_time at (0 - fixed_delta_time) in milliseconds it calls a fixed update at the start of the loop. +	this->elapsed_fixed_time +		= -std::chrono::duration_cast<std::chrono::milliseconds>(fixed_delta_time); +	this->delta_time = std::chrono::milliseconds(0); +} + +void LoopTimerManager::update() { +	auto current_frame_time = std::chrono::steady_clock::now(); +	// Convert to duration in seconds for delta time +	this->delta_time = std::chrono::duration_cast<std::chrono::duration<double>>( +		current_frame_time - last_frame_time); + +	if (this->delta_time > this->maximum_delta_time) { +		this->delta_time = this->maximum_delta_time; +	} +	this->actual_fps = 1.0 / this->delta_time.count(); + +	this->elapsed_time += this->delta_time; +	this->last_frame_time = current_frame_time; +} + +double LoopTimerManager::get_delta_time() const { return this->delta_time.count() * this->time_scale; } + +double LoopTimerManager::get_current_time() const { return this->elapsed_time.count(); } + +void LoopTimerManager::advance_fixed_update() { this->elapsed_fixed_time += this->fixed_delta_time; } + +double LoopTimerManager::get_fixed_delta_time() const { return this->fixed_delta_time.count(); } + +void LoopTimerManager::set_target_fps(int fps) { +	this->target_fps = fps; +	// target time per frame in seconds +	this->frame_target_time = std::chrono::duration<double>(1.0) / this->target_fps; +} + +int LoopTimerManager::get_fps() const { return this->actual_fps; } + +void LoopTimerManager::set_time_scale(double value) { this->time_scale = value; } + +double LoopTimerManager::get_time_scale() const { return this->time_scale; } +void LoopTimerManager::enforce_frame_rate() { +	auto current_frame_time = std::chrono::steady_clock::now(); +	auto frame_duration = current_frame_time - this->last_frame_time; + +	// Check if frame duration is less than the target frame time +	if (frame_duration < this->frame_target_time) { +		auto delay_time = std::chrono::duration_cast<std::chrono::microseconds>( +			this->frame_target_time - frame_duration); + +		if (delay_time.count() > 0) { +			std::this_thread::sleep_for(delay_time); +		} +	} +} + +double LoopTimerManager::get_lag() const { +	return (this->elapsed_time - this->elapsed_fixed_time).count(); +} diff --git a/src/crepe/api/LoopTimer.h b/src/crepe/manager/LoopTimerManager.h index 9393439..cd05bf2 100644 --- a/src/crepe/api/LoopTimer.h +++ b/src/crepe/manager/LoopTimerManager.h @@ -2,17 +2,21 @@  #include <chrono> +#include "Manager.h" +  namespace crepe { -class LoopTimer { +/** + * \brief Manages timing and frame rate for the game loop. + *  + * The LoopTimerManager class is responsible for calculating and managing timing functions  + * such as delta time, frames per second (FPS), fixed time steps, and time scaling. It ensures  + * consistent frame updates and supports game loop operations, such as handling fixed updates  + * for physics and other time-sensitive operations. + */ +class LoopTimerManager : public Manager {  public: -	/** -	 * \brief Get the singleton instance of LoopTimer. -	 * -	 * \return A reference to the LoopTimer instance. -	 */ -	static LoopTimer & get_instance(); - +	LoopTimerManager(Mediator & mediator);  	/**  	 * \brief Get the current delta time for the current frame.  	 * @@ -35,7 +39,7 @@ public:  	 *  	 * \param fps The desired frames rendered per second.  	 */ -	void set_fps(int fps); +	void set_target_fps(int fps);  	/**  	 * \brief Get the current frames per second (FPS). @@ -45,19 +49,21 @@ public:  	int get_fps() const;  	/** -	 * \brief Get the current game scale. +	 * \brief Get the current time scale.  	 * -	 * \return The current game scale, where 0 = paused, 1 = normal speed, and values > 1 speed +	 * \return The current time scale, where (0 = pause, < 1 = slow down, 1 = normal speed, > 1 = speed up).  	 * up the game.  	 */ -	double get_game_scale() const; +	double get_time_scale() const;  	/** -	 * \brief Set the game scale. +	 * \brief Set the time scale.  	 * -	 * \param game_scale The desired game scale (0 = pause, 1 = normal speed, > 1 = speed up). +	 * time_scale is a value that changes the delta time that can be retrieved using get_delta_time function.  +	 *  +	 * \param time_scale The desired time scale (0 = pause, < 1 = slow down, 1 = normal speed, > 1 = speed up).  	 */ -	void set_game_scale(double game_scale); +	void set_time_scale(double time_scale);  private:  	friend class LoopManager; @@ -68,7 +74,6 @@ private:  	 * Initializes the timer to begin tracking frame times.  	 */  	void start(); -  	/**  	 * \brief Enforce the frame rate limit.  	 * @@ -98,13 +103,6 @@ private:  	double get_lag() const;  	/** -	 * \brief Construct a new LoopTimer object. -	 * -	 * Private constructor for singleton pattern to restrict instantiation outside the class. -	 */ -	LoopTimer(); - -	/**  	 * \brief Update the timer to the current frame.  	 *  	 * Calculates and updates the delta time for the current frame and adds it to the cumulative @@ -121,16 +119,19 @@ private:  	void advance_fixed_update();  private: -	//! Current frames per second -	int fps = 50; -	//! Current game scale -	double game_scale = 1; +	//! Target frames per second +	int target_fps = 50; +	//! Actual frames per second +	int actual_fps = 0; +	//! time scale for speeding up or slowing down the game (0 = pause, < 1 = slow down, 1 = normal speed, > 1 = speed up) +	double time_scale = 1;  	//! Maximum delta time in seconds to avoid large jumps  	std::chrono::duration<double> maximum_delta_time{0.25};  	//! Delta time for the current frame in seconds  	std::chrono::duration<double> delta_time{0.0};  	//! Target time per frame in seconds -	std::chrono::duration<double> frame_target_time = std::chrono::duration<double>(1.0) / fps; +	std::chrono::duration<double> frame_target_time +		= std::chrono::duration<double>(1.0) / target_fps;  	//! Fixed delta time for fixed updates in seconds  	std::chrono::duration<double> fixed_delta_time = std::chrono::duration<double>(1.0) / 50.0;  	//! Total elapsed game time in seconds diff --git a/src/crepe/manager/Mediator.h b/src/crepe/manager/Mediator.h index 8094d80..987f4d4 100644 --- a/src/crepe/manager/Mediator.h +++ b/src/crepe/manager/Mediator.h @@ -4,15 +4,16 @@  // TODO: remove these singletons:  #include "../facade/SDLContext.h" -#include "EventManager.h" +//#include "EventManager.h"  #include "SaveManager.h" -#include "api/LoopTimer.h" +//#include "LoopTimerManager.h"  namespace crepe {  class ComponentManager;  class SceneManager; - +class LoopTimerManager; +class EventManager;  /**   * Struct to pass references to classes that would otherwise need to be singletons down to   * other classes within the engine hierarchy. Made to prevent constant changes to subclasses to @@ -28,10 +29,10 @@ class SceneManager;  struct Mediator {  	OptionalRef<ComponentManager> component_manager;  	OptionalRef<SceneManager> scene_manager; +	OptionalRef<EventManager> event_manager; +	OptionalRef<LoopTimerManager> loop_timer;  	OptionalRef<SaveManager> save_manager = SaveManager::get_instance(); -	OptionalRef<EventManager> event_manager = EventManager::get_instance();  	OptionalRef<SDLContext> sdl_context = SDLContext::get_instance(); -	OptionalRef<LoopTimer> timer = LoopTimer::get_instance();  };  } // namespace crepe diff --git a/src/crepe/system/AnimatorSystem.cpp b/src/crepe/system/AnimatorSystem.cpp index 549c35d..499f618 100644 --- a/src/crepe/system/AnimatorSystem.cpp +++ b/src/crepe/system/AnimatorSystem.cpp @@ -2,7 +2,7 @@  #include "../api/Animator.h"  #include "../manager/ComponentManager.h" -#include "api/LoopTimer.h" +#include "../manager/LoopTimerManager.h"  #include "AnimatorSystem.h" @@ -10,7 +10,7 @@ using namespace crepe;  void AnimatorSystem::update() {  	ComponentManager & mgr = this->mediator.component_manager; -	LoopTimer & timer = this->mediator.timer; +	LoopTimerManager & timer = this->mediator.loop_timer;  	RefVector<Animator> animations = mgr.get_components_by_type<Animator>();  	double elapsed_time = timer.get_current_time(); diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index c9cbac5..1c963d8 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -13,6 +13,9 @@ target_sources(test_main PUBLIC  	ValueBrokerTest.cpp  	DBTest.cpp  	Vector2Test.cpp +	LoopManagerTest.cpp +	LoopTimerTest.cpp +	  	InputTest.cpp  	ScriptEventTest.cpp  	ScriptSceneTest.cpp diff --git a/src/test/CollisionTest.cpp b/src/test/CollisionTest.cpp index dd45eb6..5dbc670 100644 --- a/src/test/CollisionTest.cpp +++ b/src/test/CollisionTest.cpp @@ -50,6 +50,7 @@ public:  class CollisionTest : public Test {  public:  	Mediator m; +	EventManager event_mgr{m};  	ComponentManager mgr{m};  	CollisionSystem collision_sys{m};  	ScriptSystem script_sys{m}; diff --git a/src/test/EventTest.cpp b/src/test/EventTest.cpp index 4a4872d..8479998 100644 --- a/src/test/EventTest.cpp +++ b/src/test/EventTest.cpp @@ -1,56 +1,41 @@  #include <gmock/gmock.h>  #include <gtest/gtest.h> -  #include <crepe/api/Event.h> -#include <crepe/api/IKeyListener.h> -#include <crepe/api/IMouseListener.h>  #include <crepe/manager/EventManager.h> - +#include <crepe/manager/Mediator.h>  using namespace std;  using namespace std::chrono_literals;  using namespace crepe;  class EventManagerTest : public ::testing::Test {  protected: +	Mediator mediator; +	EventManager event_mgr{mediator};  	void SetUp() override {  		// Clear any existing subscriptions or events before each test -		EventManager::get_instance().clear(); +		event_mgr.clear();  	}  	void TearDown() override {  		// Ensure cleanup after each test -		EventManager::get_instance().clear(); +		event_mgr.clear();  	}  }; -class MockKeyListener : public IKeyListener { -public: -	MOCK_METHOD(bool, on_key_pressed, (const KeyPressEvent & event), (override)); -	MOCK_METHOD(bool, on_key_released, (const KeyReleaseEvent & event), (override)); -}; - -class MockMouseListener : public IMouseListener { -public: -	MOCK_METHOD(bool, on_mouse_clicked, (const MouseClickEvent & event), (override)); -	MOCK_METHOD(bool, on_mouse_pressed, (const MousePressEvent & event), (override)); -	MOCK_METHOD(bool, on_mouse_released, (const MouseReleaseEvent & event), (override)); -	MOCK_METHOD(bool, on_mouse_moved, (const MouseMoveEvent & event), (override)); -}; -  TEST_F(EventManagerTest, EventSubscription) {  	EventHandler<KeyPressEvent> key_handler = [](const KeyPressEvent & e) { return true; };  	// Subscribe to KeyPressEvent -	EventManager::get_instance().subscribe<KeyPressEvent>(key_handler, 1); +	event_mgr.subscribe<KeyPressEvent>(key_handler, 1);  	// Verify subscription (not directly verifiable; test by triggering event) -	EventManager::get_instance().trigger_event<KeyPressEvent>( +	event_mgr.trigger_event<KeyPressEvent>(  		KeyPressEvent{  			.repeat = true,  			.key = Keycode::A,  		},  		1); -	EventManager::get_instance().trigger_event<KeyPressEvent>( +	event_mgr.trigger_event<KeyPressEvent>(  		KeyPressEvent{  			.repeat = true,  			.key = Keycode::A, @@ -68,12 +53,12 @@ TEST_F(EventManagerTest, EventManagerTest_trigger_all_channels) {  		EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE);  		return false;  	}; -	EventManager::get_instance().subscribe<MouseClickEvent>(mouse_handler, +	event_mgr.subscribe<MouseClickEvent>(mouse_handler,  															EventManager::CHANNEL_ALL);  	MouseClickEvent click_event{  		.mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}; -	EventManager::get_instance().trigger_event<MouseClickEvent>(click_event, +	event_mgr.trigger_event<MouseClickEvent>(click_event,  																EventManager::CHANNEL_ALL);  	EXPECT_TRUE(triggered); @@ -88,19 +73,18 @@ TEST_F(EventManagerTest, EventManagerTest_trigger_one_channel) {  		EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE);  		return false;  	}; -	EventManager::get_instance().subscribe<MouseClickEvent>(mouse_handler, test_channel); +	event_mgr.subscribe<MouseClickEvent>(mouse_handler, test_channel);  	MouseClickEvent click_event{  		.mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}; -	EventManager::get_instance().trigger_event<MouseClickEvent>(click_event, +	event_mgr.trigger_event<MouseClickEvent>(click_event,  																EventManager::CHANNEL_ALL);  	EXPECT_FALSE(triggered); -	EventManager::get_instance().trigger_event<MouseClickEvent>(click_event, test_channel); +	event_mgr.trigger_event<MouseClickEvent>(click_event, test_channel);  }  TEST_F(EventManagerTest, EventManagerTest_callback_propagation) { -	EventManager & event_manager = EventManager::get_instance();  	// Flags to track handler calls  	bool triggered_true = false; @@ -126,11 +110,11 @@ TEST_F(EventManagerTest, EventManagerTest_callback_propagation) {  	// Test event  	MouseClickEvent click_event{  		.mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}; -	event_manager.subscribe<MouseClickEvent>(mouse_handler_true, EventManager::CHANNEL_ALL); -	event_manager.subscribe<MouseClickEvent>(mouse_handler_false, EventManager::CHANNEL_ALL); +	event_mgr.subscribe<MouseClickEvent>(mouse_handler_true, EventManager::CHANNEL_ALL); +	event_mgr.subscribe<MouseClickEvent>(mouse_handler_false, EventManager::CHANNEL_ALL);  	// Trigger event -	event_manager.trigger_event<MouseClickEvent>(click_event, EventManager::CHANNEL_ALL); +	event_mgr.trigger_event<MouseClickEvent>(click_event, EventManager::CHANNEL_ALL);  	// Check that only the true handler was triggered  	EXPECT_TRUE(triggered_true); @@ -139,12 +123,12 @@ TEST_F(EventManagerTest, EventManagerTest_callback_propagation) {  	// Reset and clear  	triggered_true = false;  	triggered_false = false; -	event_manager.clear(); -	event_manager.subscribe<MouseClickEvent>(mouse_handler_false, EventManager::CHANNEL_ALL); -	event_manager.subscribe<MouseClickEvent>(mouse_handler_true, EventManager::CHANNEL_ALL); +	event_mgr.clear(); +	event_mgr.subscribe<MouseClickEvent>(mouse_handler_false, EventManager::CHANNEL_ALL); +	event_mgr.subscribe<MouseClickEvent>(mouse_handler_true, EventManager::CHANNEL_ALL);  	// Trigger event again -	event_manager.trigger_event<MouseClickEvent>(click_event, EventManager::CHANNEL_ALL); +	event_mgr.trigger_event<MouseClickEvent>(click_event, EventManager::CHANNEL_ALL);  	// Check that both handlers were triggered  	EXPECT_TRUE(triggered_true); @@ -152,47 +136,37 @@ TEST_F(EventManagerTest, EventManagerTest_callback_propagation) {  }  TEST_F(EventManagerTest, EventManagerTest_queue_dispatch) { -	EventManager & event_manager = EventManager::get_instance();  	bool triggered1 = false;  	bool triggered2 = false;  	int test_channel = 1; - -	// Adjusted to use KeyPressEvent with repeat as the first variable -	EventHandler<KeyPressEvent> key_handler1 = [&](const KeyPressEvent & e) { +	EventHandler<MouseClickEvent> mouse_handler1 = [&](const MouseClickEvent & e) {  		triggered1 = true; -		EXPECT_EQ(e.repeat, false); // Expecting repeat to be false -		EXPECT_EQ(e.key, Keycode::A); // Adjust expected key code +		EXPECT_EQ(e.mouse_x, 100); +		EXPECT_EQ(e.mouse_y, 200); +		EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE);  		return false; // Allows propagation  	}; - -	EventHandler<KeyPressEvent> key_handler2 = [&](const KeyPressEvent & e) { +	EventHandler<MouseClickEvent> mouse_handler2 = [&](const MouseClickEvent & e) {  		triggered2 = true; -		EXPECT_EQ(e.repeat, false); // Expecting repeat to be false -		EXPECT_EQ(e.key, Keycode::A); // Adjust expected key code +		EXPECT_EQ(e.mouse_x, 100); +		EXPECT_EQ(e.mouse_y, 200); +		EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE);  		return false; // Allows propagation  	}; +	event_mgr.subscribe<MouseClickEvent>(mouse_handler1); +	event_mgr.subscribe<MouseClickEvent>(mouse_handler2, test_channel); -	// Subscribe handlers to KeyPressEvent -	event_manager.subscribe<KeyPressEvent>(key_handler1); -	event_manager.subscribe<KeyPressEvent>(key_handler2, test_channel); - -	// Queue a KeyPressEvent instead of KeyDownEvent -	event_manager.queue_event<KeyPressEvent>(KeyPressEvent{ -		.repeat = false, .key = Keycode::A}); // Adjust event with repeat flag first - -	event_manager.queue_event<KeyPressEvent>( -		KeyPressEvent{.repeat = false, -					  .key = Keycode::A}, // Adjust event for second subscription +	event_mgr.queue_event<MouseClickEvent>( +		MouseClickEvent{.mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}); +	event_mgr.queue_event<MouseClickEvent>( +		MouseClickEvent{.mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE},  		test_channel); - -	event_manager.dispatch_events(); - +	event_mgr.dispatch_events();  	EXPECT_TRUE(triggered1);  	EXPECT_TRUE(triggered2);  }  TEST_F(EventManagerTest, EventManagerTest_unsubscribe) { -	EventManager & event_manager = EventManager::get_instance();  	// Flags to track if handlers are triggered  	bool triggered1 = false; @@ -215,15 +189,15 @@ TEST_F(EventManagerTest, EventManagerTest_unsubscribe) {  		return false; // Allows propagation  	};  	// Subscribe handlers -	subscription_t handler1_id = event_manager.subscribe<MouseClickEvent>(mouse_handler1); -	subscription_t handler2_id = event_manager.subscribe<MouseClickEvent>(mouse_handler2); +	subscription_t handler1_id = event_mgr.subscribe<MouseClickEvent>(mouse_handler1); +	subscription_t handler2_id = event_mgr.subscribe<MouseClickEvent>(mouse_handler2);  	// Queue events -	event_manager.queue_event<MouseClickEvent>( +	event_mgr.queue_event<MouseClickEvent>(  		MouseClickEvent{.mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE});  	// Dispatch events - both handlers should be triggered -	event_manager.dispatch_events(); +	event_mgr.dispatch_events();  	EXPECT_TRUE(triggered1); // Handler 1 should be triggered  	EXPECT_TRUE(triggered2); // Handler 2 should be triggered @@ -232,14 +206,14 @@ TEST_F(EventManagerTest, EventManagerTest_unsubscribe) {  	triggered2 = false;  	// Unsubscribe handler1 -	event_manager.unsubscribe(handler1_id); +	event_mgr.unsubscribe(handler1_id);  	// Queue the same event again -	event_manager.queue_event<MouseClickEvent>( +	event_mgr.queue_event<MouseClickEvent>(  		MouseClickEvent{.mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE});  	// Dispatch events - only handler 2 should be triggered, handler 1 should NOT -	event_manager.dispatch_events(); +	event_mgr.dispatch_events();  	EXPECT_FALSE(triggered1); // Handler 1 should NOT be triggered  	EXPECT_TRUE(triggered2); // Handler 2 should be triggered @@ -247,14 +221,14 @@ TEST_F(EventManagerTest, EventManagerTest_unsubscribe) {  	triggered2 = false;  	// Unsubscribe handler2 -	event_manager.unsubscribe(handler2_id); +	event_mgr.unsubscribe(handler2_id);  	// Queue the event again -	event_manager.queue_event<MouseClickEvent>( +	event_mgr.queue_event<MouseClickEvent>(  		MouseClickEvent{.mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE});  	// Dispatch events - no handler should be triggered -	event_manager.dispatch_events(); +	event_mgr.dispatch_events();  	EXPECT_FALSE(triggered1); // Handler 1 should NOT be triggered  	EXPECT_FALSE(triggered2); // Handler 2 should NOT be triggered  } diff --git a/src/test/InputTest.cpp b/src/test/InputTest.cpp index a7c0157..bf08a04 100644 --- a/src/test/InputTest.cpp +++ b/src/test/InputTest.cpp @@ -26,8 +26,7 @@ public:  	ComponentManager mgr{mediator};  	InputSystem input_system{mediator}; - -	EventManager & event_manager = EventManager::get_instance(); +	EventManager event_manager{mediator};  	//GameObject camera;  protected: diff --git a/src/test/LoopManagerTest.cpp b/src/test/LoopManagerTest.cpp new file mode 100644 index 0000000..13a0ada --- /dev/null +++ b/src/test/LoopManagerTest.cpp @@ -0,0 +1,67 @@ +#include <chrono> +#include <gtest/gtest.h> +#include <gmock/gmock.h> +#include <thread> +#define private public +#define protected public +#include <crepe/api/LoopManager.h> +#include <crepe/manager/LoopTimerManager.h> +#include <crepe/manager/EventManager.h> +using namespace std::chrono; +using namespace crepe; + +class LoopManagerTest : public ::testing::Test { +protected: +    class TestGameLoop : public crepe::LoopManager { +    public: +    	MOCK_METHOD(void, fixed_update, (), (override)); +        MOCK_METHOD(void, update, (), (override)); +		MOCK_METHOD(void, render, (), (override)); +    }; + +    TestGameLoop test_loop; +    void SetUp() override { +		 +    } +}; + +TEST_F(LoopManagerTest, FixedUpdate) { +    // Arrange +    test_loop.loop_timer.set_target_fps(60); + +    // Set expectations for the mock calls +    EXPECT_CALL(test_loop, render).Times(::testing::Exactly(60));  +	EXPECT_CALL(test_loop, update).Times(::testing::Exactly(60)); +    EXPECT_CALL(test_loop, fixed_update).Times(::testing::Exactly(50)); + +    // Start the loop in a separate thread +    std::thread loop_thread([&]() { test_loop.start(); }); + +    // Let the loop run for exactly 1 second +    std::this_thread::sleep_for(std::chrono::seconds(1)); + +    // Stop the game loop +    test_loop.game_running = false; +    // Wait for the loop thread to finish +    loop_thread.join(); + +    // Test finished +} +TEST_F(LoopManagerTest, ShutDown) { +    // Arrange +    test_loop.loop_timer.set_target_fps(60); + +	EXPECT_CALL(test_loop, render).Times(::testing::AtLeast(1));  +	EXPECT_CALL(test_loop, update).Times(::testing::AtLeast(1)); +    EXPECT_CALL(test_loop, fixed_update).Times(::testing::AtLeast(1)); +    // Start the loop in a separate thread +    std::thread loop_thread([&]() { test_loop.start(); }); +    std::this_thread::sleep_for(std::chrono::milliseconds(1)); +	test_loop.event_manager.trigger_event<ShutDownEvent>(ShutDownEvent{}); +    // Wait for the loop thread to finish +    loop_thread.join(); + +    // Test finished +} + + diff --git a/src/test/LoopTimerTest.cpp b/src/test/LoopTimerTest.cpp new file mode 100644 index 0000000..09b4e00 --- /dev/null +++ b/src/test/LoopTimerTest.cpp @@ -0,0 +1,75 @@ +#include <chrono> +#include <thread> +#include <gtest/gtest.h> +#define private public +#define protected public +#include <crepe/manager/LoopTimerManager.h> +#include <crepe/manager/Mediator.h> +using namespace std::chrono; +using namespace crepe; + +class LoopTimerTest : public ::testing::Test { +protected: +	Mediator mediator; +	LoopTimerManager loop_timer{mediator}; + +	void SetUp() override { loop_timer.start(); } +}; +TEST_F(LoopTimerTest, EnforcesTargetFrameRate) { +	// Set the target FPS to 60 (which gives a target time per frame of ~16.67 ms) +	loop_timer.set_target_fps(60); + +	auto start_time = steady_clock::now(); +	loop_timer.enforce_frame_rate(); + +	auto elapsed_time = steady_clock::now() - start_time; +	auto elapsed_ms = duration_cast<milliseconds>(elapsed_time).count(); + +	// For 60 FPS, the target frame time is around 16.67ms +	ASSERT_NEAR(elapsed_ms,16.7,1); +} +TEST_F(LoopTimerTest, SetTargetFps) { +	// Set the target FPS to 120 +	loop_timer.set_target_fps(120); + +	// Calculate the expected frame time (~8.33ms per frame) +	auto expected_frame_time = std::chrono::duration<double>(1.0 / 120.0); + +	ASSERT_NEAR(loop_timer.frame_target_time.count(), expected_frame_time.count(), 0.001); +} +TEST_F(LoopTimerTest, DeltaTimeCalculation) { +	// Set the target FPS to 60 (16.67 ms per frame) +	loop_timer.set_target_fps(60); + +	auto start_time = steady_clock::now(); +	loop_timer.update(); +	auto end_time = steady_clock::now(); + +	// Check the delta time +	double delta_time = loop_timer.get_delta_time(); + +	auto elapsed_time = duration_cast<seconds>(end_time - start_time).count(); + +	// Assert that delta_time is close to the elapsed time +	ASSERT_NEAR(delta_time, elapsed_time, 1); +} + +TEST_F(LoopTimerTest, getCurrentTime) { +	// Set the target FPS to 60 (16.67 ms per frame) +	loop_timer.set_target_fps(60); + +	auto start_time = steady_clock::now(); + +	// Sleep +	std::this_thread::sleep_for(std::chrono::milliseconds(100)); + +	loop_timer.update(); + +	auto end_time = steady_clock::now(); + +	// Get the elapsed time in seconds as a double +	auto elapsed_time +		= duration_cast<std::chrono::duration<double>>(end_time - start_time).count(); + +	ASSERT_NEAR(loop_timer.get_current_time(), elapsed_time, 0.001); +} diff --git a/src/test/ScriptTest.h b/src/test/ScriptTest.h index 1bbfdd3..ee68c23 100644 --- a/src/test/ScriptTest.h +++ b/src/test/ScriptTest.h @@ -7,7 +7,7 @@  #include <crepe/api/Script.h>  #include <crepe/manager/ComponentManager.h>  #include <crepe/system/ScriptSystem.h> - +#include <crepe/manager/EventManager.h>  class ScriptTest : public testing::Test {  protected:  	crepe::Mediator mediator; @@ -15,7 +15,7 @@ protected:  public:  	crepe::ComponentManager component_manager{mediator};  	crepe::ScriptSystem system{mediator}; - +	crepe::EventManager event_mgr{mediator};  	class MyScript : public crepe::Script {  		// NOTE: explicitly stating `public:` is not required on actual scripts |