aboutsummaryrefslogtreecommitdiff
path: root/src/crepe
diff options
context:
space:
mode:
Diffstat (limited to 'src/crepe')
-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/BehaviorScript.h7
-rw-r--r--src/crepe/api/BehaviorScript.hpp12
-rw-r--r--src/crepe/api/CMakeLists.txt3
-rw-r--r--src/crepe/api/Event.h12
-rw-r--r--src/crepe/api/EventHandler.hpp2
-rw-r--r--src/crepe/api/EventManager.h4
-rw-r--r--src/crepe/api/GameObject.cpp2
-rw-r--r--src/crepe/api/GameObject.h3
-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/Script.cpp15
-rw-r--r--src/crepe/api/Script.h129
-rw-r--r--src/crepe/api/Script.hpp32
-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/system/ScriptSystem.cpp29
-rw-r--r--src/crepe/system/ScriptSystem.h11
-rw-r--r--src/crepe/types.h14
-rw-r--r--src/crepe/util/Log.h10
31 files changed, 419 insertions, 160 deletions
diff --git a/src/crepe/ComponentManager.cpp b/src/crepe/ComponentManager.cpp
index 97df1f3..2d12034 100644
--- a/src/crepe/ComponentManager.cpp
+++ b/src/crepe/ComponentManager.cpp
@@ -1,4 +1,5 @@
#include "api/GameObject.h"
+#include "types.h"
#include "util/Log.h"
#include "ComponentManager.h"
@@ -34,7 +35,7 @@ void ComponentManager::delete_all_components() {
}
GameObject ComponentManager::new_object(const string & name, const string & tag,
- const Vector2 & position, double rotation,
+ const vec2 & position, double rotation,
double scale) {
// Find the first available id (taking persistent objects into account)
while (this->persistent[this->next_id]) {
diff --git a/src/crepe/ComponentManager.h b/src/crepe/ComponentManager.h
index 8fc7d6c..810bc38 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/BehaviorScript.h b/src/crepe/api/BehaviorScript.h
index 9d85d4c..d556fe5 100644
--- a/src/crepe/api/BehaviorScript.h
+++ b/src/crepe/api/BehaviorScript.h
@@ -39,11 +39,14 @@ public:
* \brief Set the concrete script of this component
*
* \tparam T Concrete script type (derived from \c crepe::Script)
+ * \tparam Args Arguments for concrete script constructor
+ *
+ * \param args Arguments for concrete script constructor (forwarded using perfect forwarding)
*
* \returns Reference to BehaviorScript component (`*this`)
*/
- template <class T>
- BehaviorScript & set_script();
+ template <class T, typename... Args>
+ BehaviorScript & set_script(Args &&... args);
protected:
//! Script instance
diff --git a/src/crepe/api/BehaviorScript.hpp b/src/crepe/api/BehaviorScript.hpp
index d80321d..bd59337 100644
--- a/src/crepe/api/BehaviorScript.hpp
+++ b/src/crepe/api/BehaviorScript.hpp
@@ -9,13 +9,17 @@
namespace crepe {
-template <class T>
-BehaviorScript & BehaviorScript::set_script() {
+template <class T, typename... Args>
+BehaviorScript & BehaviorScript::set_script(Args &&... args) {
dbg_trace();
static_assert(std::is_base_of<Script, T>::value);
- Script * s = new T();
+ Script * s = new T(std::forward<Args>(args)...);
+
s->game_object_id = this->game_object_id;
- s->component_manager_ref = &this->component_manager;
+ s->active = this->active;
+ s->component_manager = this->component_manager;
+ s->event_manager = EventManager::get_instance();
+
this->script = std::unique_ptr<Script>(s);
return *this;
}
diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt
index d6b6801..c3e0b37 100644
--- a/src/crepe/api/CMakeLists.txt
+++ b/src/crepe/api/CMakeLists.txt
@@ -14,7 +14,6 @@ target_sources(crepe PUBLIC
Metadata.cpp
Scene.cpp
SceneManager.cpp
- Vector2.cpp
Camera.cpp
Animator.cpp
EventManager.cpp
@@ -24,6 +23,7 @@ target_sources(crepe PUBLIC
LoopTimer.cpp
Asset.cpp
EventHandler.cpp
+ Script.cpp
)
target_sources(crepe PUBLIC FILE_SET HEADERS FILES
@@ -37,6 +37,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/Event.h b/src/crepe/api/Event.h
index 06cf7f3..b267e3e 100644
--- a/src/crepe/api/Event.h
+++ b/src/crepe/api/Event.h
@@ -1,10 +1,12 @@
-// TODO discussing the location of these events
#pragma once
+// TODO discussing the location of these events
#include <string>
#include "KeyCodes.h"
+namespace crepe {
+
/**
* \brief Base class for all event types in the system.
*/
@@ -91,11 +93,7 @@ public:
/**
* \brief Event triggered during a collision between objects.
*/
-class CollisionEvent : public Event {
-public:
- //! Data describing the collision (currently not implemented).
- // Collision collisionData;
-};
+class CollisionEvent : public Event {};
/**
* \brief Event triggered when text is submitted, e.g., from a text input.
@@ -110,3 +108,5 @@ public:
* \brief Event triggered to indicate the application is shutting down.
*/
class ShutDownEvent : public Event {};
+
+} // namespace crepe
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/EventManager.h b/src/crepe/api/EventManager.h
index 348a04d..1a33023 100644
--- a/src/crepe/api/EventManager.h
+++ b/src/crepe/api/EventManager.h
@@ -77,7 +77,7 @@ public:
* \param channel The channel to trigger the event on (default is CHANNEL_ALL, which triggers on all channels).
*/
template <typename EventType>
- void trigger_event(const EventType & event, event_channel_t channel = CHANNEL_ALL);
+ void trigger_event(const EventType & event = {}, event_channel_t channel = CHANNEL_ALL);
/**
* \brief Queue an event for later processing.
@@ -89,7 +89,7 @@ public:
* \param channel The channel to associate with the event (default is CHANNEL_ALL).
*/
template <typename EventType>
- void queue_event(const EventType & event, event_channel_t channel = CHANNEL_ALL);
+ void queue_event(const EventType & event = {}, event_channel_t channel = CHANNEL_ALL);
/**
* \brief Process all queued events.
diff --git a/src/crepe/api/GameObject.cpp b/src/crepe/api/GameObject.cpp
index 7c873ec..6c1de12 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 07d5ad2..a30dce3 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/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/Script.cpp b/src/crepe/api/Script.cpp
new file mode 100644
index 0000000..fcbe4c7
--- /dev/null
+++ b/src/crepe/api/Script.cpp
@@ -0,0 +1,15 @@
+#include "Script.h"
+
+using namespace crepe;
+
+Script::~Script() {
+ EventManager & evmgr = this->event_manager;
+ for (auto id : this->listeners) {
+ evmgr.unsubscribe(id);
+ }
+}
+
+template <>
+void Script::subscribe(const EventHandler<CollisionEvent> & callback) {
+ this->subscribe_internal(callback, this->game_object_id);
+}
diff --git a/src/crepe/api/Script.h b/src/crepe/api/Script.h
index 839d937..a0870cb 100644
--- a/src/crepe/api/Script.h
+++ b/src/crepe/api/Script.h
@@ -3,6 +3,9 @@
#include <vector>
#include "../types.h"
+#include "../util/OptionalRef.h"
+
+#include "EventManager.h"
namespace crepe {
@@ -16,13 +19,23 @@ class ComponentManager;
* This class is used as a base class for user-defined scripts that can be added to game
* objects using the \c BehaviorScript component.
*
- * \note Additional *events* (like Unity's OnDisable and OnEnable) should be implemented as
+ * \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 {
protected:
/**
- * \brief Script initialization function
+ * \name Interface functions
+ * \{
+ */
+ /**
+ * \brief Script initialization function (empty by default)
*
* This function is called during the ScriptSystem::update() routine *before*
* Script::update() if it (a) has not yet been called and (b) the \c BehaviorScript component
@@ -30,24 +43,31 @@ protected:
*/
virtual void init() {}
/**
- * \brief Script update function
+ * \brief Script update function (empty by default)
*
* This function is called during the ScriptSystem::update() routine if the \c BehaviorScript
* component holding this script instance is active.
*/
virtual void update() {}
+ //! \}
+
//! ScriptSystem calls \c init() and \c update()
friend class crepe::ScriptSystem;
protected:
/**
- * \brief Get single component of type \c T on this game object (utility)
+ * \name Utility functions
+ * \{
+ */
+
+ /**
+ * \brief Get single component of type \c T on this game object
*
* \tparam T Type of component
*
* \returns Reference to component
*
- * \throws nullptr 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;
@@ -55,7 +75,7 @@ protected:
// cause compile-time errors
/**
- * \brief Get all components of type \c T on this game object (utility)
+ * \brief Get all components of type \c T on this game object
*
* \tparam T Type of component
*
@@ -64,25 +84,108 @@ protected:
template <typename T>
RefVector<T> get_components() const;
+ /**
+ * \brief Log a message using Log::logf
+ *
+ * \tparam Args Log::logf parameters
+ * \param args Log::logf parameters
+ */
+ template <typename... Args>
+ void logf(Args &&... args);
+
+ /**
+ * \brief Subscribe to an event with an explicit channel
+ * \see EventManager::subscribe
+ */
+ template <typename EventType>
+ void subscribe(const EventHandler<EventType> & callback, event_channel_t channel);
+ /**
+ * \brief Subscribe to an event on EventManager::CHANNEL_ALL
+ * \see EventManager::subscribe
+ */
+ template <typename EventType>
+ void subscribe(const EventHandler<EventType> & callback);
+
+ //! \}
+
+private:
+ /**
+ * \brief Internal subscribe function
+ *
+ * This function exists so certain template specializations of Script::subscribe can be
+ * explicitly deleted, and does the following:
+ * - Wrap the user-provided callback in a check that tests if the parent BehaviorScript
+ * component is still active
+ * - Store the subscriber handle returned by the event manager so this listener is
+ * automatically unsubscribed at the end of this Script instance's life
+ *
+ * \tparam EventType concrete Event class
+ * \param callback User-provided callback function
+ * \param channel Event channel (may have been overridden by template specializations)
+ */
+ template <typename EventType>
+ void subscribe_internal(const EventHandler<EventType> & callback, event_channel_t channel);
+
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.
+ // NOTE: This must be the only constructor on Script, see "Late references" below
Script() = default;
//! Only \c BehaviorScript instantiates Script
friend class BehaviorScript;
+public:
+ // std::unique_ptr destroys script
+ virtual ~Script();
+
+private:
+ Script(const Script &) = delete;
+ Script(Script &&) = delete;
+ Script & operator=(const Script &) = delete;
+ Script & operator=(Script &&) = delete;
+
private:
- // These references are set by BehaviorScript immediately after calling the constructor of
- // Script.
- game_object_id_t game_object_id = -1;
- ComponentManager * component_manager_ref = nullptr;
- // TODO: use OptionalRef instead of pointer
+ /**
+ * \name Late references
+ *
+ * These references are set by BehaviorScript immediately after calling the constructor of
+ * Script.
+ *
+ * \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 if they want to
+ * implement a non-default constructor (e.g. for passing references to their own concrete
+ * Script classes).
+ *
+ * \{
+ */
+ //! Game object ID of game object parent BehaviorScript is attached to
+ game_object_id_t game_object_id;
+ //! Reference to parent component
+ OptionalRef<bool> active;
+ //! Reference to component manager instance
+ OptionalRef<ComponentManager> component_manager;
+ //! Reference to event manager instance
+ OptionalRef<EventManager> event_manager;
+ //! \}
private:
//! Flag to indicate if \c init() has been called already
bool initialized = false;
+ //! List of subscribed events
+ std::vector<subscription_t> listeners;
};
+/**
+ * \brief Subscribe to CollisionEvent for the current GameObject
+ *
+ * This is a template specialization for Script::subscribe which automatically sets the event
+ * channel so the callback handler is only called for CollisionEvent events that apply to the
+ * current GameObject the parent BehaviorScript is attached to.
+ */
+template <>
+void Script::subscribe(const EventHandler<CollisionEvent> & callback);
+template <>
+void Script::subscribe(const EventHandler<CollisionEvent> & callback, event_channel_t)
+ = delete;
+
} // namespace crepe
#include "Script.hpp"
diff --git a/src/crepe/api/Script.hpp b/src/crepe/api/Script.hpp
index a85d814..a2463bf 100644
--- a/src/crepe/api/Script.hpp
+++ b/src/crepe/api/Script.hpp
@@ -20,8 +20,38 @@ T & Script::get_component() const {
template <typename T>
RefVector<T> Script::get_components() const {
- auto & mgr = *this->component_manager_ref;
+ ComponentManager & mgr = this->component_manager;
+
return mgr.get_components_by_id<T>(this->game_object_id);
}
+template <typename... Args>
+void Script::logf(Args &&... args) {
+ Log::logf(std::forward<Args>(args)...);
+}
+
+template <typename EventType>
+void Script::subscribe_internal(const EventHandler<EventType> & callback,
+ event_channel_t channel) {
+ EventManager & mgr = this->event_manager;
+ subscription_t listener = mgr.subscribe<EventType>(
+ [this, callback](const EventType & data) -> bool {
+ bool & active = this->active;
+ if (!active) return false;
+ return callback(data);
+ },
+ channel);
+ this->listeners.push_back(listener);
+}
+
+template <typename EventType>
+void Script::subscribe(const EventHandler<EventType> & callback, event_channel_t channel) {
+ this->subscribe_internal(callback, channel);
+}
+
+template <typename EventType>
+void Script::subscribe(const EventHandler<EventType> & callback) {
+ this->subscribe_internal(callback, EventManager::CHANNEL_ALL);
+}
+
} // namespace crepe
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/system/ScriptSystem.cpp b/src/crepe/system/ScriptSystem.cpp
index c33309c..20a83f7 100644
--- a/src/crepe/system/ScriptSystem.cpp
+++ b/src/crepe/system/ScriptSystem.cpp
@@ -1,5 +1,3 @@
-#include <functional>
-
#include "../ComponentManager.h"
#include "../api/BehaviorScript.h"
#include "../api/Script.h"
@@ -12,30 +10,19 @@ using namespace crepe;
void ScriptSystem::update() {
dbg_trace();
- RefVector<Script> scripts = this->get_scripts();
-
- for (auto & script_ref : scripts) {
- Script & script = script_ref.get();
- if (!script.initialized) {
- script.init();
- script.initialized = true;
- }
- script.update();
- }
-}
-
-RefVector<Script> ScriptSystem::get_scripts() const {
- RefVector<Script> scripts = {};
ComponentManager & mgr = this->component_manager;
RefVector<BehaviorScript> behavior_scripts = mgr.get_components_by_type<BehaviorScript>();
- for (auto behavior_script_ref : behavior_scripts) {
- BehaviorScript & behavior_script = behavior_script_ref.get();
+ for (BehaviorScript & behavior_script : behavior_scripts) {
if (!behavior_script.active) continue;
+
Script * script = behavior_script.script.get();
if (script == nullptr) continue;
- scripts.push_back(*script);
- }
- return scripts;
+ if (!script->initialized) {
+ script->init();
+ script->initialized = true;
+ }
+ script->update();
+ }
}
diff --git a/src/crepe/system/ScriptSystem.h b/src/crepe/system/ScriptSystem.h
index 32e1fcd..936e9ca 100644
--- a/src/crepe/system/ScriptSystem.h
+++ b/src/crepe/system/ScriptSystem.h
@@ -2,8 +2,6 @@
#include "System.h"
-#include "../types.h"
-
namespace crepe {
class Script;
@@ -25,15 +23,6 @@ public:
* the \c BehaviorScript instance.
*/
void update() override;
-
-private:
- /**
- * \brief Aggregate all active \c BehaviorScript components and return a list
- * of references to their \c Script instances (utility)
- *
- * \returns List of active \c Script instances
- */
- RefVector<Script> get_scripts() const;
};
} // namespace crepe
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/crepe/util/Log.h b/src/crepe/util/Log.h
index d55b11e..fc0bb3a 100644
--- a/src/crepe/util/Log.h
+++ b/src/crepe/util/Log.h
@@ -34,11 +34,11 @@ class Log {
public:
//! Log message severity
enum Level {
- TRACE, //< Include (internal) function calls
- DEBUG, //< Include dbg_logf output
- INFO, //< General-purpose messages
- WARNING, //< Non-fatal errors
- ERROR, //< Fatal errors
+ TRACE, //!< Include (internal) function calls
+ DEBUG, //!< Include dbg_logf output
+ INFO, //!< General-purpose messages
+ WARNING, //!< Non-fatal errors
+ ERROR, //!< Fatal errors
};
/**