Skip to main content

CollisionComponent.ixx File

Component for layer-based collision detection and event generation. More...

Included Headers

Namespaces Index

namespacehelios
namespaceengine

Main engine module aggregating core infrastructure and game systems. More...

namespacemodules

Domain-specific components and systems. More...

namespacephysics

Physics simulation and collision detection subsystem for the game engine. More...

namespacecollision
namespacecomponents

Collider components for collision detection. More...

Classes Index

classCollisionComponent

Defines collision layer membership and interaction masks for a GameObject. More...

Description

Component for layer-based collision detection and event generation.

File Listing

The file content with the documentation metadata removed is:

1/**
2 * @file CollisionComponent.ixx
3 * @brief Component for layer-based collision detection and event generation.
4 */
5module;
6
7#include <array>
8#include <format>
9
10export module helios.engine.modules.physics.collision.components.CollisionComponent;
11
12
13import helios.engine.ecs.GameObject;
14
15import helios.engine.modules.physics.collision.types.CollisionBehavior;
16import helios.engine.modules.physics.collision.types.HitPolicy;
17
19
20 /**
21 * @class CollisionComponent
22 * @brief Defines collision layer membership and interaction masks for a GameObject.
23 *
24 * @details CollisionComponent enables layer-based collision filtering by assigning
25 * each entity to a specific layer and defining which other layers it can interact with.
26 * Two separate bitmasks control trigger (non-physical) or solid (physical) collision
27 * generation.
28 *
29 * Trigger collisions are asymmetric: entity A can detect entity B without B detecting A.
30 * Solid collisions should be treated symmetrically by the collision system.
31 *
32 * The collision reporter flag controls whether this entity can emit collision events.
33 * Non-reporter entities participate in collision detection but do not generate events.
34 *
35 * Example usage:
36 * ```cpp
37 * constexpr uint32_t LAYER_PLAYER = 1 << 0;
38 * constexpr uint32_t LAYER_ENEMY = 1 << 1;
39 * constexpr uint32_t LAYER_BULLET = 1 << 2;
40 *
41 * auto& collision = gameObject.add<CollisionComponent>(LAYER_PLAYER);
42 * collision.setTriggerCollisionMask(LAYER_ENEMY | LAYER_BULLET);
43 * collision.setSolidCollisionMask(LAYER_ENEMY);
44 * ```
45 */
47
49
50 /**
51 * @brief The collision layer this component belongs to.
52 */
53 uint32_t layerId_{};
54
55 /**
56 * @brief Bitmask specifying layers that generate trigger collisions.
57 *
58 * @details Trigger collision masks may be asymmetric, i.e. a component B must not
59 * know about the existence of another layerId.
60 */
61 uint32_t triggerCollisionMask_{};
62
63 /**
64 * @brief Bitmask specifying layers that generate solid collisions.
65 *
66 * @details Solid collision should be symmetric and in the calling API treated as such:
67 * `(maskB & thisLayerId) != 0 && (thisMask & layerBId) != 0`
68 */
69 uint32_t solidCollisionMask_{};
70
71 /**
72 * @brief Flag indicating whether this component can report collision events.
73 */
74 bool isCollisionReporter_ = true;
75
77
78 /**
79 * @brief Per-behavior layer masks for solid collisions.
80 *
81 * @details Each array index corresponds to a CollisionBehavior enum value.
82 * The bitmask at each index indicates which layers trigger that behavior
83 * for solid collisions.
84 */
85 std::array<
86 uint32_t,
88 > solidCollisionBehavior_{};
89
90 /**
91 * @brief Per-behavior layer masks for trigger collisions.
92 *
93 * @details Each array index corresponds to a CollisionBehavior enum value.
94 * The bitmask at each index indicates which layers trigger that behavior
95 * for trigger collisions.
96 */
97 std::array<
98 uint32_t,
100 > triggerCollisionBehavior_{};
101
102 /**
103 * @brief Controls how many collisions are reported per frame.
104 *
105 * @details Defaults to `OneHit`, reporting only the first collision.
106 * Set to `All` for multi-target collision detection.
107 *
108 * @see HitPolicy
109 */
111
112 /**
113 * @brief Whether this component is enabled.
114 */
115 bool isEnabled_ = true;
116
117 public:
118
119 /**
120 * @brief Checks whether this component is enabled.
121 *
122 * @return True if enabled, false otherwise.
123 */
124 [[nodiscard]] bool isEnabled() const noexcept {
125 return isEnabled_;
126 }
127
128 /**
129 * @brief Enables this component.
130 */
131 void enable() noexcept {
132 isEnabled_ = true;
133 }
134
135 /**
136 * @brief Disables this component.
137 */
138 void disable() noexcept {
139 isEnabled_ = false;
140 }
141
142 /**
143 * @brief Constructs a CollisionComponent with a layer ID.
144 *
145 * @param layerId The collision layer this entity belongs to.
146 * @param isCollisionReporter Whether this entity can emit collision events.
147 * @param solidCollisionMask Initial bitmask for solid collisions.
148 * @param triggerCollisionMask Initial bitmask for trigger collisions.
149 */
150 explicit CollisionComponent(uint32_t layerId, bool isCollisionReporter = true,
151 uint32_t solidCollisionMask = 0, uint32_t triggerCollisionMask = 0
152 ) :
153 layerId_(layerId),
154 isCollisionReporter_(isCollisionReporter),
155 solidCollisionMask_(solidCollisionMask),
156 triggerCollisionMask_(triggerCollisionMask){}
157
158 /**
159 * @brief Copy constructor.
160 *
161 * @details Creates a deep copy of the collision component, preserving
162 * layer ID, masks, and all behavior configurations.
163 *
164 * @param other The component to copy from.
165 */
167 layerId_(other.layerId_),
168 isCollisionReporter_(other.isCollisionReporter_),
169 solidCollisionMask_(other.solidCollisionMask_),
170 triggerCollisionMask_(other.triggerCollisionMask_),
171 solidCollisionBehavior_(other.solidCollisionBehavior_),
172 triggerCollisionBehavior_(other.triggerCollisionBehavior_),
173 hitPolicy_(other.hitPolicy_)
174 {}
175
178 CollisionComponent& operator=(CollisionComponent&&) noexcept = default;
179
180
181 /**
182 * @brief Sets whether this component should report collision events.
183 *
184 * @param isCollisionReporter True to enable event reporting, false to disable.
185 */
187 isCollisionReporter_ = isCollisionReporter;
188 }
189
190 /**
191 * @brief Sets the hit policy for collision detection.
192 *
193 * @details Controls how many collision events this entity can receive
194 * per frame:
195 * - `OneHit`: Only the first collision is reported (default)
196 * - `All`: All collisions are reported
197 *
198 * @param hitPolicy The hit policy to apply.
199 *
200 * @see HitPolicy
201 */
203 hitPolicy_ = hitPolicy;
204 }
205
206 /**
207 * @brief Returns the current hit policy.
208 *
209 * @return The configured HitPolicy for this component.
210 *
211 * @see HitPolicy
212 */
214 return hitPolicy_;
215 }
216
217 /**
218 * @brief Returns whether this component can emit collision events.
219 *
220 * @return True if collision events can be generated, false otherwise.
221 */
222 [[nodiscard]] bool isCollisionReporter() const noexcept {
223 return isCollisionReporter_;
224 }
225
226 /**
227 * @brief Sets the solid collision mask.
228 *
229 * @param solidCollisionMask Bitmask of layers to generate solid collisions with.
230 *
231 * @return Reference to this component for method chaining.
232 */
234 solidCollisionMask_ = solidCollisionMask;
235 return *this;
236 }
237
238 /**
239 * @brief Sets the trigger collision mask.
240 *
241 * @param triggerCollisionMask Bitmask of layers to generate trigger collisions with.
242 *
243 * @return Reference to this component for method chaining.
244 */
246 triggerCollisionMask_ = triggerCollisionMask;
247 return *this;
248 }
249
250 /**
251 * @brief Returns the solid collision mask.
252 *
253 * @return Bitmask of layers this entity generates solid collisions with.
254 */
255 [[nodiscard]] uint32_t solidCollisionMask() const noexcept {
256 return solidCollisionMask_;
257 }
258
259 /**
260 * @brief Returns the trigger collision mask.
261 *
262 * @return Bitmask of layers this entity generates trigger collisions with.
263 */
264 [[nodiscard]] uint32_t triggerCollisionMask() const noexcept {
265 return triggerCollisionMask_;
266 }
267
268 /**
269 * @brief Returns the collision layer ID.
270 *
271 * @return The layer this entity belongs to.
272 */
273 [[nodiscard]] unsigned int layerId() const noexcept {
274 return layerId_;
275 }
276
277 /**
278 * @brief Adds a solid collision behavior for a specific layer.
279 *
280 * @details Associates a collision behavior with a target layer for solid collisions.
281 * If a behavior was previously set for the same layer, it is replaced.
282 *
283 * @param collisionBehavior The behavior to apply on collision.
284 * @param otherLayerId The layer ID to associate the behavior with.
285 *
286 * @return Reference to this component for method chaining.
287 */
290 const uint32_t otherLayerId
291 ) noexcept {
292
293 // remove previous entries for the layerid
294 for (auto& behavior : solidCollisionBehavior_) {
295 behavior &= ~otherLayerId;
296 }
297
298 const auto rawMask = std::to_underlying(collisionBehavior);
299 for (int i = 0; i < CollisionBehaviorSize; i++) {
300 if ((rawMask >> i ) & 1) {
301 solidCollisionBehavior_[i] |= otherLayerId;
302 }
303 }
304
305 return *this;
306 }
307
308 /**
309 * @brief Returns the solid collision behavior for a specific layer.
310 *
311 * @details Looks up the configured behavior for collisions with the specified layer.
312 * Returns `CollisionBehavior::None` if no solid collision mask is set for the layer.
313 *
314 * @param otherLayerId The layer ID to query.
315 *
316 * @return The collision behavior for the specified layer.
317 */
320 if ((solidCollisionMask_ & otherLayerId) == 0) {
321 return CollisionBehavior::None;
322 }
323
324 auto resultMask = CollisionBehavior::None;
325 for (int i = 0; i < solidCollisionBehavior_.size(); i++) {
326
327 if ((solidCollisionBehavior_[i] & otherLayerId) != 0) {
328 resultMask = resultMask | static_cast<CollisionBehavior>(1 << i);
329 }
330 }
331
332 return resultMask;
333 }
334
335 /**
336 * @brief Returns the trigger collision behavior for a specific layer.
337 *
338 * @details Looks up the configured behavior for trigger collisions with the
339 * specified layer. Returns `CollisionBehavior::None` if no trigger collision
340 * mask is set for the layer.
341 *
342 * @param otherLayerId The layer ID to query.
343 *
344 * @return The collision behavior for the specified layer.
345 */
348 if ((triggerCollisionMask_ & otherLayerId) == 0) {
349 return CollisionBehavior::None;
350 }
351
352 auto resultMask = CollisionBehavior::None;
353 for (int i = 0; i < triggerCollisionBehavior_.size(); i++) {
354 if ((triggerCollisionBehavior_[i] & otherLayerId) != 0) {
355 resultMask = resultMask | static_cast<CollisionBehavior>(1 << i);
356 }
357 }
358
359 return resultMask;
360 }
361
362
363 /**
364 * @brief Adds a trigger collision behavior for a specific layer.
365 *
366 * @details Associates a collision behavior with a target layer for trigger collisions.
367 * If a behavior was previously set for the same layer, it is replaced.
368 *
369 * @param collisionBehavior The behavior to apply on collision.
370 * @param otherLayerId The layer ID to associate the behavior with.
371 *
372 * @return Reference to this component for method chaining.
373 */
376 const uint32_t otherLayerId
377 ) noexcept {
378
379 // remove previous entries for the layerid
380 for (auto& behavior : triggerCollisionBehavior_) {
381 behavior &= ~otherLayerId;
382 }
383
384 const auto rawMask = std::to_underlying(collisionBehavior);
385 for (int i = 0; i < CollisionBehaviorSize; i++) {
386 if ((rawMask >> i ) & 1) {
387 triggerCollisionBehavior_[i] |= otherLayerId;
388 }
389 }
390
391 return *this;
392 }
393
394 };
395
396
397}
398

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.15.0.