-
Notifications
You must be signed in to change notification settings - Fork 15
/
EntityFu.h
164 lines (135 loc) · 4.82 KB
/
EntityFu.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
///
/// [EntityFu](https://github.com/NatWeiss/EntityFu)
/// A simple, fast entity component system written in C++.
/// Under the MIT license.
///
#pragma once
#include <vector>
/// An `Eid` is an entity ID.
typedef unsigned Eid;
/// A `Cid` is a component ID.
typedef unsigned Cid;
namespace Entity
{
struct Component;
/// The maximum number of entities. Increase this if you need more.
enum {kMaxEntities = 8192};
/// Allocate the memory for entities and components. Can call this manually or let it allocate automatically.
void alloc();
/// Deallocate the memory for entities and components. Only do this when you no longer need the ECS.
void dealloc();
/// Create an entity and return the `Eid`.
Eid create();
/// Return a count of all entities.
unsigned count();
/// Return true if the entity has been created.
bool exists(Eid eid);
/// Destroy an entity and all its components right now.
void destroyNow(Eid eid);
/// Destroy all entities and components right now.
void destroyAll();
/// Component-related methods that require a `Cid`.
/// The templated versions of these methods do not require a `Cid`, yet incur an extra function call of overhead.
void addComponent(Cid cid, Eid eid, Component* c);
void removeComponent(Cid cid, Eid eid);
Component* getComponent(Cid cid, Eid eid);
const std::vector<Eid>& getAll(Cid cid);
unsigned count(Cid cid);
/// Add the given component to the given entity.
/// Note that components must be allocated with new.
template<class ComponentClass> inline static void addComponent(Eid eid, ComponentClass* c)
{
return Entity::addComponent(ComponentClass::cid, eid, c);
}
/// Remove a component from an entity.
template<class ComponentClass> inline static void removeComponent(Eid eid)
{
return Entity::removeComponent(ComponentClass::cid, eid);
}
/// Get a reference to a component.
/// Warning, if the Eid does not exist a blank static component will be returned,
/// so be sure to check if it is empty before writing any data to it or else
/// the blank static component will no longer be empty and the Earth will implode.
template<class ComponentClass> inline static ComponentClass& get(Eid eid)
{
auto p = static_cast<ComponentClass*>(Entity::getComponent(ComponentClass::cid, eid));
if (p != nullptr)
return *p;
static ComponentClass s;
return s;
}
/// Get a pointer to a component.
template<class ComponentClass> inline static ComponentClass* getPointer(Eid eid)
{
return static_cast<ComponentClass*>(Entity::getComponent(ComponentClass::cid, eid));
}
/// Get a vector of all Eids for the given component class.
template<class ComponentClass> inline static const std::vector<Eid>& getAll()
{
return Entity::getAll(ComponentClass::cid);
}
/// Count all the entities with the given component class.
template<class ComponentClass> inline static unsigned count()
{
return Entity::count(ComponentClass::cid);
}
/// A utility method for `Entity::create(...)`.
/// The final call to `addComponents`.
template <class C> static void addComponents(Eid eid, C* c)
{
Entity::addComponent(C::cid, eid, c);
}
/// A utility method for `Entity::create(...)`.
/// The variadic template version of `addComponents`.
template <class C, typename ...Args> static void addComponents(Eid eid, C* c, Args... args)
{
Entity::addComponent(C::cid, eid, c);
Entity::addComponents(eid, args...);
}
/// Create an entity with some components.
/// Convenience method which calls `Entity::create()` and `Entity::addComponent`.
template <typename ...Args> static Eid create(Args... args)
{
auto eid = Entity::create();
Entity::addComponents(eid, args...);
return eid;
}
};
///
/// Component
///
/// Inherit your game's components from this class.
/// Give your component some data and be sure to implement the `empty` method.
/// Also give your component class a static member `cid` of type `Cid` and increment `Entity::Component::numCids`.
/// See the example code for details.
///
struct Entity::Component
{
virtual ~Component();
virtual bool empty() const = 0;
virtual bool full() const;
static Cid numCids;
// static Cid cid;
};
///
/// Convenience macro to get a reference to a component or else run some code.
/// Example: Entity__get(eid, health, HealthComponent, continue);
///
#define Entity__get(componentClass, eid, varName, orElseCode) \
auto& (varName) = Entity::get<componentClass>((eid)); \
if ((varName).empty()) orElseCode
///
/// System
///
/// Just implement either `tick` or `animate` or both.
/// Feel free to change this per your timestep implementation.
/// `Ent` is a convenience struct which gets all the most often used components for an entity by reference,
/// hence its implementation is based on your system design.
///
class System
{
public:
struct Ent;
static void tick(double fixedDelta);
static void animate(double delta, double tickPercent);
};