diff options
Diffstat (limited to 'src')
58 files changed, 475 insertions, 285 deletions
| diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e4922df..445a8b2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -38,6 +38,5 @@ install(  target_link_libraries(test_main  	PRIVATE gtest -	PRIVATE gtest_main  	PUBLIC crepe  ) diff --git a/src/crepe/Collider.cpp b/src/crepe/Collider.cpp index bbec488..113ba61 100644 --- a/src/crepe/Collider.cpp +++ b/src/crepe/Collider.cpp @@ -1,5 +1,3 @@  #include "Collider.h"  using namespace crepe; - -Collider::Collider(game_object_id_t id) : Component(id) {} diff --git a/src/crepe/Collider.h b/src/crepe/Collider.h index 827f83d..a1e9095 100644 --- a/src/crepe/Collider.h +++ b/src/crepe/Collider.h @@ -6,7 +6,7 @@ namespace crepe {  class Collider : public Component {  public: -	Collider(game_object_id_t id); +	using Component::Component;  	int size;  }; diff --git a/src/crepe/Component.cpp b/src/crepe/Component.cpp index 73c2d07..acfd35c 100644 --- a/src/crepe/Component.cpp +++ b/src/crepe/Component.cpp @@ -1,5 +1,4 @@  #include "Component.h" -#include "types.h"  using namespace crepe; diff --git a/src/crepe/Component.h b/src/crepe/Component.h index 0fe60b2..12c10cb 100644 --- a/src/crepe/Component.h +++ b/src/crepe/Component.h @@ -2,8 +2,6 @@  #include "types.h" -#include <cstdint> -  namespace crepe {  class ComponentManager; @@ -15,16 +13,21 @@ class ComponentManager;   * interface for all components.   */  class Component { +public: +	//! Whether the component is active +	bool active = true; +	//! The id of the GameObject this component belongs to +	const game_object_id_t game_object_id; +  protected: -	//! Only the ComponentManager can create components -	friend class crepe::ComponentManager;  	/**  	 * \param id The id of the GameObject this component belongs to  	 */  	Component(game_object_id_t id); +	//! Only the ComponentManager can create components +	friend class ComponentManager;  public: -	virtual ~Component() = default;  	/**  	 * \brief Get the maximum number of instances for this component  	 * @@ -35,12 +38,6 @@ public:  	 * \return The maximum number of instances for this component  	 */  	virtual int get_instances_max() const { return -1; } - -public: -	//! The id of the GameObject this component belongs to -	const game_object_id_t game_object_id; -	//! Whether the component is active -	bool active = true;  };  } // namespace crepe diff --git a/src/crepe/ComponentManager.cpp b/src/crepe/ComponentManager.cpp index 7123905..c6b658c 100644 --- a/src/crepe/ComponentManager.cpp +++ b/src/crepe/ComponentManager.cpp @@ -1,13 +1,10 @@ +#include "api/GameObject.h"  #include "util/Log.h"  #include "ComponentManager.h"  using namespace crepe; - -ComponentManager & ComponentManager::get_instance() { -	static ComponentManager instance; -	return instance; -} +using namespace std;  void ComponentManager::delete_all_components_of_id(game_object_id_t id) {  	// Loop through all the types (in the unordered_map<>) @@ -26,5 +23,15 @@ void ComponentManager::delete_all_components() {  }  ComponentManager::ComponentManager() { dbg_trace(); } -  ComponentManager::~ComponentManager() { dbg_trace(); } + +GameObject & ComponentManager::new_object(const string & name, +										  const string & tag, +										  const Vector2 & position, +										  double rotation, double scale) { +	GameObject * object = new GameObject(*this, this->next_id, name, tag, +										 position, rotation, scale); +	this->objects.push_front(unique_ptr<GameObject>(object)); +	this->next_id++; +	return *object; +} diff --git a/src/crepe/ComponentManager.h b/src/crepe/ComponentManager.h index c8c196c..75606e0 100644 --- a/src/crepe/ComponentManager.h +++ b/src/crepe/ComponentManager.h @@ -1,15 +1,18 @@  #pragma once -#include <cstdint> +#include <forward_list>  #include <memory>  #include <typeindex>  #include <unordered_map>  #include <vector>  #include "Component.h" +#include "api/Vector2.h"  namespace crepe { +class GameObject; +  /**   * \brief Manages all components   *  @@ -18,18 +21,10 @@ namespace crepe {   */  class ComponentManager {  public: -	/** -	 * \brief Get the instance of the ComponentManager -	 *  -	 * \return The instance of the ComponentManager -	 */ -	static ComponentManager & get_instance(); -	ComponentManager(const ComponentManager &) = delete; -	ComponentManager(ComponentManager &&) = delete; -	ComponentManager & operator=(const ComponentManager &) = delete; -	ComponentManager & operator=(ComponentManager &&) = delete; -	~ComponentManager(); +	ComponentManager(); // dbg_trace +	~ComponentManager(); // dbg_trace +protected:  	/**  	 * \brief Add a component to the ComponentManager  	 *  @@ -44,6 +39,11 @@ public:  	 */  	template <typename T, typename... Args>  	T & add_component(game_object_id_t id, Args &&... args); +	//! GameObject is used as an interface to add components instead of the +	// component manager directly +	friend class GameObject; + +public:  	/**  	 * \brief Delete all components of a specific type and id  	 *  @@ -100,8 +100,11 @@ public:  	template <typename T>  	std::vector<std::reference_wrapper<T>> get_components_by_type() const; -private: -	ComponentManager(); +	// TODO: doxygen +	GameObject & new_object(const std::string & name, +							const std::string & tag = "", +							const Vector2 & position = {0, 0}, +							double rotation = 0, double scale = 0);  private:  	/** @@ -118,6 +121,10 @@ private:  	std::unordered_map<std::type_index,  					   std::vector<std::vector<std::unique_ptr<Component>>>>  		components; + +	//! ID of next GameObject +	game_object_id_t next_id = 0; +	std::forward_list<std::unique_ptr<GameObject>> objects;  };  } // namespace crepe diff --git a/src/crepe/api/Animator.cpp b/src/crepe/api/Animator.cpp index 863dce6..54b2ec3 100644 --- a/src/crepe/api/Animator.cpp +++ b/src/crepe/api/Animator.cpp @@ -9,7 +9,8 @@  using namespace crepe; -Animator::Animator(uint32_t id, Sprite & ss, int row, int col, int col_animator) +Animator::Animator(game_object_id_t id, Sprite & ss, int row, int col, +				   int col_animator)  	: Component(id),  	  spritesheet(ss),  	  row(row), diff --git a/src/crepe/api/Animator.h b/src/crepe/api/Animator.h index def0240..75b8139 100644 --- a/src/crepe/api/Animator.h +++ b/src/crepe/api/Animator.h @@ -6,6 +6,7 @@  #include "Sprite.h"  namespace crepe { +  class AnimatorSystem;  class SDLContext; @@ -35,7 +36,7 @@ public:  	 *  	 * This constructor sets up the Animator with the given parameters, and initializes the animation system.  	 */ -	Animator(uint32_t id, Sprite & spritesheet, int row, int col, +	Animator(game_object_id_t id, Sprite & spritesheet, int row, int col,  			 int col_animate);  	~Animator(); // dbg_trace diff --git a/src/crepe/api/AssetManager.h b/src/crepe/api/AssetManager.h index dbfaef3..86a9902 100644 --- a/src/crepe/api/AssetManager.h +++ b/src/crepe/api/AssetManager.h @@ -56,7 +56,8 @@ public:  	 * cache.  	 */  	template <typename T> -	std::shared_ptr<T> cache(const std::string & file_path, bool reload = false); +	std::shared_ptr<T> cache(const std::string & file_path, +							 bool reload = false);  };  } // namespace crepe diff --git a/src/crepe/api/BehaviorScript.cpp b/src/crepe/api/BehaviorScript.cpp index e69de29..7bbace0 100644 --- a/src/crepe/api/BehaviorScript.cpp +++ b/src/crepe/api/BehaviorScript.cpp @@ -0,0 +1,15 @@ +#include "BehaviorScript.h" +#include "Component.h" +#include "GameObject.h" + +using namespace crepe; + +BehaviorScript::BehaviorScript(game_object_id_t id, ComponentManager & mgr) +	: Component(id), +	  component_manager(mgr) {} + +template <> +BehaviorScript & GameObject::add_component<BehaviorScript>() { +	ComponentManager & mgr = this->component_manager; +	return mgr.add_component<BehaviorScript>(this->id, mgr); +} diff --git a/src/crepe/api/BehaviorScript.h b/src/crepe/api/BehaviorScript.h index 4160a72..2982358 100644 --- a/src/crepe/api/BehaviorScript.h +++ b/src/crepe/api/BehaviorScript.h @@ -3,6 +3,7 @@  #include <memory>  #include "../Component.h" +#include "GameObject.h"  namespace crepe { @@ -19,22 +20,52 @@ class Script;   */  class BehaviorScript : public Component {  protected: -	friend class crepe::ComponentManager; -	using Component::Component; +	BehaviorScript(game_object_id_t id, ComponentManager & component_manager); +	//! Only ComponentManager is allowed to instantiate BehaviorScript +	friend class ComponentManager;  public:  	~BehaviorScript() = default;  public: +	/** +	 * \brief Set the concrete script of this component +	 * +	 * \tparam T Concrete script type (derived from \c crepe::Script) +	 * +	 * \returns Reference to BehaviorScript component (`*this`) +	 */  	template <class T>  	BehaviorScript & set_script();  protected: -	friend class crepe::ScriptSystem; +	//! ScriptSystem needs direct access to the script instance +	friend class ScriptSystem; +	//! Flag to indicate if script->init() has been called already +	bool initialized = false;  	//! Script instance  	std::unique_ptr<Script> script = nullptr; +	//! Reference to component manager +	ComponentManager & component_manager; + +private: +	//! Script accesses the component manager directly via its parent +	// (BehaviorScript) reference +	friend class Script;  }; +/** + * \brief Add a BehaviorScript component to this game object + * + * The \c BehaviorScript class is the only exception to the ECS harmony, and + * requires a reference to the component manager passed to its constructor in + * order to function normally. This is because the \c BehaviorScript (and \c + * Script) classes are the only component-related classes that store + * implemented member functions as data. + */ +template <> +BehaviorScript & GameObject::add_component<BehaviorScript>(); +  } // namespace crepe  #include "BehaviorScript.hpp" diff --git a/src/crepe/api/BehaviorScript.hpp b/src/crepe/api/BehaviorScript.hpp index bc157fd..eec26da 100644 --- a/src/crepe/api/BehaviorScript.hpp +++ b/src/crepe/api/BehaviorScript.hpp @@ -11,10 +11,11 @@ namespace crepe {  template <class T>  BehaviorScript & BehaviorScript::set_script() { -	static_assert(std::is_base_of<Script, T>::value);  	dbg_trace(); +	static_assert(std::is_base_of<Script, T>::value);  	Script * s = new T(); -	s->parent = this; +	s->parent_ref = this; +	s->component_manager_ref = &this->component_manager;  	this->script = std::unique_ptr<Script>(s);  	return *this;  } diff --git a/src/crepe/api/Camera.cpp b/src/crepe/api/Camera.cpp index 6f0deb1..5835bdd 100644 --- a/src/crepe/api/Camera.cpp +++ b/src/crepe/api/Camera.cpp @@ -1,6 +1,3 @@ - -#include <cstdint> -  #include "util/Log.h"  #include "Camera.h" @@ -9,7 +6,7 @@  using namespace crepe; -Camera::Camera(uint32_t id, const Color & bg_color) +Camera::Camera(game_object_id_t id, const Color & bg_color)  	: Component(id),  	  bg_color(bg_color) {  	dbg_trace(); diff --git a/src/crepe/api/Camera.h b/src/crepe/api/Camera.h index ba3a9ef..d8c08a6 100644 --- a/src/crepe/api/Camera.h +++ b/src/crepe/api/Camera.h @@ -23,7 +23,7 @@ public:  	 * \param id Unique identifier for the camera component.  	 * \param bg_color Background color for the camera view.  	 */ -	Camera(uint32_t id, const Color & bg_color); +	Camera(game_object_id_t id, const Color & bg_color);  	~Camera(); // dbg_trace only  public: diff --git a/src/crepe/api/GameObject.cpp b/src/crepe/api/GameObject.cpp index d252e77..4f3c639 100644 --- a/src/crepe/api/GameObject.cpp +++ b/src/crepe/api/GameObject.cpp @@ -1,23 +1,27 @@  #include "api/Transform.h" +#include "BehaviorScript.h"  #include "GameObject.h"  #include "Metadata.h"  using namespace crepe;  using namespace std; -GameObject::GameObject(game_object_id_t id, const std::string & name, +GameObject::GameObject(ComponentManager & component_manager, +					   game_object_id_t id, const std::string & name,  					   const std::string & tag, const Vector2 & position,  					   double rotation, double scale) -	: id(id) { +	: id(id), +	  component_manager(component_manager) { +  	// Add Transform and Metadata components -	ComponentManager & mgr = ComponentManager::get_instance(); +	ComponentManager & mgr = this->component_manager;  	mgr.add_component<Transform>(this->id, position, rotation, scale);  	mgr.add_component<Metadata>(this->id, name, tag);  }  void GameObject::set_parent(const GameObject & parent) { -	ComponentManager & mgr = ComponentManager::get_instance(); +	ComponentManager & mgr = this->component_manager;  	// Set parent on own Metadata component  	vector<reference_wrapper<Metadata>> this_metadata diff --git a/src/crepe/api/GameObject.h b/src/crepe/api/GameObject.h index d703730..73ff0b8 100644 --- a/src/crepe/api/GameObject.h +++ b/src/crepe/api/GameObject.h @@ -2,11 +2,12 @@  #include <string> +#include "Vector2.h"  #include "types.h"  namespace crepe { -class Vector2; +class ComponentManager;  /**   * \brief Represents a GameObject @@ -16,11 +17,12 @@ class Vector2;   * done in the ComponentManager.   */  class GameObject { -public: +private:  	/**  	 * This constructor creates a new GameObject. It creates a new  	 * Transform and Metadata component and adds them to the ComponentManager.  	 *  +	 * \param component_manager Reference to component_manager  	 * \param id The id of the GameObject  	 * \param name The name of the GameObject  	 * \param tag The tag of the GameObject @@ -28,9 +30,13 @@ public:  	 * \param rotation The rotation of the GameObject  	 * \param scale The scale of the GameObject  	 */ -	GameObject(game_object_id_t id, const std::string & name, -			   const std::string & tag, const Vector2 & position, -			   double rotation, double scale); +	GameObject(ComponentManager & component_manager, game_object_id_t id, +			   const std::string & name, const std::string & tag, +			   const Vector2 & position, double rotation, double scale); +	//! ComponentManager instances GameObject +	friend class ComponentManager; + +public:  	/**  	 * \brief Set the parent of this GameObject  	 *  @@ -58,6 +64,9 @@ public:  public:  	//! The id of the GameObject  	const game_object_id_t id; + +protected: +	ComponentManager & component_manager;  };  } // namespace crepe diff --git a/src/crepe/api/GameObject.hpp b/src/crepe/api/GameObject.hpp index bfba7fe..17b17d7 100644 --- a/src/crepe/api/GameObject.hpp +++ b/src/crepe/api/GameObject.hpp @@ -8,7 +8,7 @@ namespace crepe {  template <typename T, typename... Args>  T & GameObject::add_component(Args &&... args) { -	ComponentManager & mgr = ComponentManager::get_instance(); +	ComponentManager & mgr = this->component_manager;  	return mgr.add_component<T>(this->id, std::forward<Args>(args)...);  } diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp index 2e9823f..f0788ab 100644 --- a/src/crepe/api/LoopManager.cpp +++ b/src/crepe/api/LoopManager.cpp @@ -1,5 +1,9 @@ -  #include "../facade/SDLContext.h" + +#include "../system/AnimatorSystem.h" +#include "../system/CollisionSystem.h" +#include "../system/ParticleSystem.h" +#include "../system/PhysicsSystem.h"  #include "../system/RenderSystem.h"  #include "../system/ScriptSystem.h" @@ -7,11 +11,25 @@  #include "LoopTimer.h"  using namespace crepe; +using namespace std; + +LoopManager::LoopManager() { +	this->load_system<AnimatorSystem>(); +	this->load_system<CollisionSystem>(); +	this->load_system<ParticleSystem>(); +	this->load_system<PhysicsSystem>(); +	this->load_system<RenderSystem>(); +	this->load_system<ScriptSystem>(); +} + +ComponentManager & LoopManager::get_component_manager() { +	return this->component_manager; +} -LoopManager::LoopManager() {}  void LoopManager::process_input() {  	SDLContext::get_instance().handle_events(this->game_running);  } +  void LoopManager::start() {  	this->setup();  	this->loop(); @@ -48,7 +66,7 @@ void LoopManager::setup() {  void LoopManager::render() {  	if (this->game_running) { -		RenderSystem::get_instance().update(); +		this->get_system<RenderSystem>().update();  	}  } diff --git a/src/crepe/api/LoopManager.h b/src/crepe/api/LoopManager.h index 2f03193..288dca2 100644 --- a/src/crepe/api/LoopManager.h +++ b/src/crepe/api/LoopManager.h @@ -2,15 +2,9 @@  #include <memory> -class RenderSystem; -class SDLContext; -class LoopTimer; -class ScriptSystem; -class SoundSystem; -class ParticleSystem; -class PhysicsSystem; -class AnimatorSystem; -class CollisionSystem; +#include "../ComponentManager.h" +#include "../system/System.h" +  namespace crepe {  class LoopManager { @@ -73,7 +67,21 @@ private:  	void render();  	bool game_running = false; -	//#TODO add system instances + +protected: +	ComponentManager & get_component_manager(); +	template <class T> +	T & get_system(); + +private: +	ComponentManager component_manager{}; +	std::unordered_map<std::type_index, std::unique_ptr<System>> systems; + +private: +	template <class T> +	void load_system();  };  } // namespace crepe + +#include "LoopManager.hpp" diff --git a/src/crepe/api/LoopManager.hpp b/src/crepe/api/LoopManager.hpp new file mode 100644 index 0000000..8fb9aa3 --- /dev/null +++ b/src/crepe/api/LoopManager.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include <cassert> +#include <memory> + +#include "../Exception.h" +#include "../system/System.h" + +#include "LoopManager.h" + +namespace crepe { + +template <class T> +T & LoopManager::get_system() { +	using namespace std; +	static_assert(is_base_of<System, T>::value, +				  "get_system must recieve a derivative class of System"); + +	const type_info & type = typeid(T); +	if (!this->systems.contains(type)) +		throw Exception("LoopManager: %s is not initialized", type.name()); + +	System * system = this->systems.at(type).get(); +	T * concrete_system = dynamic_cast<T *>(system); +	assert(concrete_system != nullptr); + +	return *concrete_system; +} + +template <class T> +void LoopManager::load_system() { +	using namespace std; +	static_assert(is_base_of<System, T>::value, +				  "load_system must recieve a derivative class of System"); + +	System * system = new T(this->component_manager); +	this->systems[typeid(T)] = unique_ptr<System>(system); +} + +} // namespace crepe diff --git a/src/crepe/api/Rigidbody.cpp b/src/crepe/api/Rigidbody.cpp index 3bf1c5b..6b87695 100644 --- a/src/crepe/api/Rigidbody.cpp +++ b/src/crepe/api/Rigidbody.cpp @@ -2,8 +2,8 @@  using namespace crepe; -crepe::Rigidbody::Rigidbody(uint32_t game_object_id, const Data & data) -	: Component(game_object_id), +crepe::Rigidbody::Rigidbody(game_object_id_t id, const Data & data) +	: Component(id),  	  data(data) {}  void crepe::Rigidbody::add_force_linear(const Vector2 & force) { diff --git a/src/crepe/api/Rigidbody.h b/src/crepe/api/Rigidbody.h index 68481f4..2e20288 100644 --- a/src/crepe/api/Rigidbody.h +++ b/src/crepe/api/Rigidbody.h @@ -82,7 +82,7 @@ public:  	 * \param game_object_id id of the gameobject the rigibody is added to.  	 * \param data struct to configure the rigidbody.  	 */ -	Rigidbody(uint32_t game_object_id, const Data & data); +	Rigidbody(game_object_id_t id, const Data & data);  	//! struct to hold data of rigidbody  	Data data; diff --git a/src/crepe/api/SceneManager.cpp b/src/crepe/api/SceneManager.cpp index dfed6ee..4a38787 100644 --- a/src/crepe/api/SceneManager.cpp +++ b/src/crepe/api/SceneManager.cpp @@ -8,10 +8,7 @@  using namespace crepe;  using namespace std; -SceneManager & SceneManager::get_instance() { -	static SceneManager instance; -	return instance; -} +SceneManager::SceneManager(ComponentManager & mgr) : component_manager(mgr) {}  void SceneManager::set_next_scene(const string & name) { next_scene = name; } @@ -30,7 +27,7 @@ void SceneManager::load_next_scene() {  	unique_ptr<Scene> & scene = *it;  	// Delete all components of the current scene -	ComponentManager & mgr = ComponentManager::get_instance(); +	ComponentManager & mgr = this->component_manager;  	mgr.delete_all_components();  	// Load the new scene diff --git a/src/crepe/api/SceneManager.h b/src/crepe/api/SceneManager.h index 1e0e670..553194f 100644 --- a/src/crepe/api/SceneManager.h +++ b/src/crepe/api/SceneManager.h @@ -8,14 +8,12 @@  namespace crepe { +class ComponentManager; +  class SceneManager {  public: -	// Singleton -	static SceneManager & get_instance(); -	SceneManager(const SceneManager &) = delete; -	SceneManager(SceneManager &&) = delete; -	SceneManager & operator=(const SceneManager &) = delete; -	SceneManager & operator=(SceneManager &&) = delete; +	SceneManager(ComponentManager & mgr); +	virtual ~SceneManager() = default;  public:  	/** @@ -38,11 +36,11 @@ public:  	void load_next_scene();  private: -	SceneManager() = default; - -private:  	std::vector<std::unique_ptr<Scene>> scenes;  	std::string next_scene; + +protected: +	ComponentManager & component_manager;  };  } // namespace crepe diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h index e6fbb5c..68a46d7 100644 --- a/src/crepe/api/Script.h +++ b/src/crepe/api/Script.h @@ -6,6 +6,7 @@ namespace crepe {  class ScriptSystem;  class BehaviorScript; +class ComponentManager;  /**   * \brief Script interface @@ -14,6 +15,7 @@ class BehaviorScript;   * added to game objects using the \c BehaviorScript component.   */  class Script { +	//! ScriptSystem calls \c update()  	friend class crepe::ScriptSystem;  protected: @@ -61,9 +63,19 @@ protected:  	template <typename T>  	std::vector<std::reference_wrapper<T>> get_components() const; +protected: +	// NOTE: Script must have a constructor without arguments so the game +	// programmer doesn't need to manually add `using Script::Script` to their +	// concrete script class. +	Script() = default; +	//! Only \c BehaviorScript instantiates Script +	friend class BehaviorScript; +  private: -	friend class crepe::BehaviorScript; -	BehaviorScript * parent = nullptr; +	// These references are set by BehaviorScript immediately after calling the +	// constructor of Script. +	BehaviorScript * parent_ref = nullptr; +	ComponentManager * component_manager_ref = nullptr;  };  } // namespace crepe diff --git a/src/crepe/api/Script.hpp b/src/crepe/api/Script.hpp index 7ec3ebe..aceb38b 100644 --- a/src/crepe/api/Script.hpp +++ b/src/crepe/api/Script.hpp @@ -21,8 +21,10 @@ T & Script::get_component() const {  template <typename T>  std::vector<std::reference_wrapper<T>> Script::get_components() const { -	ComponentManager & mgr = ComponentManager::get_instance(); -	return mgr.get_components_by_id<T>(this->parent->game_object_id); +	auto & parent = *this->parent_ref; +	auto & mgr = *this->component_manager_ref; + +	return mgr.get_components_by_id<T>(parent.game_object_id);  }  } // namespace crepe diff --git a/src/crepe/api/Transform.h b/src/crepe/api/Transform.h index 756e45b..902dafa 100644 --- a/src/crepe/api/Transform.h +++ b/src/crepe/api/Transform.h @@ -14,28 +14,26 @@ namespace crepe {   */  class Transform : public Component {  public: +	//! Translation (shift) +	Vector2 position = {0, 0}; +	//! Rotation, in degrees +	double rotation = 0; +	//! Multiplication factor +	double scale = 0; + +protected:  	/**  	 * \param id The id of the GameObject this component belongs to  	 * \param point The position of the GameObject  	 * \param rotation The rotation of the GameObject  	 * \param scale The scale of the GameObject  	 */ -	Transform(game_object_id_t id, const Vector2 & point, double rotation, -			  double scale); -	/** -	 * \brief Get the maximum number of instances for this component -	 * -	 * \return The maximum number of instances for this component -	 */ +	Transform(game_object_id_t id, const Vector2 & point, double rotation = 0, +			  double scale = 0); +	//! There is always exactly one transform component per entity  	virtual int get_instances_max() const { return 1; } - -public: -	//! Translation (shift) -	Vector2 position; -	//! Rotation, in degrees -	double rotation; -	//! Multiplication factor -	double scale; +	//! ComponentManager instantiates all components +	friend class ComponentManager;  };  } // namespace crepe diff --git a/src/crepe/api/Vector2.cpp b/src/crepe/api/Vector2.cpp index 09bb59b..7da202a 100644 --- a/src/crepe/api/Vector2.cpp +++ b/src/crepe/api/Vector2.cpp @@ -1,57 +1,43 @@  #include "Vector2.h" -namespace crepe { +using namespace crepe; -// Constructor with initial values -Vector2::Vector2(float x, float y) : x(x), y(y) {} - -// Subtracts another vector from this vector and returns the result.  Vector2 Vector2::operator-(const Vector2 & other) const {  	return {x - other.x, y - other.y};  } -// Adds another vector to this vector and returns the result.  Vector2 Vector2::operator+(const Vector2 & other) const {  	return {x + other.x, y + other.y};  } -// Multiplies this vector by a scalar and returns the result.  Vector2 Vector2::operator*(float scalar) const {  	return {x * scalar, y * scalar};  } -// Multiplies this vector by another vector element-wise and updates this vector.  Vector2 & Vector2::operator*=(const Vector2 & other) {  	x *= other.x;  	y *= other.y;  	return *this;  } -// Adds another vector to this vector and updates this vector.  Vector2 & Vector2::operator+=(const Vector2 & other) {  	x += other.x;  	y += other.y;  	return *this;  } -// Adds a scalar value to both components of this vector and updates this vector.  Vector2 & Vector2::operator+=(float other) {  	x += other;  	y += other;  	return *this;  } -// Returns the negation of this vector.  Vector2 Vector2::operator-() const { return {-x, -y}; } -// Checks if this vector is equal to another vector.  bool Vector2::operator==(const Vector2 & other) const {  	return x == other.x && y == other.y;  } -// Checks if this vector is not equal to another vector.  bool Vector2::operator!=(const Vector2 & other) const {  	return !(*this == other);  } - -} // namespace crepe diff --git a/src/crepe/api/Vector2.h b/src/crepe/api/Vector2.h index 741951b..a069a57 100644 --- a/src/crepe/api/Vector2.h +++ b/src/crepe/api/Vector2.h @@ -2,19 +2,12 @@  namespace crepe { -//! Vector2 class -class Vector2 { -public: +//! 2D vector +struct Vector2 {  	//! X component of the vector -	float x; +	float x = 0;  	//! Y component of the vector -	float y; - -	//! Default constructor -	Vector2() = default; - -	//! Constructor with initial values -	Vector2(float x, float y); +	float y = 0;  	//! Subtracts another vector from this vector and returns the result.  	Vector2 operator-(const Vector2 & other) const; diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index aa15ef6..a68d940 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -159,7 +159,7 @@ SDLContext::texture_from_path(const std::string & path) {  	SDL_Surface * tmp = IMG_Load(path.c_str());  	if (tmp == nullptr) { -		tmp = IMG_Load("../asset/texture/ERROR.png");	 +		tmp = IMG_Load("../asset/texture/ERROR.png");  	}  	std::unique_ptr<SDL_Surface, std::function<void(SDL_Surface *)>> diff --git a/src/crepe/system/AnimatorSystem.cpp b/src/crepe/system/AnimatorSystem.cpp index 1c101fa..9d18873 100644 --- a/src/crepe/system/AnimatorSystem.cpp +++ b/src/crepe/system/AnimatorSystem.cpp @@ -1,27 +1,17 @@ -  #include <cstdint>  #include <functional>  #include <vector>  #include "api/Animator.h"  #include "facade/SDLContext.h" -#include "util/Log.h"  #include "AnimatorSystem.h"  #include "ComponentManager.h"  using namespace crepe; -AnimatorSystem::AnimatorSystem() { dbg_trace(); } -AnimatorSystem::~AnimatorSystem() { dbg_trace(); } - -AnimatorSystem & AnimatorSystem::get_instance() { -	static AnimatorSystem instance; -	return instance; -} -  void AnimatorSystem::update() { -	ComponentManager & mgr = ComponentManager::get_instance(); +	ComponentManager & mgr = this->component_manager;  	std::vector<std::reference_wrapper<Animator>> animations  		= mgr.get_components_by_type<Animator>(); diff --git a/src/crepe/system/AnimatorSystem.h b/src/crepe/system/AnimatorSystem.h index 969e9d1..aa97084 100644 --- a/src/crepe/system/AnimatorSystem.h +++ b/src/crepe/system/AnimatorSystem.h @@ -17,16 +17,7 @@ namespace crepe {  class AnimatorSystem : public System {  public: -	/** -	 * \brief Retrieves the singleton instance of the AnimatorSystem. -	 * -	 * \return A reference to the single instance of the AnimatorSystem. -	 * -	 * This method ensures that there is only one instance of the AnimatorSystem, following the -	 * singleton design pattern. It can be used to access the system globally. -	 */ -	static AnimatorSystem & get_instance(); - +	using System::System;  	/**  	 * \brief Updates the Animator components.  	 * @@ -34,11 +25,7 @@ public:  	 * Animator components, moving the animations forward and managing their behavior (e.g., looping).  	 */  	void update() override; - -private: -	// private because singleton -	AnimatorSystem(); // dbg_trace -	~AnimatorSystem(); // dbg_trace +	// FIXME: never say "likely" in the documentation lmao  };  } // namespace crepe diff --git a/src/crepe/system/CMakeLists.txt b/src/crepe/system/CMakeLists.txt index 4c18b87..d658b25 100644 --- a/src/crepe/system/CMakeLists.txt +++ b/src/crepe/system/CMakeLists.txt @@ -1,4 +1,5 @@  target_sources(crepe PUBLIC +	System.cpp  	ParticleSystem.cpp  	ScriptSystem.cpp  	PhysicsSystem.cpp diff --git a/src/crepe/system/CollisionSystem.cpp b/src/crepe/system/CollisionSystem.cpp index 55e0fdc..c74ca1d 100644 --- a/src/crepe/system/CollisionSystem.cpp +++ b/src/crepe/system/CollisionSystem.cpp @@ -2,6 +2,4 @@  using namespace crepe; -CollisionSystem::CollisionSystem() {} -  void CollisionSystem::update() {} diff --git a/src/crepe/system/CollisionSystem.h b/src/crepe/system/CollisionSystem.h index 1e9f1aa..c1a70d8 100644 --- a/src/crepe/system/CollisionSystem.h +++ b/src/crepe/system/CollisionSystem.h @@ -1,11 +1,13 @@  #pragma once +#include "System.h" +  namespace crepe { -class CollisionSystem { +class CollisionSystem : public System {  public: -	CollisionSystem(); -	void update(); +	using System::System; +	void update() override;  };  } // namespace crepe diff --git a/src/crepe/system/ParticleSystem.cpp b/src/crepe/system/ParticleSystem.cpp index 397b586..fe02682 100644 --- a/src/crepe/system/ParticleSystem.cpp +++ b/src/crepe/system/ParticleSystem.cpp @@ -8,10 +8,8 @@  using namespace crepe; -ParticleSystem::ParticleSystem() : elapsed_time(0.0f) {} -  void ParticleSystem::update() { -	ComponentManager & mgr = ComponentManager::get_instance(); +	ComponentManager & mgr = this->component_manager;  	std::vector<std::reference_wrapper<ParticleEmitter>> emitters  		= mgr.get_components_by_type<ParticleEmitter>();  	float delta_time = 0.10; diff --git a/src/crepe/system/ParticleSystem.h b/src/crepe/system/ParticleSystem.h index 3ac1d3f..f171c62 100644 --- a/src/crepe/system/ParticleSystem.h +++ b/src/crepe/system/ParticleSystem.h @@ -2,17 +2,22 @@  #include "../api/ParticleEmitter.h" +#include "System.h" +  namespace crepe { -class ParticleSystem { +class ParticleSystem : public System {  public: -	ParticleSystem(); -	void update(); +	using System::System; +	void update() override;  private: -	void emit_particle(ParticleEmitter & emitter); //emits a new particle +	//! Emits a new particle +	void emit_particle(ParticleEmitter & emitter); -	float elapsed_time; //elapsed time since the last emission +	//! Elapsed time since the last emission +	float elapsed_time = 0.0; +	// TODO: to std::chrono::duration  };  } // namespace crepe diff --git a/src/crepe/system/PhysicsSystem.cpp b/src/crepe/system/PhysicsSystem.cpp index eb54ad3..da79707 100644 --- a/src/crepe/system/PhysicsSystem.cpp +++ b/src/crepe/system/PhysicsSystem.cpp @@ -11,7 +11,7 @@  using namespace crepe;  void PhysicsSystem::update() { -	ComponentManager & mgr = ComponentManager::get_instance(); +	ComponentManager & mgr = this->component_manager;  	std::vector<std::reference_wrapper<Rigidbody>> rigidbodies  		= mgr.get_components_by_type<Rigidbody>();  	std::vector<std::reference_wrapper<Transform>> transforms diff --git a/src/crepe/system/PhysicsSystem.h b/src/crepe/system/PhysicsSystem.h index cb6160e..5433a0f 100644 --- a/src/crepe/system/PhysicsSystem.h +++ b/src/crepe/system/PhysicsSystem.h @@ -1,5 +1,7 @@  #pragma once +#include "System.h" +  namespace crepe {  /** @@ -8,18 +10,15 @@ namespace crepe {   * This class is a physics system that uses a rigidbody and transform   * to add physics to a game object.   */ -class PhysicsSystem { +class PhysicsSystem : public System {  public: -	/** -	 * Constructor is default -	 */ -	PhysicsSystem() = default; +	using System::System;  	/**  	 * \brief updates the physics system.  	 *   	 * It calculates new velocties and changes the postion in the transform.  	 */ -	void update(); +	void update() override;  };  } // namespace crepe diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index 3ff5b4f..0d37808 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -11,15 +11,6 @@  using namespace crepe; -RenderSystem::RenderSystem() { dbg_trace(); } - -RenderSystem::~RenderSystem() { dbg_trace(); } - -RenderSystem & RenderSystem::get_instance() { -	static RenderSystem instance; -	return instance; -} -  void RenderSystem::clear_screen() const {  	SDLContext::get_instance().clear_screen();  } @@ -28,7 +19,7 @@ void RenderSystem::present_screen() const {  	SDLContext::get_instance().present_screen();  }  void RenderSystem::update_camera() { -	ComponentManager & mgr = ComponentManager::get_instance(); +	ComponentManager & mgr = this->component_manager;  	std::vector<std::reference_wrapper<Camera>> cameras  		= mgr.get_components_by_type<Camera>(); @@ -39,8 +30,7 @@ void RenderSystem::update_camera() {  	}  }  void RenderSystem::render_sprites() const { - -	ComponentManager & mgr = ComponentManager::get_instance(); +	ComponentManager & mgr = this->component_manager;  	std::vector<std::reference_wrapper<Sprite>> sprites  		= mgr.get_components_by_type<Sprite>(); diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h index 70db21a..da4e910 100644 --- a/src/crepe/system/RenderSystem.h +++ b/src/crepe/system/RenderSystem.h @@ -15,14 +15,8 @@ namespace crepe {   * rendering services for the application.   */  class RenderSystem : public System { -  public: -	/** -	 * \brief Gets the singleton instance of RenderSystem. -	 * \return Reference to the RenderSystem instance. -	 */ -	static RenderSystem & get_instance(); - +	using System::System;  	/**  	 * \brief Updates the RenderSystem for the current frame.  	 * This method is called to perform all rendering operations for the current game frame. @@ -30,10 +24,6 @@ public:  	void update() override;  private: -	// Private constructor to enforce singleton pattern. -	RenderSystem(); -	~RenderSystem(); -  	//! Clears the screen in preparation for rendering.  	void clear_screen() const; @@ -61,4 +51,5 @@ private:  	Camera * curr_cam = nullptr;  	// TODO: needs a better solution  }; +  } // namespace crepe diff --git a/src/crepe/system/ScriptSystem.cpp b/src/crepe/system/ScriptSystem.cpp index 807ad7f..7b22533 100644 --- a/src/crepe/system/ScriptSystem.cpp +++ b/src/crepe/system/ScriptSystem.cpp @@ -5,7 +5,6 @@  #include "../ComponentManager.h"  #include "../api/BehaviorScript.h"  #include "../api/Script.h" -#include "../util/Log.h"  #include "ScriptSystem.h" @@ -13,16 +12,24 @@ using namespace std;  using namespace crepe;  void ScriptSystem::update() { -	using namespace std;  	dbg_trace(); -	forward_list<Script *> scripts = this->get_scripts(); -	for (Script * script : scripts) script->update(); +	forward_list<reference_wrapper<Script>> scripts = this->get_scripts(); + +	for (auto & script_ref : scripts) { +		Script & script = script_ref.get(); +		BehaviorScript & component = *script.parent_ref; +		if (!component.initialized) { +			script.init(); +			component.initialized = true; +		} +		script.update(); +	}  } -forward_list<Script *> ScriptSystem::get_scripts() const { -	forward_list<Script *> scripts = {}; -	ComponentManager & mgr = ComponentManager::get_instance(); +forward_list<reference_wrapper<Script>> ScriptSystem::get_scripts() const { +	forward_list<reference_wrapper<Script>> scripts = {}; +	ComponentManager & mgr = this->component_manager;  	vector<reference_wrapper<BehaviorScript>> behavior_scripts  		= mgr.get_components_by_type<BehaviorScript>(); @@ -31,8 +38,9 @@ forward_list<Script *> ScriptSystem::get_scripts() const {  		if (!behavior_script.active) continue;  		Script * script = behavior_script.script.get();  		if (script == nullptr) continue; -		scripts.push_front(script); +		scripts.push_front(*script);  	}  	return scripts;  } + diff --git a/src/crepe/system/ScriptSystem.h b/src/crepe/system/ScriptSystem.h index 9d57640..deb89cb 100644 --- a/src/crepe/system/ScriptSystem.h +++ b/src/crepe/system/ScriptSystem.h @@ -16,6 +16,7 @@ class Script;   */  class ScriptSystem : public System {  public: +	using System::System;  	/**  	 * \brief Call Script::update() on all active \c BehaviorScript instances  	 * @@ -23,17 +24,16 @@ public:  	 * method. It also calls Script::init() if this has not been done before on  	 * the \c BehaviorScript instance.  	 */ -	void update(); +	void update() override;  private: -	// TODO: to forward_list<reference_wrapper>  	/**  	 * \brief Aggregate all active \c BehaviorScript components and return a list  	 * of references to their \c Script instances (utility)  	 *  	 * \returns List of active \c Script instances  	 */ -	std::forward_list<Script *> get_scripts() const; +	std::forward_list<std::reference_wrapper<Script>> get_scripts() const;  };  } // namespace crepe diff --git a/src/crepe/system/System.cpp b/src/crepe/system/System.cpp new file mode 100644 index 0000000..937a423 --- /dev/null +++ b/src/crepe/system/System.cpp @@ -0,0 +1,7 @@ +#include "../util/Log.h" + +#include "System.h" + +using namespace crepe; + +System::System(ComponentManager & mgr) : component_manager(mgr) { dbg_trace(); } diff --git a/src/crepe/system/System.h b/src/crepe/system/System.h index ec4507f..28ea20e 100644 --- a/src/crepe/system/System.h +++ b/src/crepe/system/System.h @@ -2,6 +2,8 @@  namespace crepe { +class ComponentManager; +  /**   * \brief Base ECS system class   * @@ -17,8 +19,11 @@ public:  	virtual void update() = 0;  public: -	System() = default; +	System(ComponentManager &);  	virtual ~System() = default; + +protected: +	ComponentManager & component_manager;  };  } // namespace crepe diff --git a/src/example/components_internal.cpp b/src/example/components_internal.cpp index f7e395b..7a8a08a 100644 --- a/src/example/components_internal.cpp +++ b/src/example/components_internal.cpp @@ -23,17 +23,16 @@ using namespace std;  int main() {  	dbg_trace(); -	auto & mgr = ComponentManager::get_instance(); +	ComponentManager mgr{};  	auto start_adding = chrono::high_resolution_clock::now();  	GameObject * game_object[OBJ_COUNT];  	for (int i = 0; i < OBJ_COUNT; ++i) { -		game_object[i] = new GameObject(i, "Name", "Tag", 0); - -		game_object[i]->add_component<Sprite>("test"); -		game_object[i]->add_component<Rigidbody>(0, 0, i); +		GameObject & obj = mgr.new_object("Name", "Tag"); +		obj.add_component<Sprite>("test"); +		obj.add_component<Rigidbody>(0, 0, i);  	}  	auto stop_adding = chrono::high_resolution_clock::now(); @@ -45,10 +44,6 @@ int main() {  	auto stop_looping = chrono::high_resolution_clock::now(); -	for (int i = 0; i < OBJ_COUNT; ++i) { -		delete game_object[i]; -	} -  	auto add_time = chrono::duration_cast<chrono::microseconds>(stop_adding  																- start_adding);  	auto loop_time = chrono::duration_cast<chrono::microseconds>(stop_looping diff --git a/src/example/ecs.cpp b/src/example/ecs.cpp index e61c398..9a008ea 100644 --- a/src/example/ecs.cpp +++ b/src/example/ecs.cpp @@ -9,13 +9,20 @@ using namespace crepe;  using namespace std;  int main() { +	ComponentManager mgr{}; +  	// Create a few GameObjects  	try { -		GameObject body(0, "body", "person", Vector2{0, 0}, 0, 1); -		GameObject right_leg(1, "rightLeg", "person", Vector2{1, 1}, 0, 1); -		GameObject left_leg(2, "leftLeg", "person", Vector2{1, 1}, 0, 1); -		GameObject right_foot(3, "rightFoot", "person", Vector2{2, 2}, 0, 1); -		GameObject left_foot(4, "leftFoot", "person", Vector2{2, 2}, 0, 1); +		GameObject & body +			= mgr.new_object("body", "person", Vector2{0, 0}, 0, 1); +		GameObject & right_leg +			= mgr.new_object("rightLeg", "person", Vector2{1, 1}, 0, 1); +		GameObject & left_leg +			= mgr.new_object("leftLeg", "person", Vector2{1, 1}, 0, 1); +		GameObject & right_foot +			= mgr.new_object("rightFoot", "person", Vector2{2, 2}, 0, 1); +		GameObject & left_foot +			= mgr.new_object("leftFoot", "person", Vector2{2, 2}, 0, 1);  		// Set the parent of each GameObject  		right_foot.set_parent(right_leg); @@ -30,7 +37,6 @@ int main() {  	}  	// Get the Metadata and Transform components of each GameObject -	ComponentManager & mgr = ComponentManager::get_instance();  	vector<reference_wrapper<Metadata>> metadata  		= mgr.get_components_by_type<Metadata>();  	vector<reference_wrapper<Transform>> transform diff --git a/src/example/physics.cpp b/src/example/physics.cpp index 848f857..2ebf779 100644 --- a/src/example/physics.cpp +++ b/src/example/physics.cpp @@ -9,9 +9,11 @@ using namespace crepe;  using namespace std;  int main(int argc, char * argv[]) { -	GameObject * game_object; -	game_object = new GameObject(0, "Name", "Tag", Vector2{0, 0}, 0, 0); -	game_object->add_component<Rigidbody>(Rigidbody::Data{ +	ComponentManager mgr{}; + +	GameObject & game_object +		= mgr.new_object("Name", "Tag", Vector2{0, 0}, 0, 0); +	game_object.add_component<Rigidbody>(Rigidbody::Data{  		.mass = 1,  		.gravity_scale = 1,  		.body_type = Rigidbody::BodyType::DYNAMIC, @@ -19,6 +21,5 @@ int main(int argc, char * argv[]) {  		.use_gravity = true,  		.bounce = false,  	}); -	delete game_object;  	return 0;  } diff --git a/src/example/rendering.cpp b/src/example/rendering.cpp index ae21f9a..74c00e2 100644 --- a/src/example/rendering.cpp +++ b/src/example/rendering.cpp @@ -20,9 +20,12 @@ using namespace crepe;  int main() {  	dbg_trace(); -	auto obj = GameObject(0, "name", "tag", Vector2{0, 0}, 1, 1); -	auto obj1 = GameObject(1, "name", "tag", Vector2{500, 0}, 1, 0.1); -	auto obj2 = GameObject(2, "name", "tag", Vector2{800, 0}, 1, 0.1); +	ComponentManager mgr{}; +	RenderSystem sys{mgr}; + +	auto & obj = mgr.new_object("name", "tag", Vector2{0, 0}, 1, 1); +	auto & obj1 = mgr.new_object("name", "tag", Vector2{500, 0}, 1, 0.1); +	auto & obj2 = mgr.new_object("name", "tag", Vector2{800, 0}, 1, 0.1);  	// Normal adding components  	{ @@ -34,7 +37,9 @@ int main() {  	}  	{  		Color color(0, 0, 0, 0); -		obj1.add_component<Sprite>(make_shared<Texture>("../asset/texture/second.png"), color, FlipSettings{true, true}); +		obj1.add_component<Sprite>( +			make_shared<Texture>("../asset/texture/second.png"), color, +			FlipSettings{true, true});  	}  	/* @@ -45,7 +50,6 @@ int main() {  	}  	*/ -	auto & sys = crepe::RenderSystem::get_instance();  	auto start = std::chrono::steady_clock::now();  	while (std::chrono::steady_clock::now() - start < std::chrono::seconds(5)) {  		sys.update(); diff --git a/src/example/scene_manager.cpp b/src/example/scene_manager.cpp index f46dc36..5cd7336 100644 --- a/src/example/scene_manager.cpp +++ b/src/example/scene_manager.cpp @@ -34,7 +34,8 @@ public:  };  int main() { -	SceneManager & scene_mgr = SceneManager::get_instance(); +	ComponentManager component_mgr{}; +	SceneManager scene_mgr{component_mgr};  	// Add the scenes to the scene manager  	scene_mgr.add_scene<ConcreteScene1>("scene1"); @@ -45,7 +46,6 @@ int main() {  	scene_mgr.load_next_scene();  	// Get the Metadata components of each GameObject of Scene1 -	ComponentManager & component_mgr = ComponentManager::get_instance();  	vector<reference_wrapper<Metadata>> metadata  		= component_mgr.get_components_by_type<Metadata>(); diff --git a/src/example/script.cpp b/src/example/script.cpp index d1388b5..c82764c 100644 --- a/src/example/script.cpp +++ b/src/example/script.cpp @@ -35,15 +35,15 @@ class MyScript : public Script {  };  int main() { +	ComponentManager component_manager{}; +	ScriptSystem system{component_manager}; +  	// Create game object with Transform and BehaviorScript components -	auto obj = GameObject(0, "name", "tag", Vector2{1.2, 3.4}, 0, 1); +	auto & obj = component_manager.new_object("name");  	obj.add_component<BehaviorScript>().set_script<MyScript>(); -	// Get ScriptSystem singleton instance (this would normally be done from the -	// game loop) -	ScriptSystem sys;  	// Update all scripts. This should result in MyScript::update being called -	sys.update(); +	system.update();  	return EXIT_SUCCESS;  } diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 0e4eaed..4dd5010 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -1,6 +1,6 @@  target_sources(test_main PUBLIC -	dummy.cpp -	# audio.cpp +	main.cpp  	PhysicsTest.cpp +	ScriptTest.cpp  ) diff --git a/src/test/PhysicsTest.cpp b/src/test/PhysicsTest.cpp index 5385962..9ac99aa 100644 --- a/src/test/PhysicsTest.cpp +++ b/src/test/PhysicsTest.cpp @@ -11,16 +11,17 @@ using namespace std::chrono_literals;  using namespace crepe;  class PhysicsTest : public ::testing::Test { -protected: -	GameObject * game_object; -	PhysicsSystem physics_system; +public: +	ComponentManager component_manager; +	PhysicsSystem system{component_manager}; +  	void SetUp() override { -		ComponentManager & mgr = ComponentManager::get_instance(); -		std::vector<std::reference_wrapper<Transform>> transforms +		ComponentManager & mgr = this->component_manager; +		vector<reference_wrapper<Transform>> transforms  			= mgr.get_components_by_id<Transform>(0);  		if (transforms.empty()) { -			game_object = new GameObject(0, "", "", Vector2{0, 0}, 0, 0); -			game_object->add_component<Rigidbody>(Rigidbody::Data{ +			auto & entity = mgr.new_object("", "", Vector2{0, 0}, 0, 0); +			entity.add_component<Rigidbody>(Rigidbody::Data{  				.mass = 1,  				.gravity_scale = 1,  				.body_type = Rigidbody::BodyType::DYNAMIC, @@ -36,7 +37,7 @@ protected:  		transform.position.x = 0.0;  		transform.position.y = 0.0;  		transform.rotation = 0.0; -		std::vector<std::reference_wrapper<Rigidbody>> rigidbodies +		vector<reference_wrapper<Rigidbody>> rigidbodies  			= mgr.get_components_by_id<Rigidbody>(0);  		Rigidbody & rigidbody = rigidbodies.front().get();  		rigidbody.data.angular_velocity = 0; @@ -47,34 +48,38 @@ protected:  TEST_F(PhysicsTest, gravity) {  	Config::get_instance().physics.gravity = 1; -	ComponentManager & mgr = ComponentManager::get_instance(); -	std::vector<std::reference_wrapper<Transform>> transforms +	ComponentManager & mgr = this->component_manager; +	vector<reference_wrapper<Transform>> transforms  		= mgr.get_components_by_id<Transform>(0);  	const Transform & transform = transforms.front().get();  	ASSERT_FALSE(transforms.empty());  	EXPECT_EQ(transform.position.y, 0); -	physics_system.update(); + +	system.update();  	EXPECT_EQ(transform.position.y, 1); -	physics_system.update(); + +	system.update();  	EXPECT_EQ(transform.position.y, 3);  }  TEST_F(PhysicsTest, max_velocity) { -	ComponentManager & mgr = ComponentManager::get_instance(); -	std::vector<std::reference_wrapper<Rigidbody>> rigidbodies +	ComponentManager & mgr = this->component_manager; +	vector<reference_wrapper<Rigidbody>> rigidbodies  		= mgr.get_components_by_id<Rigidbody>(0);  	Rigidbody & rigidbody = rigidbodies.front().get();  	ASSERT_FALSE(rigidbodies.empty());  	EXPECT_EQ(rigidbody.data.linear_velocity.y, 0); +  	rigidbody.add_force_linear({100, 100});  	rigidbody.add_force_angular(100); -	physics_system.update(); +	system.update();  	EXPECT_EQ(rigidbody.data.linear_velocity.y, 10);  	EXPECT_EQ(rigidbody.data.linear_velocity.x, 10);  	EXPECT_EQ(rigidbody.data.angular_velocity, 10); +  	rigidbody.add_force_linear({-100, -100});  	rigidbody.add_force_angular(-100); -	physics_system.update(); +	system.update();  	EXPECT_EQ(rigidbody.data.linear_velocity.y, -10);  	EXPECT_EQ(rigidbody.data.linear_velocity.x, -10);  	EXPECT_EQ(rigidbody.data.angular_velocity, -10); @@ -82,39 +87,44 @@ TEST_F(PhysicsTest, max_velocity) {  TEST_F(PhysicsTest, movement) {  	Config::get_instance().physics.gravity = 0; -	ComponentManager & mgr = ComponentManager::get_instance(); -	std::vector<std::reference_wrapper<Rigidbody>> rigidbodies +	ComponentManager & mgr = this->component_manager; +	vector<reference_wrapper<Rigidbody>> rigidbodies  		= mgr.get_components_by_id<Rigidbody>(0);  	Rigidbody & rigidbody = rigidbodies.front().get(); -	std::vector<std::reference_wrapper<Transform>> transforms +	vector<reference_wrapper<Transform>> transforms  		= mgr.get_components_by_id<Transform>(0);  	const Transform & transform = transforms.front().get();  	ASSERT_FALSE(rigidbodies.empty());  	ASSERT_FALSE(transforms.empty()); +  	rigidbody.add_force_linear({1, 1});  	rigidbody.add_force_angular(1); -	physics_system.update(); +	system.update();  	EXPECT_EQ(transform.position.x, 1);  	EXPECT_EQ(transform.position.y, 1);  	EXPECT_EQ(transform.rotation, 1); +  	rigidbody.data.constraints = {1, 1, 1};  	EXPECT_EQ(transform.position.x, 1);  	EXPECT_EQ(transform.position.y, 1);  	EXPECT_EQ(transform.rotation, 1); +  	rigidbody.data.linear_damping.x = 0.5;  	rigidbody.data.linear_damping.y = 0.5;  	rigidbody.data.angular_damping = 0.5; -	physics_system.update(); +	system.update();  	EXPECT_EQ(rigidbody.data.linear_velocity.x, 0.5);  	EXPECT_EQ(rigidbody.data.linear_velocity.y, 0.5);  	EXPECT_EQ(rigidbody.data.angular_velocity, 0.5); +  	rigidbody.data.constraints = {1, 1, 0};  	rigidbody.data.angular_damping = 0;  	rigidbody.data.max_angular_velocity = 1000;  	rigidbody.data.angular_velocity = 360; -	physics_system.update(); +	system.update();  	EXPECT_EQ(transform.rotation, 1); +  	rigidbody.data.angular_velocity = -360; -	physics_system.update(); +	system.update();  	EXPECT_EQ(transform.rotation, 1);  } diff --git a/src/test/ScriptTest.cpp b/src/test/ScriptTest.cpp new file mode 100644 index 0000000..bab9e52 --- /dev/null +++ b/src/test/ScriptTest.cpp @@ -0,0 +1,72 @@ +#include <gtest/gtest.h> + +// stupid hack to allow access to private/protected members under test +#define private public +#define protected public + +#include <crepe/ComponentManager.h> +#include <crepe/api/BehaviorScript.h> +#include <crepe/api/GameObject.h> +#include <crepe/api/Script.h> +#include <crepe/api/Vector2.h> +#include <crepe/system/ScriptSystem.h> + +using namespace std; +using namespace crepe; +using namespace testing; + +class ScriptTest : public Test { +public: +	ComponentManager component_manager{}; +	ScriptSystem system{component_manager}; + +	class MyScript : public Script { +		// NOTE: default (private) visibility of init and update shouldn't cause +		// issues! +		void init() { this->init_count++; } +		void update() { this->update_count++; } + +	public: +		unsigned init_count = 0; +		unsigned update_count = 0; +	}; + +	BehaviorScript * behaviorscript_ref = nullptr; +	MyScript * script_ref = nullptr; + +	void SetUp() override { +		auto & mgr = this->component_manager; +		GameObject & entity = mgr.new_object("name"); +		BehaviorScript & component = entity.add_component<BehaviorScript>(); + +		this->behaviorscript_ref = &component; +		EXPECT_EQ(this->behaviorscript_ref->script.get(), nullptr); +		component.set_script<MyScript>(); +		ASSERT_NE(this->behaviorscript_ref->script.get(), nullptr); + +		this->script_ref = (MyScript *) this->behaviorscript_ref->script.get(); +		ASSERT_NE(this->script_ref, nullptr); +	} +}; + +TEST_F(ScriptTest, Default) { +	EXPECT_EQ(0, this->script_ref->init_count); +	EXPECT_EQ(0, this->script_ref->update_count); +} + +TEST_F(ScriptTest, UpdateOnce) { +	EXPECT_EQ(0, this->script_ref->init_count); +	EXPECT_EQ(0, this->script_ref->update_count); + +	this->system.update(); +	EXPECT_EQ(1, this->script_ref->init_count); +	EXPECT_EQ(1, this->script_ref->update_count); +} + +TEST_F(ScriptTest, ListScripts) { +	size_t script_count = 0; +	for (auto & _ : this->system.get_scripts()) { +		script_count++; +	} +	ASSERT_EQ(1, script_count); +} diff --git a/src/test/audio.cpp b/src/test/audio.cpp deleted file mode 100644 index d6ff689..0000000 --- a/src/test/audio.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include <gtest/gtest.h> - -using namespace std; -using namespace std::chrono_literals; - -// using namespace crepe; - -// TODO: mock internal audio class - -TEST(audio, play) { ASSERT_TRUE(true); } diff --git a/src/test/dummy.cpp b/src/test/dummy.cpp deleted file mode 100644 index a00a9c6..0000000 --- a/src/test/dummy.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include <gtest/gtest.h> - -TEST(dummy, foo) { ASSERT_TRUE(1); } diff --git a/src/test/main.cpp b/src/test/main.cpp new file mode 100644 index 0000000..241015d --- /dev/null +++ b/src/test/main.cpp @@ -0,0 +1,15 @@ +#include <crepe/api/Config.h> + +#include <gtest/gtest.h> + +using namespace crepe; +using namespace testing; + +int main(int argc, char ** argv) { +	InitGoogleTest(&argc, argv); + +	auto & cfg = Config::get_instance(); +	cfg.log.level = Log::Level::ERROR; + +	return RUN_ALL_TESTS(); +} |