aboutsummaryrefslogtreecommitdiff
path: root/src/crepe/system
diff options
context:
space:
mode:
authorJAROWMR <jarorutjes07@gmail.com>2024-12-04 20:11:02 +0100
committerJAROWMR <jarorutjes07@gmail.com>2024-12-04 20:11:02 +0100
commitd76ab0bf77d0a61712dc25bbe1760995be4c4782 (patch)
treef71073322d52d6341ed46068e2c63fab8bb6f942 /src/crepe/system
parent322e9a8ceaa8b2ce5d3e6056be4a9739817d47cf (diff)
make format
Diffstat (limited to 'src/crepe/system')
-rw-r--r--src/crepe/system/CollisionSystem.cpp514
-rw-r--r--src/crepe/system/CollisionSystem.h121
-rw-r--r--src/crepe/system/PhysicsSystem.cpp9
3 files changed, 374 insertions, 270 deletions
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 <cmath>
#include <algorithm>
+#include <cmath>
#include <cstddef>
#include <functional>
+#include <optional>
#include <utility>
#include <variant>
-#include <optional>
-#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<CollisionInternal> all_colliders;
game_object_id_t id = 0;
- RefVector<Rigidbody> rigidbodies = this->component_manager.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) {
+ 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();
+ 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 = this->component_manager.get_components_by_type<BoxCollider>();
- 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<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;
+ 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<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;
- all_colliders.push_back(
- {
- .id = id,
- .collider = collider_variant{circlecollider},
- .transform = transform,
- .rigidbody = rigidbody
- }
- );
+ 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;
+ 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<std::pair<CollisionInternal,CollisionInternal>> collided = this->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) {
- 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<vec2,CollisionSystem::Direction> resolution_data = this->collision_handler(this_data,other_data,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<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<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:{
+ case CollisionInternalType::BOX_BOX: {
this_collider = std::get<std::reference_wrapper<BoxCollider>>(this_data.collider);
- other_collider = std::get<std::reference_wrapper<BoxCollider>>(other_data.collider);
+ other_collider
+ = std::get<std::reference_wrapper<BoxCollider>>(other_data.collider);
break;
}
- case CollisionInternalType::BOX_CIRCLE:{
+ case CollisionInternalType::BOX_CIRCLE: {
this_collider = std::get<std::reference_wrapper<BoxCollider>>(this_data.collider);
- other_collider = std::get<std::reference_wrapper<CircleCollider>>(other_data.collider);
+ other_collider
+ = std::get<std::reference_wrapper<CircleCollider>>(other_data.collider);
break;
}
- case CollisionInternalType::CIRCLE_BOX:{
- this_collider = std::get<std::reference_wrapper<CircleCollider>>(this_data.collider);
- other_collider = std::get<std::reference_wrapper<BoxCollider>>(other_data.collider);
+ case CollisionInternalType::CIRCLE_BOX: {
+ 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:{
- this_collider = std::get<std::reference_wrapper<CircleCollider>>(this_data.collider);
- other_collider = std::get<std::reference_wrapper<CircleCollider>>(other_data.collider);
+ case CollisionInternalType::CIRCLE_CIRCLE: {
+ 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{
- .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<vec2,CollisionSystem::Direction> CollisionSystem::collision_handler(CollisionInternal& data1,CollisionInternal& data2,CollisionInternalType type) {
+std::pair<vec2, CollisionSystem::Direction>
+CollisionSystem::collision_handler(CollisionInternal & data1, CollisionInternal & data2,
+ CollisionInternalType type) {
vec2 resolution;
switch (type) {
- 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 = 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<std::reference_wrapper<BoxCollider>>(data1.collider);
+ const BoxCollider & collider2
+ = std::get<std::reference_wrapper<BoxCollider>>(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<std::reference_wrapper<BoxCollider>>(data1.collider);
- const CircleCollider & collider2 = std::get<std::reference_wrapper<CircleCollider>>(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<std::reference_wrapper<BoxCollider>>(data1.collider);
+ const CircleCollider & collider2
+ = std::get<std::reference_wrapper<CircleCollider>>(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<std::reference_wrapper<CircleCollider>>(data1.collider);
- const CircleCollider & collider2 = std::get<std::reference_wrapper<CircleCollider>>(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<std::reference_wrapper<CircleCollider>>(data1.collider);
+ const CircleCollider & collider2
+ = std::get<std::reference_wrapper<CircleCollider>>(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<std::reference_wrapper<CircleCollider>>(data1.collider);
- const BoxCollider & collider2 = std::get<std::reference_wrapper<BoxCollider>>(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<std::reference_wrapper<CircleCollider>>(data1.collider);
+ const BoxCollider & collider2
+ = std::get<std::reference_wrapper<BoxCollider>>(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<CollisionEvent>(data, info.this_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
+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<std::pair<CollisionSystem::CollisionInternal,CollisionSystem::CollisionInternal>> CollisionSystem::gather_collisions(std::vector<CollisionInternal> & colliders) {
-
-
+std::vector<std::pair<CollisionSystem::CollisionInternal, CollisionSystem::CollisionInternal>>
+CollisionSystem::gather_collisions(std::vector<CollisionInternal> & colliders) {
+
// TODO:
// If no colliders skip
// Check if colliders has rigidbody if not skip
@@ -311,83 +354,103 @@ std::vector<std::pair<CollisionSystem::CollisionInternal,CollisionSystem::Collis
// Quadtree is placed over the input vector
// Return data of collided colliders which are variants
- std::vector<std::pair<CollisionInternal,CollisionInternal>> collisions_ret;
- //using visit to visit the variant to access the active and id.
+ std::vector<std::pair<CollisionInternal, CollisionInternal>> 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<std::reference_wrapper<CircleCollider>>(collider1)){
- if(std::holds_alternative<std::reference_wrapper<CircleCollider>>(collider2))
- {
+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)) {
return CollisionInternalType::CIRCLE_CIRCLE;
- }
- else {
+ } else {
return CollisionInternalType::CIRCLE_BOX;
}
- }
- else {
- if(std::holds_alternative<std::reference_wrapper<CircleCollider>>(collider2))
- {
+ } else {
+ if (std::holds_alternative<std::reference_wrapper<CircleCollider>>(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<std::reference_wrapper<BoxCollider>>(first_info.collider);
- const BoxCollider & box_collider2 = std::get<std::reference_wrapper<BoxCollider>>(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<std::reference_wrapper<BoxCollider>>(first_info.collider);
+ const BoxCollider & box_collider2
+ = std::get<std::reference_wrapper<BoxCollider>>(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<std::reference_wrapper<BoxCollider>>(first_info.collider);
- const CircleCollider & circle_collider = std::get<std::reference_wrapper<CircleCollider>>(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<std::reference_wrapper<BoxCollider>>(first_info.collider);
+ const CircleCollider & circle_collider
+ = std::get<std::reference_wrapper<CircleCollider>>(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<std::reference_wrapper<CircleCollider>>(first_info.collider);
- const CircleCollider & circle_collider2 = std::get<std::reference_wrapper<CircleCollider>>(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<std::reference_wrapper<CircleCollider>>(first_info.collider);
+ const CircleCollider & circle_collider2
+ = std::get<std::reference_wrapper<CircleCollider>>(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<std::reference_wrapper<CircleCollider>>(first_info.collider);
- const BoxCollider & box_collider = std::get<std::reference_wrapper<BoxCollider>>(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<std::reference_wrapper<CircleCollider>>(first_info.collider);
+ const BoxCollider & box_collider
+ = std::get<std::reference_wrapper<BoxCollider>>(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 <vector>
-#include <variant>
#include <optional>
+#include <variant>
+#include <vector>
-#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<BoxCollider>, std::reference_wrapper<CircleCollider>>;
+ using collider_variant = std::variant<std::reference_wrapper<BoxCollider>,
+ std::reference_wrapper<CircleCollider>>;
//! 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<vec2,Direction> collision_handler(CollisionInternal& data1,CollisionInternal& data2 ,CollisionInternalType type);
+ std::pair<vec2, Direction> 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<std::pair<CollisionInternal,CollisionInternal>> gather_collisions(std::vector<CollisionInternal> & colliders);
+ std::vector<std::pair<CollisionInternal, CollisionInternal>>
+ gather_collisions(std::vector<CollisionInternal> & 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