diff options
Diffstat (limited to 'src/crepe/api')
-rw-r--r-- | src/crepe/api/BehaviorScript.h | 7 | ||||
-rw-r--r-- | src/crepe/api/BehaviorScript.hpp | 12 | ||||
-rw-r--r-- | src/crepe/api/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/crepe/api/Event.h | 12 | ||||
-rw-r--r-- | src/crepe/api/EventHandler.hpp | 2 | ||||
-rw-r--r-- | src/crepe/api/EventManager.h | 4 | ||||
-rw-r--r-- | src/crepe/api/GameObject.cpp | 2 | ||||
-rw-r--r-- | src/crepe/api/GameObject.h | 3 | ||||
-rw-r--r-- | src/crepe/api/ParticleEmitter.h | 8 | ||||
-rw-r--r-- | src/crepe/api/Rigidbody.cpp | 2 | ||||
-rw-r--r-- | src/crepe/api/Rigidbody.h | 10 | ||||
-rw-r--r-- | src/crepe/api/Script.cpp | 15 | ||||
-rw-r--r-- | src/crepe/api/Script.h | 129 | ||||
-rw-r--r-- | src/crepe/api/Script.hpp | 32 | ||||
-rw-r--r-- | src/crepe/api/Transform.cpp | 2 | ||||
-rw-r--r-- | src/crepe/api/Transform.h | 7 | ||||
-rw-r--r-- | src/crepe/api/Vector2.cpp | 33 | ||||
-rw-r--r-- | src/crepe/api/Vector2.h | 55 | ||||
-rw-r--r-- | src/crepe/api/Vector2.hpp | 118 |
19 files changed, 365 insertions, 91 deletions
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 4025a63..50c51ed 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -13,7 +13,6 @@ target_sources(crepe PUBLIC Config.cpp Metadata.cpp SceneManager.cpp - Vector2.cpp Camera.cpp Animator.cpp EventManager.cpp @@ -23,6 +22,7 @@ target_sources(crepe PUBLIC LoopTimer.cpp Asset.cpp EventHandler.cpp + Script.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES @@ -36,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/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 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/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 |