aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax-001 <80035972+Max-001@users.noreply.github.com>2024-09-25 21:08:54 +0200
committerMax-001 <80035972+Max-001@users.noreply.github.com>2024-09-25 21:08:54 +0200
commit5458abaca5f01a4d34bb55b1b44dc4fb4e9890be (patch)
treea23e35dc95c69aced7d4e16550a2b4fff8507a6c
parent918392ec503a66e369fffa3a5a49c8afccf96a62 (diff)
Made a homemade ECS
-rw-r--r--mwe/ecs-homemade/CMakeLists.txt6
-rw-r--r--mwe/ecs-homemade/inc/ComponentManager.h37
-rw-r--r--mwe/ecs-homemade/inc/ComponentManager.hpp58
-rw-r--r--mwe/ecs-homemade/inc/Components.h22
-rw-r--r--mwe/ecs-homemade/inc/GameObjectMax.h20
-rw-r--r--mwe/ecs-homemade/inc/GameObjectMax.hpp6
-rw-r--r--mwe/ecs-homemade/src/ComponentManager.cpp9
-rw-r--r--mwe/ecs-homemade/src/Components.cpp10
-rw-r--r--mwe/ecs-homemade/src/GameObjectMax.cpp5
-rw-r--r--mwe/ecs-homemade/src/main.cpp36
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;
}