aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-11-12 22:43:32 +0100
committerLoek Le Blansch <loek@pipeframe.xyz>2024-11-12 22:43:32 +0100
commit3e94ecb3dac5003a3d58210ed1a4d1f1cb2083d1 (patch)
tree67c3e1c122652ae09e58e7de49db668e252c4730
parentf2509e89c02894ebd3ad992324eb300103621d26 (diff)
add script unit tests + major refactoring
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/crepe/Asset.cpp18
-rw-r--r--src/crepe/Asset.h2
-rw-r--r--src/crepe/Collider.cpp1
-rw-r--r--src/crepe/Collider.h2
-rw-r--r--src/crepe/Component.cpp4
-rw-r--r--src/crepe/Component.h21
-rw-r--r--src/crepe/ComponentManager.cpp16
-rw-r--r--src/crepe/ComponentManager.h27
-rw-r--r--src/crepe/ComponentManager.hpp5
-rw-r--r--src/crepe/Resource.h33
-rw-r--r--src/crepe/api/Animator.cpp4
-rw-r--r--src/crepe/api/Animator.h3
-rw-r--r--src/crepe/api/BehaviorScript.cpp4
-rw-r--r--src/crepe/api/BehaviorScript.h20
-rw-r--r--src/crepe/api/BehaviorScript.hpp4
-rw-r--r--src/crepe/api/CMakeLists.txt10
-rw-r--r--src/crepe/api/Camera.cpp7
-rw-r--r--src/crepe/api/Camera.h2
-rw-r--r--src/crepe/api/GameObject.cpp9
-rw-r--r--src/crepe/api/GameObject.h17
-rw-r--r--src/crepe/api/GameObject.hpp2
-rw-r--r--src/crepe/api/Metadata.cpp4
-rw-r--r--src/crepe/api/Metadata.h2
-rw-r--r--src/crepe/api/ParticleEmitter.cpp4
-rw-r--r--src/crepe/api/ParticleEmitter.h2
-rw-r--r--src/crepe/api/Rigidbody.cpp4
-rw-r--r--src/crepe/api/Rigidbody.h2
-rw-r--r--src/crepe/api/Script.cpp1
-rw-r--r--src/crepe/api/Script.h15
-rw-r--r--src/crepe/api/Script.hpp6
-rw-r--r--src/crepe/api/Sprite.cpp4
-rw-r--r--src/crepe/api/Sprite.h2
-rw-r--r--src/crepe/api/Transform.cpp4
-rw-r--r--src/crepe/api/Transform.h2
-rw-r--r--src/crepe/facade/Sound.cpp31
-rw-r--r--src/crepe/facade/Sound.h14
-rw-r--r--src/crepe/facade/SoundContext.cpp6
-rw-r--r--src/crepe/facade/SoundContext.h13
-rw-r--r--src/crepe/system/CMakeLists.txt19
-rw-r--r--src/crepe/system/ScriptSystem.cpp23
-rw-r--r--src/crepe/system/ScriptSystem.h5
-rw-r--r--src/crepe/system/System.cpp6
-rw-r--r--src/crepe/system/System.h7
-rw-r--r--src/test/CMakeLists.txt6
-rw-r--r--src/test/PhysicsTest.cpp4
-rw-r--r--src/test/ScriptTest.cpp73
-rw-r--r--src/test/audio.cpp10
-rw-r--r--src/test/dummy.cpp3
-rw-r--r--src/test/main.cpp15
50 files changed, 338 insertions, 161 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/Asset.cpp b/src/crepe/Asset.cpp
index 8a2a11c..3d4df53 100644
--- a/src/crepe/Asset.cpp
+++ b/src/crepe/Asset.cpp
@@ -1,16 +1,20 @@
#include <filesystem>
#include "Asset.h"
+#include "Exception.h"
using namespace crepe;
+using namespace std;
-Asset::Asset(const std::string & src) {
- // FIXME: restore this
- // this->src = std::filesystem::canonical(src);
- this->src = src;
- this->file = std::ifstream(this->src, std::ios::in | std::ios::binary);
+Asset::Asset(const string & src) : src(src) {
+ try {
+ this->src = filesystem::canonical(src);
+ } catch (filesystem::filesystem_error & e) {
+ throw Exception("Asset error: %s", e.what());
+ }
+ this->file = ifstream(this->src, ios::in | ios::binary);
}
-const std::istream & Asset::read() { return this->file; }
+const istream & Asset::read() { return this->file; }
-const char * Asset::canonical() { return this->src.c_str(); }
+const char * Asset::canonical() const { return this->src.c_str(); }
diff --git a/src/crepe/Asset.h b/src/crepe/Asset.h
index 0cb5834..d4e4ba1 100644
--- a/src/crepe/Asset.h
+++ b/src/crepe/Asset.h
@@ -23,7 +23,7 @@ public:
//! Get an input stream to the contents of this resource
const std::istream & read();
//! Get the canonical path to this resource
- const char * canonical();
+ const char * canonical() const;
private:
std::string src;
diff --git a/src/crepe/Collider.cpp b/src/crepe/Collider.cpp
index bbec488..b408609 100644
--- a/src/crepe/Collider.cpp
+++ b/src/crepe/Collider.cpp
@@ -2,4 +2,3 @@
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..c133739 100644
--- a/src/crepe/Component.cpp
+++ b/src/crepe/Component.cpp
@@ -1,6 +1,6 @@
#include "Component.h"
-#include "types.h"
using namespace crepe;
-Component::Component(game_object_id_t id) : game_object_id(id) {}
+Component::Component(const Data & data) : data(data) {}
+
diff --git a/src/crepe/Component.h b/src/crepe/Component.h
index 0fe60b2..c6d72df 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,13 +13,21 @@ class ComponentManager;
* interface for all components.
*/
class Component {
+public:
+ struct Data {
+ //! The ID of the GameObject this component belongs to
+ const game_object_id_t id;
+ //! The manager of this component
+ ComponentManager & component_manager;
+ };
+
protected:
- //! Only the ComponentManager can create components
- friend class crepe::ComponentManager;
/**
- * \param id The id of the GameObject this component belongs to
+ * \param base Data
*/
- Component(game_object_id_t id);
+ Component(const Data & base);
+ //! Only the ComponentManager can create components
+ friend class crepe::ComponentManager;
public:
virtual ~Component() = default;
@@ -37,8 +43,7 @@ public:
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;
+ Data data;
//! Whether the component is active
bool active = true;
};
diff --git a/src/crepe/ComponentManager.cpp b/src/crepe/ComponentManager.cpp
index 85149c8..f6acc1a 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,12 @@ 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..e37bc4a 100644
--- a/src/crepe/ComponentManager.h
+++ b/src/crepe/ComponentManager.h
@@ -1,15 +1,18 @@
#pragma once
-#include <cstdint>
#include <memory>
#include <typeindex>
#include <unordered_map>
#include <vector>
+#include <forward_list>
#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
+public:
/**
* \brief Add a component to the ComponentManager
*
@@ -100,8 +95,8 @@ 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 +113,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/ComponentManager.hpp b/src/crepe/ComponentManager.hpp
index 98efb49..89a8536 100644
--- a/src/crepe/ComponentManager.hpp
+++ b/src/crepe/ComponentManager.hpp
@@ -31,7 +31,10 @@ T & ComponentManager::add_component(game_object_id_t id, Args &&... args) {
// Create a new component of type T (arguments directly forwarded). The
// constructor must be called by ComponentManager.
- T * instance_ptr = new T(id, forward<Args>(args)...);
+ T * instance_ptr = new T(Component::Data {
+ .id = id,
+ .component_manager = *this,
+ }, forward<Args>(args)...);
if (instance_ptr == nullptr) throw std::bad_alloc();
T & instance_ref = *instance_ptr;
diff --git a/src/crepe/Resource.h b/src/crepe/Resource.h
new file mode 100644
index 0000000..dcf3dbd
--- /dev/null
+++ b/src/crepe/Resource.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <memory>
+
+namespace crepe {
+
+class ResourceManager;
+class Asset;
+
+/**
+ * Resource is an interface class used to represent a (deserialized) game
+ * resource (e.g. textures, sounds).
+ */
+class Resource {
+private:
+ /**
+ * \brief Prototype pattern clone function.
+ *
+ * \param src Source file of new resource (abstraction for file saved on
+ * disk)
+ *
+ * \returns New instance of concrete resource
+ */
+ virtual std::unique_ptr<Resource> clone(const Asset & src) const = 0;
+ /**
+ * The resource manager uses \c clone to create new instances of the concrete
+ * resource class. This may be used to inherit references to classes that
+ * would otherwise need to be implemented as singletons.
+ */
+ friend class ResourceManager;
+};
+
+} // namespace crepe
diff --git a/src/crepe/api/Animator.cpp b/src/crepe/api/Animator.cpp
index 58fee2a..ad60981 100644
--- a/src/crepe/api/Animator.cpp
+++ b/src/crepe/api/Animator.cpp
@@ -9,8 +9,8 @@
using namespace crepe;
-Animator::Animator(uint32_t id, Sprite & ss, int row, int col, int col_animator)
- : Component(id),
+Animator::Animator(const Component::Data & data, Sprite & ss, int row, int col, int col_animator)
+ : Component(data),
spritesheet(ss),
row(row),
col(col) {
diff --git a/src/crepe/api/Animator.h b/src/crepe/api/Animator.h
index def0240..f66dc1a 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(const Component::Data & data, Sprite & spritesheet, int row, int col,
int col_animate);
~Animator(); // dbg_trace
diff --git a/src/crepe/api/BehaviorScript.cpp b/src/crepe/api/BehaviorScript.cpp
index e69de29..ce1cfde 100644
--- a/src/crepe/api/BehaviorScript.cpp
+++ b/src/crepe/api/BehaviorScript.cpp
@@ -0,0 +1,4 @@
+#include "BehaviorScript.h"
+
+using namespace crepe;
+
diff --git a/src/crepe/api/BehaviorScript.h b/src/crepe/api/BehaviorScript.h
index 6b1fec7..8d21a72 100644
--- a/src/crepe/api/BehaviorScript.h
+++ b/src/crepe/api/BehaviorScript.h
@@ -12,19 +12,35 @@ class Script;
class BehaviorScript : public Component {
protected:
- friend class crepe::ComponentManager;
using Component::Component;
+ //! Only ComponentManager is allowed to instantiate BehaviorScript
+ friend class ComponentManager;
public:
virtual ~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;
std::unique_ptr<Script> script = nullptr;
+
+private:
+ //! Script accesses the component manager directly via its parent
+ // (BehaviorScript) reference
+ friend class Script;
};
} // namespace crepe
diff --git a/src/crepe/api/BehaviorScript.hpp b/src/crepe/api/BehaviorScript.hpp
index 4751607..bb5d829 100644
--- a/src/crepe/api/BehaviorScript.hpp
+++ b/src/crepe/api/BehaviorScript.hpp
@@ -11,10 +11,10 @@ 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;
this->script = std::unique_ptr<Script>(s);
return *this;
}
diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt
index 85696c4..d9cda57 100644
--- a/src/crepe/api/CMakeLists.txt
+++ b/src/crepe/api/CMakeLists.txt
@@ -14,11 +14,11 @@ target_sources(crepe PUBLIC
Config.cpp
Metadata.cpp
Scene.cpp
- SceneManager.cpp
+ # SceneManager.cpp
Vector2.cpp
Camera.cpp
Animator.cpp
- LoopManager.cpp
+ # LoopManager.cpp
LoopTimer.cpp
)
@@ -40,10 +40,10 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES
SaveManager.h
Scene.h
Metadata.h
- SceneManager.h
- SceneManager.hpp
+ # SceneManager.h
+ # SceneManager.hpp
Camera.h
Animator.h
- LoopManager.h
+ # LoopManager.h
LoopTimer.h
)
diff --git a/src/crepe/api/Camera.cpp b/src/crepe/api/Camera.cpp
index 6355a03..fece199 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,8 +6,8 @@
using namespace crepe;
-Camera::Camera(uint32_t id, const Color & bg_color)
- : Component(id),
+Camera::Camera(const Component::Data & data, const Color & bg_color)
+ : Component(data),
bg_color(bg_color) {
dbg_trace();
}
diff --git a/src/crepe/api/Camera.h b/src/crepe/api/Camera.h
index ba3a9ef..a52f2f7 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(const Component::Data & data, 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..bba1f26 100644
--- a/src/crepe/api/GameObject.cpp
+++ b/src/crepe/api/GameObject.cpp
@@ -6,18 +6,19 @@
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..d09938a 100644
--- a/src/crepe/api/GameObject.h
+++ b/src/crepe/api/GameObject.h
@@ -3,10 +3,11 @@
#include <string>
#include "types.h"
+#include "Vector2.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,11 @@ 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 +62,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/Metadata.cpp b/src/crepe/api/Metadata.cpp
index d421de5..6f0a280 100644
--- a/src/crepe/api/Metadata.cpp
+++ b/src/crepe/api/Metadata.cpp
@@ -3,7 +3,7 @@
using namespace crepe;
using namespace std;
-Metadata::Metadata(game_object_id_t id, const string & name, const string & tag)
- : Component(id),
+Metadata::Metadata(const Component::Data & data, const string & name, const string & tag)
+ : Component(data),
name(name),
tag(tag) {}
diff --git a/src/crepe/api/Metadata.h b/src/crepe/api/Metadata.h
index c61e006..8c91797 100644
--- a/src/crepe/api/Metadata.h
+++ b/src/crepe/api/Metadata.h
@@ -20,7 +20,7 @@ public:
* \param name The name of the GameObject
* \param tag The tag of the GameObject
*/
- Metadata(game_object_id_t id, const std::string & name,
+ Metadata(const Component::Data & data, const std::string & name,
const std::string & tag);
/**
* \brief Get the maximum number of instances for this component
diff --git a/src/crepe/api/ParticleEmitter.cpp b/src/crepe/api/ParticleEmitter.cpp
index 0bc2197..ed4fec8 100644
--- a/src/crepe/api/ParticleEmitter.cpp
+++ b/src/crepe/api/ParticleEmitter.cpp
@@ -6,12 +6,12 @@
using namespace crepe;
-ParticleEmitter::ParticleEmitter(game_object_id_t id, uint32_t max_particles,
+ParticleEmitter::ParticleEmitter(const Component::Data & data, uint32_t max_particles,
uint32_t emission_rate, uint32_t speed,
uint32_t speed_offset, uint32_t angle,
uint32_t angleOffset, float begin_lifespan,
float end_lifespan)
- : Component(id),
+ : Component(data),
max_particles(max_particles),
emission_rate(emission_rate),
speed(speed),
diff --git a/src/crepe/api/ParticleEmitter.h b/src/crepe/api/ParticleEmitter.h
index 5939723..ba89538 100644
--- a/src/crepe/api/ParticleEmitter.h
+++ b/src/crepe/api/ParticleEmitter.h
@@ -10,7 +10,7 @@ namespace crepe {
class ParticleEmitter : public Component {
public:
- ParticleEmitter(game_object_id_t id, uint32_t max_particles,
+ ParticleEmitter(const Component::Data & data, uint32_t max_particles,
uint32_t emission_rate, uint32_t speed,
uint32_t speed_offset, uint32_t angle, uint32_t angleOffset,
float begin_lifespan, float end_lifespan);
diff --git a/src/crepe/api/Rigidbody.cpp b/src/crepe/api/Rigidbody.cpp
index 3bf1c5b..be6bb93 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(const Component::Data & component_data, const Data & data)
+ : Component(component_data),
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..99837a6 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(const Component::Data & component_data, const Data & data);
//! struct to hold data of rigidbody
Data data;
diff --git a/src/crepe/api/Script.cpp b/src/crepe/api/Script.cpp
index 390cec7..0423315 100644
--- a/src/crepe/api/Script.cpp
+++ b/src/crepe/api/Script.cpp
@@ -1,3 +1,4 @@
#include "Script.h"
using namespace crepe;
+
diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h
index 49e625f..d543df8 100644
--- a/src/crepe/api/Script.h
+++ b/src/crepe/api/Script.h
@@ -11,6 +11,7 @@ namespace crepe {
class BehaviorScript;
class Script {
+ //! ScriptSystem calls \c update()
friend class crepe::ScriptSystem;
protected:
@@ -22,17 +23,25 @@ protected:
// added event.
protected:
+ //! Retrieve component from component manager (utility)
template <typename T>
T & get_component();
+ //! Retrieve components from component manager (utility)
template <typename T>
std::vector<std::reference_wrapper<T>> get_components();
-private:
- friend class crepe::BehaviorScript;
- BehaviorScript * parent = nullptr;
+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;
+ BehaviorScript * parent_ref = nullptr;
};
} // namespace crepe
#include "Script.hpp"
+
diff --git a/src/crepe/api/Script.hpp b/src/crepe/api/Script.hpp
index d96c0e8..68bcc29 100644
--- a/src/crepe/api/Script.hpp
+++ b/src/crepe/api/Script.hpp
@@ -18,8 +18,10 @@ T & Script::get_component() {
template <typename T>
std::vector<std::reference_wrapper<T>> Script::get_components() {
- ComponentManager & mgr = ComponentManager::get_instance();
- return mgr.get_components_by_id<T>(this->parent->game_object_id);
+ auto & parent = *this->parent_ref;
+ auto & mgr = parent.data.component_manager;
+
+ return mgr.get_components_by_id<T>(parent.data.id);
}
} // namespace crepe
diff --git a/src/crepe/api/Sprite.cpp b/src/crepe/api/Sprite.cpp
index 6f0433f..716609f 100644
--- a/src/crepe/api/Sprite.cpp
+++ b/src/crepe/api/Sprite.cpp
@@ -10,9 +10,9 @@
using namespace std;
using namespace crepe;
-Sprite::Sprite(game_object_id_t id, const shared_ptr<Texture> image,
+Sprite::Sprite(const Component::Data & data, const shared_ptr<Texture> image,
const Color & color, const FlipSettings & flip)
- : Component(id),
+ : Component(data),
color(color),
flip(flip),
sprite_image(image) {
diff --git a/src/crepe/api/Sprite.h b/src/crepe/api/Sprite.h
index deb3f93..171dfeb 100644
--- a/src/crepe/api/Sprite.h
+++ b/src/crepe/api/Sprite.h
@@ -43,7 +43,7 @@ public:
* \param color Color tint applied to the sprite.
* \param flip Flip settings for horizontal and vertical orientation.
*/
- Sprite(game_object_id_t id, const std::shared_ptr<Texture> image,
+ Sprite(const Component::Data & data, const std::shared_ptr<Texture> image,
const Color & color, const FlipSettings & flip);
/**
diff --git a/src/crepe/api/Transform.cpp b/src/crepe/api/Transform.cpp
index e401120..9645d03 100644
--- a/src/crepe/api/Transform.cpp
+++ b/src/crepe/api/Transform.cpp
@@ -4,9 +4,9 @@
using namespace crepe;
-Transform::Transform(game_object_id_t id, const Vector2 & point,
+Transform::Transform(const Component::Data & data, const Vector2 & point,
double rotation, double scale)
- : Component(id),
+ : Component(data),
position(point),
rotation(rotation),
scale(scale) {
diff --git a/src/crepe/api/Transform.h b/src/crepe/api/Transform.h
index 756e45b..a7bcd89 100644
--- a/src/crepe/api/Transform.h
+++ b/src/crepe/api/Transform.h
@@ -20,7 +20,7 @@ public:
* \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,
+ Transform(const Component::Data & data, const Vector2 & point, double rotation,
double scale);
/**
* \brief Get the maximum number of instances for this component
diff --git a/src/crepe/facade/Sound.cpp b/src/crepe/facade/Sound.cpp
index 648ec81..3a6e1e1 100644
--- a/src/crepe/facade/Sound.cpp
+++ b/src/crepe/facade/Sound.cpp
@@ -1,26 +1,24 @@
+#include <memory>
+
#include "../util/log.h"
+#include "../Asset.h"
#include "Sound.h"
#include "SoundContext.h"
using namespace crepe;
+using namespace std;
-Sound::Sound(std::unique_ptr<Asset> res) {
- dbg_trace();
- this->load(std::move(res));
-}
+Sound::Sound(SoundContext & ctx) : context(ctx) { dbg_trace(); }
-Sound::Sound(const char * src) {
- dbg_trace();
- this->load(std::make_unique<Asset>(src));
-}
-
-void Sound::load(std::unique_ptr<Asset> res) {
- this->sample.load(res->canonical());
+unique_ptr<Resource> Sound::clone(const Asset & src) const {
+ auto instance = make_unique<Sound>(*this);
+ instance->sample.load(src.canonical());
+ return instance;
}
void Sound::play() {
- SoundContext & ctx = SoundContext::get_instance();
+ SoundContext & ctx = this->context;
if (ctx.engine.getPause(this->handle)) {
// resume if paused
ctx.engine.setPause(this->handle, false);
@@ -32,13 +30,13 @@ void Sound::play() {
}
void Sound::pause() {
- SoundContext & ctx = SoundContext::get_instance();
+ SoundContext & ctx = this->context;
if (ctx.engine.getPause(this->handle)) return;
ctx.engine.setPause(this->handle, true);
}
void Sound::rewind() {
- SoundContext & ctx = SoundContext::get_instance();
+ SoundContext & ctx = this->context;
if (!ctx.engine.isValidVoiceHandle(this->handle)) return;
ctx.engine.seek(this->handle, 0);
}
@@ -46,7 +44,7 @@ void Sound::rewind() {
void Sound::set_volume(float volume) {
this->volume = volume;
- SoundContext & ctx = SoundContext::get_instance();
+ SoundContext & ctx = this->context;
if (!ctx.engine.isValidVoiceHandle(this->handle)) return;
ctx.engine.setVolume(this->handle, this->volume);
}
@@ -54,7 +52,8 @@ void Sound::set_volume(float volume) {
void Sound::set_looping(bool looping) {
this->looping = looping;
- SoundContext & ctx = SoundContext::get_instance();
+ SoundContext & ctx = this->context;
if (!ctx.engine.isValidVoiceHandle(this->handle)) return;
ctx.engine.setLooping(this->handle, this->looping);
}
+
diff --git a/src/crepe/facade/Sound.h b/src/crepe/facade/Sound.h
index 183bd7c..e5b2f19 100644
--- a/src/crepe/facade/Sound.h
+++ b/src/crepe/facade/Sound.h
@@ -4,11 +4,13 @@
#include <soloud/soloud.h>
#include <soloud/soloud_wav.h>
-#include "../Asset.h"
+#include "../Resource.h"
namespace crepe {
-class Sound {
+class SoundContext;
+
+class Sound : public Resource {
public:
/**
* \brief Pause this sample
@@ -64,15 +66,13 @@ public:
bool get_looping() const { return this->looping; }
public:
- Sound(const char * src);
- Sound(std::unique_ptr<Asset> res);
-
-private:
- void load(std::unique_ptr<Asset> res);
+ Sound(SoundContext & ctx);
+ std::unique_ptr<Resource> clone(const Asset & src) const override;
private:
SoLoud::Wav sample;
SoLoud::handle handle;
+ SoundContext & context;
float volume = 1.0f;
bool looping = false;
diff --git a/src/crepe/facade/SoundContext.cpp b/src/crepe/facade/SoundContext.cpp
index 5e5a3a9..c89fb03 100644
--- a/src/crepe/facade/SoundContext.cpp
+++ b/src/crepe/facade/SoundContext.cpp
@@ -4,11 +4,6 @@
using namespace crepe;
-SoundContext & SoundContext::get_instance() {
- static SoundContext instance;
- return instance;
-}
-
SoundContext::SoundContext() {
dbg_trace();
engine.init();
@@ -18,3 +13,4 @@ SoundContext::~SoundContext() {
dbg_trace();
engine.deinit();
}
+
diff --git a/src/crepe/facade/SoundContext.h b/src/crepe/facade/SoundContext.h
index d3123d2..c360fb8 100644
--- a/src/crepe/facade/SoundContext.h
+++ b/src/crepe/facade/SoundContext.h
@@ -7,19 +7,18 @@
namespace crepe {
class SoundContext {
-private:
+public:
SoundContext();
virtual ~SoundContext();
- // singleton
- static SoundContext & get_instance();
- SoundContext(const SoundContext &) = delete;
- SoundContext(SoundContext &&) = delete;
- SoundContext & operator=(const SoundContext &) = delete;
- SoundContext & operator=(SoundContext &&) = delete;
+ SoundContext(const SoundContext &) = delete;
+ SoundContext(SoundContext &&) = delete;
+ SoundContext & operator=(const SoundContext &) = delete;
+ SoundContext & operator=(SoundContext &&) = delete;
private:
SoLoud::Soloud engine;
+ //! Sound directly calls methods on \c engine
friend class Sound;
};
diff --git a/src/crepe/system/CMakeLists.txt b/src/crepe/system/CMakeLists.txt
index 4c18b87..9ee12f6 100644
--- a/src/crepe/system/CMakeLists.txt
+++ b/src/crepe/system/CMakeLists.txt
@@ -1,17 +1,18 @@
target_sources(crepe PUBLIC
- ParticleSystem.cpp
+ System.cpp
+ # ParticleSystem.cpp
ScriptSystem.cpp
- PhysicsSystem.cpp
- CollisionSystem.cpp
- RenderSystem.cpp
- AnimatorSystem.cpp
+ # PhysicsSystem.cpp
+ # CollisionSystem.cpp
+ # RenderSystem.cpp
+ # AnimatorSystem.cpp
)
target_sources(crepe PUBLIC FILE_SET HEADERS FILES
System.h
ScriptSystem.h
- PhysicsSystem.h
- CollisionSystem.h
- RenderSystem.h
- AnimatorSystem.h
+ # PhysicsSystem.h
+ # CollisionSystem.h
+ # RenderSystem.h
+ # AnimatorSystem.h
)
diff --git a/src/crepe/system/ScriptSystem.cpp b/src/crepe/system/ScriptSystem.cpp
index f2673e7..0a87fcc 100644
--- a/src/crepe/system/ScriptSystem.cpp
+++ b/src/crepe/system/ScriptSystem.cpp
@@ -13,16 +13,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() {
- forward_list<Script *> scripts = {};
- ComponentManager & mgr = ComponentManager::get_instance();
+forward_list<reference_wrapper<Script>> ScriptSystem::get_scripts() {
+ 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 +39,9 @@ forward_list<Script *> ScriptSystem::get_scripts() {
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 4fa6141..b52e825 100644
--- a/src/crepe/system/ScriptSystem.h
+++ b/src/crepe/system/ScriptSystem.h
@@ -7,14 +7,15 @@
namespace crepe {
class Script;
+class BehaviorScript;
class ScriptSystem : public System {
public:
+ using System::System;
void update();
private:
- // TODO: to forward_list<reference_wrapper>
- std::forward_list<Script *> get_scripts();
+ std::forward_list<std::reference_wrapper<Script>> get_scripts();
};
} // namespace crepe
diff --git a/src/crepe/system/System.cpp b/src/crepe/system/System.cpp
new file mode 100644
index 0000000..296f1ed
--- /dev/null
+++ b/src/crepe/system/System.cpp
@@ -0,0 +1,6 @@
+#include "System.h"
+
+using namespace crepe;
+
+System::System(ComponentManager & mgr) : component_manager(mgr) {}
+
diff --git a/src/crepe/system/System.h b/src/crepe/system/System.h
index 3b81bef..7970e72 100644
--- a/src/crepe/system/System.h
+++ b/src/crepe/system/System.h
@@ -2,13 +2,18 @@
namespace crepe {
+class ComponentManager;
+
class System {
public:
virtual void update() = 0;
public:
- System() = default;
+ System(ComponentManager &);
virtual ~System() = default;
+
+protected:
+ ComponentManager & component_manager;
};
} // namespace crepe
diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt
index 0e4eaed..9d303bc 100644
--- a/src/test/CMakeLists.txt
+++ b/src/test/CMakeLists.txt
@@ -1,6 +1,6 @@
target_sources(test_main PUBLIC
- dummy.cpp
- # audio.cpp
- PhysicsTest.cpp
+ main.cpp
+ # PhysicsTest.cpp
+ ScriptTest.cpp
)
diff --git a/src/test/PhysicsTest.cpp b/src/test/PhysicsTest.cpp
index 5385962..538d244 100644
--- a/src/test/PhysicsTest.cpp
+++ b/src/test/PhysicsTest.cpp
@@ -11,9 +11,11 @@ using namespace std::chrono_literals;
using namespace crepe;
class PhysicsTest : public ::testing::Test {
-protected:
+public:
GameObject * game_object;
+ ComponentManager component_manager;
PhysicsSystem physics_system;
+
void SetUp() override {
ComponentManager & mgr = ComponentManager::get_instance();
std::vector<std::reference_wrapper<Transform>> transforms
diff --git a/src/test/ScriptTest.cpp b/src/test/ScriptTest.cpp
new file mode 100644
index 0000000..ea49a35
--- /dev/null
+++ b/src/test/ScriptTest.cpp
@@ -0,0 +1,73 @@
+#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/system/ScriptSystem.h>
+#include <crepe/api/BehaviorScript.h>
+#include <crepe/api/Script.h>
+#include <crepe/api/GameObject.h>
+#include <crepe/api/Vector2.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..6830a01
--- /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 = LogLevel::ERROR;
+
+ return RUN_ALL_TESTS();
+}