-
Notifications
You must be signed in to change notification settings - Fork 1
/
EntityComponentSystem.h
129 lines (100 loc) · 2.67 KB
/
EntityComponentSystem.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#pragma once
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
#include <cassert>
#include <bitset>
#include <array>
class Component;
class Entity;
class EntityManager;
using ComponentID = std::size_t;
inline ComponentID getUniqueComponentID() {
static ComponentID lastID{ 0u };
return lastID++;
}
template <typename T> inline ComponentID getComponentTypeID() noexcept {
static ComponentID typeID{ getUniqueComponentID() };
return typeID;
}
constexpr std::size_t maxComponents = 32;
using ComponentBitset = std::bitset<maxComponents>;
using ComponentArray = std::array<Component*, maxComponents>;
class Component {
public:
Entity* mEntity = nullptr;
virtual void init() {}
virtual void update() {}
virtual void draw() {}
virtual ~Component() {}
};
class Entity {
EntityManager& mEntityManager;
bool active = true;
std::vector<std::unique_ptr<Component>> mComponents;
ComponentArray mComponentArray;
ComponentBitset mComponentBitset;
public:
int mEntityIndex = 0;
Entity(EntityManager& mManager) : mEntityManager(mManager) {}
void update() {
for (auto& c : mComponents) c->update();
}
void draw() {
for (auto& c : mComponents) c->draw();
}
bool isActive() const { return active; }
bool isInactive() const { return !active; }
void wakeUp() { active = true; }
void destroy() { active = false; }
template <typename T> bool hasComponent() const {
return mComponentBitset[getComponentTypeID<T>()];
}
template <typename T, typename... TArgs>
T& addComponent(TArgs&&... margs) {
assert(!hasComponent<T>());
T* c(new T(std::forward<TArgs>(margs)...));
c->mEntity = this;
std::unique_ptr<Component> uPtr{ c };
mComponents.emplace_back(std::move(uPtr));
mComponentArray[getComponentTypeID<T>()] = c;
mComponentBitset[getComponentTypeID<T>()] = true;
c->init();
return *c;
}
template <typename T> T& getComponent() const {
assert(hasComponent<T>());
auto ptr(mComponentArray[getComponentTypeID<T>()]);
return *static_cast<T*>(ptr);
}
};
class EntityManager {
std::vector<std::unique_ptr<Entity>> mEntities;
public:
void update() {
for (auto& e : mEntities) e->update();
}
void draw() {
for (auto& e : mEntities) e->draw();
}
void refresh() {
mEntities.erase(std::remove_if(std::begin(mEntities), std::end(mEntities),
[](const std::unique_ptr<Entity>& mEntity)
{
return !mEntity->isActive();
}),
std::end(mEntities));
}
Entity& addEntity() {
static int index = 0;
Entity* a = new Entity(*this);
a->mEntityIndex = index++;
std::unique_ptr<Entity> uPtr{ a };
mEntities.emplace_back(std::move(uPtr));
return *a;
}
std::vector<std::unique_ptr<Entity>>& getEntities() {
return mEntities;
}
};