From d76ab0bf77d0a61712dc25bbe1760995be4c4782 Mon Sep 17 00:00:00 2001 From: JAROWMR Date: Wed, 4 Dec 2024 20:11:02 +0100 Subject: make format --- src/crepe/Collider.cpp | 2 +- src/crepe/Collider.h | 2 +- src/crepe/api/BoxCollider.cpp | 7 +- src/crepe/api/BoxCollider.h | 6 +- src/crepe/api/CircleCollider.cpp | 6 +- src/crepe/api/CircleCollider.h | 3 +- src/crepe/api/Event.h | 4 +- src/crepe/api/LoopManager.cpp | 3 +- src/crepe/api/Rigidbody.cpp | 4 +- src/crepe/api/Rigidbody.h | 4 +- src/crepe/system/CollisionSystem.cpp | 514 ++++++++++++++++++++--------------- src/crepe/system/CollisionSystem.h | 121 +++++---- src/crepe/system/PhysicsSystem.cpp | 9 +- 13 files changed, 395 insertions(+), 290 deletions(-) (limited to 'src/crepe') diff --git a/src/crepe/Collider.cpp b/src/crepe/Collider.cpp index 9d94152..77e11c8 100644 --- a/src/crepe/Collider.cpp +++ b/src/crepe/Collider.cpp @@ -2,4 +2,4 @@ using namespace crepe; -Collider::Collider(game_object_id_t id, const vec2& offset) : Component(id), offset(offset) {} +Collider::Collider(game_object_id_t id, const vec2 & offset) : Component(id), offset(offset) {} diff --git a/src/crepe/Collider.h b/src/crepe/Collider.h index b3a09fb..a08a68e 100644 --- a/src/crepe/Collider.h +++ b/src/crepe/Collider.h @@ -7,7 +7,7 @@ namespace crepe { class Collider : public Component { public: - Collider(game_object_id_t id, const vec2& offset); + Collider(game_object_id_t id, const vec2 & offset); public: /** diff --git a/src/crepe/api/BoxCollider.cpp b/src/crepe/api/BoxCollider.cpp index f94ced7..c097a24 100644 --- a/src/crepe/api/BoxCollider.cpp +++ b/src/crepe/api/BoxCollider.cpp @@ -1,7 +1,10 @@ #include "BoxCollider.h" -#include "../Collider.h" +#include "../Collider.h" using namespace crepe; -BoxCollider::BoxCollider(game_object_id_t game_object_id,const vec2& offset, const vec2& dimensions) : Collider(game_object_id,offset), dimensions(dimensions) {} +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 1f5f1c1..89e43d8 100644 --- a/src/crepe/api/BoxCollider.h +++ b/src/crepe/api/BoxCollider.h @@ -1,7 +1,7 @@ #pragma once -#include "Vector2.h" #include "../Collider.h" +#include "Vector2.h" #include "types.h" namespace crepe { @@ -13,9 +13,9 @@ namespace crepe { */ class BoxCollider : public Collider { public: - BoxCollider(game_object_id_t game_object_id,const vec2& offset, const vec2& dimensions); + BoxCollider(game_object_id_t game_object_id, const vec2 & offset, const vec2 & dimensions); - //! Width and height of the box collider + //! Width and height of the box collider vec2 dimensions; }; diff --git a/src/crepe/api/CircleCollider.cpp b/src/crepe/api/CircleCollider.cpp index 473734e..a4271e9 100644 --- a/src/crepe/api/CircleCollider.cpp +++ b/src/crepe/api/CircleCollider.cpp @@ -2,5 +2,7 @@ using namespace crepe; - -CircleCollider::CircleCollider(game_object_id_t game_object_id,const vec2& offset, float radius) : Collider(game_object_id,offset), radius(radius) {} +CircleCollider::CircleCollider(game_object_id_t game_object_id, const vec2 & offset, + float radius) + : Collider(game_object_id, offset), + radius(radius) {} diff --git a/src/crepe/api/CircleCollider.h b/src/crepe/api/CircleCollider.h index bbcc330..ebd1cb2 100644 --- a/src/crepe/api/CircleCollider.h +++ b/src/crepe/api/CircleCollider.h @@ -13,8 +13,7 @@ namespace crepe { */ class CircleCollider : public Collider { public: - - CircleCollider(game_object_id_t game_object_id,const vec2& offset, float radius); + CircleCollider(game_object_id_t game_object_id, const vec2 & offset, float radius); //! Radius of the circle collider. float radius; diff --git a/src/crepe/api/Event.h b/src/crepe/api/Event.h index 259acba..152bc2c 100644 --- a/src/crepe/api/Event.h +++ b/src/crepe/api/Event.h @@ -98,8 +98,8 @@ public: class CollisionEvent : public Event { public: crepe::CollisionSystem::CollisionInfo info; - CollisionEvent(const crepe::CollisionSystem::CollisionInfo& collisionInfo) - : info(collisionInfo) {} + CollisionEvent(const crepe::CollisionSystem::CollisionInfo & collisionInfo) + : info(collisionInfo) {} }; /** diff --git a/src/crepe/api/LoopManager.cpp b/src/crepe/api/LoopManager.cpp index feb1338..d4819ea 100644 --- a/src/crepe/api/LoopManager.cpp +++ b/src/crepe/api/LoopManager.cpp @@ -1,13 +1,12 @@ #include "../facade/SDLContext.h" +#include "../system/PhysicsSystem.h" #include "../system/AnimatorSystem.h" #include "../system/CollisionSystem.h" #include "../system/ParticleSystem.h" #include "../system/PhysicsSystem.h" #include "../system/RenderSystem.h" #include "../system/ScriptSystem.h" -#include "..//system/PhysicsSystem.h" -#include "../system/CollisionSystem.h" #include "LoopManager.h" #include "LoopTimer.h" diff --git a/src/crepe/api/Rigidbody.cpp b/src/crepe/api/Rigidbody.cpp index c4b1d6f..8213afb 100644 --- a/src/crepe/api/Rigidbody.cpp +++ b/src/crepe/api/Rigidbody.cpp @@ -10,6 +10,4 @@ void crepe::Rigidbody::add_force_linear(const vec2 & force) { this->data.linear_velocity += force; } -void crepe::Rigidbody::add_force_angular(float force) { - this->data.angular_velocity += force; -} +void crepe::Rigidbody::add_force_angular(float force) { this->data.angular_velocity += force; } diff --git a/src/crepe/api/Rigidbody.h b/src/crepe/api/Rigidbody.h index 431e000..756cc28 100644 --- a/src/crepe/api/Rigidbody.h +++ b/src/crepe/api/Rigidbody.h @@ -78,9 +78,9 @@ public: //! Linear velocity of the object (speed and direction). vec2 linear_velocity; //! Maximum linear velocity of the object. This limits the object's speed. - vec2 max_linear_velocity = {INFINITY ,INFINITY}; + vec2 max_linear_velocity = {INFINITY, INFINITY}; //! Linear velocity coefficient. This scales the object's velocity for adjustment or damping. - vec2 linear_velocity_coefficient = {1,1}; + vec2 linear_velocity_coefficient = {1, 1}; //! \} /** diff --git a/src/crepe/system/CollisionSystem.cpp b/src/crepe/system/CollisionSystem.cpp index 2d5ce9d..34cd125 100644 --- a/src/crepe/system/CollisionSystem.cpp +++ b/src/crepe/system/CollisionSystem.cpp @@ -1,23 +1,23 @@ -#include #include +#include #include #include +#include #include #include -#include -#include "api/Event.h" -#include "api/EventManager.h" #include "api/BoxCollider.h" #include "api/CircleCollider.h" +#include "api/Event.h" +#include "api/EventManager.h" #include "api/Metadata.h" -#include "api/Vector2.h" #include "api/Rigidbody.h" #include "api/Transform.h" +#include "api/Vector2.h" -#include "ComponentManager.h" -#include "CollisionSystem.h" #include "Collider.h" +#include "CollisionSystem.h" +#include "ComponentManager.h" #include "types.h" #include "util/OptionalRef.h" @@ -26,158 +26,191 @@ using namespace crepe; void CollisionSystem::update() { std::vector all_colliders; game_object_id_t id = 0; - RefVector rigidbodies = this->component_manager.get_components_by_type(); + RefVector rigidbodies + = this->component_manager.get_components_by_type(); // Collisions can only happen on object with a rigidbody - for(Rigidbody& rigidbody : rigidbodies) { + for (Rigidbody & rigidbody : rigidbodies) { if (!rigidbody.active) continue; id = rigidbody.game_object_id; - Transform& transform = this->component_manager.get_components_by_id(id).front().get(); + Transform & transform + = this->component_manager.get_components_by_id(id).front().get(); // Check if the boxcollider is active and has the same id as the rigidbody. - RefVector boxcolliders = this->component_manager.get_components_by_type(); - for (BoxCollider& boxcollider : boxcolliders) { - if(boxcollider.game_object_id != id) continue; - if(!boxcollider.active) continue; - all_colliders.push_back( - { - .id = id, - .collider = collider_variant{boxcollider}, - .transform = transform, - .rigidbody = rigidbody - } - ); + RefVector boxcolliders + = this->component_manager.get_components_by_type(); + for (BoxCollider & boxcollider : boxcolliders) { + if (boxcollider.game_object_id != id) continue; + if (!boxcollider.active) continue; + all_colliders.push_back({.id = id, + .collider = collider_variant{boxcollider}, + .transform = transform, + .rigidbody = rigidbody}); } // Check if the circlecollider is active and has the same id as the rigidbody. - RefVector circlecolliders = this->component_manager.get_components_by_type(); - for (CircleCollider& circlecollider : circlecolliders) { - if(circlecollider.game_object_id != id) continue; - if(!circlecollider.active) continue; - all_colliders.push_back( - { - .id = id, - .collider = collider_variant{circlecollider}, - .transform = transform, - .rigidbody = rigidbody - } - ); + RefVector circlecolliders + = this->component_manager.get_components_by_type(); + for (CircleCollider & circlecollider : circlecolliders) { + if (circlecollider.game_object_id != id) continue; + if (!circlecollider.active) continue; + all_colliders.push_back({.id = id, + .collider = collider_variant{circlecollider}, + .transform = transform, + .rigidbody = rigidbody}); } } // Check between all colliders if there is a collision - std::vector> collided = this->gather_collisions(all_colliders); + std::vector> collided + = this->gather_collisions(all_colliders); - // For both objects call the collision handler - for (auto& collision_pair : collided) { - this->collision_handler_request(collision_pair.first,collision_pair.second); - this->collision_handler_request(collision_pair.second,collision_pair.first); + // For both objects call the collision handler + for (auto & collision_pair : collided) { + 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& this_data,CollisionInternal& other_data){ +void CollisionSystem::collision_handler_request(CollisionInternal & this_data, + CollisionInternal & other_data) { - CollisionInternalType type = this->get_collider_type(this_data.collider,other_data.collider); - std::pair resolution_data = this->collision_handler(this_data,other_data,type); + CollisionInternalType type + = this->get_collider_type(this_data.collider, other_data.collider); + std::pair resolution_data + = this->collision_handler(this_data, other_data, type); - OptionalRef this_metadata = this->component_manager.get_components_by_id(this_data.id).front().get(); - OptionalRef other_metadata = this->component_manager.get_components_by_id(other_data.id).front().get(); + OptionalRef this_metadata + = this->component_manager.get_components_by_id(this_data.id).front().get(); + OptionalRef other_metadata + = this->component_manager.get_components_by_id(other_data.id).front().get(); OptionalRef this_collider; OptionalRef other_collider; switch (type) { - case CollisionInternalType::BOX_BOX:{ + case CollisionInternalType::BOX_BOX: { this_collider = std::get>(this_data.collider); - other_collider = std::get>(other_data.collider); + other_collider + = std::get>(other_data.collider); break; } - case CollisionInternalType::BOX_CIRCLE:{ + case CollisionInternalType::BOX_CIRCLE: { this_collider = std::get>(this_data.collider); - other_collider = std::get>(other_data.collider); + other_collider + = std::get>(other_data.collider); break; } - case CollisionInternalType::CIRCLE_BOX:{ - this_collider = std::get>(this_data.collider); - other_collider = std::get>(other_data.collider); + case CollisionInternalType::CIRCLE_BOX: { + this_collider + = std::get>(this_data.collider); + other_collider + = std::get>(other_data.collider); break; } - case CollisionInternalType::CIRCLE_CIRCLE:{ - this_collider = std::get>(this_data.collider); - other_collider = std::get>(other_data.collider); + case CollisionInternalType::CIRCLE_CIRCLE: { + this_collider + = std::get>(this_data.collider); + other_collider + = std::get>(other_data.collider); break; } } // collision info crepe::CollisionSystem::CollisionInfo collision_info{ - .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, - }; + .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 - this->determine_collision_handler(collision_info); + this->determine_collision_handler(collision_info); } - -std::pair CollisionSystem::collision_handler(CollisionInternal& data1,CollisionInternal& data2,CollisionInternalType type) { +std::pair +CollisionSystem::collision_handler(CollisionInternal & data1, CollisionInternal & data2, + CollisionInternalType type) { vec2 resolution; switch (type) { - case CollisionInternalType::BOX_BOX: { - const BoxCollider & collider1 = std::get>(data1.collider); - const BoxCollider & collider2 = std::get>(data2.collider); - 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); + case CollisionInternalType::BOX_BOX: { + const BoxCollider & collider1 + = std::get>(data1.collider); + const BoxCollider & collider2 + = std::get>(data2.collider); + 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>(data1.collider); - const CircleCollider & collider2 = std::get>(data2.collider); - 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); + const BoxCollider & collider1 + = std::get>(data1.collider); + const CircleCollider & collider2 + = std::get>(data2.collider); + 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>(data1.collider); - const CircleCollider & collider2 = std::get>(data2.collider); - 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); + case CollisionInternalType::CIRCLE_CIRCLE: { + const CircleCollider & collider1 + = std::get>(data1.collider); + const CircleCollider & collider2 + = std::get>(data2.collider); + 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>(data1.collider); - const BoxCollider & collider2 = std::get>(data2.collider); - 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); + case CollisionInternalType::CIRCLE_BOX: { + const CircleCollider & collider1 + = std::get>(data1.collider); + const BoxCollider & collider2 + = std::get>(data2.collider); + 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; } } Direction resolution_direction = Direction::NONE; - if(resolution.x != 0 && resolution.y > 0) { + if (resolution.x != 0 && resolution.y > 0) { resolution_direction = Direction::BOTH; } else if (resolution.x != 0) { resolution_direction = Direction::X_DIRECTION; - if(data1.rigidbody.data.linear_velocity.y != 0) - resolution.y = data1.rigidbody.data.linear_velocity.y * (resolution.x/data1.rigidbody.data.linear_velocity.x); + if (data1.rigidbody.data.linear_velocity.y != 0) + resolution.y = data1.rigidbody.data.linear_velocity.y + * (resolution.x / data1.rigidbody.data.linear_velocity.x); } else if (resolution.y != 0) { resolution_direction = Direction::Y_DIRECTION; - if(data1.rigidbody.data.linear_velocity.x != 0) - resolution.x = data1.rigidbody.data.linear_velocity.x * (resolution.y/data1.rigidbody.data.linear_velocity.y); + if (data1.rigidbody.data.linear_velocity.x != 0) + resolution.x = data1.rigidbody.data.linear_velocity.x + * (resolution.y / data1.rigidbody.data.linear_velocity.y); } - return std::make_pair(resolution,resolution_direction); + return std::make_pair(resolution, resolution_direction); } -vec2 CollisionSystem::get_box_box_resolution(const BoxCollider& box_collider1,const BoxCollider& box_collider2,const vec2& final_position1,const vec2& final_position2) const -{ +vec2 CollisionSystem::get_box_box_resolution(const BoxCollider & box_collider1, + const BoxCollider & box_collider2, + const vec2 & final_position1, + const vec2 & final_position2) const { vec2 resolution; // Default resolution vector vec2 delta = final_position2 - final_position1; @@ -210,97 +243,107 @@ vec2 CollisionSystem::get_box_box_resolution(const BoxCollider& box_collider1,co return resolution; } -vec2 CollisionSystem::get_circle_circle_resolution(const CircleCollider& circle_collider1, const CircleCollider& circle_collider2, const vec2& final_position1, const vec2& final_position2) const -{ - vec2 delta = final_position2 - final_position1; +vec2 CollisionSystem::get_circle_circle_resolution(const CircleCollider & circle_collider1, + const CircleCollider & circle_collider2, + const vec2 & final_position1, + const vec2 & final_position2) const { + vec2 delta = final_position2 - final_position1; - // Compute the distance between the two circle centers - float distance = std::sqrt(delta.x * delta.x + delta.y * delta.y); + // Compute the distance between the two circle centers + float distance = std::sqrt(delta.x * delta.x + delta.y * delta.y); - // Compute the combined radii of the two circles - float combined_radius = circle_collider1.radius + circle_collider2.radius; + // Compute the combined radii of the two circles + float combined_radius = circle_collider1.radius + circle_collider2.radius; - // Compute the penetration depth - float penetration_depth = combined_radius - distance; + // Compute the penetration depth + float penetration_depth = combined_radius - distance; - // Normalize the delta vector to get the collision direction - vec2 collision_normal = delta / distance; + // Normalize the delta vector to get the collision direction + vec2 collision_normal = delta / distance; - // Compute the resolution vector - vec2 resolution = collision_normal * penetration_depth; + // Compute the resolution vector + vec2 resolution = collision_normal * penetration_depth; - return resolution; + return resolution; } -vec2 CollisionSystem::get_circle_box_resolution(const CircleCollider& circle_collider, const BoxCollider& box_collider, const vec2& circle_position, const vec2& box_position) const -{ - vec2 delta = circle_position - box_position; +vec2 CollisionSystem::get_circle_box_resolution(const CircleCollider & circle_collider, + const BoxCollider & box_collider, + const vec2 & circle_position, + const vec2 & box_position) const { + vec2 delta = circle_position - box_position; - // Compute half-dimensions of the box - float half_width = box_collider.dimensions.x / 2.0f; - float half_height = box_collider.dimensions.y / 2.0f; + // Compute half-dimensions of the box + 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; - closest_point.x = std::clamp(delta.x, -half_width, half_width); - closest_point.y = std::clamp(delta.y, -half_height, half_height); + // Clamp circle center to the nearest point on the box + vec2 closest_point; + closest_point.x = std::clamp(delta.x, -half_width, half_width); + closest_point.y = std::clamp(delta.y, -half_height, half_height); - // Find the vector from the circle center to the closest point - vec2 closest_delta = delta - closest_point; + // Find the vector from the circle center to the closest point + vec2 closest_delta = delta - closest_point; - // Normalize the delta to get the collision direction - float distance = std::sqrt(closest_delta.x * closest_delta.x + closest_delta.y * closest_delta.y); - vec2 collision_normal = closest_delta / distance; + // Normalize the delta to get the collision direction + float distance + = std::sqrt(closest_delta.x * closest_delta.x + closest_delta.y * closest_delta.y); + vec2 collision_normal = closest_delta / distance; - // Compute penetration depth - float penetration_depth = circle_collider.radius - distance; + // Compute penetration depth + float penetration_depth = circle_collider.radius - distance; - // Compute the resolution vector - vec2 resolution = collision_normal * penetration_depth; + // Compute the resolution vector + vec2 resolution = collision_normal * penetration_depth; - return resolution; + return resolution; } - -void CollisionSystem::determine_collision_handler(CollisionInfo& info){ +void CollisionSystem::determine_collision_handler(CollisionInfo & info) { // Check rigidbody type for static - if(info.this_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.other_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(data, info.this_collider.game_object_id); + EventManager::get_instance().trigger_event( + data, info.this_collider.game_object_id); } -void CollisionSystem::static_collision_handler(CollisionInfo& info){ - // Move object back using calculate move back value +void CollisionSystem::static_collision_handler(CollisionInfo & info) { + // Move object back using calculate move back value info.this_transform.position += info.resolution; // If bounce is enabled mirror velocity - if(info.this_rigidbody.data.elastisity_coefficient > 0) { - if(info.resolution_direction == Direction::BOTH) - { - 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.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.this_rigidbody.data.linear_velocity.x = -info.this_rigidbody.data.linear_velocity.x * info.this_rigidbody.data.elastisity_coefficient; + if (info.this_rigidbody.data.elastisity_coefficient > 0) { + if (info.resolution_direction == Direction::BOTH) { + 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.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.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.this_rigidbody.data.linear_velocity = {0,0}; + info.this_rigidbody.data.linear_velocity = {0, 0}; } } -std::vector> CollisionSystem::gather_collisions(std::vector & colliders) { - - +std::vector> +CollisionSystem::gather_collisions(std::vector & colliders) { + // TODO: // If no colliders skip // Check if colliders has rigidbody if not skip @@ -311,83 +354,103 @@ std::vector> collisions_ret; - //using visit to visit the variant to access the active and id. + std::vector> collisions_ret; + //using visit to visit the variant to access the active and id. for (size_t i = 0; i < colliders.size(); ++i) { for (size_t j = i + 1; j < colliders.size(); ++j) { - if(colliders[i].id == colliders[j].id) continue; - CollisionInternalType type = get_collider_type(colliders[i].collider,colliders[j].collider); - if(!get_collision({ - .collider = colliders[i].collider, - .transform = colliders[i].transform, - .rigidbody = colliders[i].rigidbody, + if (colliders[i].id == colliders[j].id) continue; + CollisionInternalType type + = get_collider_type(colliders[i].collider, colliders[j].collider); + if (!get_collision( + { + .collider = colliders[i].collider, + .transform = colliders[i].transform, + .rigidbody = colliders[i].rigidbody, }, { - .collider = colliders[j].collider, - .transform = colliders[j].transform, - .rigidbody = colliders[j].rigidbody, + .collider = colliders[j].collider, + .transform = colliders[j].transform, + .rigidbody = colliders[j].rigidbody, }, - type)) continue; - collisions_ret.emplace_back(colliders[i],colliders[j]); + type)) + continue; + collisions_ret.emplace_back(colliders[i], colliders[j]); } } - + return collisions_ret; } -CollisionSystem::CollisionInternalType CollisionSystem::get_collider_type(const collider_variant& collider1,const collider_variant& collider2) const{ - if(std::holds_alternative>(collider1)){ - if(std::holds_alternative>(collider2)) - { +CollisionSystem::CollisionInternalType +CollisionSystem::get_collider_type(const collider_variant & collider1, + const collider_variant & collider2) const { + if (std::holds_alternative>(collider1)) { + if (std::holds_alternative>(collider2)) { return CollisionInternalType::CIRCLE_CIRCLE; - } - else { + } else { return CollisionInternalType::CIRCLE_BOX; } - } - else { - if(std::holds_alternative>(collider2)) - { + } else { + if (std::holds_alternative>(collider2)) { return CollisionInternalType::BOX_CIRCLE; - } - else { + } else { return CollisionInternalType::BOX_BOX; } } } -bool CollisionSystem::get_collision(const CollisionInternal& first_info,const CollisionInternal& second_info, CollisionInternalType type) const{ +bool CollisionSystem::get_collision(const CollisionInternal & first_info, + const CollisionInternal & second_info, + CollisionInternalType type) const { switch (type) { - case CollisionInternalType::BOX_BOX: { - const BoxCollider & box_collider1 = std::get>(first_info.collider); - const BoxCollider & box_collider2 = std::get>(second_info.collider); - 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_BOX: { + const BoxCollider & box_collider1 + = std::get>(first_info.collider); + const BoxCollider & box_collider2 + = std::get>(second_info.collider); + 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>(first_info.collider); - const CircleCollider & circle_collider = std::get>(second_info.collider); - return this->get_box_circle_collision(box_collider,circle_collider,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody); + const BoxCollider & box_collider + = std::get>(first_info.collider); + const CircleCollider & circle_collider + = std::get>(second_info.collider); + 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>(first_info.collider); - const CircleCollider & circle_collider2 = std::get>(second_info.collider); - 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_CIRCLE: { + const CircleCollider & circle_collider1 + = std::get>(first_info.collider); + const CircleCollider & circle_collider2 + = std::get>(second_info.collider); + 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>(first_info.collider); - const BoxCollider & box_collider = std::get>(second_info.collider); - 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_BOX: { + const CircleCollider & circle_collider + = std::get>(first_info.collider); + const BoxCollider & box_collider + = std::get>(second_info.collider); + return this->get_box_circle_collision( + box_collider, circle_collider, first_info.transform, second_info.transform, + second_info.rigidbody, second_info.rigidbody); } } return false; } - -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 -{ +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 = this->get_current_position(box1.offset,transform1,rigidbody1); - vec2 final_position2 = this->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.dimensions.x / 2.0; @@ -396,13 +459,18 @@ bool CollisionSystem::get_box_box_collision(const BoxCollider& box1, const BoxCo 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 && - final_position1.x - half_width1 < final_position2.x + half_width2 && - final_position1.y + half_height1 > final_position2.y - half_height2 && - final_position1.y - half_height1 < final_position2.y + half_height2); + return (final_position1.x + half_width1 > final_position2.x - half_width2 + && final_position1.x - half_width1 < final_position2.x + half_width2 + && final_position1.y + half_height1 > final_position2.y - half_height2 + && final_position1.y - half_height1 < final_position2.y + half_height2); } -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 { +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 = this->get_current_position(box1.offset, transform1, rigidbody1); vec2 final_position2 = this->get_current_position(circle2.offset, transform2, rigidbody2); @@ -412,8 +480,10 @@ bool CollisionSystem::get_box_circle_collision(const BoxCollider& box1, const Ci 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)); - float closest_y = std::max(final_position1.y - half_height, std::min(final_position2.y, final_position1.y + half_height)); + float closest_x = std::max(final_position1.x - half_width, + std::min(final_position2.x, final_position1.x + half_width)); + float closest_y = std::max(final_position1.y - half_height, + std::min(final_position2.y, final_position1.y + half_height)); // Calculate the distance squared between the circle's center and the closest point on the box float distance_x = final_position2.x - closest_x; @@ -424,10 +494,15 @@ bool CollisionSystem::get_box_circle_collision(const BoxCollider& box1, const Ci return distance_squared <= circle2.radius * circle2.radius; } -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 { +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 = this->get_current_position(circle1.offset,transform1,rigidbody1); - vec2 final_position2 = this->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; @@ -440,7 +515,9 @@ bool CollisionSystem::get_circle_circle_collision(const CircleCollider& circle1, return distance_squared <= radius_sum * radius_sum; } -vec2 CollisionSystem::get_current_position(const vec2& collider_offset, const Transform& transform, const Rigidbody& rigidbody) const { +vec2 CollisionSystem::get_current_position(const vec2 & collider_offset, + const Transform & transform, + const Rigidbody & rigidbody) const { // Get the rotation in radians float radians1 = transform.rotation * (M_PI / 180.0); @@ -448,10 +525,11 @@ vec2 CollisionSystem::get_current_position(const vec2& collider_offset, const Tr vec2 total_offset = (rigidbody.data.offset + collider_offset) * transform.scale; // Rotate - float rotated_total_offset_x1 = total_offset.x * cos(radians1) - total_offset.y * sin(radians1); - float rotated_total_offset_y1 = total_offset.x * sin(radians1) + total_offset.y * cos(radians1); + float rotated_total_offset_x1 + = total_offset.x * cos(radians1) - total_offset.y * sin(radians1); + float rotated_total_offset_y1 + = total_offset.x * sin(radians1) + total_offset.y * cos(radians1); // Final positions considering scaling and rotation - return(transform.position + vec2(rotated_total_offset_x1, rotated_total_offset_y1)); - + return (transform.position + vec2(rotated_total_offset_x1, rotated_total_offset_y1)); } diff --git a/src/crepe/system/CollisionSystem.h b/src/crepe/system/CollisionSystem.h index 85ae5ad..6b5a4bb 100644 --- a/src/crepe/system/CollisionSystem.h +++ b/src/crepe/system/CollisionSystem.h @@ -1,38 +1,37 @@ #pragma once -#include -#include #include +#include +#include -#include "api/Rigidbody.h" -#include "api/Transform.h" #include "api/BoxCollider.h" #include "api/CircleCollider.h" #include "api/Metadata.h" +#include "api/Rigidbody.h" +#include "api/Transform.h" #include "api/Vector2.h" #include "Collider.h" #include "System.h" - namespace crepe { - //! A system responsible for detecting and handling collisions between colliders. class CollisionSystem : public System { public: using System::System; + private: - //! A variant type that can hold either a BoxCollider or a CircleCollider. - using collider_variant = std::variant, std::reference_wrapper>; + using collider_variant = std::variant, + std::reference_wrapper>; //! Enum representing the types of collider pairs for collision detection. enum class CollisionInternalType { - BOX_BOX, - CIRCLE_CIRCLE, - BOX_CIRCLE, - CIRCLE_BOX, + BOX_BOX, + CIRCLE_CIRCLE, + BOX_CIRCLE, + CIRCLE_BOX, }; /** @@ -45,21 +44,21 @@ private: */ struct CollisionInternal { game_object_id_t id = 0; - collider_variant collider; - Transform& transform; - Rigidbody& rigidbody; + collider_variant collider; + Transform & transform; + Rigidbody & rigidbody; }; - + //! Enum representing movement directions during collision resolution. enum class Direction { //! No movement required. - NONE, + NONE, //! Movement in the X direction. - X_DIRECTION, + X_DIRECTION, //! Movement in the Y direction. - Y_DIRECTION, + Y_DIRECTION, //! Movement in both X and Y directions. - BOTH + BOTH }; public: @@ -68,15 +67,15 @@ public: * * Includes information about the colliding objects and the resolution data for handling the collision. */ - struct CollisionInfo{ - Collider& this_collider; - Transform& this_transform; - Rigidbody& this_rigidbody; - Metadata& this_metadata; - Collider& other_collider; - Transform& other_transform; - Rigidbody& other_rigidbody; - Metadata& other_metadata; + struct CollisionInfo { + 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. @@ -84,11 +83,10 @@ public: }; public: - //! Updates the collision system by checking for collisions between colliders and handling them. void update() override; -private: +private: /** * \brief Determines the type of collider pair from two colliders. * @@ -98,7 +96,8 @@ private: * \param collider2 Second collider variant (BoxCollider or CircleCollider). * \return The combined type of the two colliders. */ - CollisionInternalType get_collider_type(const collider_variant& collider1,const collider_variant& collider2) const; + CollisionInternalType get_collider_type(const collider_variant & collider1, + const collider_variant & collider2) const; /** * \brief Calculates the current position of a collider. @@ -110,10 +109,10 @@ private: * \param rigidbody The Rigidbody of the associated game object. * \return The calculated position of the collider. */ - vec2 get_current_position(const vec2& collider_offset, const Transform& transform, const Rigidbody& rigidbody) const; + vec2 get_current_position(const vec2 & collider_offset, const Transform & transform, + const Rigidbody & rigidbody) const; private: - /** * \brief Handles collision resolution between two colliders. * @@ -122,7 +121,7 @@ private: * \param data1 Collision data for the first collider. * \param data2 Collision data for the second collider. */ - void collision_handler_request(CollisionInternal& data1,CollisionInternal& data2); + void collision_handler_request(CollisionInternal & data1, CollisionInternal & data2); /** * \brief Resolves collision between two colliders and calculates the movement required. @@ -134,7 +133,9 @@ private: * \param type The type of collider pair. * \return A pair containing the resolution vector and direction for the first collider. */ - std::pair collision_handler(CollisionInternal& data1,CollisionInternal& data2 ,CollisionInternalType type); + std::pair collision_handler(CollisionInternal & data1, + CollisionInternal & data2, + CollisionInternalType type); /** * \brief Calculates the resolution vector for two BoxColliders. @@ -147,7 +148,9 @@ private: * \param position2 The position of the second BoxCollider. * \return The resolution vector for the collision. */ - vec2 get_box_box_resolution(const BoxCollider& box_collider1,const BoxCollider& box_collider2,const vec2& position1,const vec2& position2) const; + vec2 get_box_box_resolution(const BoxCollider & box_collider1, + const BoxCollider & box_collider2, const vec2 & position1, + const vec2 & position2) const; /** * \brief Calculates the resolution vector for two CircleCollider. @@ -160,7 +163,10 @@ private: * \param position2 The position of the second CircleCollider. * \return The resolution vector for the collision. */ - vec2 get_circle_circle_resolution(const CircleCollider& circle_collider1, const CircleCollider& circle_collider2, const vec2& final_position1, const vec2& final_position2) const; + vec2 get_circle_circle_resolution(const CircleCollider & circle_collider1, + const CircleCollider & circle_collider2, + const vec2 & final_position1, + const vec2 & final_position2) const; /** * \brief Calculates the resolution vector for two CircleCollider. @@ -173,7 +179,10 @@ private: * \param box_position The position of the BocCollider. * \return The resolution vector for the collision. */ - vec2 get_circle_box_resolution(const CircleCollider& circle_collider, const BoxCollider& box_collider, const vec2& circle_position, const vec2& box_position) const; + vec2 get_circle_box_resolution(const CircleCollider & circle_collider, + const BoxCollider & box_collider, + const vec2 & circle_position, + const vec2 & box_position) const; /** * \brief Determines the appropriate collision handler for a collision. @@ -182,7 +191,7 @@ private: * * \param info Collision information containing data about both colliders. */ - void determine_collision_handler(CollisionInfo& info); + void determine_collision_handler(CollisionInfo & info); /** * \brief Handles collisions involving static objects. @@ -191,9 +200,9 @@ private: * * \param info Collision information containing data about both colliders. */ - void static_collision_handler(CollisionInfo& info); + void static_collision_handler(CollisionInfo & info); + private: - /** * \brief Checks for collisions between colliders. * @@ -202,7 +211,8 @@ private: * \param colliders A collection of all active colliders. * \return A list of collision pairs with their associated data. */ - std::vector> gather_collisions(std::vector & colliders); + std::vector> + gather_collisions(std::vector & colliders); /** * \brief Checks for collision between two colliders. @@ -214,8 +224,10 @@ private: * \param type The type of collider pair. * \return True if a collision is detected, otherwise false. */ - bool get_collision(const CollisionInternal& first_info,const CollisionInternal& second_info, CollisionInternalType type) const; - + bool get_collision(const CollisionInternal & first_info, + const CollisionInternal & second_info, + CollisionInternalType type) const; + /** * \brief Detects collisions between two BoxColliders. * @@ -227,8 +239,11 @@ private: * \param rigidbody2 Rigidbody of the second object. * \return True if a collision is detected, otherwise false. */ - bool get_box_box_collision(const BoxCollider& box1, const BoxCollider& box2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2) const; - + bool get_box_box_collision(const BoxCollider & box1, const BoxCollider & box2, + const Transform & transform1, const Transform & transform2, + const Rigidbody & rigidbody1, + const Rigidbody & rigidbody2) const; + /** * \brief Check collision for box on circle collider * @@ -240,7 +255,10 @@ private: * \param rigidbody2 Rigidbody of the second object. * \return True if a collision is detected, otherwise false. */ - bool get_box_circle_collision(const BoxCollider& box1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2) const; + bool get_box_circle_collision(const BoxCollider & box1, const CircleCollider & circle2, + const Transform & transform1, const Transform & transform2, + const Rigidbody & rigidbody1, + const Rigidbody & rigidbody2) const; /** * \brief Check collision for circle on circle collider @@ -255,7 +273,12 @@ private: * * \return status of collision */ - bool get_circle_circle_collision(const CircleCollider& circle1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2) const; + bool get_circle_circle_collision(const CircleCollider & circle1, + const CircleCollider & circle2, + const Transform & transform1, + const Transform & transform2, + const Rigidbody & rigidbody1, + const Rigidbody & rigidbody2) const; }; } // namespace crepe diff --git a/src/crepe/system/PhysicsSystem.cpp b/src/crepe/system/PhysicsSystem.cpp index b5da042..b3adfa1 100644 --- a/src/crepe/system/PhysicsSystem.cpp +++ b/src/crepe/system/PhysicsSystem.cpp @@ -32,10 +32,13 @@ void PhysicsSystem::update() { } // Add damping if (rigidbody.data.angular_velocity_coefficient > 0) { - rigidbody.data.angular_velocity *= rigidbody.data.angular_velocity_coefficient; + rigidbody.data.angular_velocity + *= rigidbody.data.angular_velocity_coefficient; } - if (rigidbody.data.linear_velocity_coefficient.x > 0 && rigidbody.data.linear_velocity_coefficient.y > 0) { - rigidbody.data.linear_velocity *= rigidbody.data.linear_velocity_coefficient; + if (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 -- cgit v1.2.3