From c39adf3040c3f2f7cfcab5ce5b7e39b815e8131d Mon Sep 17 00:00:00 2001
From: Max-001 <80035972+Max-001@users.noreply.github.com>
Date: Sat, 5 Oct 2024 11:05:59 +0200
Subject: Setup ecs-memory-efficient

---
 mwe/ecs-memory-efficient/src/ComponentManager.cpp |  21 +++++
 mwe/ecs-memory-efficient/src/Components.cpp       |  10 ++
 mwe/ecs-memory-efficient/src/GameObjectMax.cpp    |   5 +
 mwe/ecs-memory-efficient/src/main.cpp             | 108 ++++++++++++++++++++++
 4 files changed, 144 insertions(+)
 create mode 100644 mwe/ecs-memory-efficient/src/ComponentManager.cpp
 create mode 100644 mwe/ecs-memory-efficient/src/Components.cpp
 create mode 100644 mwe/ecs-memory-efficient/src/GameObjectMax.cpp
 create mode 100644 mwe/ecs-memory-efficient/src/main.cpp

(limited to 'mwe/ecs-memory-efficient/src')

diff --git a/mwe/ecs-memory-efficient/src/ComponentManager.cpp b/mwe/ecs-memory-efficient/src/ComponentManager.cpp
new file mode 100644
index 0000000..16cc2b6
--- /dev/null
+++ b/mwe/ecs-memory-efficient/src/ComponentManager.cpp
@@ -0,0 +1,21 @@
+#include "ComponentManager.h"
+
+ComponentManager ComponentManager::mInstance;
+
+ComponentManager& ComponentManager::GetInstance() {
+	return mInstance;
+}
+
+ComponentManager::ComponentManager() {}
+
+void ComponentManager::DeleteAllComponentsOfId(std::uint32_t id) {
+    for(auto& [type, componentArray] : mComponents) {	//Loop through all the types (in the unordered_map<>)
+        if (id < componentArray.size()) {	//Make sure that the id (that we are looking for) is within the boundaries of the vector<>
+            componentArray[id].clear();	//Clear the components at this specific id
+        }
+    }
+}
+
+void ComponentManager::DeleteAllComponents() {
+	mComponents.clear();	//Clear the whole unordered_map<>
+}
diff --git a/mwe/ecs-memory-efficient/src/Components.cpp b/mwe/ecs-memory-efficient/src/Components.cpp
new file mode 100644
index 0000000..69b5eaa
--- /dev/null
+++ b/mwe/ecs-memory-efficient/src/Components.cpp
@@ -0,0 +1,10 @@
+#include "Components.h"
+#include <iostream>
+
+Component::Component() : mActive(true) {}
+
+Sprite::Sprite(std::string path) : mPath(path) {}
+
+Rigidbody::Rigidbody(int mass, int gravityScale, int bodyType) : mMass(mass), mGravityScale(gravityScale), mBodyType(bodyType) {}
+
+Colider::Colider(int size) : mSize(size) {}
diff --git a/mwe/ecs-memory-efficient/src/GameObjectMax.cpp b/mwe/ecs-memory-efficient/src/GameObjectMax.cpp
new file mode 100644
index 0000000..62c41de
--- /dev/null
+++ b/mwe/ecs-memory-efficient/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-memory-efficient/src/main.cpp b/mwe/ecs-memory-efficient/src/main.cpp
new file mode 100644
index 0000000..9e8fbd5
--- /dev/null
+++ b/mwe/ecs-memory-efficient/src/main.cpp
@@ -0,0 +1,108 @@
+#include <iostream>
+#include <vector>
+#include <cstdint>
+
+#include "ComponentManager.h"
+#include "GameObjectMax.h"
+#include "Components.h"
+
+int main() {
+	GameObject gameObect0(0, "Name: 0", "Tag: 0", 0);	//Entity 0
+	GameObject gameObect1(1, "Name: 1", "Tag: 1", 1);	//Entity 1
+	GameObject gameObect2(2, "Name: 2", "Tag: 2", 2);	//Entity 2
+	GameObject gameObect3(3, "Name: 3", "Tag: 3", 3);	//Entity 3
+	GameObject gameObect4(4, "Name: 4", "Tag: 4", 4);	//Entity 4
+	GameObject gameObect5(5, "Name: 5", "Tag: 5", 5);	//Entity 5
+	GameObject gameObect6(6, "Name: 6", "Tag: 6", 6);	//Entity 6
+	GameObject gameObect7(7, "Name: 7", "Tag: 7", 7);	//Entity 7
+
+	gameObect0.AddComponent<Sprite>("C:/object0");	//Add a sprite to entity0
+	gameObect0.AddComponent<Rigidbody>(1, 2, 3);	//Also add a rigidbody to entity0
+	gameObect0.AddComponent<Rigidbody>(3, 2, 1);	//Add a second rigidbody to entity0
+
+	gameObect1.AddComponent<Rigidbody>(4, 5, 6);	//Only add a rigidbody to entity1
+
+	gameObect2.AddComponent<Sprite>("C:/object2/1");	//Add four sprites to entity2
+	gameObect2.AddComponent<Sprite>("C:/object2/2");
+	gameObect2.AddComponent<Sprite>("C:/object2/3");
+	gameObect2.AddComponent<Sprite>("C:/object2/4");
+	gameObect2.AddComponent<Rigidbody>(10, 100, 500);	//Add four rigidbodies to entity2
+	gameObect2.AddComponent<Rigidbody>(10, 100, 501);
+	gameObect2.AddComponent<Rigidbody>(10, 100, 502);
+	gameObect2.AddComponent<Rigidbody>(10, 100, 500);
+	
+	//Add non components to entity3, entity4, entity5 and entity6
+
+	gameObect7.AddComponent<Sprite>("C:/object7");	//Add a sprite to entity 7
+	gameObect7.AddComponent<Colider>(30);	//Add a colder to entity 7
+
+	//The entities are now initialized
+	//Now I will demonstrate some ways of retreiving/getting components
+
+	std::cout << "Finding all sprites of entity 0" << std::endl;
+	std::vector<std::reference_wrapper<Sprite>> spriteOfEntity0 = ComponentManager::GetInstance().GetComponentsByID<Sprite>(gameObect0.mId);
+	for(Sprite& spriteEntity0 : spriteOfEntity0) {
+		std::cout << "Sprite of entity 0: " << spriteEntity0.mPath << std::endl;
+	}
+	std::cout << std::endl;
+
+	std::cout << "Finding all rigidbodies of entity 0" << std::endl;
+	std::vector<std::reference_wrapper<Rigidbody>> rigidbodyOfEntity0 = ComponentManager::GetInstance().GetComponentsByID<Rigidbody>(gameObect0.mId);
+	for(Rigidbody& rigidbodyEntity0 : rigidbodyOfEntity0) {
+		std::cout << "Rigidbody of entity 0: " << rigidbodyEntity0.mMass << " " << rigidbodyEntity0.mGravityScale << " " << rigidbodyEntity0.mBodyType << std::endl;
+
+		rigidbodyEntity0.mMass = 15;
+	}
+	std::cout << std::endl;
+
+	std::cout << "Finding all coliders of entity 0" << std::endl;
+	std::vector<std::reference_wrapper<Colider>> coliderOfEntity0 = ComponentManager::GetInstance().GetComponentsByID<Colider>(gameObect0.mId);
+	for(Colider& coliderEntity0 : coliderOfEntity0) {
+		std::cout << "Colider of entity 0: " << coliderEntity0.mSize << std::endl;
+	}
+	std::cout << std::endl;
+
+	std::cout << "Finding all sprites of entity 3" << std::endl;
+	std::vector<std::reference_wrapper<Sprite>> spriteOfEntity3 = ComponentManager::GetInstance().GetComponentsByID<Sprite>(gameObect3.mId);
+	for(Sprite& spriteEntity3 : spriteOfEntity3) {
+		std::cout << "Sprite of entity 3: " << spriteEntity3.mPath << std::endl;
+	}
+	std::cout << std::endl;
+
+	std::cout << "Finding all rigidbodies of entity 3" << std::endl;
+	std::vector<std::reference_wrapper<Rigidbody>> rigidbodyOfEntity3 = ComponentManager::GetInstance().GetComponentsByID<Rigidbody>(gameObect3.mId);
+	for(Rigidbody& rigidbodyEntity3 : rigidbodyOfEntity3) {
+		std::cout << "Rigidbody of entity 3: " << rigidbodyEntity3.mMass << " " << rigidbodyEntity3.mGravityScale << " " << rigidbodyEntity3.mBodyType << std::endl;
+	}
+	std::cout << std::endl;
+
+	std::cout << "Finding all sprites of all entities" << std::endl;
+	std::vector<std::pair<std::reference_wrapper<Sprite>, std::uint32_t>> sprites = ComponentManager::GetInstance().GetComponentsByType<Sprite>();
+	for(auto& [sprite, id] : sprites) {
+		std::cout << "Sprite of id: " << id << ": " << sprite.get().mPath << std::endl;
+	}
+	std::cout << std::endl;
+
+	std::cout << "Finding all coliders of all entities" << std::endl;
+	std::vector<std::pair<std::reference_wrapper<Colider>, std::uint32_t>> coliders = ComponentManager::GetInstance().GetComponentsByType<Colider>();
+	for(auto& [colider, id] : coliders) {
+		std::cout << "Colder of id: " << id << ": " << colider.get().mSize << std::endl;
+	}
+	std::cout << std::endl;
+
+	std::cout << "Finding all rigidbodies of all entities" << std::endl;
+	std::vector<std::pair<std::reference_wrapper<Rigidbody>, std::uint32_t>> rigidBodies = ComponentManager::GetInstance().GetComponentsByType<Rigidbody>();
+	for(auto& [rigidbody, id] : rigidBodies) {
+		std::cout << "Rigidbody of id: " << id << ": " << rigidbody.get().mMass << " " << rigidbody.get().mGravityScale << " " << rigidbody.get().mBodyType << std::endl;
+
+		rigidbody.get().mMass = -1;
+	}
+	std::cout << std::endl;
+
+	std::cout << "Finding all rigidbodies of all entities for the second time (after changing mMass to -1)" << std::endl;
+	std::vector<std::pair<std::reference_wrapper<Rigidbody>, std::uint32_t>> rigidBodies2 = ComponentManager::GetInstance().GetComponentsByType<Rigidbody>();
+	for(auto& [rigidbody2, id2] : rigidBodies2) {
+		std::cout << "Rigidbody of id: " << id2 << ": " << rigidbody2.get().mMass << " " << rigidbody2.get().mGravityScale << " " << rigidbody2.get().mBodyType << std::endl;
+	}
+	std::cout << std::endl;
+}
-- 
cgit v1.2.3


From c767ef1e3d1d78e50eb1b6d9824b1c8961d68524 Mon Sep 17 00:00:00 2001
From: Max-001 <80035972+Max-001@users.noreply.github.com>
Date: Sat, 5 Oct 2024 12:07:18 +0200
Subject: First setup

---
 .vscode/settings.json                              |   6 +-
 mwe/ecs-memory-efficient/inc/ComponentManager.h    |  38 +++-----
 mwe/ecs-memory-efficient/inc/ComponentManager.hpp  |  93 ++----------------
 mwe/ecs-memory-efficient/inc/ContiguousContainer.h |  34 +++++++
 .../inc/ContiguousContainer.hpp                    |  84 ++++++++++++++++
 mwe/ecs-memory-efficient/inc/GameObjectMax.h       |   8 +-
 mwe/ecs-memory-efficient/inc/GameObjectMax.hpp     |  16 +++-
 mwe/ecs-memory-efficient/src/ComponentManager.cpp  |  16 ++--
 mwe/ecs-memory-efficient/src/main.cpp              | 106 +++++----------------
 9 files changed, 199 insertions(+), 202 deletions(-)
 create mode 100644 mwe/ecs-memory-efficient/inc/ContiguousContainer.h
 create mode 100644 mwe/ecs-memory-efficient/inc/ContiguousContainer.hpp

(limited to 'mwe/ecs-memory-efficient/src')

diff --git a/.vscode/settings.json b/.vscode/settings.json
index 52c6107..27ae565 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -54,6 +54,10 @@
 		"cinttypes": "cpp",
 		"typeindex": "cpp",
 		"typeinfo": "cpp",
-		"variant": "cpp"
+		"variant": "cpp",
+		"chrono": "cpp",
+		"ratio": "cpp",
+		"iomanip": "cpp",
+		"sstream": "cpp"
 	}
 }
diff --git a/mwe/ecs-memory-efficient/inc/ComponentManager.h b/mwe/ecs-memory-efficient/inc/ComponentManager.h
index 893aa56..066795a 100644
--- a/mwe/ecs-memory-efficient/inc/ComponentManager.h
+++ b/mwe/ecs-memory-efficient/inc/ComponentManager.h
@@ -1,12 +1,7 @@
 #pragma once
 
 #include "Components.h"
-#include <cstdint>
-#include <unordered_map>
-#include <vector>
-#include <typeindex>
-#include <memory>
-#include <utility>
+#include "ContiguousContainer.h"
 
 class ComponentManager {
 public:
@@ -17,32 +12,25 @@ public:
     ComponentManager& operator=(const ComponentManager&) = delete;	//Singleton
     ComponentManager& operator=(ComponentManager&&) = delete;	//Singleton
 
-	template <typename T, typename... Args>
-	void AddComponent(std::uint32_t id, Args&&... args);	//Add a component of a specific type
-	template <typename T>
-	void DeleteComponentsById(std::uint32_t id);	//Deletes all components of a specific type and id
-	template <typename T>
-	void DeleteComponents();	//Deletes all components of a specific type
-	void DeleteAllComponentsOfId(std::uint32_t id);	//Deletes all components of a specific id
-	void DeleteAllComponents();	//Deletes all components
+	template<typename... Args>
+    void addSpriteComponent(Args&&... args);
+	template<typename... Args>
+    void addRigidbodyComponent(Args&&... args);
+	template<typename... Args>
+    void addColiderComponent(Args&&... args);
 
-	template <typename T>
-    std::vector<std::reference_wrapper<T>> GetComponentsByID(std::uint32_t id) const;	//Get a vector<> of all components at specific type and id
-	template <typename T>
-	std::vector<std::pair<std::reference_wrapper<T>, std::uint32_t>> GetComponentsByType() const;	//Get a vector<> of all components of a specific type
+	std::vector<std::reference_wrapper<Sprite>> getAllSpriteReferences();
+	std::vector<std::reference_wrapper<Rigidbody>> getAllRigidbodyReferences();
+	std::vector<std::reference_wrapper<Colider>> getAllColiderReferences();
 
 private:
     static ComponentManager mInstance;	//Singleton
 
     ComponentManager();	//Singleton
 
-	/*
-	 * The std::unordered_map<std::type_index, std::vector<std::vector<std::unique_ptr<Component>>>> below might seem a bit strange, let me explain this structure:
-	 * The std::unordered_map<> has a key and value. The key is a std::type_index and the value is a std::vector. So, a new std::vector will be created for each new std::type_index.
-	 * The first std::vector<> stores another vector<>. This first vector<> is to bind the entity's id to a component.
-	 * The second std::vector<> stores unique_ptrs. Each component can be gathered via an unique_ptr. This second vector<> allows multiple components of the same std::type_index for one entity (id).
-	 */
-	std::unordered_map<std::type_index, std::vector<std::vector<std::unique_ptr<Component>>>> mComponents;
+	ContiguousContainer<Sprite> mSpriteContainer;
+	ContiguousContainer<Rigidbody> mRigidbodyContainer;
+	ContiguousContainer<Colider> mColiderContainer;
 };
 
 #include "ComponentManager.hpp"
diff --git a/mwe/ecs-memory-efficient/inc/ComponentManager.hpp b/mwe/ecs-memory-efficient/inc/ComponentManager.hpp
index 53dfddd..1607c0c 100644
--- a/mwe/ecs-memory-efficient/inc/ComponentManager.hpp
+++ b/mwe/ecs-memory-efficient/inc/ComponentManager.hpp
@@ -1,88 +1,15 @@
-
-template <typename T, typename... Args>
-void ComponentManager::AddComponent(std::uint32_t id, Args&&... args) {
-    std::type_index type = typeid(T);	//Determine the type of T (this is used as the key of the unordered_map<>)
-
-    if (mComponents.find(type) == mComponents.end()) {	//Check if this component type is already in the unordered_map<>
-        mComponents[type] = std::vector<std::vector<std::unique_ptr<Component>>>();	//If not, create a new (empty) vector<> of vector<unique_ptr<Component>>
-    }
-
-    if (id >= mComponents[type].size()) {	//Resize the vector<> if the id is greater than the current size
-        mComponents[type].resize(id + 1);	//Initialize new slots to nullptr (resize does automatically init to nullptr)
-    }
-
-    mComponents[type][id].push_back(std::make_unique<T>(std::forward<Args>(args)...));	//Create a new component of type T using perfect forwarding and store its unique_ptr in the vector<>
-}
-
-template <typename T>
-void ComponentManager::DeleteComponentsById(std::uint32_t id) {
-	std::type_index type = typeid(T);	//Determine the type of T (this is used as the key of the unordered_map<>)
-
-	if (mComponents.find(type) != mComponents.end()) {	//Find the type (in the unordered_map<>)
-		std::vector<std::vector<std::unique_ptr<Component>>>& componentArray = mComponents[type];	//Get the correct vector<>
-
-        if (id < componentArray.size()) {	//Make sure that the id (that we are looking for) is within the boundaries of the vector<>
-            componentArray[id].clear();	//Clear the whole vector<> of this specific type and id
-        }
-	}
-}
-
-template <typename T>
-void ComponentManager::DeleteComponents() {
-	std::type_index type = typeid(T);	//Determine the type of T (this is used as the key of the unordered_map<>)
-
-	if (mComponents.find(type) != mComponents.end()) {	//Find the type (in the unordered_map<>)
-		mComponents[type].clear();	//Clear the whole vector<> of this specific type
-	}
+	
+template<typename... Args>
+void ComponentManager::addSpriteComponent(Args&&... args) {
+	mSpriteContainer.pushBack(std::forward<Args>(args)...);
 }
 
-template <typename T>
-std::vector<std::reference_wrapper<T>> ComponentManager::GetComponentsByID(std::uint32_t id) const {
-    std::type_index type = typeid(T);	//Determine the type of T (this is used as the key of the unordered_map<>)
-
-	std::vector<std::reference_wrapper<T>> componentVector;	//Create an empty vector<>
-
-    if (mComponents.find(type) != mComponents.end()) {	//Find the type (in the unordered_map<>)
-
-        const std::vector<std::vector<std::unique_ptr<Component>>>& componentArray = mComponents.at(type);	//Get the correct vector<>
-
-        if (id < componentArray.size()) {	//Make sure that the id (that we are looking for) is within the boundaries of the vector<>
-            for (const std::unique_ptr<Component>& componentPtr : componentArray[id]) {	//Loop trough the whole vector<>
-                T* castedComponent = static_cast<T*>(componentPtr.get());	//Cast the unique_ptr to a raw pointer
-
-                if (castedComponent) {	//Ensure that the cast was successful
-                    componentVector.push_back(*castedComponent); //Add the dereferenced raw pointer to the vector<>
-                }
-            }
-        }
-    }
-
-    return componentVector; //Return the vector<>
+template<typename... Args>
+void ComponentManager::addRigidbodyComponent(Args&&... args) {
+	mRigidbodyContainer.pushBack(std::forward<Args>(args)...);
 }
 
-template <typename T>
-std::vector<std::pair<std::reference_wrapper<T>, std::uint32_t>> ComponentManager::GetComponentsByType() const {
-    std::type_index type = typeid(T);	//Determine the type of T (this is used as the key of the unordered_map<>)
-
-    std::vector<std::pair<std::reference_wrapper<T>, std::uint32_t>> componentVector;	//Create an empty vector<>
-	std::uint32_t id = 0;	//Set the id to 0 (the id will also be stored in the returned vector<>)
-
-    if (mComponents.find(type) != mComponents.end()) {	//Find the type (in the unordered_map<>)
-
-        const std::vector<std::vector<std::unique_ptr<Component>>>& componentArray = mComponents.at(type);	//Get the correct vector<>
-
-        for (const std::vector<std::unique_ptr<Component>>& component : componentArray) {	//Loop through the whole vector<>
-            for (const std::unique_ptr<Component>& componentPtr : component) {	//Loop trough the whole vector<>
-                T* castedComponent = static_cast<T*>(componentPtr.get());	//Cast the unique_ptr to a raw pointer
-
-                if (castedComponent) {	//Ensure that the cast was successful
-                    componentVector.emplace_back(std::ref(*castedComponent), id);	//Pair the dereferenced raw pointer and the id and add it to the vector<>
-                }
-            }
-
-			++id;	//Increase the id (the id will also be stored in the returned vector<>)
-        }
-    }
-
-    return componentVector;	//Return the vector<>
+template<typename... Args>
+void ComponentManager::addColiderComponent(Args&&... args){
+	mColiderContainer.pushBack(std::forward<Args>(args)...);
 }
diff --git a/mwe/ecs-memory-efficient/inc/ContiguousContainer.h b/mwe/ecs-memory-efficient/inc/ContiguousContainer.h
new file mode 100644
index 0000000..dd0321e
--- /dev/null
+++ b/mwe/ecs-memory-efficient/inc/ContiguousContainer.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <cstdlib>   // For malloc and free
+#include <new>       // For placement new
+#include <utility>   // For std::move and std::forward
+#include <stdexcept> // For std::bad_alloc
+#include <vector>    // For returning references
+
+template<typename T>
+class ContiguousContainer {
+public:
+    ContiguousContainer();
+    ~ContiguousContainer();
+
+    // Use perfect forwarding for pushBack
+    template<typename... Args>
+    void pushBack(Args&&... args);
+    
+    void popBack();
+    T& operator[](size_t index);
+    size_t getSize() const;
+
+	// Function to return references to all stored objects
+    std::vector<std::reference_wrapper<T>> getAllReferences();
+
+private:
+    T* mData;
+    size_t mSize;
+    size_t mCapacity;
+
+    void resize(size_t new_capacity);  // Resize function to allocate more space
+};
+
+#include "ContiguousContainer.hpp"
diff --git a/mwe/ecs-memory-efficient/inc/ContiguousContainer.hpp b/mwe/ecs-memory-efficient/inc/ContiguousContainer.hpp
new file mode 100644
index 0000000..878a85f
--- /dev/null
+++ b/mwe/ecs-memory-efficient/inc/ContiguousContainer.hpp
@@ -0,0 +1,84 @@
+template<typename T>
+ContiguousContainer<T>::ContiguousContainer()
+    : mSize(0), mCapacity(10) {
+    // Allocate memory for 10 objects initially
+    mData = static_cast<T*>(malloc(mCapacity * sizeof(T)));
+    if (!mData) {
+        throw std::bad_alloc();
+    }
+}
+
+template<typename T>
+ContiguousContainer<T>::~ContiguousContainer() {
+    // Destroy all constructed objects
+    for (size_t i = 0; i < mSize; ++i) {
+        mData[i].~T();
+    }
+    // Free the allocated memory
+    free(mData);
+}
+
+template<typename T>
+template<typename... Args>
+void ContiguousContainer<T>::pushBack(Args&&... args) {
+    if (mSize == mCapacity) {
+        // Double the capacity if the container is full
+        resize(mCapacity * 2);
+    }
+    // Use placement new with perfect forwarding to construct the object in place
+    new (mData + mSize) T(std::forward<Args>(args)...);
+    ++mSize;
+}
+
+template<typename T>
+void ContiguousContainer<T>::popBack() {
+    if (mSize > 0) {
+        --mSize;
+        // Explicitly call the destructor
+        mData[mSize].~T();
+    }
+}
+
+template<typename T>
+T& ContiguousContainer<T>::operator[](size_t index) {
+    if (index >= mSize) {
+        throw std::out_of_range("Index out of range");
+    }
+    return mData[index];
+}
+
+template<typename T>
+size_t ContiguousContainer<T>::getSize() const {
+    return mSize;
+}
+
+// Function that returns a vector of references to all stored objects
+template<typename T>
+std::vector<std::reference_wrapper<T>> ContiguousContainer<T>::getAllReferences() {
+    std::vector<std::reference_wrapper<T>> references;
+    references.reserve(mSize);  // Reserve space to avoid reallocation
+    for (size_t i = 0; i < mSize; ++i) {
+        references.push_back(std::ref(mData[i]));
+    }
+    return references;
+}
+
+template<typename T>
+void ContiguousContainer<T>::resize(size_t new_capacity) {
+    // Allocate new memory block with the updated capacity
+    T* new_data = static_cast<T*>(malloc(new_capacity * sizeof(T)));
+    if (!new_data) {
+        throw std::bad_alloc();
+    }
+
+    // Move or copy existing objects to the new memory block
+    for (size_t i = 0; i < mSize; ++i) {
+        new (new_data + i) T(std::move(mData[i])); // Move the objects
+        mData[i].~T(); // Call the destructor for the old object
+    }
+
+    // Free the old memory block
+    free(mData);
+    mData = new_data;
+    mCapacity = new_capacity;
+}
diff --git a/mwe/ecs-memory-efficient/inc/GameObjectMax.h b/mwe/ecs-memory-efficient/inc/GameObjectMax.h
index f0bcec9..62cd3e6 100644
--- a/mwe/ecs-memory-efficient/inc/GameObjectMax.h
+++ b/mwe/ecs-memory-efficient/inc/GameObjectMax.h
@@ -7,8 +7,12 @@ class GameObject {
 public:
 	GameObject(std::uint32_t id, std::string name, std::string tag, int layer);
 
-	template <typename T, typename... Args>
-	void AddComponent(Args&&... args);
+	template<typename... Args>
+    void addSpriteComponent(Args&&... args);
+	template<typename... Args>
+    void addRigidbodyComponent(Args&&... args);
+	template<typename... Args>
+    void addColiderComponent(Args&&... args);
 
 	std::uint32_t mId;
 	std::string mName;
diff --git a/mwe/ecs-memory-efficient/inc/GameObjectMax.hpp b/mwe/ecs-memory-efficient/inc/GameObjectMax.hpp
index 1e952ba..aac9811 100644
--- a/mwe/ecs-memory-efficient/inc/GameObjectMax.hpp
+++ b/mwe/ecs-memory-efficient/inc/GameObjectMax.hpp
@@ -1,6 +1,16 @@
 #include "ComponentManager.h"
 
-template <typename T, typename... Args>
-void GameObject::AddComponent(Args&&... args) {
-	ComponentManager::GetInstance().AddComponent<T>(mId, std::forward<Args>(args)...);
+template <typename... Args>
+void GameObject::addSpriteComponent(Args&&... args) {
+	ComponentManager::GetInstance().addSpriteComponent(std::forward<Args>(args)...);
+}
+
+template <typename... Args>
+void GameObject::addRigidbodyComponent(Args&&... args) {
+	ComponentManager::GetInstance().addRigidbodyComponent(std::forward<Args>(args)...);
+}
+
+template <typename... Args>
+void GameObject::addColiderComponent(Args&&... args) {
+	ComponentManager::GetInstance().addColiderComponent(std::forward<Args>(args)...);
 }
diff --git a/mwe/ecs-memory-efficient/src/ComponentManager.cpp b/mwe/ecs-memory-efficient/src/ComponentManager.cpp
index 16cc2b6..20d0ce0 100644
--- a/mwe/ecs-memory-efficient/src/ComponentManager.cpp
+++ b/mwe/ecs-memory-efficient/src/ComponentManager.cpp
@@ -8,14 +8,14 @@ ComponentManager& ComponentManager::GetInstance() {
 
 ComponentManager::ComponentManager() {}
 
-void ComponentManager::DeleteAllComponentsOfId(std::uint32_t id) {
-    for(auto& [type, componentArray] : mComponents) {	//Loop through all the types (in the unordered_map<>)
-        if (id < componentArray.size()) {	//Make sure that the id (that we are looking for) is within the boundaries of the vector<>
-            componentArray[id].clear();	//Clear the components at this specific id
-        }
-    }
+std::vector<std::reference_wrapper<Sprite>> ComponentManager::getAllSpriteReferences() {
+	return mSpriteContainer.getAllReferences();
 }
 
-void ComponentManager::DeleteAllComponents() {
-	mComponents.clear();	//Clear the whole unordered_map<>
+std::vector<std::reference_wrapper<Rigidbody>> ComponentManager::getAllRigidbodyReferences() {
+	return mRigidbodyContainer.getAllReferences();
+}
+
+std::vector<std::reference_wrapper<Colider>> ComponentManager::getAllColiderReferences() {
+	return mColiderContainer.getAllReferences();
 }
diff --git a/mwe/ecs-memory-efficient/src/main.cpp b/mwe/ecs-memory-efficient/src/main.cpp
index 9e8fbd5..71b6b3c 100644
--- a/mwe/ecs-memory-efficient/src/main.cpp
+++ b/mwe/ecs-memory-efficient/src/main.cpp
@@ -1,108 +1,54 @@
 #include <iostream>
 #include <vector>
 #include <cstdint>
+#include <chrono>
 
 #include "ComponentManager.h"
 #include "GameObjectMax.h"
 #include "Components.h"
 
 int main() {
-	GameObject gameObect0(0, "Name: 0", "Tag: 0", 0);	//Entity 0
-	GameObject gameObect1(1, "Name: 1", "Tag: 1", 1);	//Entity 1
-	GameObject gameObect2(2, "Name: 2", "Tag: 2", 2);	//Entity 2
-	GameObject gameObect3(3, "Name: 3", "Tag: 3", 3);	//Entity 3
-	GameObject gameObect4(4, "Name: 4", "Tag: 4", 4);	//Entity 4
-	GameObject gameObect5(5, "Name: 5", "Tag: 5", 5);	//Entity 5
-	GameObject gameObect6(6, "Name: 6", "Tag: 6", 6);	//Entity 6
-	GameObject gameObect7(7, "Name: 7", "Tag: 7", 7);	//Entity 7
+	auto startAdding = std::chrono::high_resolution_clock::now();
 
-	gameObect0.AddComponent<Sprite>("C:/object0");	//Add a sprite to entity0
-	gameObect0.AddComponent<Rigidbody>(1, 2, 3);	//Also add a rigidbody to entity0
-	gameObect0.AddComponent<Rigidbody>(3, 2, 1);	//Add a second rigidbody to entity0
+	GameObject* gameObject[1000];
 
-	gameObect1.AddComponent<Rigidbody>(4, 5, 6);	//Only add a rigidbody to entity1
+	for(int i = 0; i < 1000; ++i) {
+		gameObject[i] = new GameObject(i, "Name", "Tag", 0);
 
-	gameObect2.AddComponent<Sprite>("C:/object2/1");	//Add four sprites to entity2
-	gameObect2.AddComponent<Sprite>("C:/object2/2");
-	gameObect2.AddComponent<Sprite>("C:/object2/3");
-	gameObect2.AddComponent<Sprite>("C:/object2/4");
-	gameObect2.AddComponent<Rigidbody>(10, 100, 500);	//Add four rigidbodies to entity2
-	gameObect2.AddComponent<Rigidbody>(10, 100, 501);
-	gameObect2.AddComponent<Rigidbody>(10, 100, 502);
-	gameObect2.AddComponent<Rigidbody>(10, 100, 500);
-	
-	//Add non components to entity3, entity4, entity5 and entity6
-
-	gameObect7.AddComponent<Sprite>("C:/object7");	//Add a sprite to entity 7
-	gameObect7.AddComponent<Colider>(30);	//Add a colder to entity 7
-
-	//The entities are now initialized
-	//Now I will demonstrate some ways of retreiving/getting components
-
-	std::cout << "Finding all sprites of entity 0" << std::endl;
-	std::vector<std::reference_wrapper<Sprite>> spriteOfEntity0 = ComponentManager::GetInstance().GetComponentsByID<Sprite>(gameObect0.mId);
-	for(Sprite& spriteEntity0 : spriteOfEntity0) {
-		std::cout << "Sprite of entity 0: " << spriteEntity0.mPath << std::endl;
-	}
-	std::cout << std::endl;
-
-	std::cout << "Finding all rigidbodies of entity 0" << std::endl;
-	std::vector<std::reference_wrapper<Rigidbody>> rigidbodyOfEntity0 = ComponentManager::GetInstance().GetComponentsByID<Rigidbody>(gameObect0.mId);
-	for(Rigidbody& rigidbodyEntity0 : rigidbodyOfEntity0) {
-		std::cout << "Rigidbody of entity 0: " << rigidbodyEntity0.mMass << " " << rigidbodyEntity0.mGravityScale << " " << rigidbodyEntity0.mBodyType << std::endl;
-
-		rigidbodyEntity0.mMass = 15;
+		gameObject[i]->addSpriteComponent("C:/Test");
+		gameObject[i]->addRigidbodyComponent(0, 0, i);
+		gameObject[i]->addColiderComponent(i);
 	}
-	std::cout << std::endl;
 
-	std::cout << "Finding all coliders of entity 0" << std::endl;
-	std::vector<std::reference_wrapper<Colider>> coliderOfEntity0 = ComponentManager::GetInstance().GetComponentsByID<Colider>(gameObect0.mId);
-	for(Colider& coliderEntity0 : coliderOfEntity0) {
-		std::cout << "Colider of entity 0: " << coliderEntity0.mSize << std::endl;
-	}
-	std::cout << std::endl;
+	auto stopAdding = std::chrono::high_resolution_clock::now();
 
-	std::cout << "Finding all sprites of entity 3" << std::endl;
-	std::vector<std::reference_wrapper<Sprite>> spriteOfEntity3 = ComponentManager::GetInstance().GetComponentsByID<Sprite>(gameObect3.mId);
-	for(Sprite& spriteEntity3 : spriteOfEntity3) {
-		std::cout << "Sprite of entity 3: " << spriteEntity3.mPath << std::endl;
-	}
-	std::cout << std::endl;
+	//This is what systems would do:
 
-	std::cout << "Finding all rigidbodies of entity 3" << std::endl;
-	std::vector<std::reference_wrapper<Rigidbody>> rigidbodyOfEntity3 = ComponentManager::GetInstance().GetComponentsByID<Rigidbody>(gameObect3.mId);
-	for(Rigidbody& rigidbodyEntity3 : rigidbodyOfEntity3) {
-		std::cout << "Rigidbody of entity 3: " << rigidbodyEntity3.mMass << " " << rigidbodyEntity3.mGravityScale << " " << rigidbodyEntity3.mBodyType << std::endl;
+	std::vector<std::reference_wrapper<Sprite>> allSprites = ComponentManager::GetInstance().getAllSpriteReferences();
+	for(Sprite& sprite : allSprites) {
+		std::cout << sprite.mPath << std::endl;
 	}
 	std::cout << std::endl;
 
-	std::cout << "Finding all sprites of all entities" << std::endl;
-	std::vector<std::pair<std::reference_wrapper<Sprite>, std::uint32_t>> sprites = ComponentManager::GetInstance().GetComponentsByType<Sprite>();
-	for(auto& [sprite, id] : sprites) {
-		std::cout << "Sprite of id: " << id << ": " << sprite.get().mPath << std::endl;
+	std::vector<std::reference_wrapper<Rigidbody>> allRigidbody = ComponentManager::GetInstance().getAllRigidbodyReferences();
+	for(Rigidbody& rigidbody : allRigidbody) {
+		std::cout << rigidbody.mMass << " " << rigidbody.mGravityScale << " " << rigidbody.mBodyType << std::endl;
 	}
 	std::cout << std::endl;
 
-	std::cout << "Finding all coliders of all entities" << std::endl;
-	std::vector<std::pair<std::reference_wrapper<Colider>, std::uint32_t>> coliders = ComponentManager::GetInstance().GetComponentsByType<Colider>();
-	for(auto& [colider, id] : coliders) {
-		std::cout << "Colder of id: " << id << ": " << colider.get().mSize << std::endl;
+	std::vector<std::reference_wrapper<Colider>> allColider = ComponentManager::GetInstance().getAllColiderReferences();
+	for(Colider& colider : allColider) {
+		std::cout << colider.mSize << std::endl;
 	}
-	std::cout << std::endl;
 
-	std::cout << "Finding all rigidbodies of all entities" << std::endl;
-	std::vector<std::pair<std::reference_wrapper<Rigidbody>, std::uint32_t>> rigidBodies = ComponentManager::GetInstance().GetComponentsByType<Rigidbody>();
-	for(auto& [rigidbody, id] : rigidBodies) {
-		std::cout << "Rigidbody of id: " << id << ": " << rigidbody.get().mMass << " " << rigidbody.get().mGravityScale << " " << rigidbody.get().mBodyType << std::endl;
+	auto stopLooping = std::chrono::high_resolution_clock::now();
 
-		rigidbody.get().mMass = -1;
+	for (int i = 0; i < 1000; ++i) {
+    	delete gameObject[i];
 	}
-	std::cout << std::endl;
 
-	std::cout << "Finding all rigidbodies of all entities for the second time (after changing mMass to -1)" << std::endl;
-	std::vector<std::pair<std::reference_wrapper<Rigidbody>, std::uint32_t>> rigidBodies2 = ComponentManager::GetInstance().GetComponentsByType<Rigidbody>();
-	for(auto& [rigidbody2, id2] : rigidBodies2) {
-		std::cout << "Rigidbody of id: " << id2 << ": " << rigidbody2.get().mMass << " " << rigidbody2.get().mGravityScale << " " << rigidbody2.get().mBodyType << std::endl;
-	}
-	std::cout << std::endl;
+	auto Addtime = std::chrono::duration_cast<std::chrono::microseconds>(stopAdding - startAdding);
+	auto LoopTime = std::chrono::duration_cast<std::chrono::microseconds>(stopLooping - stopAdding);
+	std::cout << "AddTime: " << Addtime.count() << " us" << std::endl;
+	std::cout << "LoopTime: " << LoopTime.count() << " us" << std::endl;
 }
-- 
cgit v1.2.3


From 809db83cd515c6c2b1d404811354208cf97a5c07 Mon Sep 17 00:00:00 2001
From: Max-001 <80035972+Max-001@users.noreply.github.com>
Date: Sat, 5 Oct 2024 12:28:58 +0200
Subject: Improved test

---
 mwe/ecs-memory-efficient/src/main.cpp | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

(limited to 'mwe/ecs-memory-efficient/src')

diff --git a/mwe/ecs-memory-efficient/src/main.cpp b/mwe/ecs-memory-efficient/src/main.cpp
index 71b6b3c..c25816b 100644
--- a/mwe/ecs-memory-efficient/src/main.cpp
+++ b/mwe/ecs-memory-efficient/src/main.cpp
@@ -10,9 +10,9 @@
 int main() {
 	auto startAdding = std::chrono::high_resolution_clock::now();
 
-	GameObject* gameObject[1000];
+	GameObject* gameObject[100000];
 
-	for(int i = 0; i < 1000; ++i) {
+	for(int i = 0; i < 100000; ++i) {
 		gameObject[i] = new GameObject(i, "Name", "Tag", 0);
 
 		gameObject[i]->addSpriteComponent("C:/Test");
@@ -26,24 +26,24 @@ int main() {
 
 	std::vector<std::reference_wrapper<Sprite>> allSprites = ComponentManager::GetInstance().getAllSpriteReferences();
 	for(Sprite& sprite : allSprites) {
-		std::cout << sprite.mPath << std::endl;
+		//std::cout << sprite.mPath << std::endl;
 	}
-	std::cout << std::endl;
+	//std::cout << std::endl;
 
 	std::vector<std::reference_wrapper<Rigidbody>> allRigidbody = ComponentManager::GetInstance().getAllRigidbodyReferences();
 	for(Rigidbody& rigidbody : allRigidbody) {
-		std::cout << rigidbody.mMass << " " << rigidbody.mGravityScale << " " << rigidbody.mBodyType << std::endl;
+		//std::cout << rigidbody.mMass << " " << rigidbody.mGravityScale << " " << rigidbody.mBodyType << std::endl;
 	}
-	std::cout << std::endl;
+	//std::cout << std::endl;
 
 	std::vector<std::reference_wrapper<Colider>> allColider = ComponentManager::GetInstance().getAllColiderReferences();
 	for(Colider& colider : allColider) {
-		std::cout << colider.mSize << std::endl;
+		//std::cout << colider.mSize << std::endl;
 	}
 
 	auto stopLooping = std::chrono::high_resolution_clock::now();
 
-	for (int i = 0; i < 1000; ++i) {
+	for (int i = 0; i < 100000; ++i) {
     	delete gameObject[i];
 	}
 
-- 
cgit v1.2.3