aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-11-13 16:26:38 +0100
committerLoek Le Blansch <loek@pipeframe.xyz>2024-11-13 16:26:38 +0100
commitb63f4700f7bda696afb14cc3111be0f8b0eed458 (patch)
tree08c4b00b249a4fa672d97a5bc79927adac0a0257
parent2933655dea64f11f200f42fe51e58dacc5f160eb (diff)
parent9e87a556a5f68c5f9bb04bef9a66880536ccd6e8 (diff)
merge `loek/tests` into `loek/cleanup` (close #32)
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/crepe/Collider.cpp2
-rw-r--r--src/crepe/Collider.h2
-rw-r--r--src/crepe/Component.cpp1
-rw-r--r--src/crepe/Component.h19
-rw-r--r--src/crepe/ComponentManager.cpp19
-rw-r--r--src/crepe/ComponentManager.h35
-rw-r--r--src/crepe/api/Animator.cpp3
-rw-r--r--src/crepe/api/Animator.h3
-rw-r--r--src/crepe/api/AssetManager.h3
-rw-r--r--src/crepe/api/BehaviorScript.cpp15
-rw-r--r--src/crepe/api/BehaviorScript.h37
-rw-r--r--src/crepe/api/BehaviorScript.hpp5
-rw-r--r--src/crepe/api/Camera.cpp5
-rw-r--r--src/crepe/api/Camera.h2
-rw-r--r--src/crepe/api/GameObject.cpp12
-rw-r--r--src/crepe/api/GameObject.h19
-rw-r--r--src/crepe/api/GameObject.hpp2
-rw-r--r--src/crepe/api/LoopManager.cpp24
-rw-r--r--src/crepe/api/LoopManager.h28
-rw-r--r--src/crepe/api/LoopManager.hpp40
-rw-r--r--src/crepe/api/Rigidbody.cpp4
-rw-r--r--src/crepe/api/Rigidbody.h2
-rw-r--r--src/crepe/api/SceneManager.cpp7
-rw-r--r--src/crepe/api/SceneManager.h16
-rw-r--r--src/crepe/api/Script.h16
-rw-r--r--src/crepe/api/Script.hpp6
-rw-r--r--src/crepe/api/Transform.h28
-rw-r--r--src/crepe/api/Vector2.cpp16
-rw-r--r--src/crepe/api/Vector2.h15
-rw-r--r--src/crepe/facade/SDLContext.cpp2
-rw-r--r--src/crepe/system/AnimatorSystem.cpp12
-rw-r--r--src/crepe/system/AnimatorSystem.h17
-rw-r--r--src/crepe/system/CMakeLists.txt1
-rw-r--r--src/crepe/system/CollisionSystem.cpp2
-rw-r--r--src/crepe/system/CollisionSystem.h8
-rw-r--r--src/crepe/system/ParticleSystem.cpp4
-rw-r--r--src/crepe/system/ParticleSystem.h15
-rw-r--r--src/crepe/system/PhysicsSystem.cpp2
-rw-r--r--src/crepe/system/PhysicsSystem.h11
-rw-r--r--src/crepe/system/RenderSystem.cpp14
-rw-r--r--src/crepe/system/RenderSystem.h13
-rw-r--r--src/crepe/system/ScriptSystem.cpp24
-rw-r--r--src/crepe/system/ScriptSystem.h6
-rw-r--r--src/crepe/system/System.cpp7
-rw-r--r--src/crepe/system/System.h7
-rw-r--r--src/example/components_internal.cpp13
-rw-r--r--src/example/ecs.cpp18
-rw-r--r--src/example/physics.cpp9
-rw-r--r--src/example/rendering.cpp14
-rw-r--r--src/example/scene_manager.cpp4
-rw-r--r--src/example/script.cpp10
-rw-r--r--src/test/CMakeLists.txt4
-rw-r--r--src/test/PhysicsTest.cpp56
-rw-r--r--src/test/ScriptTest.cpp72
-rw-r--r--src/test/audio.cpp10
-rw-r--r--src/test/dummy.cpp3
-rw-r--r--src/test/main.cpp15
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();
+}