aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contributing.md24
-rw-r--r--src/crepe/ComponentManager.cpp3
-rw-r--r--src/crepe/ComponentManager.h4
-rw-r--r--src/crepe/Particle.cpp2
-rw-r--r--src/crepe/Particle.h11
-rw-r--r--src/crepe/api/CMakeLists.txt3
-rw-r--r--src/crepe/api/Config.h13
-rw-r--r--src/crepe/api/EventHandler.hpp2
-rw-r--r--src/crepe/api/GameObject.cpp2
-rw-r--r--src/crepe/api/GameObject.h3
-rw-r--r--src/crepe/api/LoopManager.cpp2
-rw-r--r--src/crepe/api/LoopTimer.cpp2
-rw-r--r--src/crepe/api/LoopTimer.h4
-rw-r--r--src/crepe/api/ParticleEmitter.h8
-rw-r--r--src/crepe/api/Rigidbody.cpp2
-rw-r--r--src/crepe/api/Rigidbody.h10
-rw-r--r--src/crepe/api/Scene.cpp5
-rw-r--r--src/crepe/api/Scene.h23
-rw-r--r--src/crepe/api/SceneManager.h4
-rw-r--r--src/crepe/api/SceneManager.hpp12
-rw-r--r--src/crepe/api/Script.h7
-rw-r--r--src/crepe/api/Texture.cpp13
-rw-r--r--src/crepe/api/Texture.h12
-rw-r--r--src/crepe/api/Transform.cpp2
-rw-r--r--src/crepe/api/Transform.h7
-rw-r--r--src/crepe/api/Vector2.cpp33
-rw-r--r--src/crepe/api/Vector2.h55
-rw-r--r--src/crepe/api/Vector2.hpp118
-rw-r--r--src/crepe/facade/SDLContext.cpp11
-rw-r--r--src/crepe/facade/SDLContext.h7
-rw-r--r--src/crepe/system/ParticleSystem.cpp19
-rw-r--r--src/crepe/system/PhysicsSystem.cpp2
-rw-r--r--src/crepe/types.h14
-rw-r--r--src/doc/feature/scene.dox10
-rw-r--r--src/doc/internal/component.dox41
-rw-r--r--src/doc/internal/resource.dox12
-rw-r--r--src/doc/internal/style.dox9
-rw-r--r--src/doc/internal/system.dox26
-rw-r--r--src/doc/internals.dox10
-rw-r--r--src/doc/layout.xml21
-rw-r--r--src/doc/style.css2
-rw-r--r--src/example/rendering_particle.cpp11
-rw-r--r--src/test/AssetTest.cpp13
-rw-r--r--src/test/CMakeLists.txt2
-rw-r--r--src/test/ECSTest.cpp36
-rw-r--r--src/test/ParticleTest.cpp10
-rw-r--r--src/test/PhysicsTest.cpp4
-rw-r--r--src/test/RenderSystemTest.cpp8
-rw-r--r--src/test/SceneManagerTest.cpp60
-rw-r--r--src/test/Vector2Test.cpp384
-rw-r--r--src/test/main.cpp23
51 files changed, 900 insertions, 221 deletions
diff --git a/contributing.md b/contributing.md
index 77a2908..0a90e86 100644
--- a/contributing.md
+++ b/contributing.md
@@ -17,6 +17,7 @@ that you can click on to open them.
working/compiling version of the project
- Pull requests for new code include either automated tests for the new code or
an explanation as to why the code can not (reliably) be tested
+
<!--
- TODO: tagging / versions
-->
@@ -495,6 +496,12 @@ that you can click on to open them.
</td></tr></table></details>
- <details><summary>
Ensure const-correctness
+
+ > [!IMPORTANT]
+ > C-style APIs that work on (possibly internal) references to structs can be
+ > called from const member functions in C++. If the compiler allows you to
+ > mark a function as `const` even though it has side effects, it should
+ > **not** be marked as `const`.
</summary><table><tr><th>Good</th><th>Bad</th></tr><tr><td>
```cpp
@@ -795,6 +802,23 @@ that you can click on to open them.
```
</td></tr></table></details>
- Do not implement new classes as singletons
+- <details><summary>
+ Retrieving the first or last indices for iterators with a known or expected
+ size should be done using <code>.front()</code> or <code>.back()</code>
+ instead of by index
+ </summary><table><tr><th>Good</th><th>Bad</th></tr><tr><td>
+
+ ```cpp
+ vector<int> foo = { 1, 2, 3 };
+ int bar = foo.first();
+ ```
+ </td><td>
+
+ ```cpp
+ vector<int> foo = { 1, 2, 3 };
+ int bar = foo[0];
+ ```
+ </td></tr></table></details>
## CMakeLists-specific
diff --git a/src/crepe/ComponentManager.cpp b/src/crepe/ComponentManager.cpp
index e310577..e4de027 100644
--- a/src/crepe/ComponentManager.cpp
+++ b/src/crepe/ComponentManager.cpp
@@ -26,8 +26,7 @@ void ComponentManager::delete_all_components() {
}
GameObject ComponentManager::new_object(const string & name, const string & tag,
- const Vector2 & position, double rotation,
- double scale) {
+ const vec2 & position, double rotation, double scale) {
GameObject object{*this, this->next_id, name, tag, position, rotation, scale};
this->next_id++;
return object;
diff --git a/src/crepe/ComponentManager.h b/src/crepe/ComponentManager.h
index 0956d1e..1cb0b5f 100644
--- a/src/crepe/ComponentManager.h
+++ b/src/crepe/ComponentManager.h
@@ -5,8 +5,6 @@
#include <unordered_map>
#include <vector>
-#include "api/Vector2.h"
-
#include "Component.h"
#include "types.h"
@@ -45,7 +43,7 @@ public:
* \note This method automatically assigns a new entity ID
*/
GameObject new_object(const std::string & name, const std::string & tag = "",
- const Vector2 & position = {0, 0}, double rotation = 0,
+ const vec2 & position = {0, 0}, double rotation = 0,
double scale = 1);
protected:
diff --git a/src/crepe/Particle.cpp b/src/crepe/Particle.cpp
index 1068cbf..485a0d4 100644
--- a/src/crepe/Particle.cpp
+++ b/src/crepe/Particle.cpp
@@ -2,7 +2,7 @@
using namespace crepe;
-void Particle::reset(uint32_t lifespan, const Vector2 & position, const Vector2 & velocity,
+void Particle::reset(uint32_t lifespan, const vec2 & position, const vec2 & velocity,
double angle) {
// Initialize the particle state
this->time_in_life = 0;
diff --git a/src/crepe/Particle.h b/src/crepe/Particle.h
index 19859fe..d0397c9 100644
--- a/src/crepe/Particle.h
+++ b/src/crepe/Particle.h
@@ -2,7 +2,7 @@
#include <cstdint>
-#include "api/Vector2.h"
+#include "types.h"
namespace crepe {
@@ -18,11 +18,11 @@ class Particle {
public:
//! Position of the particle in 2D space.
- Vector2 position;
+ vec2 position;
//! Velocity vector indicating the speed and direction of the particle.
- Vector2 velocity;
+ vec2 velocity;
//! Accumulated force affecting the particle over time.
- Vector2 force_over_time;
+ vec2 force_over_time;
//! Total lifespan of the particle in milliseconds.
uint32_t lifespan;
//! Active state of the particle; true if it is in use, false otherwise.
@@ -43,8 +43,7 @@ public:
* \param velocity The initial velocity of the particle.
* \param angle The angle of the particle's trajectory or orientation.
*/
- void reset(uint32_t lifespan, const Vector2 & position, const Vector2 & velocity,
- double angle);
+ void reset(uint32_t lifespan, const vec2 & position, const vec2 & velocity, double angle);
/**
* \brief Updates the particle's state.
*
diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt
index 602ab52..50c51ed 100644
--- a/src/crepe/api/CMakeLists.txt
+++ b/src/crepe/api/CMakeLists.txt
@@ -12,9 +12,7 @@ target_sources(crepe PUBLIC
SaveManager.cpp
Config.cpp
Metadata.cpp
- Scene.cpp
SceneManager.cpp
- Vector2.cpp
Camera.cpp
Animator.cpp
EventManager.cpp
@@ -38,6 +36,7 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES
Rigidbody.h
Sprite.h
Vector2.h
+ Vector2.hpp
Color.h
Texture.h
AssetManager.h
diff --git a/src/crepe/api/Config.h b/src/crepe/api/Config.h
index 13eabd1..0c9d116 100644
--- a/src/crepe/api/Config.h
+++ b/src/crepe/api/Config.h
@@ -11,19 +11,18 @@ namespace crepe {
* modified *before* execution is handed over from the game programmer to the engine (i.e. the
* main loop is started).
*/
-class Config {
+class Config final {
public:
//! Retrieve handle to global Config instance
static Config & get_instance();
private:
Config() = default;
-
- // singleton
- Config(const Config &) = delete;
- Config(Config &&) = delete;
- Config & operator=(const Config &) = delete;
- Config & operator=(Config &&) = delete;
+ ~Config() = default;
+ Config(const Config &) = default;
+ Config(Config &&) = default;
+ Config & operator=(const Config &) = default;
+ Config & operator=(Config &&) = default;
public:
//! Logging-related settings
diff --git a/src/crepe/api/EventHandler.hpp b/src/crepe/api/EventHandler.hpp
index 391dcca..050e57e 100644
--- a/src/crepe/api/EventHandler.hpp
+++ b/src/crepe/api/EventHandler.hpp
@@ -1,3 +1,5 @@
+#pragma once
+
#include <typeindex>
#include "EventHandler.h"
diff --git a/src/crepe/api/GameObject.cpp b/src/crepe/api/GameObject.cpp
index 4874426..3c36a21 100644
--- a/src/crepe/api/GameObject.cpp
+++ b/src/crepe/api/GameObject.cpp
@@ -9,7 +9,7 @@ using namespace std;
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)
+ const vec2 & position, double rotation, double scale)
: id(id),
component_manager(component_manager) {
diff --git a/src/crepe/api/GameObject.h b/src/crepe/api/GameObject.h
index 34ef8bb..fcb8d9a 100644
--- a/src/crepe/api/GameObject.h
+++ b/src/crepe/api/GameObject.h
@@ -2,7 +2,6 @@
#include <string>
-#include "Vector2.h"
#include "types.h"
namespace crepe {
@@ -30,7 +29,7 @@ private:
* \param scale The scale of the GameObject
*/
GameObject(ComponentManager & component_manager, game_object_id_t id,
- const std::string & name, const std::string & tag, const Vector2 & position,
+ const std::string & name, const std::string & tag, const vec2 & position,
double rotation, double scale);
//! ComponentManager instances GameObject
friend class ComponentManager;
diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp
index a64366f..7edf4d1 100644
--- a/src/crepe/api/LoopManager.cpp
+++ b/src/crepe/api/LoopManager.cpp
@@ -57,7 +57,7 @@ void LoopManager::loop() {
void LoopManager::setup() {
this->game_running = true;
LoopTimer::get_instance().start();
- LoopTimer::get_instance().set_fps(60);
+ LoopTimer::get_instance().set_fps(200);
}
void LoopManager::render() {
diff --git a/src/crepe/api/LoopTimer.cpp b/src/crepe/api/LoopTimer.cpp
index a9800b7..15a0e3a 100644
--- a/src/crepe/api/LoopTimer.cpp
+++ b/src/crepe/api/LoopTimer.cpp
@@ -47,7 +47,7 @@ double LoopTimer::get_fixed_delta_time() const { return this->fixed_delta_time.c
void LoopTimer::set_fps(int fps) {
this->fps = fps;
// target time per frame in seconds
- this->frame_target_time = std::chrono::seconds(1) / fps;
+ this->frame_target_time = std::chrono::duration<double>(1.0) / fps;
}
int LoopTimer::get_fps() const { return this->fps; }
diff --git a/src/crepe/api/LoopTimer.h b/src/crepe/api/LoopTimer.h
index f277d7b..9393439 100644
--- a/src/crepe/api/LoopTimer.h
+++ b/src/crepe/api/LoopTimer.h
@@ -130,9 +130,9 @@ private:
//! Delta time for the current frame in seconds
std::chrono::duration<double> delta_time{0.0};
//! Target time per frame in seconds
- std::chrono::duration<double> frame_target_time = std::chrono::seconds(1) / fps;
+ std::chrono::duration<double> frame_target_time = std::chrono::duration<double>(1.0) / fps;
//! Fixed delta time for fixed updates in seconds
- std::chrono::duration<double> fixed_delta_time = std::chrono::seconds(1) / 50;
+ std::chrono::duration<double> fixed_delta_time = std::chrono::duration<double>(1.0) / 50.0;
//! Total elapsed game time in seconds
std::chrono::duration<double> elapsed_time{0.0};
//! Total elapsed time for fixed updates in seconds
diff --git a/src/crepe/api/ParticleEmitter.h b/src/crepe/api/ParticleEmitter.h
index 33112e1..b83fd61 100644
--- a/src/crepe/api/ParticleEmitter.h
+++ b/src/crepe/api/ParticleEmitter.h
@@ -4,7 +4,7 @@
#include "Component.h"
#include "Particle.h"
-#include "Vector2.h"
+#include "types.h"
namespace crepe {
@@ -30,7 +30,7 @@ public:
//! boundary height (midpoint is emitter location)
double height = 0.0;
//! boundary offset from particle emitter location
- Vector2 offset;
+ vec2 offset;
//! reset on exit or stop velocity and set max postion
bool reset_on_exit = false;
};
@@ -43,7 +43,7 @@ public:
*/
struct Data {
//! position of the emitter
- Vector2 position;
+ vec2 position;
//! maximum number of particles
const unsigned int max_particles = 0;
//! rate of particle emission per update (Lowest value = 0.001 any lower is ignored)
@@ -61,7 +61,7 @@ public:
//! end Lifespan of particle
double end_lifespan = 0.0;
//! force over time (physics)
- Vector2 force_over_time;
+ vec2 force_over_time;
//! particle boundary
Boundary boundary;
//! collection of particles
diff --git a/src/crepe/api/Rigidbody.cpp b/src/crepe/api/Rigidbody.cpp
index 6b87695..576ca45 100644
--- a/src/crepe/api/Rigidbody.cpp
+++ b/src/crepe/api/Rigidbody.cpp
@@ -6,7 +6,7 @@ crepe::Rigidbody::Rigidbody(game_object_id_t id, const Data & data)
: Component(id),
data(data) {}
-void crepe::Rigidbody::add_force_linear(const Vector2 & force) {
+void crepe::Rigidbody::add_force_linear(const vec2 & force) {
this->data.linear_velocity += force;
}
diff --git a/src/crepe/api/Rigidbody.h b/src/crepe/api/Rigidbody.h
index 3e5c7a3..3b0588f 100644
--- a/src/crepe/api/Rigidbody.h
+++ b/src/crepe/api/Rigidbody.h
@@ -2,7 +2,7 @@
#include "../Component.h"
-#include "Vector2.h"
+#include "types.h"
namespace crepe {
@@ -56,11 +56,11 @@ public:
//! Changes if physics apply
BodyType body_type = BodyType::DYNAMIC;
//! linear velocity of object
- Vector2 linear_velocity;
+ vec2 linear_velocity;
//! maximum linear velocity of object
- Vector2 max_linear_velocity;
+ vec2 max_linear_velocity;
//! linear damping of object
- Vector2 linear_damping;
+ vec2 linear_damping;
//! angular velocity of object
double angular_velocity = 0.0;
//! max angular velocity of object
@@ -90,7 +90,7 @@ public:
*
* \param force Vector2 that is added to the linear force.
*/
- void add_force_linear(const Vector2 & force);
+ void add_force_linear(const vec2 & force);
/**
* \brief add a angular force to the Rigidbody.
*
diff --git a/src/crepe/api/Scene.cpp b/src/crepe/api/Scene.cpp
deleted file mode 100644
index 849945e..0000000
--- a/src/crepe/api/Scene.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-#include "Scene.h"
-
-using namespace crepe;
-
-Scene::Scene(ComponentManager & mgr) : component_manager(mgr) {}
diff --git a/src/crepe/api/Scene.h b/src/crepe/api/Scene.h
index 869bf6f..f6fdb2a 100644
--- a/src/crepe/api/Scene.h
+++ b/src/crepe/api/Scene.h
@@ -2,6 +2,8 @@
#include <string>
+#include "../util/OptionalRef.h"
+
namespace crepe {
class SceneManager;
@@ -15,11 +17,8 @@ class ComponentManager;
*/
class Scene {
protected:
- //TODO: Use Loek's custom reference class to set ComponentManger via SceneManager instead of via constructor
- /**
- * \param mgr Reference to the ComponentManager
- */
- Scene(ComponentManager & mgr);
+ // NOTE: This must be the only constructor on Scene, see "Late references" below
+ Scene() = default;
//! SceneManager instances Scene
friend class SceneManager;
@@ -36,8 +35,20 @@ public:
virtual std::string get_name() const = 0;
protected:
+ /**
+ * \name Late references
+ *
+ * These references are set by SceneManager immediately after calling the constructor of Scene.
+ *
+ * \note Scene must have a constructor without arguments so the game programmer doesn't need to
+ * manually add `using Scene::Scene` to their concrete scene class, if they want to add a
+ * constructor with arguments (e.g. for passing references to their own concrete Scene classes).
+ *
+ * \{
+ */
//! Reference to the ComponentManager
- ComponentManager & component_manager;
+ OptionalRef<ComponentManager> component_manager;
+ //! \}
};
} // namespace crepe
diff --git a/src/crepe/api/SceneManager.h b/src/crepe/api/SceneManager.h
index 45ba668..f6f62cd 100644
--- a/src/crepe/api/SceneManager.h
+++ b/src/crepe/api/SceneManager.h
@@ -26,8 +26,8 @@ public:
*
* \tparam T Type of concrete scene
*/
- template <typename T>
- void add_scene();
+ template <typename T, typename... Args>
+ void add_scene(Args &&... args);
/**
* \brief Set the next scene
*
diff --git a/src/crepe/api/SceneManager.hpp b/src/crepe/api/SceneManager.hpp
index 94e5946..5c8e417 100644
--- a/src/crepe/api/SceneManager.hpp
+++ b/src/crepe/api/SceneManager.hpp
@@ -4,13 +4,17 @@
namespace crepe {
-template <typename T>
-void SceneManager::add_scene() {
+template <typename T, typename... Args>
+void SceneManager::add_scene(Args &&... args) {
using namespace std;
static_assert(is_base_of<Scene, T>::value, "T must be derived from Scene");
- Scene * scene = new T(this->component_manager);
- this->scenes.emplace_back(unique_ptr<Scene>(scene));
+ Scene * scene = new T(std::forward<Args>(args)...);
+ unique_ptr<Scene> unique_scene(scene);
+
+ unique_scene->component_manager = this->component_manager;
+
+ this->scenes.emplace_back(std::move(unique_scene));
// The first scene added, is the one that will be loaded at the beginning
if (next_scene.empty()) {
diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h
index f0b9c73..a0870cb 100644
--- a/src/crepe/api/Script.h
+++ b/src/crepe/api/Script.h
@@ -22,6 +22,10 @@ class ComponentManager;
* \info Additional *events* (like Unity's OnDisable and OnEnable) should be implemented as
* member or lambda methods in derivative user script classes and registered in \c init().
*
+ * \warning Concrete scripts are allowed do create a custom constructor, but the utility
+ * functions should not be called inside the constructor as they rely on late references that
+ * are only available after the constructor returns.
+ *
* \see feature_script
*/
class Script {
@@ -63,8 +67,7 @@ protected:
*
* \returns Reference to component
*
- * \throws std::runtime_error if this game object does not have a component matching type \c
- * T
+ * \throws std::runtime_error if this game object does not have a component with type \c T
*/
template <typename T>
T & get_component() const;
diff --git a/src/crepe/api/Texture.cpp b/src/crepe/api/Texture.cpp
index 9be9421..264d7b1 100644
--- a/src/crepe/api/Texture.cpp
+++ b/src/crepe/api/Texture.cpp
@@ -9,14 +9,9 @@
using namespace crepe;
using namespace std;
-Texture::Texture(unique_ptr<Asset> res) {
+Texture::Texture(const Asset & src) {
dbg_trace();
- this->load(std::move(res));
-}
-
-Texture::Texture(const char * src) {
- dbg_trace();
- this->load(make_unique<Asset>(src));
+ this->load(src);
}
Texture::~Texture() {
@@ -24,9 +19,9 @@ Texture::~Texture() {
this->texture.reset();
}
-void Texture::load(unique_ptr<Asset> res) {
+void Texture::load(const Asset & res) {
SDLContext & ctx = SDLContext::get_instance();
- this->texture = std::move(ctx.texture_from_path(res->get_path()));
+ this->texture = ctx.texture_from_path(res.get_path());
}
int Texture::get_width() const {
diff --git a/src/crepe/api/Texture.h b/src/crepe/api/Texture.h
index 6965223..b4f7d07 100644
--- a/src/crepe/api/Texture.h
+++ b/src/crepe/api/Texture.h
@@ -25,16 +25,10 @@ class Texture {
public:
/**
- * \brief Constructs a Texture from a file path.
- * \param src Path to the image file to be loaded as a texture.
- */
- Texture(const char * src);
-
- /**
* \brief Constructs a Texture from an Asset resource.
- * \param res Unique pointer to an Asset resource containing texture data.
+ * \param src Asset with texture data to load.
*/
- Texture(std::unique_ptr<Asset> res);
+ Texture(const Asset & src);
/**
* \brief Destroys the Texture instance, freeing associated resources.
@@ -59,7 +53,7 @@ private:
* \brief Loads the texture from an Asset resource.
* \param res Unique pointer to an Asset resource to load the texture from.
*/
- void load(std::unique_ptr<Asset> res);
+ void load(const Asset & res);
private:
//! The texture of the class from the library
diff --git a/src/crepe/api/Transform.cpp b/src/crepe/api/Transform.cpp
index cd944bd..a85b792 100644
--- a/src/crepe/api/Transform.cpp
+++ b/src/crepe/api/Transform.cpp
@@ -4,7 +4,7 @@
using namespace crepe;
-Transform::Transform(game_object_id_t id, const Vector2 & point, double rotation, double scale)
+Transform::Transform(game_object_id_t id, const vec2 & point, double rotation, double scale)
: Component(id),
position(point),
rotation(rotation),
diff --git a/src/crepe/api/Transform.h b/src/crepe/api/Transform.h
index 18aa293..6243a93 100644
--- a/src/crepe/api/Transform.h
+++ b/src/crepe/api/Transform.h
@@ -1,8 +1,7 @@
#pragma once
-#include "api/Vector2.h"
-
#include "Component.h"
+#include "types.h"
namespace crepe {
@@ -15,7 +14,7 @@ namespace crepe {
class Transform : public Component {
public:
//! Translation (shift)
- Vector2 position = {0, 0};
+ vec2 position = {0, 0};
//! Rotation, in degrees
double rotation = 0;
//! Multiplication factor
@@ -28,7 +27,7 @@ protected:
* \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);
+ Transform(game_object_id_t id, const vec2 & point, double rotation, double scale);
/**
* There is always exactly one transform component per entity
* \return 1
diff --git a/src/crepe/api/Vector2.cpp b/src/crepe/api/Vector2.cpp
deleted file mode 100644
index 30b968e..0000000
--- a/src/crepe/api/Vector2.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-#include "Vector2.h"
-
-using namespace crepe;
-
-Vector2 Vector2::operator-(const Vector2 & other) const { return {x - other.x, y - other.y}; }
-
-Vector2 Vector2::operator+(const Vector2 & other) const { return {x + other.x, y + other.y}; }
-
-Vector2 Vector2::operator*(double scalar) const { return {x * scalar, y * scalar}; }
-
-Vector2 & Vector2::operator*=(const Vector2 & other) {
- x *= other.x;
- y *= other.y;
- return *this;
-}
-
-Vector2 & Vector2::operator+=(const Vector2 & other) {
- x += other.x;
- y += other.y;
- return *this;
-}
-
-Vector2 & Vector2::operator+=(double other) {
- x += other;
- y += other;
- return *this;
-}
-
-Vector2 Vector2::operator-() const { return {-x, -y}; }
-
-bool Vector2::operator==(const Vector2 & other) const { return x == other.x && y == other.y; }
-
-bool Vector2::operator!=(const Vector2 & other) const { return !(*this == other); }
diff --git a/src/crepe/api/Vector2.h b/src/crepe/api/Vector2.h
index 2fb6136..c278c87 100644
--- a/src/crepe/api/Vector2.h
+++ b/src/crepe/api/Vector2.h
@@ -3,38 +3,71 @@
namespace crepe {
//! 2D vector
+template <class T>
struct Vector2 {
//! X component of the vector
- double x = 0;
+ T x = 0;
//! Y component of the vector
- double y = 0;
+ T y = 0;
//! Subtracts another vector from this vector and returns the result.
- Vector2 operator-(const Vector2 & other) const;
+ Vector2 operator-(const Vector2<T> & other) const;
+
+ //! Subtracts a scalar value from both components of this vector and returns the result.
+ Vector2 operator-(T scalar) const;
//! Adds another vector to this vector and returns the result.
- Vector2 operator+(const Vector2 & other) const;
+ Vector2 operator+(const Vector2<T> & other) const;
+
+ //! Adds a scalar value to both components of this vector and returns the result.
+ Vector2 operator+(T scalar) const;
+
+ //! Multiplies this vector by another vector element-wise and returns the result.
+ Vector2 operator*(const Vector2<T> & other) const;
//! Multiplies this vector by a scalar and returns the result.
- Vector2 operator*(double scalar) const;
+ Vector2 operator*(T scalar) const;
- //! Multiplies this vector by another vector element-wise and updates this vector.
- Vector2 & operator*=(const Vector2 & other);
+ //! Divides this vector by another vector element-wise and returns the result.
+ Vector2 operator/(const Vector2<T> & other) const;
+
+ //! Divides this vector by a scalar and returns the result.
+ Vector2 operator/(T scalar) const;
//! Adds another vector to this vector and updates this vector.
- Vector2 & operator+=(const Vector2 & other);
+ Vector2 & operator+=(const Vector2<T> & other);
//! Adds a scalar value to both components of this vector and updates this vector.
- Vector2 & operator+=(double other);
+ Vector2 & operator+=(T other);
+
+ //! Subtracts another vector from this vector and updates this vector.
+ Vector2 & operator-=(const Vector2<T> & other);
+
+ //! Subtracts a scalar value from both components of this vector and updates this vector.
+ Vector2 & operator-=(T other);
+
+ //! Multiplies this vector by another vector element-wise and updates this vector.
+ Vector2 & operator*=(const Vector2<T> & other);
+
+ //! Multiplies this vector by a scalar and updates this vector.
+ Vector2 & operator*=(T other);
+
+ //! Divides this vector by another vector element-wise and updates this vector.
+ Vector2 & operator/=(const Vector2<T> & other);
+
+ //! Divides this vector by a scalar and updates this vector.
+ Vector2 & operator/=(T other);
//! Returns the negation of this vector.
Vector2 operator-() const;
//! Checks if this vector is equal to another vector.
- bool operator==(const Vector2 & other) const;
+ bool operator==(const Vector2<T> & other) const;
//! Checks if this vector is not equal to another vector.
- bool operator!=(const Vector2 & other) const;
+ bool operator!=(const Vector2<T> & other) const;
};
} // namespace crepe
+
+#include "Vector2.hpp"
diff --git a/src/crepe/api/Vector2.hpp b/src/crepe/api/Vector2.hpp
new file mode 100644
index 0000000..cad15f8
--- /dev/null
+++ b/src/crepe/api/Vector2.hpp
@@ -0,0 +1,118 @@
+#pragma once
+
+#include "Vector2.h"
+
+namespace crepe {
+
+template <class T>
+Vector2<T> Vector2<T>::operator-(const Vector2<T> & other) const {
+ return {x - other.x, y - other.y};
+}
+
+template <class T>
+Vector2<T> Vector2<T>::operator-(T scalar) const {
+ return {x - scalar, y - scalar};
+}
+
+template <class T>
+Vector2<T> Vector2<T>::operator+(const Vector2<T> & other) const {
+ return {x + other.x, y + other.y};
+}
+
+template <class T>
+Vector2<T> Vector2<T>::operator+(T scalar) const {
+ return {x + scalar, y + scalar};
+}
+
+template <class T>
+Vector2<T> Vector2<T>::operator*(const Vector2<T> & other) const {
+ return {x * other.x, y * other.y};
+}
+
+template <class T>
+Vector2<T> Vector2<T>::operator*(T scalar) const {
+ return {x * scalar, y * scalar};
+}
+
+template <class T>
+Vector2<T> Vector2<T>::operator/(const Vector2<T> & other) const {
+ return {x / other.x, y / other.y};
+}
+
+template <class T>
+Vector2<T> Vector2<T>::operator/(T scalar) const {
+ return {x / scalar, y / scalar};
+}
+
+template <class T>
+Vector2<T> & Vector2<T>::operator+=(const Vector2<T> & other) {
+ x += other.x;
+ y += other.y;
+ return *this;
+}
+
+template <class T>
+Vector2<T> & Vector2<T>::operator+=(T other) {
+ x += other;
+ y += other;
+ return *this;
+}
+
+template <class T>
+Vector2<T> & Vector2<T>::operator-=(const Vector2<T> & other) {
+ x -= other.x;
+ y -= other.y;
+ return *this;
+}
+
+template <class T>
+Vector2<T> & Vector2<T>::operator-=(T other) {
+ x -= other;
+ y -= other;
+ return *this;
+}
+
+template <class T>
+Vector2<T> & Vector2<T>::operator*=(const Vector2<T> & other) {
+ x *= other.x;
+ y *= other.y;
+ return *this;
+}
+
+template <class T>
+Vector2<T> & Vector2<T>::operator*=(T other) {
+ x *= other;
+ y *= other;
+ return *this;
+}
+
+template <class T>
+Vector2<T> & Vector2<T>::operator/=(const Vector2<T> & other) {
+ x /= other.x;
+ y /= other.y;
+ return *this;
+}
+
+template <class T>
+Vector2<T> & Vector2<T>::operator/=(T other) {
+ x /= other;
+ y /= other;
+ return *this;
+}
+
+template <class T>
+Vector2<T> Vector2<T>::operator-() const {
+ return {-x, -y};
+}
+
+template <class T>
+bool Vector2<T>::operator==(const Vector2<T> & other) const {
+ return x == other.x && y == other.y;
+}
+
+template <class T>
+bool Vector2<T>::operator!=(const Vector2<T> & other) const {
+ return !(*this == other);
+}
+
+} // namespace crepe
diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp
index 00523a6..b3298a7 100644
--- a/src/crepe/facade/SDLContext.cpp
+++ b/src/crepe/facade/SDLContext.cpp
@@ -104,13 +104,13 @@ SDL_Rect SDLContext::get_src_rect(const Sprite & sprite) const {
.h = sprite.sprite_rect.h,
};
}
-SDL_Rect SDLContext::get_dst_rect(const Sprite & sprite, const Vector2 & pos,
+SDL_Rect SDLContext::get_dst_rect(const Sprite & sprite, const vec2 & pos,
const double & scale, const Camera & cam) const {
- double adjusted_x = (pos.x - cam.x) * cam.zoom;
- double adjusted_y = (pos.y - cam.y) * cam.zoom;
double adjusted_w = sprite.sprite_rect.w * scale * cam.zoom;
double adjusted_h = sprite.sprite_rect.h * scale * cam.zoom;
+ double adjusted_x = (pos.x - cam.x) * cam.zoom - adjusted_w / 2;
+ double adjusted_y = (pos.y - cam.y) * cam.zoom - adjusted_h / 2;
return SDL_Rect{
.x = static_cast<int>(adjusted_x),
@@ -120,9 +120,8 @@ SDL_Rect SDLContext::get_dst_rect(const Sprite & sprite, const Vector2 & pos,
};
}
-void SDLContext::draw_particle(const Sprite & sprite, const Vector2 & pos,
- const double & angle, const double & scale,
- const Camera & camera) {
+void SDLContext::draw_particle(const Sprite & sprite, const vec2 & pos, const double & angle,
+ const double & scale, const Camera & camera) {
SDL_RendererFlip render_flip
= (SDL_RendererFlip) ((SDL_FLIP_HORIZONTAL * sprite.flip.flip_x)
diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h
index 841ffc9..20e30b3 100644
--- a/src/crepe/facade/SDLContext.h
+++ b/src/crepe/facade/SDLContext.h
@@ -12,7 +12,8 @@
#include "../api/Sprite.h"
#include "../api/Transform.h"
#include "api/Camera.h"
-#include "api/Vector2.h"
+
+#include "types.h"
namespace crepe {
@@ -120,7 +121,7 @@ private:
*/
void draw(const Sprite & sprite, const Transform & transform, const Camera & camera);
- void draw_particle(const Sprite & sprite, const Vector2 & pos, const double & angle,
+ void draw_particle(const Sprite & sprite, const vec2 & pos, const double & angle,
const double & scale, const Camera & camera);
//! Clears the screen, preparing for a new frame.
@@ -153,7 +154,7 @@ private:
* on the camera
* \return sdl rectangle to draw a dst image to draw on the screen
*/
- SDL_Rect get_dst_rect(const Sprite & sprite, const Vector2 & pos, const double & scale,
+ SDL_Rect get_dst_rect(const Sprite & sprite, const vec2 & pos, const double & scale,
const Camera & cam) const;
private:
diff --git a/src/crepe/system/ParticleSystem.cpp b/src/crepe/system/ParticleSystem.cpp
index fcf7522..0e62a57 100644
--- a/src/crepe/system/ParticleSystem.cpp
+++ b/src/crepe/system/ParticleSystem.cpp
@@ -4,7 +4,6 @@
#include "api/ParticleEmitter.h"
#include "api/Transform.h"
-#include "api/Vector2.h"
#include "ComponentManager.h"
#include "ParticleSystem.h"
@@ -42,17 +41,15 @@ void ParticleSystem::update() {
}
void ParticleSystem::emit_particle(ParticleEmitter & emitter, const Transform & transform) {
- constexpr double DEG_TO_RAD = M_PI / 180.0;
+ constexpr float DEG_TO_RAD = M_PI / 180.0;
- Vector2 initial_position = emitter.data.position + transform.position;
- double random_angle
- = generate_random_angle(emitter.data.min_angle, emitter.data.max_angle);
+ vec2 initial_position = emitter.data.position + transform.position;
+ float random_angle = generate_random_angle(emitter.data.min_angle, emitter.data.max_angle);
- double random_speed
- = generate_random_speed(emitter.data.min_speed, emitter.data.max_speed);
- double angle_radians = random_angle * DEG_TO_RAD;
+ float random_speed = generate_random_speed(emitter.data.min_speed, emitter.data.max_speed);
+ float angle_radians = random_angle * DEG_TO_RAD;
- Vector2 velocity
+ vec2 velocity
= {random_speed * std::cos(angle_radians), random_speed * std::sin(angle_radians)};
for (Particle & particle : emitter.data.particles) {
@@ -77,7 +74,7 @@ int ParticleSystem::calculate_update(int count, double emission) const {
}
void ParticleSystem::check_bounds(ParticleEmitter & emitter, const Transform & transform) {
- Vector2 offset = emitter.data.boundary.offset + transform.position + emitter.data.position;
+ vec2 offset = emitter.data.boundary.offset + transform.position + emitter.data.position;
double half_width = emitter.data.boundary.width / 2.0;
double half_height = emitter.data.boundary.height / 2.0;
@@ -87,7 +84,7 @@ void ParticleSystem::check_bounds(ParticleEmitter & emitter, const Transform & t
const double BOTTOM = offset.y + half_height;
for (Particle & particle : emitter.data.particles) {
- const Vector2 & position = particle.position;
+ const vec2 & position = particle.position;
bool within_bounds = (position.x >= LEFT && position.x <= RIGHT && position.y >= TOP
&& position.y <= BOTTOM);
diff --git a/src/crepe/system/PhysicsSystem.cpp b/src/crepe/system/PhysicsSystem.cpp
index bcde431..514a4b3 100644
--- a/src/crepe/system/PhysicsSystem.cpp
+++ b/src/crepe/system/PhysicsSystem.cpp
@@ -34,7 +34,7 @@ void PhysicsSystem::update() {
if (rigidbody.data.angular_damping != 0) {
rigidbody.data.angular_velocity *= rigidbody.data.angular_damping;
}
- if (rigidbody.data.linear_damping != Vector2{0, 0}) {
+ if (rigidbody.data.linear_damping != vec2{0, 0}) {
rigidbody.data.linear_velocity *= rigidbody.data.linear_damping;
}
diff --git a/src/crepe/types.h b/src/crepe/types.h
index 914c76c..17f1619 100644
--- a/src/crepe/types.h
+++ b/src/crepe/types.h
@@ -1,5 +1,7 @@
#pragma once
+#include "api/Vector2.h"
+
#include <cstdint>
#include <functional>
#include <vector>
@@ -13,4 +15,16 @@ typedef uint32_t game_object_id_t;
template <typename T>
using RefVector = std::vector<std::reference_wrapper<T>>;
+//! Default Vector2<int> type
+typedef Vector2<int> ivec2;
+
+//! Default Vector2<unsigned int> type
+typedef Vector2<unsigned int> uvec2;
+
+//! Default Vector2<float> type
+typedef Vector2<float> vec2;
+
+//! Default Vector2<double> type
+typedef Vector2<double> dvec2;
+
} // namespace crepe
diff --git a/src/doc/feature/scene.dox b/src/doc/feature/scene.dox
index 5f34446..d81df4c 100644
--- a/src/doc/feature/scene.dox
+++ b/src/doc/feature/scene.dox
@@ -36,18 +36,16 @@ concrete scene to be added.
#include <crepe/api/LoopManager.h>
#include <crepe/api/GameObject.h>
#include <crepe/api/Scene.h>
-#include <crepe/api/Vector2.h>
+#include <crepe/types.h>
using namespace crepe;
class MyScene : public Scene {
public:
- using Scene::Scene;
-
void load_scene() {
- auto & mgr = this->component_manager;
- GameObject object1 = mgr.new_object("object1", "tag_my_scene", Vector2{0, 0}, 0, 1);
- GameObject object2 = mgr.new_object("object2", "tag_my_scene", Vector2{1, 0}, 0, 1);
+ ComponentManager & mgr = this->component_manager;
+ GameObject object1 = mgr.new_object("object1", "tag_my_scene", vec2{0, 0}, 0, 1);
+ GameObject object2 = mgr.new_object("object2", "tag_my_scene", vec2{1, 0}, 0, 1);
}
string get_name() const { return "my_scene"; }
diff --git a/src/doc/internal/component.dox b/src/doc/internal/component.dox
new file mode 100644
index 0000000..0dd4cb5
--- /dev/null
+++ b/src/doc/internal/component.dox
@@ -0,0 +1,41 @@
+// vim:ft=doxygen
+namespace crepe {
+/**
+
+\defgroup internal_component Components
+\ingroup internal
+\brief ECS Components
+
+Components are attached to GameObject instances and are composed by the game
+programmer to create specific entities in the game world. While they are
+implemented as C++ classes, components should be treated as C-style structs,
+meaning all members are public and they do not contain functions.
+
+A basic component has the following structure:
+```cpp
+#include <crepe/Component.h>
+
+class MyComponent : public crepe::Component {
+public:
+ // Add your custom component's ininitializer properties after the `id`
+ // parameter. The first parameter is controlled by GameObject::add_component,
+ // while all other parameters are forwarded using std::forward.
+ MyComponent(game_object_id_t id, ...);
+
+ // Optionally define the `get_instances_max` method to limit the amount of
+ // instances of this component per GameObject. The default implementation for
+ // this function returns -1, which means the instance count does not have an
+ // upper limit:
+ virtual int get_instances_max() const { return -1; }
+
+ // Properties
+ // ...
+};
+```
+
+Generally, components are "handled" by \ref internal_system "systems", which may
+optionally change the components' state. Components' state may also be
+controlled by the game programmer through \ref feature_script "scripts".
+
+*/
+}
diff --git a/src/doc/internal/resource.dox b/src/doc/internal/resource.dox
new file mode 100644
index 0000000..56f1de0
--- /dev/null
+++ b/src/doc/internal/resource.dox
@@ -0,0 +1,12 @@
+// vim:ft=doxygen
+namespace crepe {
+/**
+
+\defgroup internal_resource Resources
+\ingroup internal
+\brief Concrete resources
+
+\todo This section is incomplete
+
+*/
+}
diff --git a/src/doc/internal/style.dox b/src/doc/internal/style.dox
new file mode 100644
index 0000000..dad2df0
--- /dev/null
+++ b/src/doc/internal/style.dox
@@ -0,0 +1,9 @@
+// vim:ft=doxygen
+/**
+
+\defgroup internal_style Code style
+\ingroup internal
+\brief Coding conventions
+\include{doc} contributing.md
+
+*/
diff --git a/src/doc/internal/system.dox b/src/doc/internal/system.dox
new file mode 100644
index 0000000..17a101e
--- /dev/null
+++ b/src/doc/internal/system.dox
@@ -0,0 +1,26 @@
+// vim:ft=doxygen
+namespace crepe {
+/**
+
+\defgroup internal_system Systems
+\ingroup internal
+\brief ECS Systems
+
+\todo This section is incomplete
+
+A system is responsible for processing the data stored in \ref
+internal_component "components".
+
+A basic system has the following structure:
+```cpp
+#include <crepe/system/System.h>
+
+class MySystem : public System {
+public:
+ using System::System;
+ void update() override;
+};
+```
+
+*/
+}
diff --git a/src/doc/internals.dox b/src/doc/internals.dox
new file mode 100644
index 0000000..2d2ca56
--- /dev/null
+++ b/src/doc/internals.dox
@@ -0,0 +1,10 @@
+// vim:ft=doxygen
+/**
+
+\defgroup internal Internals
+\brief Internal engine structure and other conventions
+
+\todo This page is incomplete
+\todo Anything about Contexts?
+
+*/
diff --git a/src/doc/layout.xml b/src/doc/layout.xml
index 7f514d4..fb4cc0c 100644
--- a/src/doc/layout.xml
+++ b/src/doc/layout.xml
@@ -1,10 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<doxygenlayout version="1.0">
<navindex>
- <tab type="mainpage" visible="yes" title=""/>
+ <tab type="mainpage" visible="yes" title="Intro"/>
+ <tab type="user" url="@ref install" title="Installation"/>
+ <tab type="user" url="@ref feature" title="Features"/>
+ <tab type="user" url="@ref internal" title="Internals"/>
<tab type="pages" visible="no" title="" intro=""/>
- <tab type="topics" visible="yes" title="" intro=""/>
- <tab type="modules" visible="yes" title="" intro="">
+ <tab type="topics" visible="no" title="" intro=""/>
+ <tab type="modules" visible="no" title="" intro="">
<tab type="modulelist" visible="yes" title="" intro=""/>
<tab type="modulemembers" visible="yes" title="" intro=""/>
</tab>
@@ -12,9 +15,9 @@
<tab type="namespacelist" visible="yes" title="" intro=""/>
<tab type="namespacemembers" visible="yes" title="" intro=""/>
</tab>
- <tab type="concepts" visible="yes" title="">
+ <tab type="concepts" visible="no" title="">
</tab>
- <tab type="interfaces" visible="yes" title="">
+ <tab type="interfaces" visible="no" title="">
<tab type="interfacelist" visible="yes" title="" intro=""/>
<tab type="interfaceindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="interfacehierarchy" visible="yes" title="" intro=""/>
@@ -25,20 +28,20 @@
<tab type="hierarchy" visible="yes" title="" intro=""/>
<tab type="classmembers" visible="yes" title="" intro=""/>
</tab>
- <tab type="structs" visible="yes" title="">
+ <tab type="structs" visible="no" title="">
<tab type="structlist" visible="yes" title="" intro=""/>
<tab type="structindex" visible="$ALPHABETICAL_INDEX" title=""/>
</tab>
- <tab type="exceptions" visible="yes" title="">
+ <tab type="exceptions" visible="no" title="">
<tab type="exceptionlist" visible="yes" title="" intro=""/>
<tab type="exceptionindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="exceptionhierarchy" visible="yes" title="" intro=""/>
</tab>
- <tab type="files" visible="yes" title="">
+ <tab type="files" visible="no" title="">
<tab type="filelist" visible="yes" title="" intro=""/>
<tab type="globals" visible="yes" title="" intro=""/>
</tab>
- <tab type="examples" visible="yes" title="" intro=""/>
+ <tab type="examples" visible="no" title="" intro=""/>
</navindex>
<class>
<briefdescription visible="yes"/>
diff --git a/src/doc/style.css b/src/doc/style.css
index 08bc9f5..daabd39 100644
--- a/src/doc/style.css
+++ b/src/doc/style.css
@@ -2,3 +2,5 @@
address {
display: none;
}
+
+h2.groupheader { margin-top: revert; }
diff --git a/src/example/rendering_particle.cpp b/src/example/rendering_particle.cpp
index 4571afb..b38e860 100644
--- a/src/example/rendering_particle.cpp
+++ b/src/example/rendering_particle.cpp
@@ -1,5 +1,6 @@
#include "api/Camera.h"
#include "system/ParticleSystem.h"
+#include "types.h"
#include <SDL2/SDL_timer.h>
#include <crepe/ComponentManager.h>
@@ -23,14 +24,14 @@ using namespace std;
int main(int argc, char * argv[]) {
ComponentManager mgr;
- GameObject game_object = mgr.new_object("", "", Vector2{100, 100}, 0, 0.1);
+ GameObject game_object = mgr.new_object("", "", vec2{0, 0}, 0, 0.1);
RenderSystem sys{mgr};
ParticleSystem psys{mgr};
Color color(255, 255, 255, 255);
Sprite & test_sprite = game_object.add_component<Sprite>(
- make_shared<Texture>("../asset/texture/img.png"), color, FlipSettings{false, false});
+ make_shared<Texture>("asset/texture/img.png"), color, FlipSettings{false, false});
test_sprite.order_in_layer = 5;
auto & test = game_object.add_component<ParticleEmitter>(ParticleEmitter::Data{
@@ -43,11 +44,11 @@ int main(int argc, char * argv[]) {
.max_angle = 20,
.begin_lifespan = 0,
.end_lifespan = 60,
- .force_over_time = Vector2{0, 0},
+ .force_over_time = vec2{0, 0},
.boundary{
.width = 1000,
.height = 1000,
- .offset = Vector2{0, 0},
+ .offset = vec2{0, 0},
.reset_on_exit = false,
},
.sprite = test_sprite,
@@ -55,7 +56,7 @@ int main(int argc, char * argv[]) {
game_object.add_component<Camera>(Color::WHITE);
game_object
- .add_component<Sprite>(make_shared<Texture>("../asset/texture/img.png"), color,
+ .add_component<Sprite>(make_shared<Texture>("asset/texture/img.png"), color,
FlipSettings{false, false})
.order_in_layer
= 6;
diff --git a/src/test/AssetTest.cpp b/src/test/AssetTest.cpp
index 8aa7629..93fd6a9 100644
--- a/src/test/AssetTest.cpp
+++ b/src/test/AssetTest.cpp
@@ -7,17 +7,12 @@ using namespace std;
using namespace crepe;
using namespace testing;
-class AssetTest : public Test {
-public:
- Config & cfg = Config::get_instance();
- void SetUp() override { this->cfg.asset.root_pattern = ".crepe-root"; }
-};
-
-TEST_F(AssetTest, Existant) { ASSERT_NO_THROW(Asset{"asset/texture/img.png"}); }
+TEST(AssetTest, Existant) { ASSERT_NO_THROW(Asset{"asset/texture/img.png"}); }
-TEST_F(AssetTest, Nonexistant) { ASSERT_ANY_THROW(Asset{"asset/nonexistant"}); }
+TEST(AssetTest, Nonexistant) { ASSERT_ANY_THROW(Asset{"asset/nonexistant"}); }
-TEST_F(AssetTest, Rootless) {
+TEST(AssetTest, Rootless) {
+ Config & cfg = Config::get_instance();
cfg.asset.root_pattern.clear();
string arbitrary = "\\/this is / /../passed through as-is";
diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt
index 8cb4232..d310f6a 100644
--- a/src/test/CMakeLists.txt
+++ b/src/test/CMakeLists.txt
@@ -11,5 +11,5 @@ target_sources(test_main PUBLIC
SceneManagerTest.cpp
ValueBrokerTest.cpp
DBTest.cpp
+ Vector2Test.cpp
)
-
diff --git a/src/test/ECSTest.cpp b/src/test/ECSTest.cpp
index d5a5826..80b936b 100644
--- a/src/test/ECSTest.cpp
+++ b/src/test/ECSTest.cpp
@@ -17,7 +17,7 @@ public:
};
TEST_F(ECSTest, createGameObject) {
- GameObject obj = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1);
+ GameObject obj = mgr.new_object("body", "person", vec2{0, 0}, 0, 1);
vector<reference_wrapper<Metadata>> metadata = mgr.get_components_by_type<Metadata>();
vector<reference_wrapper<Transform>> transform = mgr.get_components_by_type<Transform>();
@@ -37,8 +37,8 @@ TEST_F(ECSTest, createGameObject) {
}
TEST_F(ECSTest, deleteAllGameObjects) {
- GameObject obj0 = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1);
- GameObject obj1 = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1);
+ GameObject obj0 = mgr.new_object("body", "person", vec2{0, 0}, 0, 1);
+ GameObject obj1 = mgr.new_object("body", "person", vec2{0, 0}, 0, 1);
mgr.delete_all_components();
@@ -48,7 +48,7 @@ TEST_F(ECSTest, deleteAllGameObjects) {
EXPECT_EQ(metadata.size(), 0);
EXPECT_EQ(transform.size(), 0);
- GameObject obj2 = mgr.new_object("body2", "person2", Vector2{1, 0}, 5, 1);
+ GameObject obj2 = mgr.new_object("body2", "person2", vec2{1, 0}, 5, 1);
metadata = mgr.get_components_by_type<Metadata>();
transform = mgr.get_components_by_type<Transform>();
@@ -70,8 +70,8 @@ TEST_F(ECSTest, deleteAllGameObjects) {
}
TEST_F(ECSTest, deleteGameObject) {
- GameObject obj0 = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1);
- GameObject obj1 = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1);
+ GameObject obj0 = mgr.new_object("body", "person", vec2{0, 0}, 0, 1);
+ GameObject obj1 = mgr.new_object("body", "person", vec2{0, 0}, 0, 1);
mgr.delete_all_components_of_id(0);
@@ -96,7 +96,7 @@ TEST_F(ECSTest, deleteGameObject) {
TEST_F(ECSTest, manyGameObjects) {
for (int i = 0; i < 5000; i++) {
- GameObject obj = mgr.new_object("body", "person", Vector2{0, 0}, 0, i);
+ GameObject obj = mgr.new_object("body", "person", vec2{0, 0}, 0, i);
}
vector<reference_wrapper<Metadata>> metadata = mgr.get_components_by_type<Metadata>();
@@ -128,7 +128,7 @@ TEST_F(ECSTest, manyGameObjects) {
for (int i = 0; i < 10000 - 5000; i++) {
string tag = "person" + to_string(i);
- GameObject obj = mgr.new_object("body", tag, Vector2{0, 0}, i, 0);
+ GameObject obj = mgr.new_object("body", tag, vec2{0, 0}, i, 0);
}
metadata = mgr.get_components_by_type<Metadata>();
@@ -139,8 +139,8 @@ TEST_F(ECSTest, manyGameObjects) {
}
TEST_F(ECSTest, getComponentsByID) {
- GameObject obj0 = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1);
- GameObject obj1 = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1);
+ GameObject obj0 = mgr.new_object("body", "person", vec2{0, 0}, 0, 1);
+ GameObject obj1 = mgr.new_object("body", "person", vec2{0, 0}, 0, 1);
vector<reference_wrapper<Metadata>> metadata = mgr.get_components_by_id<Metadata>(0);
vector<reference_wrapper<Transform>> transform = mgr.get_components_by_id<Transform>(1);
@@ -163,15 +163,15 @@ TEST_F(ECSTest, getComponentsByID) {
TEST_F(ECSTest, tooMuchComponents) {
try {
- GameObject obj0 = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1);
- obj0.add_component<Transform>(Vector2{10, 10}, 0, 1);
+ GameObject obj0 = mgr.new_object("body", "person", vec2{0, 0}, 0, 1);
+ obj0.add_component<Transform>(vec2{10, 10}, 0, 1);
} catch (const exception & e) {
EXPECT_EQ(e.what(),
string("Exceeded maximum number of instances for this component type"));
}
try {
- GameObject obj1 = mgr.new_object("body", "person", Vector2{0, 0}, 0, 1);
+ GameObject obj1 = mgr.new_object("body", "person", vec2{0, 0}, 0, 1);
obj1.add_component<Metadata>("body", "person");
} catch (const exception & e) {
EXPECT_EQ(e.what(),
@@ -187,11 +187,11 @@ TEST_F(ECSTest, tooMuchComponents) {
TEST_F(ECSTest, partentChild) {
{
- 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);
+ GameObject body = mgr.new_object("body", "person", vec2{0, 0}, 0, 1);
+ GameObject right_leg = mgr.new_object("rightLeg", "person", vec2{1, 1}, 0, 1);
+ GameObject left_leg = mgr.new_object("leftLeg", "person", vec2{1, 1}, 0, 1);
+ GameObject right_foot = mgr.new_object("rightFoot", "person", vec2{2, 2}, 0, 1);
+ GameObject left_foot = mgr.new_object("leftFoot", "person", vec2{2, 2}, 0, 1);
// Set the parent of each GameObject
right_foot.set_parent(right_leg);
diff --git a/src/test/ParticleTest.cpp b/src/test/ParticleTest.cpp
index eee022f..8b81e74 100644
--- a/src/test/ParticleTest.cpp
+++ b/src/test/ParticleTest.cpp
@@ -25,7 +25,7 @@ public:
std::vector<std::reference_wrapper<Transform>> transforms
= mgr.get_components_by_id<Transform>(0);
if (transforms.empty()) {
- GameObject game_object = mgr.new_object("", "", Vector2{0, 0}, 0, 0);
+ GameObject game_object = mgr.new_object("", "", vec2{0, 0}, 0, 0);
Color color(0, 0, 0, 0);
Sprite & test_sprite = game_object.add_component<Sprite>(
@@ -42,11 +42,11 @@ public:
.max_angle = 0,
.begin_lifespan = 0,
.end_lifespan = 0,
- .force_over_time = Vector2{0, 0},
+ .force_over_time = vec2{0, 0},
.boundary{
.width = 0,
.height = 0,
- .offset = Vector2{0, 0},
+ .offset = vec2{0, 0},
.reset_on_exit = false,
},
.sprite = test_sprite,
@@ -68,8 +68,8 @@ public:
emitter.data.max_angle = 0;
emitter.data.begin_lifespan = 0;
emitter.data.end_lifespan = 0;
- emitter.data.force_over_time = Vector2{0, 0};
- emitter.data.boundary = {0, 0, Vector2{0, 0}, false};
+ emitter.data.force_over_time = vec2{0, 0};
+ emitter.data.boundary = {0, 0, vec2{0, 0}, false};
for (auto & particle : emitter.data.particles) {
particle.active = false;
}
diff --git a/src/test/PhysicsTest.cpp b/src/test/PhysicsTest.cpp
index 1e37c26..33b6020 100644
--- a/src/test/PhysicsTest.cpp
+++ b/src/test/PhysicsTest.cpp
@@ -20,12 +20,12 @@ public:
vector<reference_wrapper<Transform>> transforms
= mgr.get_components_by_id<Transform>(0);
if (transforms.empty()) {
- auto entity = mgr.new_object("", "", Vector2{0, 0}, 0, 0);
+ auto entity = mgr.new_object("", "", vec2{0, 0}, 0, 0);
entity.add_component<Rigidbody>(Rigidbody::Data{
.mass = 1,
.gravity_scale = 1,
.body_type = Rigidbody::BodyType::DYNAMIC,
- .max_linear_velocity = Vector2{10, 10},
+ .max_linear_velocity = vec2{10, 10},
.max_angular_velocity = 10,
.constraints = {0, 0},
.use_gravity = true,
diff --git a/src/test/RenderSystemTest.cpp b/src/test/RenderSystemTest.cpp
index ac479d3..f37fb56 100644
--- a/src/test/RenderSystemTest.cpp
+++ b/src/test/RenderSystemTest.cpp
@@ -30,7 +30,7 @@ public:
void SetUp() override {
auto & sprite1
- = entity1.add_component<Sprite>(make_shared<Texture>("../asset/texture/img.png"),
+ = entity1.add_component<Sprite>(make_shared<Texture>("asset/texture/img.png"),
Color(0, 0, 0, 0), FlipSettings{false, false});
ASSERT_NE(sprite1.sprite_image.get(), nullptr);
sprite1.order_in_layer = 5;
@@ -38,7 +38,7 @@ public:
EXPECT_EQ(sprite1.order_in_layer, 5);
EXPECT_EQ(sprite1.sorting_in_layer, 5);
auto & sprite2
- = entity2.add_component<Sprite>(make_shared<Texture>("../asset/texture/img.png"),
+ = entity2.add_component<Sprite>(make_shared<Texture>("asset/texture/img.png"),
Color(0, 0, 0, 0), FlipSettings{false, false});
ASSERT_NE(sprite2.sprite_image.get(), nullptr);
sprite2.sorting_in_layer = 2;
@@ -48,7 +48,7 @@ public:
EXPECT_EQ(sprite2.order_in_layer, 1);
auto & sprite3
- = entity3.add_component<Sprite>(make_shared<Texture>("../asset/texture/img.png"),
+ = entity3.add_component<Sprite>(make_shared<Texture>("asset/texture/img.png"),
Color(0, 0, 0, 0), FlipSettings{false, false});
ASSERT_NE(sprite3.sprite_image.get(), nullptr);
sprite3.sorting_in_layer = 1;
@@ -58,7 +58,7 @@ public:
EXPECT_EQ(sprite3.order_in_layer, 2);
auto & sprite4
- = entity4.add_component<Sprite>(make_shared<Texture>("../asset/texture/img.png"),
+ = entity4.add_component<Sprite>(make_shared<Texture>("asset/texture/img.png"),
Color(0, 0, 0, 0), FlipSettings{false, false});
ASSERT_NE(sprite4.sprite_image.get(), nullptr);
sprite4.sorting_in_layer = 1;
diff --git a/src/test/SceneManagerTest.cpp b/src/test/SceneManagerTest.cpp
index 1efcfb2..62b7d33 100644
--- a/src/test/SceneManagerTest.cpp
+++ b/src/test/SceneManagerTest.cpp
@@ -1,3 +1,4 @@
+#include "types.h"
#include <crepe/ComponentManager.h>
#include <crepe/api/GameObject.h>
#include <crepe/api/Metadata.h>
@@ -12,13 +13,11 @@ using namespace crepe;
class ConcreteScene1 : public Scene {
public:
- using Scene::Scene;
-
void load_scene() {
- auto & mgr = this->component_manager;
- GameObject object1 = mgr.new_object("scene_1", "tag_scene_1", Vector2{0, 0}, 0, 1);
- GameObject object2 = mgr.new_object("scene_1", "tag_scene_1", Vector2{1, 0}, 0, 1);
- GameObject object3 = mgr.new_object("scene_1", "tag_scene_1", Vector2{2, 0}, 0, 1);
+ ComponentManager & mgr = this->component_manager;
+ GameObject object1 = mgr.new_object("scene_1", "tag_scene_1", vec2{0, 0}, 0, 1);
+ GameObject object2 = mgr.new_object("scene_1", "tag_scene_1", vec2{1, 0}, 0, 1);
+ GameObject object3 = mgr.new_object("scene_1", "tag_scene_1", vec2{2, 0}, 0, 1);
}
string get_name() const { return "scene1"; }
@@ -26,19 +25,32 @@ public:
class ConcreteScene2 : public Scene {
public:
- using Scene::Scene;
-
void load_scene() {
- auto & mgr = this->component_manager;
- GameObject object1 = mgr.new_object("scene_2", "tag_scene_2", Vector2{0, 0}, 0, 1);
- GameObject object2 = mgr.new_object("scene_2", "tag_scene_2", Vector2{0, 1}, 0, 1);
- GameObject object3 = mgr.new_object("scene_2", "tag_scene_2", Vector2{0, 2}, 0, 1);
- GameObject object4 = mgr.new_object("scene_2", "tag_scene_2", Vector2{0, 3}, 0, 1);
+ ComponentManager & mgr = this->component_manager;
+ GameObject object1 = mgr.new_object("scene_2", "tag_scene_2", vec2{0, 0}, 0, 1);
+ GameObject object2 = mgr.new_object("scene_2", "tag_scene_2", vec2{0, 1}, 0, 1);
+ GameObject object3 = mgr.new_object("scene_2", "tag_scene_2", vec2{0, 2}, 0, 1);
+ GameObject object4 = mgr.new_object("scene_2", "tag_scene_2", vec2{0, 3}, 0, 1);
}
string get_name() const { return "scene2"; }
};
+class ConcreteScene3 : public Scene {
+public:
+ ConcreteScene3(const string & name) : name(name) {}
+
+ void load_scene() {
+ ComponentManager & mgr = this->component_manager;
+ GameObject object1 = mgr.new_object("scene_3", "tag_scene_3", vec2{0, 0}, 0, 1);
+ }
+
+ string get_name() const { return name; }
+
+private:
+ const string name;
+};
+
class SceneManagerTest : public ::testing::Test {
public:
ComponentManager component_mgr{};
@@ -124,3 +136,25 @@ TEST_F(SceneManagerTest, loadScene) {
EXPECT_EQ(transform[3].get().position.x, 0);
EXPECT_EQ(transform[3].get().position.y, 3);
}
+
+TEST_F(SceneManagerTest, perfectForwarding) {
+ scene_mgr.add_scene<ConcreteScene3>("scene3");
+
+ scene_mgr.load_next_scene();
+
+ vector<reference_wrapper<Metadata>> metadata
+ = component_mgr.get_components_by_type<Metadata>();
+ vector<reference_wrapper<Transform>> transform
+ = component_mgr.get_components_by_type<Transform>();
+
+ EXPECT_EQ(metadata.size(), 1);
+ EXPECT_EQ(transform.size(), 1);
+
+ EXPECT_EQ(metadata[0].get().game_object_id, 0);
+ EXPECT_EQ(metadata[0].get().name, "scene_3");
+ EXPECT_EQ(metadata[0].get().tag, "tag_scene_3");
+ EXPECT_EQ(metadata[0].get().parent, -1);
+ EXPECT_EQ(metadata[0].get().children.size(), 0);
+ EXPECT_EQ(transform[0].get().position.x, 0);
+ EXPECT_EQ(transform[0].get().position.y, 0);
+}
diff --git a/src/test/Vector2Test.cpp b/src/test/Vector2Test.cpp
new file mode 100644
index 0000000..17bca41
--- /dev/null
+++ b/src/test/Vector2Test.cpp
@@ -0,0 +1,384 @@
+#include <gtest/gtest.h>
+
+#include <crepe/api/Vector2.h>
+
+using namespace crepe;
+
+class Vector2Test : public ::testing::Test {
+public:
+ Vector2<int> int_vec1;
+ Vector2<int> int_vec2;
+ Vector2<double> double_vec1;
+ Vector2<double> double_vec2;
+ Vector2<long> long_vec1;
+ Vector2<long> long_vec2;
+ Vector2<float> float_vec1;
+ Vector2<float> float_vec2;
+
+ void SetUp() override {
+ int_vec1 = {1, 2};
+ int_vec2 = {3, 4};
+ double_vec1 = {1.0, 2.0};
+ double_vec2 = {3.0, 4.0};
+ long_vec1 = {1, 2};
+ long_vec2 = {3, 4};
+ float_vec1 = {1.0f, 2.0f};
+ float_vec2 = {3.0f, 4.0f};
+ }
+};
+
+TEST_F(Vector2Test, Subtract) {
+ Vector2<int> result = int_vec1 - int_vec2;
+ EXPECT_EQ(result.x, -2);
+ EXPECT_EQ(result.y, -2);
+
+ Vector2<double> result2 = double_vec1 - double_vec2;
+ EXPECT_FLOAT_EQ(result2.x, -2.0);
+ EXPECT_FLOAT_EQ(result2.y, -2.0);
+
+ Vector2<long> result3 = long_vec1 - long_vec2;
+ EXPECT_EQ(result3.x, -2);
+ EXPECT_EQ(result3.y, -2);
+
+ Vector2<float> result4 = float_vec1 - float_vec2;
+ EXPECT_FLOAT_EQ(result4.x, -2.0f);
+ EXPECT_FLOAT_EQ(result4.y, -2.0f);
+}
+
+TEST_F(Vector2Test, SubtractScalar) {
+ Vector2<int> result = int_vec1 - 1;
+ EXPECT_EQ(result.x, 0);
+ EXPECT_EQ(result.y, 1);
+
+ Vector2<double> result2 = double_vec1 - 1.0;
+ EXPECT_FLOAT_EQ(result2.x, 0.0);
+ EXPECT_FLOAT_EQ(result2.y, 1.0);
+
+ Vector2<long> result3 = long_vec1 - 1;
+ EXPECT_EQ(result3.x, 0);
+ EXPECT_EQ(result3.y, 1);
+
+ Vector2<float> result4 = float_vec1 - 1.0f;
+ EXPECT_FLOAT_EQ(result4.x, 0.0f);
+ EXPECT_FLOAT_EQ(result4.y, 1.0f);
+}
+
+TEST_F(Vector2Test, Add) {
+ Vector2<int> result = int_vec1 + int_vec2;
+ EXPECT_EQ(result.x, 4);
+ EXPECT_EQ(result.y, 6);
+
+ Vector2<double> result2 = double_vec1 + double_vec2;
+ EXPECT_FLOAT_EQ(result2.x, 4.0);
+ EXPECT_FLOAT_EQ(result2.y, 6.0);
+
+ Vector2<long> result3 = long_vec1 + long_vec2;
+ EXPECT_EQ(result3.x, 4);
+ EXPECT_EQ(result3.y, 6);
+
+ Vector2<float> result4 = float_vec1 + float_vec2;
+ EXPECT_FLOAT_EQ(result4.x, 4.0f);
+ EXPECT_FLOAT_EQ(result4.y, 6.0f);
+}
+
+TEST_F(Vector2Test, AddScalar) {
+ Vector2<int> result = int_vec1 + 1;
+ EXPECT_EQ(result.x, 2);
+ EXPECT_EQ(result.y, 3);
+
+ Vector2<double> result2 = double_vec1 + 1.0;
+ EXPECT_FLOAT_EQ(result2.x, 2.0);
+ EXPECT_FLOAT_EQ(result2.y, 3.0);
+
+ Vector2<long> result3 = long_vec1 + 1;
+ EXPECT_EQ(result3.x, 2);
+ EXPECT_EQ(result3.y, 3);
+
+ Vector2<float> result4 = float_vec1 + 1.0f;
+ EXPECT_FLOAT_EQ(result4.x, 2.0f);
+ EXPECT_FLOAT_EQ(result4.y, 3.0f);
+}
+
+TEST_F(Vector2Test, Multiply) {
+ Vector2<int> result = int_vec1 * int_vec2;
+ EXPECT_EQ(result.x, 3);
+ EXPECT_EQ(result.y, 8);
+
+ Vector2<double> result2 = double_vec1 * double_vec2;
+ EXPECT_FLOAT_EQ(result2.x, 3.0);
+ EXPECT_FLOAT_EQ(result2.y, 8.0);
+
+ Vector2<long> result3 = long_vec1 * long_vec2;
+ EXPECT_EQ(result3.x, 3);
+ EXPECT_EQ(result3.y, 8);
+
+ Vector2<float> result4 = float_vec1 * float_vec2;
+ EXPECT_FLOAT_EQ(result4.x, 3.0f);
+ EXPECT_FLOAT_EQ(result4.y, 8.0f);
+}
+
+TEST_F(Vector2Test, MultiplyScalar) {
+ Vector2<int> result = int_vec1 * 2;
+ EXPECT_EQ(result.x, 2);
+ EXPECT_EQ(result.y, 4);
+
+ Vector2<double> result2 = double_vec1 * 2.0;
+ EXPECT_FLOAT_EQ(result2.x, 2.0);
+ EXPECT_FLOAT_EQ(result2.y, 4.0);
+
+ Vector2<long> result3 = long_vec1 * 2;
+ EXPECT_EQ(result3.x, 2);
+ EXPECT_EQ(result3.y, 4);
+
+ Vector2<float> result4 = float_vec1 * 2.0f;
+ EXPECT_FLOAT_EQ(result4.x, 2.0f);
+ EXPECT_FLOAT_EQ(result4.y, 4.0f);
+}
+
+TEST_F(Vector2Test, Divide) {
+ Vector2<int> result = int_vec1 / int_vec2;
+ EXPECT_EQ(result.x, 0);
+ EXPECT_EQ(result.y, 0);
+
+ Vector2<double> result2 = double_vec1 / double_vec2;
+ EXPECT_FLOAT_EQ(result2.x, 0.33333333333333331);
+ EXPECT_FLOAT_EQ(result2.y, 0.5);
+
+ Vector2<long> result3 = long_vec1 / long_vec2;
+ EXPECT_EQ(result3.x, 0);
+ EXPECT_EQ(result3.y, 0);
+
+ Vector2<float> result4 = float_vec1 / float_vec2;
+ EXPECT_FLOAT_EQ(result4.x, 0.333333343f);
+ EXPECT_FLOAT_EQ(result4.y, 0.5f);
+}
+
+TEST_F(Vector2Test, DivideScalar) {
+ Vector2<int> result = int_vec1 / 2;
+ EXPECT_EQ(result.x, 0);
+ EXPECT_EQ(result.y, 1);
+
+ Vector2<double> result2 = double_vec1 / 2.0;
+ EXPECT_FLOAT_EQ(result2.x, 0.5);
+ EXPECT_FLOAT_EQ(result2.y, 1.0);
+
+ Vector2<long> result3 = long_vec1 / 2;
+ EXPECT_EQ(result3.x, 0);
+ EXPECT_EQ(result3.y, 1);
+
+ Vector2<float> result4 = float_vec1 / 2.0f;
+ EXPECT_FLOAT_EQ(result4.x, 0.5f);
+ EXPECT_FLOAT_EQ(result4.y, 1.0f);
+}
+
+TEST_F(Vector2Test, AddChain) {
+ Vector2<int> result = int_vec1;
+ result += int_vec2;
+ EXPECT_EQ(result.x, 4);
+ EXPECT_EQ(result.y, 6);
+
+ Vector2<double> result2 = double_vec1;
+ result2 += double_vec2;
+ EXPECT_FLOAT_EQ(result2.x, 4.0);
+ EXPECT_FLOAT_EQ(result2.y, 6.0);
+
+ Vector2<long> result3 = long_vec1;
+ result3 += long_vec2;
+ EXPECT_EQ(result3.x, 4);
+ EXPECT_EQ(result3.y, 6);
+
+ Vector2<float> result4 = float_vec1;
+ result4 += float_vec2;
+ EXPECT_FLOAT_EQ(result4.x, 4.0f);
+ EXPECT_FLOAT_EQ(result4.y, 6.0f);
+}
+
+TEST_F(Vector2Test, AddScalarChain) {
+ Vector2<int> result = int_vec1;
+ result += 1;
+ EXPECT_EQ(result.x, 2);
+ EXPECT_EQ(result.y, 3);
+
+ Vector2<double> result2 = double_vec1;
+ result2 += 1.0;
+ EXPECT_FLOAT_EQ(result2.x, 2.0);
+ EXPECT_FLOAT_EQ(result2.y, 3.0);
+
+ Vector2<long> result3 = long_vec1;
+ result3 += 1;
+ EXPECT_EQ(result3.x, 2);
+ EXPECT_EQ(result3.y, 3);
+
+ Vector2<float> result4 = float_vec1;
+ result4 += 1.0f;
+ EXPECT_FLOAT_EQ(result4.x, 2.0f);
+ EXPECT_FLOAT_EQ(result4.y, 3.0f);
+}
+
+TEST_F(Vector2Test, SubtractChain) {
+ Vector2<int> result = int_vec1;
+ result -= int_vec2;
+ EXPECT_EQ(result.x, -2);
+ EXPECT_EQ(result.y, -2);
+
+ Vector2<double> result2 = double_vec1;
+ result2 -= double_vec2;
+ EXPECT_FLOAT_EQ(result2.x, -2.0);
+ EXPECT_FLOAT_EQ(result2.y, -2.0);
+
+ Vector2<long> result3 = long_vec1;
+ result3 -= long_vec2;
+ EXPECT_EQ(result3.x, -2);
+ EXPECT_EQ(result3.y, -2);
+
+ Vector2<float> result4 = float_vec1;
+ result4 -= float_vec2;
+ EXPECT_FLOAT_EQ(result4.x, -2.0f);
+ EXPECT_FLOAT_EQ(result4.y, -2.0f);
+}
+
+TEST_F(Vector2Test, SubtractScalarChain) {
+ Vector2<int> result = int_vec1;
+ result -= 1;
+ EXPECT_EQ(result.x, 0);
+ EXPECT_EQ(result.y, 1);
+
+ Vector2<double> result2 = double_vec1;
+ result2 -= 1.0;
+ EXPECT_FLOAT_EQ(result2.x, 0.0);
+ EXPECT_FLOAT_EQ(result2.y, 1.0);
+
+ Vector2<long> result3 = long_vec1;
+ result3 -= 1;
+ EXPECT_EQ(result3.x, 0);
+ EXPECT_EQ(result3.y, 1);
+
+ Vector2<float> result4 = float_vec1;
+ result4 -= 1.0f;
+ EXPECT_FLOAT_EQ(result4.x, 0.0f);
+ EXPECT_FLOAT_EQ(result4.y, 1.0f);
+}
+
+TEST_F(Vector2Test, MultiplyChain) {
+ Vector2<int> result = int_vec1;
+ result *= int_vec2;
+ EXPECT_EQ(result.x, 3);
+ EXPECT_EQ(result.y, 8);
+
+ Vector2<double> result2 = double_vec1;
+ result2 *= double_vec2;
+ EXPECT_FLOAT_EQ(result2.x, 3.0);
+ EXPECT_FLOAT_EQ(result2.y, 8.0);
+
+ Vector2<long> result3 = long_vec1;
+ result3 *= long_vec2;
+ EXPECT_EQ(result3.x, 3);
+ EXPECT_EQ(result3.y, 8);
+
+ Vector2<float> result4 = float_vec1;
+ result4 *= float_vec2;
+ EXPECT_FLOAT_EQ(result4.x, 3.0f);
+ EXPECT_FLOAT_EQ(result4.y, 8.0f);
+}
+
+TEST_F(Vector2Test, MultiplyScalarChain) {
+ Vector2<int> result = int_vec1;
+ result *= 2;
+ EXPECT_EQ(result.x, 2);
+ EXPECT_EQ(result.y, 4);
+
+ Vector2<double> result2 = double_vec1;
+ result2 *= 2.0;
+ EXPECT_FLOAT_EQ(result2.x, 2.0);
+ EXPECT_FLOAT_EQ(result2.y, 4.0);
+
+ Vector2<long> result3 = long_vec1;
+ result3 *= 2;
+ EXPECT_EQ(result3.x, 2);
+ EXPECT_EQ(result3.y, 4);
+
+ Vector2<float> result4 = float_vec1;
+ result4 *= 2.0f;
+ EXPECT_FLOAT_EQ(result4.x, 2.0f);
+ EXPECT_FLOAT_EQ(result4.y, 4.0f);
+}
+
+TEST_F(Vector2Test, DivideChain) {
+ Vector2<int> result = int_vec1;
+ result /= int_vec2;
+ EXPECT_EQ(result.x, 0);
+ EXPECT_EQ(result.y, 0);
+
+ Vector2<double> result2 = double_vec1;
+ result2 /= double_vec2;
+ EXPECT_FLOAT_EQ(result2.x, 0.33333333333333331);
+ EXPECT_FLOAT_EQ(result2.y, 0.5);
+
+ Vector2<long> result3 = long_vec1;
+ result3 /= long_vec2;
+ EXPECT_EQ(result3.x, 0);
+ EXPECT_EQ(result3.y, 0);
+
+ Vector2<float> result4 = float_vec1;
+ result4 /= float_vec2;
+ EXPECT_FLOAT_EQ(result4.x, 0.333333343f);
+ EXPECT_FLOAT_EQ(result4.y, 0.5f);
+}
+
+TEST_F(Vector2Test, DivideScalarChain) {
+ Vector2<int> result = int_vec1;
+ result /= 2;
+ EXPECT_EQ(result.x, 0);
+ EXPECT_EQ(result.y, 1);
+
+ Vector2<double> result2 = double_vec1;
+ result2 /= 2.0;
+ EXPECT_FLOAT_EQ(result2.x, 0.5);
+ EXPECT_FLOAT_EQ(result2.y, 1.0);
+
+ Vector2<long> result3 = long_vec1;
+ result3 /= 2;
+ EXPECT_EQ(result3.x, 0);
+ EXPECT_EQ(result3.y, 1);
+
+ Vector2<float> result4 = float_vec1;
+ result4 /= 2.0f;
+ EXPECT_FLOAT_EQ(result4.x, 0.5f);
+ EXPECT_FLOAT_EQ(result4.y, 1.0f);
+}
+
+TEST_F(Vector2Test, Negatation) {
+ Vector2<int> result = -int_vec1;
+ EXPECT_EQ(result.x, -1);
+ EXPECT_EQ(result.y, -2);
+
+ Vector2<double> result2 = -double_vec1;
+ EXPECT_FLOAT_EQ(result2.x, -1.0);
+ EXPECT_FLOAT_EQ(result2.y, -2.0);
+
+ Vector2<long> result3 = -long_vec1;
+ EXPECT_EQ(result3.x, -1);
+ EXPECT_EQ(result3.y, -2);
+
+ Vector2<float> result4 = -float_vec1;
+ EXPECT_FLOAT_EQ(result4.x, -1.0f);
+ EXPECT_FLOAT_EQ(result4.y, -2.0f);
+}
+
+TEST_F(Vector2Test, Equals) {
+ EXPECT_TRUE(int_vec1 == int_vec1);
+ EXPECT_FALSE(int_vec1 == int_vec2);
+ EXPECT_TRUE(double_vec1 == double_vec1);
+ EXPECT_FALSE(double_vec1 == double_vec2);
+ EXPECT_TRUE(long_vec1 == long_vec1);
+ EXPECT_FALSE(long_vec1 == long_vec2);
+}
+
+TEST_F(Vector2Test, NotEquals) {
+ EXPECT_FALSE(int_vec1 != int_vec1);
+ EXPECT_TRUE(int_vec1 != int_vec2);
+ EXPECT_FALSE(double_vec1 != double_vec1);
+ EXPECT_TRUE(double_vec1 != double_vec2);
+ EXPECT_FALSE(long_vec1 != long_vec1);
+ EXPECT_TRUE(long_vec1 != long_vec2);
+}
diff --git a/src/test/main.cpp b/src/test/main.cpp
index 241015d..aece72d 100644
--- a/src/test/main.cpp
+++ b/src/test/main.cpp
@@ -1,15 +1,30 @@
-#include <crepe/api/Config.h>
-
#include <gtest/gtest.h>
+#define protected public
+#define private public
+
+#include <crepe/api/Config.h>
+
using namespace crepe;
using namespace testing;
+class GlobalConfigReset : public EmptyTestEventListener {
+public:
+ Config & cfg = Config::get_instance();
+ Config cfg_default = Config();
+
+ // This function is called before each test
+ void OnTestStart(const TestInfo &) override {
+ cfg = cfg_default;
+ cfg.log.level = Log::Level::WARNING;
+ }
+};
+
int main(int argc, char ** argv) {
InitGoogleTest(&argc, argv);
- auto & cfg = Config::get_instance();
- cfg.log.level = Log::Level::ERROR;
+ UnitTest & ut = *UnitTest::GetInstance();
+ ut.listeners().Append(new GlobalConfigReset);
return RUN_ALL_TESTS();
}