aboutsummaryrefslogtreecommitdiff
path: root/src/crepe/system/CollisionSystem.cpp
diff options
context:
space:
mode:
authorJAROWMR <jarorutjes07@gmail.com>2024-12-03 19:32:15 +0100
committerJAROWMR <jarorutjes07@gmail.com>2024-12-03 19:32:15 +0100
commitff618da3f97237796042fa3664da59ed147bc1da (patch)
treecfc283425f145b16a2b2e3b1a0a5760e8015a2b1 /src/crepe/system/CollisionSystem.cpp
parentfb018cd8511e9cae408f8ea7d2b73e66a452625b (diff)
improved comments
Diffstat (limited to 'src/crepe/system/CollisionSystem.cpp')
-rw-r--r--src/crepe/system/CollisionSystem.cpp167
1 files changed, 76 insertions, 91 deletions
diff --git a/src/crepe/system/CollisionSystem.cpp b/src/crepe/system/CollisionSystem.cpp
index 380cc3d..2d5ce9d 100644
--- a/src/crepe/system/CollisionSystem.cpp
+++ b/src/crepe/system/CollisionSystem.cpp
@@ -10,6 +10,7 @@
#include "api/EventManager.h"
#include "api/BoxCollider.h"
#include "api/CircleCollider.h"
+#include "api/Metadata.h"
#include "api/Vector2.h"
#include "api/Rigidbody.h"
#include "api/Transform.h"
@@ -23,18 +24,16 @@
using namespace crepe;
void CollisionSystem::update() {
-
std::vector<CollisionInternal> all_colliders;
- ComponentManager & mgr = this->component_manager;
game_object_id_t id = 0;
- RefVector<Rigidbody> rigidbodies = mgr.get_components_by_type<Rigidbody>();
+ RefVector<Rigidbody> rigidbodies = this->component_manager.get_components_by_type<Rigidbody>();
// Collisions can only happen on object with a rigidbody
for(Rigidbody& rigidbody : rigidbodies) {
if (!rigidbody.active) continue;
id = rigidbody.game_object_id;
Transform& transform = this->component_manager.get_components_by_id<Transform>(id).front().get();
// Check if the boxcollider is active and has the same id as the rigidbody.
- RefVector<BoxCollider> boxcolliders = mgr.get_components_by_type<BoxCollider>();
+ RefVector<BoxCollider> boxcolliders = this->component_manager.get_components_by_type<BoxCollider>();
for (BoxCollider& boxcollider : boxcolliders) {
if(boxcollider.game_object_id != id) continue;
if(!boxcollider.active) continue;
@@ -48,7 +47,7 @@ void CollisionSystem::update() {
);
}
// Check if the circlecollider is active and has the same id as the rigidbody.
- RefVector<CircleCollider> circlecolliders = mgr.get_components_by_type<CircleCollider>();
+ RefVector<CircleCollider> circlecolliders = this->component_manager.get_components_by_type<CircleCollider>();
for (CircleCollider& circlecollider : circlecolliders) {
if(circlecollider.game_object_id != id) continue;
if(!circlecollider.active) continue;
@@ -64,59 +63,63 @@ void CollisionSystem::update() {
}
// Check between all colliders if there is a collision
- std::vector<std::pair<CollisionInternal,CollisionInternal>> collided = gather_collisions(all_colliders);
+ std::vector<std::pair<CollisionInternal,CollisionInternal>> collided = this->gather_collisions(all_colliders);
// For both objects call the collision handler
for (auto& collision_pair : collided) {
- collision_handler_request(collision_pair.first,collision_pair.second);
- collision_handler_request(collision_pair.second,collision_pair.first);
+ this->collision_handler_request(collision_pair.first,collision_pair.second);
+ this->collision_handler_request(collision_pair.second,collision_pair.first);
}
}
-void CollisionSystem::collision_handler_request(CollisionInternal& data1,CollisionInternal& data2){
+void CollisionSystem::collision_handler_request(CollisionInternal& this_data,CollisionInternal& other_data){
- CollisionInternalType type = get_collider_type(data1.collider,data2.collider);
- std::pair<vec2,CollisionSystem::Direction> resolution_data = collision_handler(data1,data2,type);
+ CollisionInternalType type = this->get_collider_type(this_data.collider,other_data.collider);
+ std::pair<vec2,CollisionSystem::Direction> resolution_data = this->collision_handler(this_data,other_data,type);
- OptionalRef<Collider> collider1;
- OptionalRef<Collider> collider2;
+ OptionalRef<Metadata> this_metadata = this->component_manager.get_components_by_id<Metadata>(this_data.id).front().get();
+ OptionalRef<Metadata> other_metadata = this->component_manager.get_components_by_id<Metadata>(other_data.id).front().get();
+ OptionalRef<Collider> this_collider;
+ OptionalRef<Collider> other_collider;
switch (type) {
case CollisionInternalType::BOX_BOX:{
- collider1 = std::get<std::reference_wrapper<BoxCollider>>(data1.collider);
- collider2 = std::get<std::reference_wrapper<BoxCollider>>(data2.collider);
+ this_collider = std::get<std::reference_wrapper<BoxCollider>>(this_data.collider);
+ other_collider = std::get<std::reference_wrapper<BoxCollider>>(other_data.collider);
break;
}
case CollisionInternalType::BOX_CIRCLE:{
- collider1 = std::get<std::reference_wrapper<BoxCollider>>(data1.collider);
- collider2 = std::get<std::reference_wrapper<CircleCollider>>(data2.collider);
+ this_collider = std::get<std::reference_wrapper<BoxCollider>>(this_data.collider);
+ other_collider = std::get<std::reference_wrapper<CircleCollider>>(other_data.collider);
break;
}
case CollisionInternalType::CIRCLE_BOX:{
- collider1 = std::get<std::reference_wrapper<CircleCollider>>(data1.collider);
- collider2 = std::get<std::reference_wrapper<BoxCollider>>(data2.collider);
+ this_collider = std::get<std::reference_wrapper<CircleCollider>>(this_data.collider);
+ other_collider = std::get<std::reference_wrapper<BoxCollider>>(other_data.collider);
break;
}
case CollisionInternalType::CIRCLE_CIRCLE:{
- collider1 = std::get<std::reference_wrapper<CircleCollider>>(data1.collider);
- collider2 = std::get<std::reference_wrapper<CircleCollider>>(data2.collider);
+ this_collider = std::get<std::reference_wrapper<CircleCollider>>(this_data.collider);
+ other_collider = std::get<std::reference_wrapper<CircleCollider>>(other_data.collider);
break;
}
}
-
+
// collision info
crepe::CollisionSystem::CollisionInfo collision_info{
- .first_collider = collider1,
- .first_transform = data1.transform,
- .first_rigidbody = data1.rigidbody,
- .second_collider = collider2,
- .second_transform = data2.transform,
- .second_rigidbody = data2.rigidbody,
+ .this_collider = this_collider,
+ .this_transform = this_data.transform,
+ .this_rigidbody = this_data.rigidbody,
+ .this_metadata = this_metadata,
+ .other_collider = other_collider,
+ .other_transform = other_data.transform,
+ .other_rigidbody = other_data.rigidbody,
+ .other_metadata = other_metadata,
.resolution = resolution_data.first,
.resolution_direction = resolution_data.second,
};
// Determine if static needs to be called
- determine_collision_handler(collision_info);
+ this->determine_collision_handler(collision_info);
}
@@ -126,33 +129,33 @@ std::pair<vec2,CollisionSystem::Direction> CollisionSystem::collision_handler(Co
case CollisionInternalType::BOX_BOX: {
const BoxCollider & collider1 = std::get<std::reference_wrapper<BoxCollider>>(data1.collider);
const BoxCollider & collider2 = std::get<std::reference_wrapper<BoxCollider>>(data2.collider);
- vec2 collider_pos1 = get_current_position(collider1.offset, data1.transform, data1.rigidbody);
- vec2 collider_pos2 = get_current_position(collider2.offset, data2.transform, data2.rigidbody);
- resolution = get_box_box_resolution(collider1,collider2,collider_pos1,collider_pos2);
+ vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform, data1.rigidbody);
+ vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform, data2.rigidbody);
+ resolution = this->get_box_box_resolution(collider1,collider2,collider_pos1,collider_pos2);
break;
}
case CollisionInternalType::BOX_CIRCLE: {
const BoxCollider & collider1 = std::get<std::reference_wrapper<BoxCollider>>(data1.collider);
const CircleCollider & collider2 = std::get<std::reference_wrapper<CircleCollider>>(data2.collider);
- vec2 collider_pos1 = get_current_position(collider1.offset, data1.transform, data1.rigidbody);
- vec2 collider_pos2 = get_current_position(collider2.offset, data2.transform, data2.rigidbody);
- resolution = get_circle_box_resolution(collider2,collider1,collider_pos2,collider_pos1);
+ vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform, data1.rigidbody);
+ vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform, data2.rigidbody);
+ resolution = this->get_circle_box_resolution(collider2,collider1,collider_pos2,collider_pos1);
break;
}
case CollisionInternalType::CIRCLE_CIRCLE: {
const CircleCollider & collider1 = std::get<std::reference_wrapper<CircleCollider>>(data1.collider);
const CircleCollider & collider2 = std::get<std::reference_wrapper<CircleCollider>>(data2.collider);
- vec2 collider_pos1 = get_current_position(collider1.offset, data1.transform, data1.rigidbody);
- vec2 collider_pos2 = get_current_position(collider2.offset, data2.transform, data2.rigidbody);
- resolution = get_circle_circle_resolution(collider1,collider2,collider_pos1,collider_pos2);
+ vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform, data1.rigidbody);
+ vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform, data2.rigidbody);
+ resolution = this->get_circle_circle_resolution(collider1,collider2,collider_pos1,collider_pos2);
break;
}
case CollisionInternalType::CIRCLE_BOX: {
const CircleCollider & collider1 = std::get<std::reference_wrapper<CircleCollider>>(data1.collider);
const BoxCollider & collider2 = std::get<std::reference_wrapper<BoxCollider>>(data2.collider);
- vec2 collider_pos1 = get_current_position(collider1.offset, data1.transform, data1.rigidbody);
- vec2 collider_pos2 = get_current_position(collider2.offset, data2.transform, data2.rigidbody);
- resolution = get_circle_box_resolution(collider1,collider2,collider_pos1,collider_pos2);
+ vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform, data1.rigidbody);
+ vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform, data2.rigidbody);
+ resolution = this->get_circle_box_resolution(collider1,collider2,collider_pos1,collider_pos2);
break;
}
}
@@ -179,10 +182,10 @@ vec2 CollisionSystem::get_box_box_resolution(const BoxCollider& box_collider1,co
vec2 delta = final_position2 - final_position1;
// Compute half-dimensions of the boxes
- float half_width1 = box_collider1.width / 2.0;
- float half_height1 = box_collider1.height / 2.0;
- float half_width2 = box_collider2.width / 2.0;
- float half_height2 = box_collider2.height / 2.0;
+ float half_width1 = box_collider1.dimensions.x / 2.0;
+ float half_height1 = box_collider1.dimensions.y / 2.0;
+ float half_width2 = box_collider2.dimensions.x / 2.0;
+ float half_height2 = box_collider2.dimensions.y / 2.0;
// Calculate overlaps along X and Y axes
float overlap_x = (half_width1 + half_width2) - std::abs(delta.x);
@@ -234,8 +237,8 @@ vec2 CollisionSystem::get_circle_box_resolution(const CircleCollider& circle_col
vec2 delta = circle_position - box_position;
// Compute half-dimensions of the box
- float half_width = box_collider.width / 2.0f;
- float half_height = box_collider.height / 2.0f;
+ float half_width = box_collider.dimensions.x / 2.0f;
+ float half_height = box_collider.dimensions.y / 2.0f;
// Clamp circle center to the nearest point on the box
vec2 closest_point;
@@ -261,37 +264,37 @@ vec2 CollisionSystem::get_circle_box_resolution(const CircleCollider& circle_col
void CollisionSystem::determine_collision_handler(CollisionInfo& info){
// Check rigidbody type for static
- if(info.first_rigidbody.data.body_type == Rigidbody::BodyType::STATIC) return;
+ if(info.this_rigidbody.data.body_type == Rigidbody::BodyType::STATIC) return;
// If second body is static perform the static collision handler in this system
- if(info.second_rigidbody.data.body_type == Rigidbody::BodyType::STATIC){
+ if(info.other_rigidbody.data.body_type == Rigidbody::BodyType::STATIC){
static_collision_handler(info);
};
// Call collision event for user
CollisionEvent data(info);
- EventManager::get_instance().trigger_event<CollisionEvent>(data, info.first_collider.game_object_id);
+ EventManager::get_instance().trigger_event<CollisionEvent>(data, info.this_collider.game_object_id);
}
void CollisionSystem::static_collision_handler(CollisionInfo& info){
// Move object back using calculate move back value
- info.first_transform.position += info.resolution;
+ info.this_transform.position += info.resolution;
// If bounce is enabled mirror velocity
- if(info.first_rigidbody.data.elastisity > 0) {
+ if(info.this_rigidbody.data.elastisity_coefficient > 0) {
if(info.resolution_direction == Direction::BOTH)
{
- info.first_rigidbody.data.linear_velocity.y = -info.first_rigidbody.data.linear_velocity.y * info.first_rigidbody.data.elastisity;
- info.first_rigidbody.data.linear_velocity.x = -info.first_rigidbody.data.linear_velocity.x * info.first_rigidbody.data.elastisity;
+ info.this_rigidbody.data.linear_velocity.y = -info.this_rigidbody.data.linear_velocity.y * info.this_rigidbody.data.elastisity_coefficient;
+ info.this_rigidbody.data.linear_velocity.x = -info.this_rigidbody.data.linear_velocity.x * info.this_rigidbody.data.elastisity_coefficient;
}
else if(info.resolution_direction == Direction::Y_DIRECTION) {
- info.first_rigidbody.data.linear_velocity.y = -info.first_rigidbody.data.linear_velocity.y * info.first_rigidbody.data.elastisity;
+ info.this_rigidbody.data.linear_velocity.y = -info.this_rigidbody.data.linear_velocity.y * info.this_rigidbody.data.elastisity_coefficient;
}
else if(info.resolution_direction == Direction::X_DIRECTION){
- info.first_rigidbody.data.linear_velocity.x = -info.first_rigidbody.data.linear_velocity.x * info.first_rigidbody.data.elastisity;
+ info.this_rigidbody.data.linear_velocity.x = -info.this_rigidbody.data.linear_velocity.x * info.this_rigidbody.data.elastisity_coefficient;
}
}
// Stop movement if bounce is disabled
else {
- info.first_rigidbody.data.linear_velocity = {0,0};
+ info.this_rigidbody.data.linear_velocity = {0,0};
}
}
@@ -332,24 +335,6 @@ std::vector<std::pair<CollisionSystem::CollisionInternal,CollisionSystem::Collis
return collisions_ret;
}
-std::optional<std::pair<std::reference_wrapper<Transform>, std::reference_wrapper<Rigidbody>>>
-CollisionSystem::get_active_transform_and_rigidbody(game_object_id_t game_object_id) const{
- RefVector<Transform> transforms = this->component_manager.get_components_by_id<Transform>(game_object_id);
- if (transforms.empty()) return std::nullopt;
-
- Transform& transform = transforms.front().get();
- if (!transform.active) return std::nullopt;
-
- RefVector<Rigidbody> rigidbodies = this->component_manager.get_components_by_id<Rigidbody>(game_object_id);
- if (rigidbodies.empty()) return std::nullopt;
-
- Rigidbody& rigidbody = rigidbodies.front().get();
- if (!rigidbody.active) return std::nullopt;
-
- // Return the active components
- return std::make_pair(std::ref(transform), std::ref(rigidbody));
-}
-
CollisionSystem::CollisionInternalType CollisionSystem::get_collider_type(const collider_variant& collider1,const collider_variant& collider2) const{
if(std::holds_alternative<std::reference_wrapper<CircleCollider>>(collider1)){
if(std::holds_alternative<std::reference_wrapper<CircleCollider>>(collider2))
@@ -376,22 +361,22 @@ bool CollisionSystem::get_collision(const CollisionInternal& first_info,const Co
case CollisionInternalType::BOX_BOX: {
const BoxCollider & box_collider1 = std::get<std::reference_wrapper<BoxCollider>>(first_info.collider);
const BoxCollider & box_collider2 = std::get<std::reference_wrapper<BoxCollider>>(second_info.collider);
- return get_box_box_collision(box_collider1,box_collider2,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody);
+ return this->get_box_box_collision(box_collider1,box_collider2,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody);
}
case CollisionInternalType::BOX_CIRCLE: {
const BoxCollider & box_collider = std::get<std::reference_wrapper<BoxCollider>>(first_info.collider);
const CircleCollider & circle_collider = std::get<std::reference_wrapper<CircleCollider>>(second_info.collider);
- return get_box_circle_collision(box_collider,circle_collider,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody);
+ return this->get_box_circle_collision(box_collider,circle_collider,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody);
}
case CollisionInternalType::CIRCLE_CIRCLE: {
const CircleCollider & circle_collider1 = std::get<std::reference_wrapper<CircleCollider>>(first_info.collider);
const CircleCollider & circle_collider2 = std::get<std::reference_wrapper<CircleCollider>>(second_info.collider);
- return get_circle_circle_collision(circle_collider1,circle_collider2,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody);
+ return this->get_circle_circle_collision(circle_collider1,circle_collider2,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody);
}
case CollisionInternalType::CIRCLE_BOX: {
const CircleCollider & circle_collider = std::get<std::reference_wrapper<CircleCollider>>(first_info.collider);
const BoxCollider & box_collider = std::get<std::reference_wrapper<BoxCollider>>(second_info.collider);
- return get_box_circle_collision(box_collider,circle_collider,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody);
+ return this->get_box_circle_collision(box_collider,circle_collider,first_info.transform,second_info.transform,second_info.rigidbody,second_info.rigidbody);
}
}
return false;
@@ -401,14 +386,14 @@ bool CollisionSystem::get_collision(const CollisionInternal& first_info,const Co
bool CollisionSystem::get_box_box_collision(const BoxCollider& box1, const BoxCollider& box2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2) const
{
// Get current positions of colliders
- vec2 final_position1 = get_current_position(box1.offset,transform1,rigidbody1);
- vec2 final_position2 = get_current_position(box2.offset,transform2,rigidbody2);
+ vec2 final_position1 = this->get_current_position(box1.offset,transform1,rigidbody1);
+ vec2 final_position2 = this->get_current_position(box2.offset,transform2,rigidbody2);
// Calculate half-extents (half width and half height)
- float half_width1 = box1.width / 2.0;
- float half_height1 = box1.height / 2.0;
- float half_width2 = box2.width / 2.0;
- float half_height2 = box2.height / 2.0;
+ float half_width1 = box1.dimensions.x / 2.0;
+ float half_height1 = box1.dimensions.y / 2.0;
+ float half_width2 = box2.dimensions.x / 2.0;
+ float half_height2 = box2.dimensions.y / 2.0;
// Check if the boxes overlap along the X and Y axes
return (final_position1.x + half_width1 > final_position2.x - half_width2 &&
@@ -419,12 +404,12 @@ bool CollisionSystem::get_box_box_collision(const BoxCollider& box1, const BoxCo
bool CollisionSystem::get_box_circle_collision(const BoxCollider& box1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2) const {
// Get current positions of colliders
- vec2 final_position1 = get_current_position(box1.offset, transform1, rigidbody1);
- vec2 final_position2 = get_current_position(circle2.offset, transform2, rigidbody2);
+ vec2 final_position1 = this->get_current_position(box1.offset, transform1, rigidbody1);
+ vec2 final_position2 = this->get_current_position(circle2.offset, transform2, rigidbody2);
// Calculate box half-extents
- float half_width = box1.width / 2.0;
- float half_height = box1.height / 2.0;
+ float half_width = box1.dimensions.x / 2.0;
+ float half_height = box1.dimensions.y / 2.0;
// Find the closest point on the box to the circle's center
float closest_x = std::max(final_position1.x - half_width, std::min(final_position2.x, final_position1.x + half_width));
@@ -441,8 +426,8 @@ bool CollisionSystem::get_box_circle_collision(const BoxCollider& box1, const Ci
bool CollisionSystem::get_circle_circle_collision(const CircleCollider& circle1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2) const {
// Get current positions of colliders
- vec2 final_position1 = get_current_position(circle1.offset,transform1,rigidbody1);
- vec2 final_position2 = get_current_position(circle2.offset,transform2,rigidbody2);
+ vec2 final_position1 = this->get_current_position(circle1.offset,transform1,rigidbody1);
+ vec2 final_position2 = this->get_current_position(circle2.offset,transform2,rigidbody2);
float distance_x = final_position1.x - final_position2.x;
float distance_y = final_position1.y - final_position2.y;