MCPcopy Create free account
hub / github.com/alecthomas/entityx / CollisionSystem

Class CollisionSystem

examples/example.cc:164–236  ·  view source on GitHub ↗

Determines if two Collideable bodies have collided. If they have it emits a CollisionEvent. This is used by ExplosionSystem to create explosion particles, but it could be used by a SoundSystem to play an explosion sound, etc.. Uses a fairly rudimentary 2D partition system, but performs reasonably well.

Source from the content-addressed store, hash-verified

162//
163// Uses a fairly rudimentary 2D partition system, but performs reasonably well.
164class CollisionSystem : public ex::System<CollisionSystem> {
165 static const int PARTITIONS = 200;
166
167 struct Candidate {
168 sf::Vector2f position;
169 float radius;
170 ex::Entity entity;
171 };
172
173public:
174 explicit CollisionSystem(sf::RenderTarget &target) : size(target.getSize()) {
175 size.x = size.x / PARTITIONS + 1;
176 size.y = size.y / PARTITIONS + 1;
177 }
178
179 void update(ex::EntityManager &es, ex::EventManager &events, ex::TimeDelta dt) override {
180 reset();
181 collect(es);
182 collide(events);
183 };
184
185private:
186 std::vector<std::vector<Candidate>> grid;
187 sf::Vector2u size;
188
189 void reset() {
190 grid.clear();
191 grid.resize(size.x * size.y);
192 }
193
194 void collect(ex::EntityManager &entities) {
195 ex::ComponentHandle<Body> body;
196 ex::ComponentHandle<Collideable> collideable;
197 for (ex::Entity entity : entities.entities_with_components(body, collideable)) {
198 unsigned int
199 left = static_cast<int>(body->position.x - collideable->radius) / PARTITIONS,
200 top = static_cast<int>(body->position.y - collideable->radius) / PARTITIONS,
201 right = static_cast<int>(body->position.x + collideable->radius) / PARTITIONS,
202 bottom = static_cast<int>(body->position.y + collideable->radius) / PARTITIONS;
203 Candidate candidate {body->position, collideable->radius, entity};
204 unsigned int slots[4] = {
205 left + top * size.x,
206 right + top * size.x,
207 left + bottom * size.x,
208 right + bottom * size.x,
209 };
210 grid[slots[0]].push_back(candidate);
211 if (slots[0] != slots[1]) grid[slots[1]].push_back(candidate);
212 if (slots[1] != slots[2]) grid[slots[2]].push_back(candidate);
213 if (slots[2] != slots[3]) grid[slots[3]].push_back(candidate);
214 }
215 }
216
217 void collide(ex::EventManager &events) {
218 for (const std::vector<Candidate> &candidates : grid) {
219 for (const Candidate &left : candidates) {
220 for (const Candidate &right : candidates) {
221 if (left.entity == right.entity) continue;

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected