diff options
author | Max-001 <80035972+Max-001@users.noreply.github.com> | 2024-09-25 21:08:54 +0200 |
---|---|---|
committer | Max-001 <80035972+Max-001@users.noreply.github.com> | 2024-09-25 21:08:54 +0200 |
commit | 5458abaca5f01a4d34bb55b1b44dc4fb4e9890be (patch) | |
tree | a23e35dc95c69aced7d4e16550a2b4fff8507a6c /mwe/ecs-homemade | |
parent | 918392ec503a66e369fffa3a5a49c8afccf96a62 (diff) |
Made a homemade ECS
Diffstat (limited to 'mwe/ecs-homemade')
-rw-r--r-- | mwe/ecs-homemade/CMakeLists.txt | 6 | ||||
-rw-r--r-- | mwe/ecs-homemade/inc/ComponentManager.h | 37 | ||||
-rw-r--r-- | mwe/ecs-homemade/inc/ComponentManager.hpp | 58 | ||||
-rw-r--r-- | mwe/ecs-homemade/inc/Components.h | 22 | ||||
-rw-r--r-- | mwe/ecs-homemade/inc/GameObjectMax.h | 20 | ||||
-rw-r--r-- | mwe/ecs-homemade/inc/GameObjectMax.hpp | 6 | ||||
-rw-r--r-- | mwe/ecs-homemade/src/ComponentManager.cpp | 9 | ||||
-rw-r--r-- | mwe/ecs-homemade/src/Components.cpp | 10 | ||||
-rw-r--r-- | mwe/ecs-homemade/src/GameObjectMax.cpp | 5 | ||||
-rw-r--r-- | mwe/ecs-homemade/src/main.cpp | 36 |
10 files changed, 207 insertions, 2 deletions
diff --git a/mwe/ecs-homemade/CMakeLists.txt b/mwe/ecs-homemade/CMakeLists.txt index 26bf600..5960181 100644 --- a/mwe/ecs-homemade/CMakeLists.txt +++ b/mwe/ecs-homemade/CMakeLists.txt @@ -2,9 +2,13 @@ cmake_minimum_required(VERSION 3.5) project(ecs-homemake) # Set the C++ standard (optional, but good practice) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED True) add_executable(ecs-homemake src/main.cpp + src/ComponentManager.cpp + src/Components.cpp + src/GameObjectMax.cpp ) +target_include_directories(ecs-homemake PRIVATE "${CMAKE_SOURCE_DIR}/inc") diff --git a/mwe/ecs-homemade/inc/ComponentManager.h b/mwe/ecs-homemade/inc/ComponentManager.h new file mode 100644 index 0000000..cfc5f20 --- /dev/null +++ b/mwe/ecs-homemade/inc/ComponentManager.h @@ -0,0 +1,37 @@ +#pragma once + +#include "Components.h" +#include <cstdint> +#include <unordered_map> +#include <vector> +#include <typeindex> +#include <memory> +#include <any> + +class ComponentManager { +public: + static ComponentManager& GetInstance(); + + ComponentManager(const ComponentManager&) = delete; + ComponentManager(ComponentManager&&) = delete; + ComponentManager& operator=(const ComponentManager&) = delete; + ComponentManager& operator=(ComponentManager&&) = delete; + + template <typename T> + void AddComponent(T* component, std::uint32_t id); + template <typename T> + T* GetComponent(std::uint32_t id); + template <typename T> + std::vector<std::uint32_t> GetAllComponentIDs(); + template <typename T> + std::vector<T*> GetAllComponentPointer(); + +private: + static ComponentManager mInstance; + + ComponentManager(); + + std::unordered_map<std::type_index, std::vector<Component*>> mComponents; //TODO: Make this not only work with Component* OR add extra checks at templated methodes!!! +}; + +#include "ComponentManager.hpp" diff --git a/mwe/ecs-homemade/inc/ComponentManager.hpp b/mwe/ecs-homemade/inc/ComponentManager.hpp new file mode 100644 index 0000000..df8ea32 --- /dev/null +++ b/mwe/ecs-homemade/inc/ComponentManager.hpp @@ -0,0 +1,58 @@ +// AddComponent implementation +template <typename T> +void ComponentManager::AddComponent(T* component, std::uint32_t id) { + std::type_index type = typeid(T); + if (mComponents.find(type) == mComponents.end()) { + mComponents[type] = std::vector<Component*>(); + } + // Resize the vector if the id is greater than current size + if (id >= mComponents[type].size()) { + mComponents[type].resize(id + 1, nullptr); // Initialize new slots to nullptr + } + mComponents[type][id] = component; // Store the raw pointer +} + +// GetComponent implementation +template <typename T> +T* ComponentManager::GetComponent(std::uint32_t id) { + std::type_index type = typeid(T); + if (mComponents.find(type) != mComponents.end()) { + auto& componentArray = mComponents[type]; + if (id < componentArray.size()) { + return static_cast<T*>(componentArray[id]); // Cast to the correct type + } + } + return nullptr; // Return nullptr if not found +} + +// GetAllComponentIDs implementation +template <typename T> +std::vector<std::uint32_t> ComponentManager::GetAllComponentIDs() { + std::type_index type = typeid(T); + std::vector<std::uint32_t> ids; + if (mComponents.find(type) != mComponents.end()) { + const auto& componentArray = mComponents[type]; + for (std::uint32_t id = 0; id < componentArray.size(); ++id) { + if (componentArray[id] != nullptr) { + ids.push_back(id); // Collect IDs of non-null components + } + } + } + return ids; +} + +// GetAllComponentPointer implementation +template <typename T> +std::vector<T*> ComponentManager::GetAllComponentPointer() { + std::type_index type = typeid(T); + std::vector<T*> pointers; + if (mComponents.find(type) != mComponents.end()) { + const auto& componentArray = mComponents[type]; + for (const auto& component : componentArray) { + if (component != nullptr) { + pointers.push_back(static_cast<T*>(component)); // Cast to the correct type + } + } + } + return pointers; +} diff --git a/mwe/ecs-homemade/inc/Components.h b/mwe/ecs-homemade/inc/Components.h new file mode 100644 index 0000000..1ea8428 --- /dev/null +++ b/mwe/ecs-homemade/inc/Components.h @@ -0,0 +1,22 @@ +#pragma once + +class Component { +public: + Component(); + + bool mActive; +}; + +class Sprite : public Component { +public: + void Render(); +}; + +class Rigidbody : public Component { +public: + Rigidbody(int mass, int gravityScale, int bodyType); + + int mMass; + int mGravityScale; + int mBodyType; +}; diff --git a/mwe/ecs-homemade/inc/GameObjectMax.h b/mwe/ecs-homemade/inc/GameObjectMax.h new file mode 100644 index 0000000..dbfe981 --- /dev/null +++ b/mwe/ecs-homemade/inc/GameObjectMax.h @@ -0,0 +1,20 @@ +#pragma once + +#include <cstdint> +#include <string> + +class GameObject { +public: + GameObject(std::uint32_t id, std::string name, std::string tag, int layer); + + template <typename T> + void AddComponent(T* component); + + std::uint32_t mId; + std::string mName; + std::string mTag; + bool mActive; + int mLayer; +}; + +#include "GameObjectMax.hpp" diff --git a/mwe/ecs-homemade/inc/GameObjectMax.hpp b/mwe/ecs-homemade/inc/GameObjectMax.hpp new file mode 100644 index 0000000..e1a49be --- /dev/null +++ b/mwe/ecs-homemade/inc/GameObjectMax.hpp @@ -0,0 +1,6 @@ +#include "ComponentManager.h" + +template <typename T> +void GameObject::AddComponent(T* component) { + ComponentManager::GetInstance().AddComponent(component, mId); +} diff --git a/mwe/ecs-homemade/src/ComponentManager.cpp b/mwe/ecs-homemade/src/ComponentManager.cpp new file mode 100644 index 0000000..287da38 --- /dev/null +++ b/mwe/ecs-homemade/src/ComponentManager.cpp @@ -0,0 +1,9 @@ +#include "ComponentManager.h" + +ComponentManager ComponentManager::mInstance; + +ComponentManager& ComponentManager::GetInstance() { + return mInstance; +} + +ComponentManager::ComponentManager() {} diff --git a/mwe/ecs-homemade/src/Components.cpp b/mwe/ecs-homemade/src/Components.cpp new file mode 100644 index 0000000..3aece4b --- /dev/null +++ b/mwe/ecs-homemade/src/Components.cpp @@ -0,0 +1,10 @@ +#include "Components.h" +#include <iostream> + +Component::Component() : mActive(true) {} + +void Sprite::Render() { + std::cout << "Rendering sprite" << std::endl; +} + +Rigidbody::Rigidbody(int mass, int gravityScale, int bodyType) : mMass(mass), mGravityScale(gravityScale), mBodyType(bodyType) {} diff --git a/mwe/ecs-homemade/src/GameObjectMax.cpp b/mwe/ecs-homemade/src/GameObjectMax.cpp new file mode 100644 index 0000000..62c41de --- /dev/null +++ b/mwe/ecs-homemade/src/GameObjectMax.cpp @@ -0,0 +1,5 @@ +#include "GameObjectMax.h" + +#include "ComponentManager.h" + +GameObject::GameObject(std::uint32_t id, std::string name, std::string tag, int layer) : mId(id), mName(name), mTag(tag), mActive(true), mLayer(layer) {} diff --git a/mwe/ecs-homemade/src/main.cpp b/mwe/ecs-homemade/src/main.cpp index f8b829c..3dd082f 100644 --- a/mwe/ecs-homemade/src/main.cpp +++ b/mwe/ecs-homemade/src/main.cpp @@ -1,5 +1,39 @@ #include <iostream> +#include <vector> +#include <cstdint> + +#include "ComponentManager.h" +#include "GameObjectMax.h" +#include "Components.h" int main() { - std::cout << "Hello, world!" << std::endl; + GameObject gameObect0(0, "Name: 0", "Tag: 0", 0); //Entity 0 + GameObject gameObect1(1, "Name: 1", "Tag: 1", 1); //Entity 1 + + Sprite sprite0; + Rigidbody rigidbody0(1, 2, 3); + gameObect0.AddComponent<Sprite>(&sprite0); //Add a sprite to entity0 + gameObect0.AddComponent<Rigidbody>(&rigidbody0); //Also add a rigidbody to entity0 + + Rigidbody rigidbody1(4, 5, 6); + gameObect1.AddComponent<Rigidbody>(&rigidbody1); //Only add a rigidbody to entity1 + + //The entities are now initialized + //Now I will demonstrate some ways of retreiving/getting components + + Rigidbody* rigidbodyOfEntity0 = ComponentManager::GetInstance().GetComponent<Rigidbody>(gameObect0.mId); //Get the pointer to the Rigidbody component of entity 0 + std::cout << "rigidbodyOfEntity0: " << rigidbodyOfEntity0->mMass << " " << rigidbodyOfEntity0->mGravityScale << " " << rigidbodyOfEntity0->mBodyType << std::endl; + std::cout << std::endl; + + std::vector<std::uint32_t> rigidbodyIDs = ComponentManager::GetInstance().GetAllComponentIDs<Rigidbody>(); //Get all the IDs that have a Rigidbody component + for(std::uint32_t ID : rigidbodyIDs) { + std::cout << "Rigidbody ID: " << ID << std::endl; + } + std::cout << std::endl; + + std::vector<Rigidbody*> rigidbodyComponents = ComponentManager::GetInstance().GetAllComponentPointer<Rigidbody>(); //Get all the pointers to the Rigidbody component(s) + for(Rigidbody* rigidbody : rigidbodyComponents) { + std::cout << "rigidbody: " << rigidbody->mMass << " " << rigidbody->mGravityScale << " " << rigidbody->mBodyType << std::endl; + } + std::cout << std::endl; } |