aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/crepe/system/CollisionSystem.cpp97
-rw-r--r--src/crepe/system/CollisionSystem.h37
-rw-r--r--src/example/collision.cpp33
3 files changed, 124 insertions, 43 deletions
diff --git a/src/crepe/system/CollisionSystem.cpp b/src/crepe/system/CollisionSystem.cpp
index d59539e..4b74e67 100644
--- a/src/crepe/system/CollisionSystem.cpp
+++ b/src/crepe/system/CollisionSystem.cpp
@@ -28,7 +28,7 @@ void CollisionSystem::update() {
std::vector<std::reference_wrapper<CircleCollider>> circlecolliders = mgr.get_components_by_type<CircleCollider>();
std::vector<std::pair<CollidedInfoStor,CollidedInfoStor>> collided = check_collisions(boxcolliders,circlecolliders);
// std::cout << "DEBUG INFO" << std::endl;
- for (const auto& collision_pair : collided) {
+ for (auto& collision_pair : collided) {
call_collision_handler(collision_pair.first,collision_pair.second); // First collider
call_collision_handler(collision_pair.second,collision_pair.first); // First collider
}
@@ -38,9 +38,14 @@ void CollisionSystem::update() {
}
}
-void CollisionSystem::call_collision_handler(const CollidedInfoStor& data1,const CollidedInfoStor& data2){
+void CollisionSystem::call_collision_handler(CollidedInfoStor& data1,CollidedInfoStor& data2){
const Collider* collider1 = nullptr;
const Collider* collider2 = nullptr;
+ double height1 = 0,width1 = 0;
+ double height2 = 0,width2 = 0;
+ Vector2 final_position1;
+ Vector2 final_position2;
+ Vector2 temp;
// Check collision type and get values for handler
game_object_id_t first = 0,second = 0;
if (std::holds_alternative<BoxCollider>(data1.collider)) {
@@ -51,6 +56,38 @@ void CollisionSystem::call_collision_handler(const CollidedInfoStor& data1,const
collider2 = &box_collider2;
first = box_collider1.game_object_id;
second = box_collider2.game_object_id;
+ height1 = box_collider1.height;
+ height2 = box_collider2.height;
+ width1 = box_collider1.width;
+ width2 = box_collider2.width;
+ final_position1 = current_position(box_collider1,data1.transform,data1.rigidbody);
+ final_position2 = current_position(box_collider2,data2.transform,data2.rigidbody);
+
+ Vector2 delta = final_position2 - final_position1;
+
+ double half_width1 = width1 / 2.0;
+ double half_height1 = height1 / 2.0;
+ double half_width2 = width2 / 2.0;
+ double half_height2 = height2 / 2.0;
+
+ // Compute overlap in X and Y directions
+ double overlap_x = (half_width1 + half_width2) - std::abs(delta.x);
+ double overlap_y = (half_height1 + half_height2) - std::abs(delta.y);
+
+ // Check if there is actually a collision
+ if (overlap_x > 0 && overlap_y > 0) {
+ // Resolve in the smallest overlap direction
+ if (overlap_x < overlap_y) {
+ // Resolve along X-axis
+ temp = {delta.x > 0 ? -overlap_x : overlap_x, 0};
+ } else {
+ // Resolve along Y-axis
+ temp = {0, delta.y > 0 ? -overlap_y : overlap_y};
+ }
+ }
+
+
+
}
else {
const BoxCollider& box_collider = std::get<BoxCollider>(data1.collider);
@@ -59,6 +96,10 @@ void CollisionSystem::call_collision_handler(const CollidedInfoStor& data1,const
collider2 = &circle_collider;
first = box_collider.game_object_id;
second = circle_collider.game_object_id;
+ height1 = box_collider.height;
+ height2 = circle_collider.radius + circle_collider.radius;
+ width1 = box_collider.width;
+ width2 = circle_collider.radius + circle_collider.radius;
}
}
else {
@@ -69,6 +110,10 @@ void CollisionSystem::call_collision_handler(const CollidedInfoStor& data1,const
collider2 = &circle_collider2;
first = circle_collider1.game_object_id;
second = circle_collider2.game_object_id;
+ height1 = circle_collider1.radius + circle_collider1.radius;
+ height2 = circle_collider2.radius + circle_collider2.radius;
+ width1 = circle_collider1.radius + circle_collider1.radius;
+ width2 = circle_collider2.radius + circle_collider2.radius;
}
else {
const CircleCollider& circle_collider = std::get<CircleCollider>(data1.collider);
@@ -77,8 +122,17 @@ void CollisionSystem::call_collision_handler(const CollidedInfoStor& data1,const
collider2 = &box_collider;
first = circle_collider.game_object_id;
second = box_collider.game_object_id;
+ height1 = circle_collider.radius + circle_collider.radius;
+ height2 = box_collider.height;
+ width1 = circle_collider.radius + circle_collider.radius;
+ width2 = box_collider.width;
}
}
+ crepe::CollisionSystem::CollisionInfo collision_info{
+ .first={ *collider1, data1.transform, data1.rigidbody },
+ .second={ *collider2, data2.transform, data2.rigidbody },
+ .move_back_value = temp,
+ };
// check rigidbody type
if(data1.rigidbody.data.body_type != Rigidbody::BodyType::STATIC)
@@ -86,17 +140,21 @@ void CollisionSystem::call_collision_handler(const CollidedInfoStor& data1,const
// If second body is static move back
if(data2.rigidbody.data.body_type == Rigidbody::BodyType::STATIC){
//call static handler (is bounce true?)
+ static_collision_handler(collision_info);
};
- crepe::CollisionSystem::CollisionInfo collision_info{
- { *collider1, data1.transform, data1.rigidbody },
- { *collider2, data2.transform, data2.rigidbody }
- };
+
CollisionEvent data(collision_info);
EventManager::get_instance().trigger_event<CollisionEvent>(data, first);
}
}
+void CollisionSystem::static_collision_handler(CollisionInfo& info){
+ std::cout << "INFO: x:" << info.first.transform.position.x << "y:" << info.first.transform.position.y << std::endl;
+ info.first.transform.position += info.move_back_value;
+ info.first.rigidbody.data.linear_velocity = {0,0};
+}
+
std::vector<std::pair<CollisionSystem::CollidedInfoStor,CollisionSystem::CollidedInfoStor>> CollisionSystem::check_collisions(const std::vector<std::reference_wrapper<BoxCollider>>& boxcolliders, const std::vector<std::reference_wrapper<CircleCollider>>& circlecolliders) {
ComponentManager & mgr = ComponentManager::get_instance();
std::vector<std::pair<CollidedInfoStor,CollidedInfoStor>> collisions_ret;
@@ -202,12 +260,12 @@ bool CollisionSystem::check_box_box_collision(const BoxCollider& box1, const Box
Vector2 final_position2 = current_position(box2,transform2,rigidbody2);
// Log final positions for debugging purposes
- // std::cout << "Final Position of Box 1: (" << final_position1.x << ", " << final_position1.y << ")" << std::endl;
- // std::cout << "Final Position of Box 2: (" << final_position2.x << ", " << final_position2.y << ")" << std::endl;
+ std::cout << "Final Position of Box 1: (" << final_position1.x << ", " << final_position1.y << ")" << std::endl;
+ std::cout << "Final Position of Box 2: (" << final_position2.x << ", " << final_position2.y << ")" << std::endl;
// Log rotation values for debugging
- // std::cout << "Rotation of Box 1: " << transform1.rotation << " degrees" << std::endl;
- // std::cout << "Rotation of Box 2: " << transform2.rotation << " degrees" << std::endl;
+ std::cout << "Rotation of Box 1: " << transform1.rotation << " degrees" << std::endl;
+ std::cout << "Rotation of Box 2: " << transform2.rotation << " degrees" << std::endl;
// Calculate half-extents (half width and half height)
@@ -216,11 +274,22 @@ bool CollisionSystem::check_box_box_collision(const BoxCollider& box1, const Box
double half_width2 = box2.width / 2.0;
double half_height2 = box2.height / 2.0;
+ std::cout << "half_width of Box 1: " << half_width1 << std::endl;
+ std::cout << "half_height of Box 2: " << half_height1 << std::endl;
+ std::cout << "half_width of Box 1: " << half_width2 << std::endl;
+ std::cout << "half_height of Box 2: " << half_height2 << std::endl;
+
+
+ std::cout << "final_position1.x + half_width1 < final_position2.x - half_width2 " << (final_position1.x + half_width1 < final_position2.x - half_width2) << std::endl;
+ std::cout << "final_position1.x - half_width1 > final_position2.x + half_width2 " << (final_position1.x - half_width1 > final_position2.x + half_width2) << std::endl;
+ std::cout << "final_position1.y + half_height1 < final_position2.y - half_height2 " << (final_position1.y + half_height1 < final_position2.y - half_height2) << std::endl;
+ std::cout << "final_position1.y - half_height1 > final_position2.y + half_height2 " << (final_position1.y - half_height1 > final_position2.y + half_height2) << std::endl;
+
// Check if the boxes overlap along the X and Y axes
- return !(final_position1.x + half_width1 < final_position2.x - half_width2 || // box1 is left of box2
- final_position1.x - half_width1 > final_position2.x + half_width2 || // box1 is right of box2
- final_position1.y + half_height1 < final_position2.y - half_height2 || // box1 is above box2
- final_position1.y - half_height1 > final_position2.y + half_height2); // box1 is below box2
+ return !(final_position1.x + half_width1 <= final_position2.x - half_width2 || // box1 is left of box2
+ final_position1.x - half_width1 >= final_position2.x + half_width2 || // box1 is right of box2
+ final_position1.y + half_height1 <= final_position2.y - half_height2 || // box1 is above box2
+ final_position1.y - half_height1 >= final_position2.y + half_height2); // box1 is below box2
}
bool CollisionSystem::check_box_circle_collision(const BoxCollider& box1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2) {
diff --git a/src/crepe/system/CollisionSystem.h b/src/crepe/system/CollisionSystem.h
index a31ac48..cfa599e 100644
--- a/src/crepe/system/CollisionSystem.h
+++ b/src/crepe/system/CollisionSystem.h
@@ -5,6 +5,7 @@
#include "api/Transform.h"
#include "api/BoxCollider.h"
#include "api/CircleCollider.h"
+#include "api/Vector2.h"
#include <tuple>
#include <vector>
#include <variant>
@@ -19,29 +20,35 @@ private:
struct CollidedInfoStor {
//! Store either BoxCollider or CircleCollider
collider_stor collider;
- Transform transform;
- Rigidbody rigidbody; // Rigidbody data
+ Transform& transform;
+ Rigidbody& rigidbody; // Rigidbody data
};
public:
- CollisionSystem();
- void update();
-private:
- void call_collision_handler(const CollidedInfoStor& data1,const CollidedInfoStor& data2);
- std::vector<std::pair<CollidedInfoStor,CollidedInfoStor>> check_collisions(const std::vector<std::reference_wrapper<BoxCollider>>& boxcolliders, const std::vector<std::reference_wrapper<CircleCollider>>& circlecolliders);
- bool check_box_box_collision(const BoxCollider& box1, const BoxCollider& box2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2);
- bool check_box_circle_collision(const BoxCollider& box1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2);
- bool check_circle_circle_collision(const CircleCollider& circle1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2);
- Vector2 current_position(const Collider& collider, const Transform& transform, const Rigidbody& rigidbody);
-public:
struct ColliderInfo {
- Collider collider;
- Transform transform;
- Rigidbody rigidbody;
+ const Collider& collider;
+ Transform& transform;
+ Rigidbody& rigidbody;
};
struct CollisionInfo{
ColliderInfo first;
ColliderInfo second;
+ Vector2 move_back_value;
};
+public:
+ CollisionSystem();
+ void update();
+private: //handling
+ void call_collision_handler(CollidedInfoStor& data1,CollidedInfoStor& data2);
+ void static_collision_handler(CollisionInfo& info);
+private: //detection
+
+ std::vector<std::pair<CollidedInfoStor,CollidedInfoStor>> check_collisions(const std::vector<std::reference_wrapper<BoxCollider>>& boxcolliders, const std::vector<std::reference_wrapper<CircleCollider>>& circlecolliders);
+ bool check_box_box_collision(const BoxCollider& box1, const BoxCollider& box2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2);
+ bool check_box_circle_collision(const BoxCollider& box1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2);
+ bool check_circle_circle_collision(const CircleCollider& circle1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2);
+ Vector2 current_position(const Collider& collider, const Transform& transform, const Rigidbody& rigidbody);
+
+
};
} // namespace crepe
diff --git a/src/example/collision.cpp b/src/example/collision.cpp
index a1b22f0..a5cec83 100644
--- a/src/example/collision.cpp
+++ b/src/example/collision.cpp
@@ -49,8 +49,11 @@ int main(int argc, char * argv[]) {
LoopManager gameloop;
Color color(0, 0, 0, 0);
+ double screen_size_width = 1280;
+ double screen_size_height = 960;
+ double world_collider = 1000;
//define playable world
- GameObject World(0, "Name", "Tag", Vector2{0, 0}, 0, 1);
+ GameObject World(0, "Name", "Tag", Vector2{screen_size_width/2, screen_size_height/2}, 0, 1);
World.add_component<Rigidbody>(Rigidbody::Data{
.mass = 0,
.gravity_scale = 0,
@@ -58,46 +61,48 @@ int main(int argc, char * argv[]) {
.constraints = {0, 0, 0},
.use_gravity = false,
.bounce = false,
- .offset = {320,240}
+ .offset = {0,0}
});
- World.add_component<BoxCollider>(Vector2{0, -740}, 1000, 1000); // Top
- World.add_component<BoxCollider>(Vector2{0, 740}, 1000, 1000); // Bottom
- World.add_component<BoxCollider>(Vector2{-820, 0}, 1000, 1000); // Left
- World.add_component<BoxCollider>(Vector2{820, 0}, 1000, 1000); // right
+ // World.add_component<BoxCollider>(Vector2{0, -740}, 1000, 1000); // Top
+ World.add_component<BoxCollider>(Vector2{0, screen_size_height/2+world_collider/2}, world_collider, world_collider); // Bottom
+ // World.add_component<BoxCollider>(Vector2{-820, 0}, 1000, 1000); // Left
+ // World.add_component<BoxCollider>(Vector2{820, 0}, 1000, 1000); // right
- GameObject game_object1(1, "Name", "Tag", Vector2{320, 240}, 0, 1);
+ GameObject game_object1(1, "Name", "Tag", Vector2{screen_size_width/2, screen_size_height/2}, 0, 1);
game_object1.add_component<Rigidbody>(Rigidbody::Data{
.mass = 1,
.gravity_scale = 1,
.body_type = Rigidbody::BodyType::DYNAMIC,
+ .linear_velocity = {0,1},
.constraints = {0, 0, 0},
.use_gravity = false,
.bounce = false,
- .offset = {0,0}
+ .offset = {0,0},
});
- game_object1.add_component<BoxCollider>(Vector2{5, 5}, 5, 5);
+ game_object1.add_component<BoxCollider>(Vector2{0, 0}, 40, 40);
game_object1.add_component<BehaviorScript>().set_script<MyScript>();
game_object1.add_component<Sprite>(
- make_shared<Texture>("/home/jaro/crepe/asset/texture/img.png"), color,
+ make_shared<Texture>("/home/jaro/crepe/asset/texture/green_square.png"), color,
FlipSettings{true, true});
game_object1.add_component<Camera>(Color::get_white());
- // GameObject game_object2(2, "Name", "Tag", Vector2{10, 10}, 0, 1);
+ // GameObject game_object2(2, "Name", "Tag", Vector2{screen_size_width/2, screen_size_height/2+100}, 0, 1);
// game_object2.add_component<Rigidbody>(Rigidbody::Data{
// .mass = 1,
// .gravity_scale = 1,
// .body_type = Rigidbody::BodyType::DYNAMIC,
+ // .linear_velocity = {0,0},
// .constraints = {0, 0, 0},
// .use_gravity = false,
// .bounce = false,
- // .offset = {0,0}
+ // .offset = {0,0},
// });
- // game_object2.add_component<BoxCollider>(Vector2{5, 5}, 5, 5);
+ // game_object2.add_component<BoxCollider>(Vector2{0, 0}, 40, 40);
// game_object2.add_component<BehaviorScript>().set_script<MyScript>();
// game_object2.add_component<Sprite>(
- // make_shared<Texture>("/home/jaro/crepe/asset/texture/img.png"), color,
+ // make_shared<Texture>("/home/jaro/crepe/asset/texture/red_square.png"), color,
// FlipSettings{true, true});