-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathecs.cpp
183 lines (153 loc) · 6.64 KB
/
ecs.cpp
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#include <iostream>
#include <algorithm>
#include <numeric>
#include <thh-packed-hashtable/packed-hashtable.hpp>
int main(int argc, char** argv)
{
struct transform_component_t
{
char id_; // debug identifier
};
struct physics_component_t
{
char id_; // debug identifier
};
// note: in future this could potentially be used to store a bitmask for
// components that the entity has
struct empty_t
{
};
using entity_id_t = thh::typed_handle_t<struct entity_id_tag>;
thh::handle_vector_t<empty_t, struct entity_id_tag> entity_ids;
constexpr int EntityCount = 12;
std::vector<entity_id_t> entity_handles;
entity_handles.reserve(EntityCount);
for (int i = 0; i < EntityCount; ++i) {
entity_handles.push_back(entity_ids.add());
}
std::cout << "allocated entity ids\n";
for (int i = 0; i < EntityCount; ++i) {
auto handle = entity_ids.handle_from_index(i);
std::cout << handle.id_ << ", ";
}
std::cout << '\n';
thh::packed_hashtable_rl_t<
entity_id_t, transform_component_t,
thh::typed_handle_hash_t<struct entity_id_tag>, std::equal_to<entity_id_t>,
struct transform_tag>
transform_components;
thh::packed_hashtable_rl_t<
entity_id_t, physics_component_t,
thh::typed_handle_hash_t<struct entity_id_tag>, std::equal_to<entity_id_t>,
struct physics_tag>
physics_components;
// add transform components in a random order to entities (12)
transform_components.add({entity_handles[2], transform_component_t{'c'}});
transform_components.add({entity_handles[1], transform_component_t{'b'}});
transform_components.add({entity_handles[5], transform_component_t{'f'}});
transform_components.add({entity_handles[4], transform_component_t{'e'}});
transform_components.add({entity_handles[0], transform_component_t{'a'}});
transform_components.add({entity_handles[3], transform_component_t{'d'}});
transform_components.add({entity_handles[8], transform_component_t{'i'}});
transform_components.add({entity_handles[7], transform_component_t{'h'}});
transform_components.add({entity_handles[11], transform_component_t{'l'}});
transform_components.add({entity_handles[6], transform_component_t{'g'}});
transform_components.add({entity_handles[10], transform_component_t{'k'}});
transform_components.add({entity_handles[9], transform_component_t{'j'}});
// add physics components in a random order to half entities (6)
physics_components.add({entity_handles[4], physics_component_t{'e'}});
physics_components.add({entity_handles[5], physics_component_t{'f'}});
physics_components.add({entity_handles[0], physics_component_t{'a'}});
physics_components.add({entity_handles[1], physics_component_t{'b'}});
physics_components.add({entity_handles[3], physics_component_t{'d'}});
physics_components.add({entity_handles[2], physics_component_t{'c'}});
const auto components_display =
[](const auto& components, const std::string& component_name) {
std::cout << component_name << " entity ids\n";
for (auto it = components.vbegin(); it != components.vend(); ++it) {
const auto handle = components.handle_from_index(
static_cast<int32_t>(std::distance(components.vbegin(), it)));
if (auto entity_id = components.key_from_handle(handle);
entity_id.has_value()) {
std::cout << entity_id->id_ << ", ";
}
}
std::cout << '\n';
std::cout << component_name << " values\n";
for (const auto& v : components.value_iteration()) {
std::cout << v.id_ << ", ";
}
std::cout << '\n';
};
components_display(transform_components, "transform component");
components_display(physics_components, "physics component");
std::vector<entity_id_t> physics_value_order_entity_ids;
// physics components is smaller than transform
// build entity id list for physics components
for (int32_t index = 0; index < physics_components.size(); ++index) {
if (auto entity_id = physics_components.key_from_index(index);
entity_id.has_value()) {
physics_value_order_entity_ids.push_back(entity_id.value());
}
}
std::vector<entity_id_t> transform_value_order_entity_ids;
for (int32_t index = 0; index < transform_components.size(); ++index) {
if (auto entity_id = transform_components.key_from_index(index);
entity_id.has_value()) {
transform_value_order_entity_ids.push_back(entity_id.value());
}
}
std::cout << "entity ids in transform component order\n";
for (auto& value_order_entity_id : transform_value_order_entity_ids) {
std::cout << value_order_entity_id.id_ << ", ";
}
std::cout << '\n';
std::cout << "entity ids in physics component order\n";
for (auto& value_order_entity_id : physics_value_order_entity_ids) {
std::cout << value_order_entity_id.id_ << ", ";
}
std::cout << '\n';
// find the smallest list of components (note: in this example we know physics
// components is the smallest list)
// partition all transform components so those in the first half all
// also have a physics component
// (partition larget set of components based on those in the smaller set or
// not)
auto second = transform_components.partition(
[&physics_components, &transform_components](const int32_t index) {
const auto handle = transform_components.handle_from_index(index);
return physics_components.has(
transform_components.key_from_handle(handle).value());
});
// sort first half (valid/left) of the transform components partition based on
// entity id
transform_components.sort(
0, second,
[&transform_value_order_entity_ids](const int32_t lhs, const int32_t rhs) {
return transform_value_order_entity_ids[lhs].id_
< transform_value_order_entity_ids[rhs].id_;
});
// sort physics components based on entity id
physics_components.sort(
[&physics_value_order_entity_ids](const int32_t lhs, const int32_t rhs) {
return physics_value_order_entity_ids[lhs].id_
< physics_value_order_entity_ids[rhs].id_;
});
components_display(transform_components, "transform component");
components_display(physics_components, "physics component");
// example ecs system - iterate
auto physics_system_fn =
[](transform_component_t& transform, physics_component_t& physics) {
std::cout << "transform: " << transform.id_ << " physics: " << physics.id_
<< '\n';
};
// iterate over shortest list of components
auto t_it = transform_components.vbegin();
auto p_it = physics_components.vbegin();
for (;
t_it != transform_components.vend() && p_it != physics_components.vend();
++p_it, ++t_it) {
physics_system_fn(*t_it, *p_it);
}
return 0;
}