diff options
author | JAROWMR <jarorutjes07@gmail.com> | 2024-12-03 19:32:15 +0100 |
---|---|---|
committer | JAROWMR <jarorutjes07@gmail.com> | 2024-12-03 19:32:15 +0100 |
commit | ff618da3f97237796042fa3664da59ed147bc1da (patch) | |
tree | cfc283425f145b16a2b2e3b1a0a5760e8015a2b1 /src | |
parent | fb018cd8511e9cae408f8ea7d2b73e66a452625b (diff) |
improved comments
Diffstat (limited to 'src')
-rw-r--r-- | src/crepe/Collider.h | 18 | ||||
-rw-r--r-- | src/crepe/api/BoxCollider.cpp | 2 | ||||
-rw-r--r-- | src/crepe/api/BoxCollider.h | 10 | ||||
-rw-r--r-- | src/crepe/api/Rigidbody.h | 128 | ||||
-rw-r--r-- | src/crepe/system/CollisionSystem.cpp | 167 | ||||
-rw-r--r-- | src/crepe/system/CollisionSystem.h | 32 | ||||
-rw-r--r-- | src/crepe/system/PhysicsSystem.cpp | 8 | ||||
-rw-r--r-- | src/example/game.cpp | 4 | ||||
-rw-r--r-- | src/test/CollisionTest.cpp | 56 | ||||
-rw-r--r-- | src/test/PhysicsTest.cpp | 8 | ||||
-rw-r--r-- | src/test/Profiling.cpp | 2 |
11 files changed, 257 insertions, 178 deletions
diff --git a/src/crepe/Collider.h b/src/crepe/Collider.h index 15d3a24..f5f53d2 100644 --- a/src/crepe/Collider.h +++ b/src/crepe/Collider.h @@ -10,7 +10,23 @@ public: Collider(game_object_id_t id, const vec2& offset); public: - //! Offset of the collider relative to rigidbody position + /** + * \brief Offset of the collider relative to the rigidbody position. + * + * The `offset` defines the positional shift applied to the collider relative to the position of the rigidbody it is attached to. + * This allows the collider to be placed at a different position than the rigidbody, which can be useful for scenarios + * where the collider's position needs to differ from the rigidbody's center, such as in non-centered colliders. + * + * - The `offset` is typically used when the collider is not meant to be centered exactly on the rigidbody's position. + * - For example, the collider might need to be shifted to account for an object with an asymmetrical shape or for objects + * where the pivot point of the rigidbody is different from the collider's center. + * + * When multiple colliders are added to the same object (e.g., a character with separate body parts or a vehicle with multiple zones), + * the offset is important for properly positioning each collider relative to the rigidbody, allowing accurate collision detection. + * + * - Multiple colliders can be used on the same object, and each can have its own unique offset. + * - Overlap between colliders is allowed and does not impact performance. + */ vec2 offset; }; diff --git a/src/crepe/api/BoxCollider.cpp b/src/crepe/api/BoxCollider.cpp index 1069e90..f94ced7 100644 --- a/src/crepe/api/BoxCollider.cpp +++ b/src/crepe/api/BoxCollider.cpp @@ -4,4 +4,4 @@ using namespace crepe; -BoxCollider::BoxCollider(game_object_id_t game_object_id,const vec2& offset, float width, float height) : Collider(game_object_id,offset), width(width), height(height) {} +BoxCollider::BoxCollider(game_object_id_t game_object_id,const vec2& offset, const vec2& dimensions) : Collider(game_object_id,offset), dimensions(dimensions) {} diff --git a/src/crepe/api/BoxCollider.h b/src/crepe/api/BoxCollider.h index c83d54a..1f5f1c1 100644 --- a/src/crepe/api/BoxCollider.h +++ b/src/crepe/api/BoxCollider.h @@ -2,6 +2,7 @@ #include "Vector2.h" #include "../Collider.h" +#include "types.h" namespace crepe { @@ -12,13 +13,10 @@ namespace crepe { */ class BoxCollider : public Collider { public: - BoxCollider(game_object_id_t game_object_id,const vec2& offset, float width, float height); + BoxCollider(game_object_id_t game_object_id,const vec2& offset, const vec2& dimensions); - //! Width of box collider - float width; - - //! Height of box collider - float height; + //! Width and height of the box collider + vec2 dimensions; }; } // namespace crepe diff --git a/src/crepe/api/Rigidbody.h b/src/crepe/api/Rigidbody.h index 63b1b51..9cdf3f5 100644 --- a/src/crepe/api/Rigidbody.h +++ b/src/crepe/api/Rigidbody.h @@ -36,11 +36,11 @@ public: * the systems will not move the object. */ struct PhysicsConstraints { - //! X constraint + //! Prevent movement along X axis bool x = false; - //! Y constraint + //! Prevent movement along Y axis bool y = false; - //! rotation constraint + //! Prevent rotation bool rotation = false; }; @@ -53,27 +53,112 @@ public: struct Data { //! objects mass float mass = 0.0; - //! gravtiy scale + /** + * \brief Gravity scale factor. + * + * The `gravity_scale` controls how much gravity affects the object. It is a multiplier applied to the default + * gravity force, allowing for fine-grained control over how the object responds to gravity. + * + * - A value of `0.0` means that gravity has **no effect** on the object (i.e., the object is completely immune to gravity). + * - A value of `1.0` means that gravity is applied at its **normal intensity** (the default behavior). + * - A value greater than `1.0` means the object is affected by gravity more strongly than normal. + * - A value less than `1.0` (but greater than `0.0`) reduces the effect of gravity on the object. + * + * This is useful in cases where you need objects to behave differently under gravity, such as lighter objects (like feathers), + * objects that float in water, or heavier objects that fall faster. + */ float gravity_scale = 0; - //! Changes if physics apply + /** + * \brief Defines the type of the physics body, which determines how the physics system interacts with the object. + * + * - **Static**: The object does not move and is not affected by forces. It is used for immovable objects like walls or terrain. Does not have collision detection. + * - **Dynamic**: The object is fully affected by physics forces, including gravity, collisions, and other physical interactions. It can move and be moved by forces. + * - **Kinematic**: The object does not move and is not affected by forces. It is typically controlled by external factors (e.g., animations or user input), and collision detection is handled without affecting its velocity. + * + * The `body_type` defines the behavior of the object in the physics system. + * + * \default BodyType::DYNAMIC + */ BodyType body_type = BodyType::DYNAMIC; - //! linear velocity of object + + /** + * \name Linear (positional) motion + * + * These variables define the linear motion (movement along the position) of an object. + * The linear velocity is applied to the object's position in each update of the PhysicsSystem. + * The motion is affected by the object's linear velocity, its maximum velocity, and a coefficient + * that can scale the velocity over time. + * + * \{ + */ + //! Linear velocity of the object (speed and direction). vec2 linear_velocity; - //! maximum linear velocity of object + //! Maximum linear velocity of the object. This limits the object's speed. vec2 max_linear_velocity = {INFINITY ,INFINITY}; - //! linear damping of object - vec2 linear_velocity_factor; - //! angular velocity of object + //! Linear velocity coefficient. This scales the object's velocity for adjustment or damping. + vec2 linear_velocity_coefficient = {1,1}; + //! \} + + /** + * \name Angular (rotational) motion + * + * These variables define the angular motion (rotation) of an object. + * The angular velocity determines how quickly the object rotates, while the maximum angular velocity + * sets a limit on the rotation speed. The angular velocity coefficient applies damping or scaling + * to the angular velocity, which can be used to simulate friction or other effects that slow down rotation. + * + * \{ + */ + //! Angular velocity of the object, representing the rate of rotation (in radians per second). float angular_velocity = 1; - //! max angular velocity of object + //! Maximum angular velocity of the object. This limits the maximum rate of rotation. float max_angular_velocity = INFINITY; - //! angular damping of object - float angular_velocity_factor = 1; - //! movements constraints of object + //! Angular velocity coefficient. This scales the object's angular velocity, typically used for damping. + float angular_velocity_coefficient = 1; + //! \} + + /** + * \brief Movement constraints for an object. + * + * The `PhysicsConstraints` struct defines the constraints that restrict an object's movement + * in certain directions or prevent rotation. These constraints effect only the physics system + * to prevent the object from moving or rotating in specified ways. + * + * - **X Constraint**: If enabled, the object cannot move along the X-axis. + * - **Y Constraint**: If enabled, the object cannot move along the Y-axis. + * - **Rotation Constraint**: If enabled, the object cannot rotate. + * + * These constraints allow you to restrict movement for specific scenarios (e.g., a platform that shouldn't move + * or a character that should only move horizontally). + */ PhysicsConstraints constraints; - //! bounce factor of material. 0.0 <= means all velocity is lost, 1.0 means it gets the same momentum but the mirrored direction. 0.5 is half of the velocity is saved. - float elastisity = 0.0; - //! offset of all colliders relative to transform position + + /** + * \brief Elasticity factor of the material (bounce factor). + * + * The `elasticity_coefficient` controls how much of the object's velocity is retained after a collision. + * It represents the material's ability to bounce or recover velocity upon impact. The coefficient is a value + * between 0.0 and 1.0, where: + * + * - **0.0** means no velocity is retained after the collision (all velocity is lost, and the object does not bounce). + * - **1.0** means the object retains its full velocity but in the opposite direction (perfect elastic bounce). + * - **0.5** means the object retains half of its velocity, resulting in a bounce with reduced speed. + * + * This factor can be used to simulate different materials, such as rubber (high elasticity) or concrete (low elasticity). + */ + float elastisity_coefficient = 0.0; + + /** + * \brief Offset of all colliders relative to the object's transform position. + * + * The `offset` defines a positional shift applied to all colliders associated with the object, relative to the object's + * transform position. This allows for the colliders to be placed at a different position than the object's actual + * position, without modifying the object's transform itself. + * + * - The `offset` is typically used to adjust the collider's position in cases where all colluders should be moved. + * - For example, if a character has a animation where all colliders should be moved this offset can be used to + * achieve this. + */ vec2 offset; }; @@ -99,6 +184,15 @@ public: * \param force Vector2 that is added to the angular force. */ void add_force_angular(float force); + +protected: + /** + * Ensures there is at most one Rigidbody component per entity. + * \return Always returns 1, indicating this constraint. + */ + virtual int get_instances_max() const { return 1; } + //! ComponentManager instantiates all components + friend class ComponentManager; }; } // namespace crepe diff --git a/src/crepe/system/CollisionSystem.cpp b/src/crepe/system/CollisionSystem.cpp index 380cc3d..2d5ce9d 100644 --- a/src/crepe/system/CollisionSystem.cpp +++ b/src/crepe/system/CollisionSystem.cpp @@ -10,6 +10,7 @@ #include "api/EventManager.h" #include "api/BoxCollider.h" #include "api/CircleCollider.h" +#include "api/Metadata.h" #include "api/Vector2.h" #include "api/Rigidbody.h" #include "api/Transform.h" @@ -23,18 +24,16 @@ using namespace crepe; void CollisionSystem::update() { - std::vector<CollisionInternal> all_colliders; - ComponentManager & mgr = this->component_manager; game_object_id_t id = 0; - RefVector<Rigidbody> rigidbodies = mgr.get_components_by_type<Rigidbody>(); + RefVector<Rigidbody> rigidbodies = this->component_manager.get_components_by_type<Rigidbody>(); // Collisions can only happen on object with a rigidbody for(Rigidbody& rigidbody : rigidbodies) { if (!rigidbody.active) continue; id = rigidbody.game_object_id; Transform& transform = this->component_manager.get_components_by_id<Transform>(id).front().get(); // Check if the boxcollider is active and has the same id as the rigidbody. - RefVector<BoxCollider> boxcolliders = mgr.get_components_by_type<BoxCollider>(); + RefVector<BoxCollider> boxcolliders = this->component_manager.get_components_by_type<BoxCollider>(); for (BoxCollider& boxcollider : boxcolliders) { if(boxcollider.game_object_id != id) continue; if(!boxcollider.active) continue; @@ -48,7 +47,7 @@ void CollisionSystem::update() { ); } // Check if the circlecollider is active and has the same id as the rigidbody. - RefVector<CircleCollider> circlecolliders = mgr.get_components_by_type<CircleCollider>(); + RefVector<CircleCollider> circlecolliders = this->component_manager.get_components_by_type<CircleCollider>(); for (CircleCollider& circlecollider : circlecolliders) { if(circlecollider.game_object_id != id) continue; if(!circlecollider.active) continue; @@ -64,59 +63,63 @@ void CollisionSystem::update() { } // Check between all colliders if there is a collision - std::vector<std::pair<CollisionInternal,CollisionInternal>> collided = gather_collisions(all_colliders); + std::vector<std::pair<CollisionInternal,CollisionInternal>> collided = this->gather_collisions(all_colliders); // For both objects call the collision handler for (auto& collision_pair : collided) { - collision_handler_request(collision_pair.first,collision_pair.second); - collision_handler_request(collision_pair.second,collision_pair.first); + this->collision_handler_request(collision_pair.first,collision_pair.second); + this->collision_handler_request(collision_pair.second,collision_pair.first); } } -void CollisionSystem::collision_handler_request(CollisionInternal& data1,CollisionInternal& data2){ +void CollisionSystem::collision_handler_request(CollisionInternal& this_data,CollisionInternal& other_data){ - CollisionInternalType type = get_collider_type(data1.collider,data2.collider); - std::pair<vec2,CollisionSystem::Direction> resolution_data = collision_handler(data1,data2,type); + CollisionInternalType type = this->get_collider_type(this_data.collider,other_data.collider); + std::pair<vec2,CollisionSystem::Direction> resolution_data = this->collision_handler(this_data,other_data,type); - OptionalRef<Collider> collider1; - OptionalRef<Collider> collider2; + OptionalRef<Metadata> this_metadata = this->component_manager.get_components_by_id<Metadata>(this_data.id).front().get(); + OptionalRef<Metadata> other_metadata = this->component_manager.get_components_by_id<Metadata>(other_data.id).front().get(); + OptionalRef<Collider> this_collider; + OptionalRef<Collider> other_collider; switch (type) { case CollisionInternalType::BOX_BOX:{ - collider1 = std::get<std::reference_wrapper<BoxCollider>>(data1.collider); - collider2 = std::get<std::reference_wrapper<BoxCollider>>(data2.collider); + this_collider = std::get<std::reference_wrapper<BoxCollider>>(this_data.collider); + other_collider = std::get<std::reference_wrapper<BoxCollider>>(other_data.collider); break; } case CollisionInternalType::BOX_CIRCLE:{ - collider1 = std::get<std::reference_wrapper<BoxCollider>>(data1.collider); - collider2 = std::get<std::reference_wrapper<CircleCollider>>(data2.collider); + this_collider = std::get<std::reference_wrapper<BoxCollider>>(this_data.collider); + other_collider = std::get<std::reference_wrapper<CircleCollider>>(other_data.collider); break; } case CollisionInternalType::CIRCLE_BOX:{ - collider1 = std::get<std::reference_wrapper<CircleCollider>>(data1.collider); - collider2 = std::get<std::reference_wrapper<BoxCollider>>(data2.collider); + this_collider = std::get<std::reference_wrapper<CircleCollider>>(this_data.collider); + other_collider = std::get<std::reference_wrapper<BoxCollider>>(other_data.collider); break; } case CollisionInternalType::CIRCLE_CIRCLE:{ - collider1 = std::get<std::reference_wrapper<CircleCollider>>(data1.collider); - collider2 = std::get<std::reference_wrapper<CircleCollider>>(data2.collider); + this_collider = std::get<std::reference_wrapper<CircleCollider>>(this_data.collider); + other_collider = std::get<std::reference_wrapper<CircleCollider>>(other_data.collider); break; } } - + // collision info crepe::CollisionSystem::CollisionInfo collision_info{ - .first_collider = collider1, - .first_transform = data1.transform, - .first_rigidbody = data1.rigidbody, - .second_collider = collider2, - .second_transform = data2.transform, - .second_rigidbody = data2.rigidbody, + .this_collider = this_collider, + .this_transform = this_data.transform, + .this_rigidbody = this_data.rigidbody, + .this_metadata = this_metadata, + .other_collider = other_collider, + .other_transform = other_data.transform, + .other_rigidbody = other_data.rigidbody, + .other_metadata = other_metadata, .resolution = resolution_data.first, .resolution_direction = resolution_data.second, }; // Determine if static needs to be called - determine_collision_handler(collision_info); + this->determine_collision_handler(collision_info); } @@ -126,33 +129,33 @@ std::pair<vec2,CollisionSystem::Direction> CollisionSystem::collision_handler(Co case CollisionInternalType::BOX_BOX: { const BoxCollider & collider1 = std::get<std::reference_wrapper<BoxCollider>>(data1.collider); const BoxCollider & collider2 = std::get<std::reference_wrapper<BoxCollider>>(data2.collider); - vec2 collider_pos1 = get_current_position(collider1.offset, data1.transform, data1.rigidbody); - vec2 collider_pos2 = get_current_position(collider2.offset, data2.transform, data2.rigidbody); - resolution = get_box_box_resolution(collider1,collider2,collider_pos1,collider_pos2); + vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform, data1.rigidbody); + vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform, data2.rigidbody); + resolution = this->get_box_box_resolution(collider1,collider2,collider_pos1,collider_pos2); break; } case CollisionInternalType::BOX_CIRCLE: { const BoxCollider & collider1 = std::get<std::reference_wrapper<BoxCollider>>(data1.collider); const CircleCollider & collider2 = std::get<std::reference_wrapper<CircleCollider>>(data2.collider); - vec2 collider_pos1 = get_current_position(collider1.offset, data1.transform, data1.rigidbody); - vec2 collider_pos2 = get_current_position(collider2.offset, data2.transform, data2.rigidbody); - resolution = get_circle_box_resolution(collider2,collider1,collider_pos2,collider_pos1); + vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform, data1.rigidbody); + vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform, data2.rigidbody); + resolution = this->get_circle_box_resolution(collider2,collider1,collider_pos2,collider_pos1); break; } case CollisionInternalType::CIRCLE_CIRCLE: { const CircleCollider & collider1 = std::get<std::reference_wrapper<CircleCollider>>(data1.collider); const CircleCollider & collider2 = std::get<std::reference_wrapper<CircleCollider>>(data2.collider); - vec2 collider_pos1 = get_current_position(collider1.offset, data1.transform, data1.rigidbody); - vec2 collider_pos2 = get_current_position(collider2.offset, data2.transform, data2.rigidbody); - resolution = get_circle_circle_resolution(collider1,collider2,collider_pos1,collider_pos2); + vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform, data1.rigidbody); + vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform, data2.rigidbody); + resolution = this->get_circle_circle_resolution(collider1,collider2,collider_pos1,collider_pos2); break; } case CollisionInternalType::CIRCLE_BOX: { const CircleCollider & collider1 = std::get<std::reference_wrapper<CircleCollider>>(data1.collider); const BoxCollider & collider2 = std::get<std::reference_wrapper<BoxCollider>>(data2.collider); - vec2 collider_pos1 = get_current_position(collider1.offset, data1.transform, data1.rigidbody); - vec2 collider_pos2 = get_current_position(collider2.offset, data2.transform, data2.rigidbody); - resolution = get_circle_box_resolution(collider1,collider2,collider_pos1,collider_pos2); + vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform, data1.rigidbody); + vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform, data2.rigidbody); + resolution = this->get_circle_box_resolution(collider1,collider2,collider_pos1,collider_pos2); break; } } @@ -179,10 +182,10 @@ vec2 CollisionSystem::get_box_box_resolution(const BoxCollider& box_collider1,co vec2 delta = final_position2 - final_position1; // Compute half-dimensions of the boxes - float half_width1 = box_collider1.width / 2.0; - float half_height1 = box_collider1.height / 2.0; - float half_width2 = box_collider2.width / 2.0; - float half_height2 = box_collider2.height / 2.0; + float half_width1 = box_collider1.dimensions.x / 2.0; + float half_height1 = box_collider1.dimensions.y / 2.0; + float half_width2 = box_collider2.dimensions.x / 2.0; + float half_height2 = box_collider2.dimensions.y / 2.0; // Calculate overlaps along X and Y axes float overlap_x = (half_width1 + half_width2) - std::abs(delta.x); @@ -234,8 +237,8 @@ vec2 CollisionSystem::get_circle_box_resolution(const CircleCollider& circle_col vec2 delta = circle_position - box_position; // Compute half-dimensions of the box - float half_width = box_collider.width / 2.0f; - float half_height = box_collider.height / 2.0f; + float half_width = box_collider.dimensions.x / 2.0f; + float half_height = box_collider.dimensions.y / 2.0f; // Clamp circle center to the nearest point on the box vec2 closest_point; @@ -261,37 +264,37 @@ vec2 CollisionSystem::get_circle_box_resolution(const CircleCollider& circle_col void CollisionSystem::determine_collision_handler(CollisionInfo& info){ // Check rigidbody type for static - if(info.first_rigidbody.data.body_type == Rigidbody::BodyType::STATIC) return; + if(info.this_rigidbody.data.body_type == Rigidbody::BodyType::STATIC) return; // If second body is static perform the static collision handler in this system - if(info.second_rigidbody.data.body_type == Rigidbody::BodyType::STATIC){ + if(info.other_rigidbody.data.body_type == Rigidbody::BodyType::STATIC){ static_collision_handler(info); }; // Call collision event for user CollisionEvent data(info); - EventManager::get_instance().trigger_event<CollisionEvent>(data, info.first_collider.game_object_id); + EventManager::get_instance().trigger_event<CollisionEvent>(data, info.this_collider.game_object_id); } void CollisionSystem::static_collision_handler(CollisionInfo& info){ // Move object back using calculate move back value - info.first_transform.position += info.resolution; + info.this_transform.position += info.resolution; // If bounce is enabled mirror velocity - if(info.first_rigidbody.data.elastisity > 0) { + if(info.this_rigidbody.data.elastisity_coefficient > 0) { if(info.resolution_direction == Direction::BOTH) { - info.first_rigidbody.data.linear_velocity.y = -info.first_rigidbody.data.linear_velocity.y * info.first_rigidbody.data.elastisity; - info.first_rigidbody.data.linear_velocity.x = -info.first_rigidbody.data.linear_velocity.x * info.first_rigidbody.data.elastisity; + info.this_rigidbody.data.linear_velocity.y = -info.this_rigidbody.data.linear_velocity.y * info.this_rigidbody.data.elastisity_coefficient; + info.this_rigidbody.data.linear_velocity.x = -info.this_rigidbody.data.linear_velocity.x * info.this_rigidbody.data.elastisity_coefficient; } else if(info.resolution_direction == Direction::Y_DIRECTION) { - info.first_rigidbody.data.linear_velocity.y = -info.first_rigidbody.data.linear_velocity.y * info.first_rigidbody.data.elastisity; + info.this_rigidbody.data.linear_velocity.y = -info.this_rigidbody.data.linear_velocity.y * info.this_rigidbody.data.elastisity_coefficient; } else if(info.resolution_direction == Direction::X_DIRECTION){ - info.first_rigidbody.data.linear_velocity.x = -info.first_rigidbody.data.linear_velocity.x * info.first_rigidbody.data.elastisity; + info.this_rigidbody.data.linear_velocity.x = -info.this_rigidbody.data.linear_velocity.x * info.this_rigidbody.data.elastisity_coefficient; } } // Stop movement if bounce is disabled else { - info.first_rigidbody.data.linear_velocity = {0,0}; + info.this_rigidbody.data.linear_velocity = {0,0}; } } @@ -332,24 +335,6 @@ std::vector<std::pair<CollisionSystem::CollisionInternal,CollisionSystem::Collis return collisions_ret; } -std::optional<std::pair<std::reference_wrapper<Transform>, std::reference_wrapper<Rigidbody>>> -CollisionSystem::get_active_transform_and_rigidbody(game_object_id_t game_object_id) const{ - RefVector<Transform> transforms = this->component_manager.get_components_by_id<Transform>(game_object_id); - if (transforms.empty()) return std::nullopt; - - Transform& transform = transforms.front().get(); - if (!transform.active) return std::nullopt; - - RefVector<Rigidbody> rigidbodies = this->component_manager.get_components_by_id<Rigidbody>(game_object_id); - if (rigidbodies.empty()) return std::nullopt; - - Rigidbody& rigidbody = rigidbodies.front().get(); - if (!rigidbody.active) return std::nullopt; - - // Return the active components - return std::make_pair(std::ref(transform), std::ref(rigidbody)); -} - CollisionSystem::CollisionInternalType CollisionSystem::get_collider_type(const collider_variant& collider1,const collider_variant& collider2) const{ if(std::holds_alternative<std::reference_wrapper<CircleCollider>>(collider1)){ if(std::holds_alternative<std::reference_wrapper<CircleCollider>>(collider2)) @@ -376,22 +361,22 @@ bool CollisionSystem::get_collision(const CollisionInternal& first_info,const Co case CollisionInternalType::BOX_BOX: { const BoxCollider & box_collider1 = std::get<std::reference_wrapper<BoxCollider>>(first_info.collider); const BoxCollider & box_collider2 = std::get<std::reference_wrapper<BoxCollider>>(second_info.collider); - return get_box_box_collision(box_collider1,box_collider2,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody); + return this->get_box_box_collision(box_collider1,box_collider2,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody); } case CollisionInternalType::BOX_CIRCLE: { const BoxCollider & box_collider = std::get<std::reference_wrapper<BoxCollider>>(first_info.collider); const CircleCollider & circle_collider = std::get<std::reference_wrapper<CircleCollider>>(second_info.collider); - return get_box_circle_collision(box_collider,circle_collider,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody); + return this->get_box_circle_collision(box_collider,circle_collider,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody); } case CollisionInternalType::CIRCLE_CIRCLE: { const CircleCollider & circle_collider1 = std::get<std::reference_wrapper<CircleCollider>>(first_info.collider); const CircleCollider & circle_collider2 = std::get<std::reference_wrapper<CircleCollider>>(second_info.collider); - return get_circle_circle_collision(circle_collider1,circle_collider2,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody); + return this->get_circle_circle_collision(circle_collider1,circle_collider2,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody); } case CollisionInternalType::CIRCLE_BOX: { const CircleCollider & circle_collider = std::get<std::reference_wrapper<CircleCollider>>(first_info.collider); const BoxCollider & box_collider = std::get<std::reference_wrapper<BoxCollider>>(second_info.collider); - return get_box_circle_collision(box_collider,circle_collider,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody); + return this->get_box_circle_collision(box_collider,circle_collider,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody); } } return false; @@ -401,14 +386,14 @@ bool CollisionSystem::get_collision(const CollisionInternal& first_info,const Co bool CollisionSystem::get_box_box_collision(const BoxCollider& box1, const BoxCollider& box2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2) const { // Get current positions of colliders - vec2 final_position1 = get_current_position(box1.offset,transform1,rigidbody1); - vec2 final_position2 = get_current_position(box2.offset,transform2,rigidbody2); + vec2 final_position1 = this->get_current_position(box1.offset,transform1,rigidbody1); + vec2 final_position2 = this->get_current_position(box2.offset,transform2,rigidbody2); // Calculate half-extents (half width and half height) - float half_width1 = box1.width / 2.0; - float half_height1 = box1.height / 2.0; - float half_width2 = box2.width / 2.0; - float half_height2 = box2.height / 2.0; + float half_width1 = box1.dimensions.x / 2.0; + float half_height1 = box1.dimensions.y / 2.0; + float half_width2 = box2.dimensions.x / 2.0; + float half_height2 = box2.dimensions.y / 2.0; // Check if the boxes overlap along the X and Y axes return (final_position1.x + half_width1 > final_position2.x - half_width2 && @@ -419,12 +404,12 @@ bool CollisionSystem::get_box_box_collision(const BoxCollider& box1, const BoxCo bool CollisionSystem::get_box_circle_collision(const BoxCollider& box1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2) const { // Get current positions of colliders - vec2 final_position1 = get_current_position(box1.offset, transform1, rigidbody1); - vec2 final_position2 = get_current_position(circle2.offset, transform2, rigidbody2); + vec2 final_position1 = this->get_current_position(box1.offset, transform1, rigidbody1); + vec2 final_position2 = this->get_current_position(circle2.offset, transform2, rigidbody2); // Calculate box half-extents - float half_width = box1.width / 2.0; - float half_height = box1.height / 2.0; + float half_width = box1.dimensions.x / 2.0; + float half_height = box1.dimensions.y / 2.0; // Find the closest point on the box to the circle's center float closest_x = std::max(final_position1.x - half_width, std::min(final_position2.x, final_position1.x + half_width)); @@ -441,8 +426,8 @@ bool CollisionSystem::get_box_circle_collision(const BoxCollider& box1, const Ci bool CollisionSystem::get_circle_circle_collision(const CircleCollider& circle1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2) const { // Get current positions of colliders - vec2 final_position1 = get_current_position(circle1.offset,transform1,rigidbody1); - vec2 final_position2 = get_current_position(circle2.offset,transform2,rigidbody2); + vec2 final_position1 = this->get_current_position(circle1.offset,transform1,rigidbody1); + vec2 final_position2 = this->get_current_position(circle2.offset,transform2,rigidbody2); float distance_x = final_position1.x - final_position2.x; float distance_y = final_position1.y - final_position2.y; diff --git a/src/crepe/system/CollisionSystem.h b/src/crepe/system/CollisionSystem.h index 7fb8b45..85ae5ad 100644 --- a/src/crepe/system/CollisionSystem.h +++ b/src/crepe/system/CollisionSystem.h @@ -8,6 +8,7 @@ #include "api/Transform.h" #include "api/BoxCollider.h" #include "api/CircleCollider.h" +#include "api/Metadata.h" #include "api/Vector2.h" #include "Collider.h" @@ -68,12 +69,14 @@ public: * Includes information about the colliding objects and the resolution data for handling the collision. */ struct CollisionInfo{ - Collider& first_collider; - Transform& first_transform; - Rigidbody& first_rigidbody; - Collider& second_collider; - Transform& second_transform; - Rigidbody& second_rigidbody; + Collider& this_collider; + Transform& this_transform; + Rigidbody& this_rigidbody; + Metadata& this_metadata; + Collider& other_collider; + Transform& other_transform; + Rigidbody& other_rigidbody; + Metadata& other_metadata; //! The resolution vector for the collision. vec2 resolution; //! The direction of movement for resolving the collision. @@ -214,23 +217,6 @@ private: bool get_collision(const CollisionInternal& first_info,const CollisionInternal& second_info, CollisionInternalType type) const; /** - * \brief Retrieves the active Transform and Rigidbody components for a given game object. - * - * This function looks up the Transform and Rigidbody components associated with the specified - * game object ID. It checks if both components are present and active. If both are found - * to be active, they are returned wrapped in reference wrappers; otherwise, an empty - * optional is returned. - * - * \param game_object_id The ID of the game object for which to retrieve the components. - * - * \return A std::optional containing a pair of reference wrappers to the active Transform - * and Rigidbody components, or std::nullopt if either component is not found - * or not active. - */ - std::optional<std::pair<std::reference_wrapper<Transform>, std::reference_wrapper<Rigidbody>>> get_active_transform_and_rigidbody(game_object_id_t game_object_id) const; - - - /** * \brief Detects collisions between two BoxColliders. * * \param box1 The first BoxCollider. diff --git a/src/crepe/system/PhysicsSystem.cpp b/src/crepe/system/PhysicsSystem.cpp index 8f21727..f3833cb 100644 --- a/src/crepe/system/PhysicsSystem.cpp +++ b/src/crepe/system/PhysicsSystem.cpp @@ -31,11 +31,11 @@ void PhysicsSystem::update() { * gravity); } // Add damping - if (rigidbody.data.angular_velocity_factor != 1 && rigidbody.data.angular_velocity_factor > 0) { - rigidbody.data.angular_velocity *= rigidbody.data.angular_velocity_factor; + if (rigidbody.data.angular_velocity_coefficient != 1 && rigidbody.data.angular_velocity_coefficient > 0) { + rigidbody.data.angular_velocity *= rigidbody.data.angular_velocity_coefficient; } - if (rigidbody.data.linear_velocity_factor != vec2{1, 1} && rigidbody.data.linear_velocity_factor.x > 0 && rigidbody.data.linear_velocity_factor.y > 0) { - rigidbody.data.linear_velocity *= rigidbody.data.linear_velocity_factor; + if (rigidbody.data.linear_velocity_coefficient != vec2{1, 1} && rigidbody.data.linear_velocity_coefficient.x > 0 && rigidbody.data.linear_velocity_coefficient.y > 0) { + rigidbody.data.linear_velocity *= rigidbody.data.linear_velocity_coefficient; } // Max velocity check diff --git a/src/example/game.cpp b/src/example/game.cpp index c439f5d..4e16d4a 100644 --- a/src/example/game.cpp +++ b/src/example/game.cpp @@ -18,7 +18,7 @@ using namespace std; class MyScript : public Script { bool oncollision(const CollisionEvent& test) { - Log::logf("Box {} script on_collision()", test.info.first_collider.game_object_id); + Log::logf("Box {} script on_collision()", test.info.this_collider.game_object_id); return true; } void init() { @@ -65,7 +65,7 @@ public: .body_type = Rigidbody::BodyType::DYNAMIC, .linear_velocity = {1,1}, .constraints = {0, 0, 0}, - .elastisity = 1, + .elastisity_coefficient = 1, .offset = {0,0}, }); game_object1.add_component<BoxCollider>(vec2{0, 0}, 20, 20); diff --git a/src/test/CollisionTest.cpp b/src/test/CollisionTest.cpp index 92ff7ba..fec42f3 100644 --- a/src/test/CollisionTest.cpp +++ b/src/test/CollisionTest.cpp @@ -68,10 +68,10 @@ public: .offset = {0,0}, }); // Create a box with an inner size of 10x10 units - world.add_component<BoxCollider>(vec2{0, -100}, 100, 100); // Top - world.add_component<BoxCollider>(vec2{0, 100}, 100, 100); // Bottom - world.add_component<BoxCollider>(vec2{-100, 0}, 100, 100); // Left - world.add_component<BoxCollider>(vec2{100, 0}, 100, 100); // right + world.add_component<BoxCollider>(vec2{0, -100}, vec2{100, 100}); // Top + world.add_component<BoxCollider>(vec2{0, 100}, vec2{100, 100}); // Bottom + world.add_component<BoxCollider>(vec2{-100, 0}, vec2{100, 100}); // Left + world.add_component<BoxCollider>(vec2{100, 0}, vec2{100, 100}); // right game_object1.add_component<Rigidbody>(Rigidbody::Data{ .mass = 1, @@ -79,10 +79,10 @@ public: .body_type = Rigidbody::BodyType::DYNAMIC, .linear_velocity = {0,0}, .constraints = {0, 0, 0}, - .elastisity = 1, + .elastisity_coefficient = 1, .offset = {0,0}, }); - game_object1.add_component<BoxCollider>(vec2{0, 0}, 10, 10); + game_object1.add_component<BoxCollider>(vec2{0, 0}, vec2{10, 10}); BehaviorScript & script_object1 = game_object1.add_component<BehaviorScript>().set_script<CollisionHandler>(1); script_object1_ref = static_cast<CollisionHandler*>(script_object1.script.get()); ASSERT_NE(script_object1_ref, nullptr); @@ -93,10 +93,10 @@ public: .body_type = Rigidbody::BodyType::DYNAMIC, .linear_velocity = {0,0}, .constraints = {0, 0, 0}, - .elastisity = 1, + .elastisity_coefficient = 1, .offset = {0,0}, }); - game_object2.add_component<BoxCollider>(vec2{0, 0}, 10, 10); + game_object2.add_component<BoxCollider>(vec2{0, 0}, vec2{10, 10}); BehaviorScript & script_object2 = game_object2.add_component<BehaviorScript>().set_script<CollisionHandler>(2); script_object2_ref = static_cast<CollisionHandler*>(script_object2.script.get()); ASSERT_NE(script_object2_ref, nullptr); @@ -110,11 +110,11 @@ TEST_F(CollisionTest, collision_example) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 2); + EXPECT_EQ(ev.info.this_collider.game_object_id, 2); }; EXPECT_FALSE(collision_happend); collision_sys.update(); @@ -125,14 +125,14 @@ TEST_F(CollisionTest, collision_box_box_dynamic_both_no_velocity) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, 10); EXPECT_EQ(ev.info.resolution.y, 10); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::BOTH); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 2); + EXPECT_EQ(ev.info.this_collider.game_object_id, 2); EXPECT_EQ(ev.info.resolution.x, 10); EXPECT_EQ(ev.info.resolution.y, 10); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::BOTH); @@ -148,14 +148,14 @@ TEST_F(CollisionTest, collision_box_box_dynamic_x_direction_no_velocity) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, -5); EXPECT_EQ(ev.info.resolution.y, 0); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 2); + EXPECT_EQ(ev.info.this_collider.game_object_id, 2); EXPECT_EQ(ev.info.resolution.x, 5); EXPECT_EQ(ev.info.resolution.y, 0); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); @@ -171,14 +171,14 @@ TEST_F(CollisionTest, collision_box_box_dynamic_y_direction_no_velocity) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, 0); EXPECT_EQ(ev.info.resolution.y, -5); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 2); + EXPECT_EQ(ev.info.this_collider.game_object_id, 2); EXPECT_EQ(ev.info.resolution.x, 0); EXPECT_EQ(ev.info.resolution.y, 5); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); @@ -194,14 +194,14 @@ TEST_F(CollisionTest, collision_box_box_dynamic_both) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, 10); EXPECT_EQ(ev.info.resolution.y, 10); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::BOTH); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 2); + EXPECT_EQ(ev.info.this_collider.game_object_id, 2); EXPECT_EQ(ev.info.resolution.x, 10); EXPECT_EQ(ev.info.resolution.y, 10); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::BOTH); @@ -221,14 +221,14 @@ TEST_F(CollisionTest, collision_box_box_dynamic_x_direction) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, -5); EXPECT_EQ(ev.info.resolution.y, -5); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 2); + EXPECT_EQ(ev.info.this_collider.game_object_id, 2); EXPECT_EQ(ev.info.resolution.x, 5); EXPECT_EQ(ev.info.resolution.y, 5); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); @@ -248,14 +248,14 @@ TEST_F(CollisionTest, collision_box_box_dynamic_y_direction) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, -5); EXPECT_EQ(ev.info.resolution.y, -5); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); }; script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 2); + EXPECT_EQ(ev.info.this_collider.game_object_id, 2); EXPECT_EQ(ev.info.resolution.x, 5); EXPECT_EQ(ev.info.resolution.y, 5); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); @@ -276,7 +276,7 @@ TEST_F(CollisionTest, collision_box_box_static_both) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, 10); EXPECT_EQ(ev.info.resolution.y, 10); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::BOTH); @@ -298,7 +298,7 @@ TEST_F(CollisionTest, collision_box_box_static_x_direction) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, -5); EXPECT_EQ(ev.info.resolution.y, -5); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::X_DIRECTION); @@ -322,7 +322,7 @@ TEST_F(CollisionTest, collision_box_box_static_y_direction) { bool collision_happend = false; script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); EXPECT_EQ(ev.info.resolution.x, -5); EXPECT_EQ(ev.info.resolution.y, -5); EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::Y_DIRECTION); @@ -348,8 +348,8 @@ TEST_F(CollisionTest, collision_box_box_static_multiple) {//todo check visually float resolution = 0; script_object1_ref->test_fn = [&](const CollisionEvent & ev) { collision_happend = true; - EXPECT_EQ(ev.info.first_collider.game_object_id, 1); - EXPECT_EQ(ev.info.first_collider.offset.x , offset_value); + EXPECT_EQ(ev.info.this_collider.game_object_id, 1); + EXPECT_EQ(ev.info.this_collider.offset.x , offset_value); EXPECT_EQ(ev.info.resolution.x , resolution); }; script_object2_ref->test_fn = [&](const CollisionEvent & ev) { @@ -365,7 +365,7 @@ TEST_F(CollisionTest, collision_box_box_static_multiple) {//todo check visually rg2.data.body_type = crepe::Rigidbody::BodyType::STATIC; BoxCollider & bxc = this->mgr.get_components_by_id<BoxCollider>(1).front().get(); bxc.offset = {5,0}; - this->game_object1.add_component<BoxCollider>(vec2{-5, 0}, 10, 10); + this->game_object1.add_component<BoxCollider>(vec2{-5, 0}, vec2{10, 10}); offset_value = 5; resolution = 10; collision_sys.update(); diff --git a/src/test/PhysicsTest.cpp b/src/test/PhysicsTest.cpp index 5dd448f..ad7cb03 100644 --- a/src/test/PhysicsTest.cpp +++ b/src/test/PhysicsTest.cpp @@ -103,16 +103,16 @@ TEST_F(PhysicsTest, movement) { EXPECT_EQ(transform.position.y, 1); EXPECT_EQ(transform.rotation, 1); - rigidbody.data.linear_velocity_factor.x = 0.5; - rigidbody.data.linear_velocity_factor.y = 0.5; - rigidbody.data.angular_velocity_factor = 0.5; + rigidbody.data.linear_velocity_coefficient.x = 0.5; + rigidbody.data.linear_velocity_coefficient.y = 0.5; + rigidbody.data.angular_velocity_coefficient = 0.5; system.update(); EXPECT_EQ(rigidbody.data.linear_velocity.x, 0.5); EXPECT_EQ(rigidbody.data.linear_velocity.y, 0.5); EXPECT_EQ(rigidbody.data.angular_velocity, 0.5); rigidbody.data.constraints = {1, 1, 0}; - rigidbody.data.angular_velocity_factor = 0; + rigidbody.data.angular_velocity_coefficient = 0; rigidbody.data.max_angular_velocity = 1000; rigidbody.data.angular_velocity = 360; system.update(); diff --git a/src/test/Profiling.cpp b/src/test/Profiling.cpp index e46d5ff..fa0f5f3 100644 --- a/src/test/Profiling.cpp +++ b/src/test/Profiling.cpp @@ -28,7 +28,7 @@ using namespace testing; class TestScript : public Script { bool oncollision(const CollisionEvent& test) { - Log::logf("Box {} script on_collision()", test.info.first_collider.game_object_id); + Log::logf("Box {} script on_collision()", test.info.this_collider.game_object_id); return true; } void init() { |