Skip to main content

LevelBoundsBehaviorSystem.ixx File

System for handling entity behavior at level boundaries. More...

Included Headers

#include <cassert> #include <helios.engine.common.tags.SystemRole> #include <helios.engine.mechanics.lifecycle.components.Active> #include <helios.engine.runtime.world.UpdateContext> #include <helios.engine.runtime.spawn.commands.DespawnCommand> #include <helios.engine.ecs.View> #include <helios.engine.modules.scene.components.SceneNodeComponent> #include <helios.engine.modules.rendering.model.components.ModelAabbComponent> #include <helios.engine.modules.spatial.transform.components.RotationStateComponent> #include <helios.engine.mechanics.spawn.components.SpawnedByProfileComponent> #include <helios.engine.modules.physics.collision.components.AabbColliderComponent> #include <helios.math> #include <helios.engine.mechanics.bounds.components.LevelBoundsBehaviorComponent> #include <helios.engine.runtime.messaging.command.EngineCommandBuffer> #include <helios.engine.modules.physics.collision.types.CollisionBehavior> #include <helios.engine.state.Bindings> #include <helios.engine.modules.physics.collision.types.CollisionResponse> #include <helios.engine.modules.physics.motion.components.Move2DComponent> #include <helios.engine.ecs.GameObject> #include <helios.scene.SceneNode> #include <helios.engine.modules.physics.motion.components.SteeringComponent> #include <helios.engine.modules.spatial.transform.components.ComposeTransformComponent> #include <helios.engine.runtime.world.GameWorld> #include <helios.engine.modules.spatial.transform.components.TranslationStateComponent> #include <helios.engine.modules.physics.motion.components.DirectionComponent>

Namespaces Index

namespacehelios
namespaceengine

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

namespacemechanics

High-level gameplay systems and components for game logic. More...

namespacebounds
namespacesystems

Boundary detection and response systems. More...

Classes Index

classLevelBoundsBehaviorSystem

System that handles entity behavior when colliding with level boundaries. More...

structBounceResult

Result of a bounce calculation against level bounds. More...

Description

System for handling entity behavior at level boundaries.

File Listing

The file content with the documentation metadata removed is:

1/**
2 * @file LevelBoundsBehaviorSystem.ixx
3 * @brief System for handling entity behavior at level boundaries.
4 */
5module;
6
7#include <cassert>
8
9export module helios.engine.mechanics.bounds.systems.LevelBoundsBehaviorSystem;
10
11
12
13import helios.math;
14
15import helios.engine.state.Bindings;
16import helios.engine.runtime.messaging.command.EngineCommandBuffer;
17
18import helios.engine.modules.physics.collision.types.CollisionBehavior;
19import helios.engine.modules.physics.collision.types.CollisionResponse;
20
21import helios.engine.ecs.GameObject;
22import helios.engine.runtime.world.GameWorld;
23import helios.engine.modules.physics.motion.components.Move2DComponent;
24import helios.engine.modules.physics.motion.components.SteeringComponent;
25import helios.engine.modules.spatial.transform.components.ComposeTransformComponent;
26import helios.engine.modules.spatial.transform.components.TranslationStateComponent;
27import helios.engine.modules.physics.motion.components.DirectionComponent;
28import helios.engine.mechanics.bounds.components.LevelBoundsBehaviorComponent;
29import helios.engine.modules.physics.collision.components.AabbColliderComponent;
30import helios.engine.modules.spatial.transform.components.RotationStateComponent;
31import helios.engine.modules.rendering.model.components.ModelAabbComponent;
32import helios.scene.SceneNode;
33import helios.engine.modules.scene.components.SceneNodeComponent;
34
35import helios.engine.ecs.View;
36
37import helios.engine.runtime.world.UpdateContext;
38
39import helios.engine.runtime.spawn.commands.DespawnCommand;
40
41import helios.engine.mechanics.spawn.components.SpawnedByProfileComponent;
42
43import helios.engine.mechanics.lifecycle.components.Active;
44
45
46import helios.engine.common.tags.SystemRole;
47
49
50 /**
51 * @brief System that handles entity behavior when colliding with level boundaries.
52 *
53 * @details
54 * This system checks if entities with movement components have exceeded the level bounds.
55 * When an entity leaves the bounds, it applies bounce behavior based on the
56 * LevelBoundsBehaviorComponent's restitution coefficient.
57 */
59
60 /**
61 * @brief Result of a bounce calculation against level bounds.
62 */
63 struct BounceResult {
64 /** @brief True if the X-axis boundary was hit. */
65 bool hitX;
66 /** @brief True if the Y-axis boundary was hit. */
67 bool hitY;
68 /** @brief The corrected world position. */
69 helios::math::vec3f translation;
70 /** @brief The new velocity after bounce. */
71 helios::math::vec3f velocity;
72 /** @brief The new direction vector. */
73 helios::math::vec3f direction;
74 };
75
76
77 public:
78
80
81 /**
82 * @brief Updates all entities that may have left level bounds.
83 *
84 * @details
85 * For each entity with the required components, checks if its world-space
86 * AABB is within level bounds. If not, applies bounce behavior.
87 *
88 * @param updateContext Context containing deltaTime and other frame data.
89 */
91
93
94 for (auto [entity, m2d, ab, sc, dc, tsc, bc, bbc, active] : updateContext.view<
103 >().whereEnabled()) {
104
105
106 auto& objectBounds = bc->bounds();
107 auto levelBounds = updateContext.level()->bounds();
108
109 if (!levelBounds.contains(objectBounds)) {
110
111 helios::math::mat4f parentWorldTransform = sc->sceneNode()->parent()->worldTransform();
112 helios::math::vec4f childWorldTranslation = parentWorldTransform * tsc->translation().toVec4(1.0f);
113
114 helios::math::vec3f bouncedWorldTranslation;
115
116 BounceResult bounceResult{};
117
118 if (bbc->collisionBehavior() == CollisionBehavior::Reflect || bbc->collisionBehavior() == CollisionBehavior::Bounce) {
119
120 bounceResult = bounce(
121 childWorldTranslation.toVec3(), objectBounds, levelBounds,
122 bbc->collisionBehavior() == CollisionBehavior::Reflect ? 1.0f : bbc->restitution(),
123 *m2d, *dc
124 );
125
126 bouncedWorldTranslation = bounceResult.translation;
127 updateCollisionResponse(entity, bounceResult, bbc->collisionResponse());
128
129 } else if (bbc->collisionBehavior() == CollisionBehavior::Despawn) {
130 /**
131 * @todo optimize
132 */
134 assert(sbp && "Unexpected missing SpawnProfile");
135
137 entity.entityHandle(), sbp->spawnProfileId()
138 );
139
140 }
141
142
143 if (bounceResult.hitX || bounceResult.hitY) {
144 m2d->setVelocity(bounceResult.velocity);
145 dc->setDirection(bounceResult.direction);
146 }
147
148 auto parentTransform_inverse = parentWorldTransform.inverse();
149 auto childLocalTranslation = parentTransform_inverse * bouncedWorldTranslation.toVec4(1.0f);
150
151 tsc->setTranslation(childLocalTranslation.toVec3());
152 bc->setBounds(ab->aabb().applyTransform(
153 parentWorldTransform.withTranslation(bouncedWorldTranslation)
154 ));
155
156 }
157 }
158 }
159
160 private:
161
162 /**
163 * @brief Updates the entity's state based on the configured collision response.
164 *
165 * @details
166 * If the response is set to AlignHeadingToDirection, this method updates the
167 * SteeringComponent to match the new bounce direction.
168 *
169 * @param go Pointer to the GameObject to update.
170 * @param bounceResult The result data from the bounce calculation.
171 * @param collisionResponse The type of response to apply.
172 */
173 void updateCollisionResponse(
175 BounceResult bounceResult,
177
180
181 const auto direction = bounceResult.direction;
182
183 if (psc) {
184 psc->setSteeringIntent(
185 bounceResult.direction, 1.0f
186 );
187 }
188 }
189 }
190
191 /**
192 * @brief Applies bounce behavior to an entity that has left level bounds.
193 *
194 * @details
195 * Calculates the corrected position and reflected velocity when an entity
196 * collides with level boundaries. The restitution coefficient determines
197 * how much velocity is preserved after the bounce. The DirectionComponent
198 * will be updated with the new direction.
199 *
200 * @param worldTranslation Current world position of the entity.
201 * @param objectBounds World-space AABB of the entity.
202 * @param levelBounds World-space AABB of the level.
203 * @param restitution
204 * @param m2d Reference to the Move2DComponent for velocity modification.
205 * @param dc Reference to the DirectionComponent for direction update.
206 *
207 * @return Corrected world position after bounce.
208 */
209 [[nodiscard]] BounceResult bounce(
210 helios::math::vec3f worldTranslation,
211 helios::math::aabbf objectBounds,
212 helios::math::aabbf levelBounds,
213 const float restitution,
216 ) noexcept {
217
218
219 auto velocity = m2d.velocity();
220 bool hitX = false;
221 bool hitY = false;
222 auto translation = worldTranslation;
223
224 // Check left boundary collision
225 if (objectBounds.min()[0] < levelBounds.min()[0]) {
226 translation[0] += (levelBounds.min()[0] - objectBounds.min()[0]);
227 if (velocity[0] < 0) {
228 velocity = (velocity.withX(restitution * -velocity[0]));
229 }
230 hitX = true;
231 // Check right boundary collision
232 } else if (objectBounds.max()[0] > levelBounds.max()[0]) {
233 translation[0] -= (objectBounds.max()[0] - levelBounds.max()[0]) ;
234 if (velocity[0] > 0) {
235 velocity = (velocity.withX(restitution * -velocity[0]));
236 }
237 hitX = true;
238 }
239
240 objectBounds = objectBounds + (translation - worldTranslation);
241
242 // Check bottom boundary collision
243 if (objectBounds.min()[1] < levelBounds.min()[1]) {
244 translation[1] += (levelBounds.min()[1] - objectBounds.min()[1]);
245 if (velocity[1] < 0) {
246 velocity = velocity.withY(restitution * -velocity[1]);
247 }
248 hitY = true;
249 // Check top boundary collision
250 } else if (objectBounds.max()[1] > levelBounds.max()[1]) {
251 translation[1] -= (objectBounds.max()[1] - levelBounds.max()[1]);
252 if (velocity[1] > 0) {
253 velocity = velocity.withY(restitution * -velocity[1]);
254 }
255 hitY = true;
256 }
257
258
259 return {
260 hitX, hitY, translation, velocity, velocity.normalize()
261 };
262 }
263
264 };
265
266};

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.15.0.