diff --git a/CMakeLists.txt b/CMakeLists.txt index 252cda2..c9dcdb9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,8 @@ set (SOURCE_FILES "src/vpg/ecs/transform.hpp" "src/vpg/ecs/transform.cpp" + "src/vpg/ecs/behaviour.hpp" + "src/vpg/ecs/behaviour.cpp" ) add_executable(vpg ${SOURCE_FILES}) diff --git a/src/vpg/ecs/behaviour.cpp b/src/vpg/ecs/behaviour.cpp new file mode 100644 index 0000000..b8295df --- /dev/null +++ b/src/vpg/ecs/behaviour.cpp @@ -0,0 +1,35 @@ +#include + +using namespace vpg::ecs; + +vpg::ecs::Behaviour::Behaviour() { + this->behaviour = nullptr; +} + +Behaviour::Behaviour(Behaviour&& rhs) noexcept { + this->behaviour = rhs.behaviour; + rhs.behaviour = nullptr; +} + +Behaviour::~Behaviour() { + if (this->behaviour != nullptr) { + delete this->behaviour; + } +} + +void vpg::ecs::Behaviour::update(float dt) { + if (this->behaviour != nullptr) { + this->behaviour->update(dt); + } +} + +BehaviourSystem::BehaviourSystem() { + this->signature.set(Coordinator::get_component_type()); +} + +void BehaviourSystem::update(float dt) { + for (auto& entity : this->entities) { + auto& behaviour = *Coordinator::get_component(entity); + behaviour.update(dt); + } +} diff --git a/src/vpg/ecs/behaviour.hpp b/src/vpg/ecs/behaviour.hpp new file mode 100644 index 0000000..774a265 --- /dev/null +++ b/src/vpg/ecs/behaviour.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include + +namespace vpg::ecs { + class IBehaviour { + public: + virtual ~IBehaviour() = default; + + inline virtual void update(float dt) {} + }; + + class Behaviour { + public: + Behaviour(); + template + static Behaviour create(Entity entity, TArgs... args); + Behaviour(Behaviour&& rhs) noexcept; + Behaviour(const Behaviour&) = delete; + ~Behaviour(); + + void update(float dt); + + private: + IBehaviour* behaviour; + }; + + template + inline static Behaviour Behaviour::create(Entity entity, TArgs ...args) { + static_assert(std::is_base_of::value); + Behaviour ret; + ret.behaviour = new T(entity, args...); + return std::move(ret); + } + + class BehaviourSystem : public System { + public: + BehaviourSystem(); + + void update(float dt); + }; +} \ No newline at end of file diff --git a/src/vpg/ecs/component_array.hpp b/src/vpg/ecs/component_array.hpp index e1ae786..31d4170 100644 --- a/src/vpg/ecs/component_array.hpp +++ b/src/vpg/ecs/component_array.hpp @@ -43,7 +43,8 @@ namespace vpg::ecs { abort(); } - this->components[this->count] = std::move(component); + this->components[this->count].~T(); + new (&this->components[this->count]) T(std::move(component)); this->index_to_entity.emplace(this->count, entity); this->entity_to_index.emplace(entity, this->count); this->count += 1; @@ -62,7 +63,8 @@ namespace vpg::ecs { this->entity_to_index.erase(it); this->count -= 1; - this->components[index] = std::move(this->components[this->count]); + this->components[index].~T(); + new (&this->components[this->count]) T(std::move(this->components[this->count])); auto last_entity = this->index_to_entity[this->count]; this->index_to_entity.erase(this->count); this->entity_to_index[last_entity] = index; diff --git a/src/vpg/entry.cpp b/src/vpg/entry.cpp index a7ad05a..3d7db9b 100644 --- a/src/vpg/entry.cpp +++ b/src/vpg/entry.cpp @@ -5,6 +5,8 @@ #include #include +#include +#include #include #include @@ -14,6 +16,21 @@ using namespace vpg; +class MyBehaviour : public ecs::IBehaviour { +public: + MyBehaviour(ecs::Entity entity) { + std::cout << "Initialized MyBehaviour on entity " << entity << '\n'; + } + + ~MyBehaviour() { + std::cout << "Destroyed MyBehaviour\n"; + } + + virtual void update(float dt) override { + std::cout << "Updated MyBehaviour with dt " << dt << '\n'; + } +}; + int main(int argc, char** argv) { Config::load(argc, argv); @@ -62,14 +79,29 @@ int main(int argc, char** argv) { auto shader = data::Manager::load("shader.mesh"); auto model = data::Manager::load("model.chr_knight"); + // Init Entity-Component System + ecs::Coordinator::register_component(); + ecs::Coordinator::register_component(); + auto behaviour_sys = ecs::Coordinator::register_system(); + + auto last_time = (float)glfwGetTime(); + auto delta_time = 0.0f; while (!glfwWindowShouldClose(window)) { glfwPollEvents(); + // Update behaviours + behaviour_sys->update(delta_time); + // Render here lighting->get_shader().bind(); glDrawArrays(GL_TRIANGLES, 0, 6); glfwSwapBuffers(window); + + // Calculate delta time + auto new_time = (float)glfwGetTime(); + delta_time = new_time - last_time; + last_time = new_time; } // Unload assets