-
Notifications
You must be signed in to change notification settings - Fork 0
/
Refactor_ecs.txt
123 lines (99 loc) · 2.64 KB
/
Refactor_ecs.txt
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
Refactor goal : implement Instance based ECS system
0. Predicates
1, For entity A, B in { all entities }, if (A < B), then for all components of the same type of A and B, address(Com_A) + N * sizeof(Com_A) = address(Com_B), where N is a samll finite integer.
2, For S in { all systems }, any iteration on entities within the logic flow of S should be incremental, meaning for entity A in {a iteration of entities}, A < A_next.
These are the Two Predicates of ECS
1.
In order to replace the current implementation of the struct Entity, which is
struct CACHE_ALIGN8 Entity
{
EntityID m_id{ 0 };
EntityType m_type{ 0 };
}
We need to implement a type component, which can be defined as the following:
#define TYPE_NAME_MAX_LEN 32
struct CACHE_ALIGN32 TypeNameCom final : BaseComponent<TypeNameCom>
{
char m_type[TYPE_NAME_MAX_LEN] = "";
void SetTypeName(cosnt char* typeName)
{
if (std::strlen(m_type))
{
throw exception;
}
if (std::strlen(typeName) <= TYPE_NAME_MAX_LEN)
{
strcpy(m_type, typeName);
}
else
{
throw exception;
}
}
bool IsSameType(cosnt char* typeName) const
{
return strcmp(m_type, typeName) == 0;
}
bool IsBaseTypeOf(const char* typeName) const
{
if (std::strlen(m_type) > std::strlen(typeName))
{
return false;
}
else
{
for (int i = 0; i < std::strlen(m_type); ++i)
{
if (typeName[i] != m_type[i])
{
return false;
}
}
return true;
}
}
bool IsDerivedTypeOf(const char* typeName) const
{
if (std::strlen(m_type) < std::strlen(typeName))
{
return false;
}
else
{
for (int i = 0; i < std::strlen(typeName); ++i)
{
if (typeName[i] != m_type[i])
{
return false;
}
}
return true;
}
}
}
#undef TYPE_NAME_MAX_LEN
The new Entity struct should be simply
struct CACHE_ALIGN8 Entity
{
uint64_t m_id{ 0 };
}
Now, instead of using Entity to hold its type info, we need the GameWorld to hold the type info of each entity
Entity GameWorld::GenerateEntityWithTypeName(const std::string& typeName)
{
}
void GameWorld::BindEntityWithTypeName(Entity e, const std::string& typeName)
{
auto& vec = m_typeNameToEntitiesMap[typeName];
if (int index = LongMarch_lowerBoundFindIndex(vec, e); index != -1) [[unlikely]]
{
vec.insert(index, e);
}
else [[likely]]
{
vec.push_back(e);
}
}
Since we already manage entity type by gameworld, we simply transfer all functionality from EntityManager to GameWorld.
2. Refactory insert erase mechanism to compliance with the predicate(X)
3. Refactor bitmask entity dual map such that query all entities with some defined components would be much faster
Also, move bitmask from gameworld to entity manager