aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJAROWMR <jarorutjes07@gmail.com>2024-11-12 16:09:43 +0100
committerJAROWMR <jarorutjes07@gmail.com>2024-11-12 16:09:43 +0100
commit73127fd15a3b074cb3c964da448b6bb3d237ee73 (patch)
treed2f5bd2708fca0f44d767ee8f7cb0a5aeb00939e
parentd3c9a8afa68e79e7cf9a82ecd78be532751913dc (diff)
added collision methodes
-rw-r--r--src/crepe/system/CollisionSystem.cpp156
-rw-r--r--src/crepe/system/CollisionSystem.h7
-rw-r--r--src/example/collision.cpp26
3 files changed, 147 insertions, 42 deletions
diff --git a/src/crepe/system/CollisionSystem.cpp b/src/crepe/system/CollisionSystem.cpp
index 75d5c58..71bca6b 100644
--- a/src/crepe/system/CollisionSystem.cpp
+++ b/src/crepe/system/CollisionSystem.cpp
@@ -1,4 +1,6 @@
#include <cmath>
+#include <algorithm>
+#include <cstddef>
#include "CollisionSystem.h"
@@ -19,48 +21,55 @@ CollisionSystem::CollisionSystem() {}
void CollisionSystem::update() {
ComponentManager & mgr = ComponentManager::get_instance();
std::vector<std::reference_wrapper<BoxCollider>> boxcolliders = mgr.get_components_by_type<BoxCollider>();
-
- Transform & transform1 = mgr.get_components_by_id<Transform>(boxcolliders[0].get().game_object_id).front().get();
- Rigidbody & rigidbody1 = mgr.get_components_by_id<Rigidbody>(boxcolliders[0].get().game_object_id).front().get();
- Transform & transform2 = mgr.get_components_by_id<Transform>(boxcolliders[1].get().game_object_id).front().get();
- Rigidbody & rigidbody2 = mgr.get_components_by_id<Rigidbody>(boxcolliders[1].get().game_object_id).front().get();
- BoxCollider & collider1 = boxcolliders[0].get();
- BoxCollider & collider2 = boxcolliders[1].get();
- bool test = check_box_box_collision(collider1, collider2, transform1, transform2, rigidbody1, rigidbody2);
- std::cout << "collided? " << test << std::endl;
+ std::vector<std::reference_wrapper<CircleCollider>> circlecolliders = mgr.get_components_by_type<CircleCollider>();
+ check_collisions(boxcolliders,circlecolliders);
}
+void CollisionSystem::check_collisions(const std::vector<std::reference_wrapper<BoxCollider>>& boxcolliders, const std::vector<std::reference_wrapper<CircleCollider>>& circlecolliders) {
+ ComponentManager & mgr = ComponentManager::get_instance();
+ //if no colliders skip
+ //check if colliders has rigibocdy if not skip
+
+ //if amount is higer than lets say 16 for now use quadtree otwerwise skip
+ //quadtree code
+ //quadtree is placed over the input vector
+
+ //check collision
+ for (size_t i = 0; i < boxcolliders.size(); ++i) {
+ for (size_t j = i + 1; j < boxcolliders.size(); ++j) {
+ if(boxcolliders[i].get().game_object_id == boxcolliders[j].get().game_object_id){continue;}
+ Transform & transform1 = mgr.get_components_by_id<Transform>(boxcolliders[i].get().game_object_id).front().get();
+ Rigidbody & rigidbody1 = mgr.get_components_by_id<Rigidbody>(boxcolliders[i].get().game_object_id).front().get();
+ Transform & transform2 = mgr.get_components_by_id<Transform>(boxcolliders[j].get().game_object_id).front().get();
+ Rigidbody & rigidbody2 = mgr.get_components_by_id<Rigidbody>(boxcolliders[j].get().game_object_id).front().get();
+ check_box_box_collision(boxcolliders[i], boxcolliders[j], transform1, transform2, rigidbody1, rigidbody2);
+ }
+ for (size_t j = 0; j < circlecolliders.size(); ++j) {
+ if(boxcolliders[i].get().game_object_id == circlecolliders[j].get().game_object_id){continue;}
+ Transform & transform1 = mgr.get_components_by_id<Transform>(boxcolliders[i].get().game_object_id).front().get();
+ Rigidbody & rigidbody1 = mgr.get_components_by_id<Rigidbody>(boxcolliders[i].get().game_object_id).front().get();
+ Transform & transform2 = mgr.get_components_by_id<Transform>(circlecolliders[j].get().game_object_id).front().get();
+ Rigidbody & rigidbody2 = mgr.get_components_by_id<Rigidbody>(circlecolliders[j].get().game_object_id).front().get();
+ check_box_circle_collision(boxcolliders[i], circlecolliders[j], transform1, transform2, rigidbody1, rigidbody2);
+ }
+ }
+ for (size_t i = 0; i < circlecolliders.size(); ++i) {
+ for (size_t j = i + 1; j < circlecolliders.size(); ++j) {
+ if(circlecolliders[i].get().game_object_id == circlecolliders[j].get().game_object_id){continue;}
+ Transform & transform1 = mgr.get_components_by_id<Transform>(circlecolliders[i].get().game_object_id).front().get();
+ Rigidbody & rigidbody1 = mgr.get_components_by_id<Rigidbody>(circlecolliders[i].get().game_object_id).front().get();
+ Transform & transform2 = mgr.get_components_by_id<Transform>(circlecolliders[j].get().game_object_id).front().get();
+ Rigidbody & rigidbody2 = mgr.get_components_by_id<Rigidbody>(circlecolliders[j].get().game_object_id).front().get();
+ check_circle_circle_collision(circlecolliders[i], circlecolliders[j], transform1, transform2, rigidbody1, rigidbody2);
+ }
+ }
+}
-
-bool CollisionSystem::check_collisions(const std::vector<Collider*>& colliders1, const std::vector<Collider*>& colliders2) {}
bool CollisionSystem::check_box_box_collision(const BoxCollider& box1, const BoxCollider& box2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2)
{
- // Function to convert degrees to radians
- auto degrees_to_radians = [](double degrees) {
- return degrees * (M_PI / 180.0);
- };
-
- // Get the rotation in radians
- double radians1 = degrees_to_radians(transform1.rotation);
- double radians2 = degrees_to_radians(transform2.rotation);
-
- // Calculate the scale factor (for both rigidbody and box offsets)
- double scale1 = transform1.scale;
- double scale2 = transform2.scale;
-
- Vector2 total_offset1 = (rigidbody1.data.offset + box1.offset) * transform1.scale;
- Vector2 total_offset2 = (rigidbody2.data.offset + box2.offset) * transform2.scale;
-
- // Rotate
- double rotated_total_offset_x1 = total_offset1.x * cos(radians1) - total_offset1.y * sin(radians1);
- double rotated_total_offset_y1 = total_offset1.x * sin(radians1) + total_offset1.y * cos(radians1);
-
- double rotated_total_offset_x2 = total_offset2.x * cos(radians2) - total_offset2.y * sin(radians2);
- double rotated_total_offset_y2 = total_offset2.x * sin(radians2) + total_offset2.y * cos(radians2);
-
- // Final positions considering scaling and rotation
- Vector2 final_position1 = transform1.position + Vector2(rotated_total_offset_x1, rotated_total_offset_y1);
- Vector2 final_position2 = transform2.position + Vector2(rotated_total_offset_x2, rotated_total_offset_y2);
+ // Get current positions of colliders
+ Vector2 final_position1 = current_position(box1,transform1,rigidbody1);
+ 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;
@@ -83,5 +92,74 @@ bool CollisionSystem::check_box_box_collision(const BoxCollider& box1, const Box
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& box, const CircleCollider& circle) {}
-bool CollisionSystem::check_circle_circle_collision(const CircleCollider& circle1, const CircleCollider& circle2) {}
+
+bool CollisionSystem::check_box_circle_collision(const BoxCollider& box1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2) {
+ // Get current positions of colliders
+ Vector2 final_position1 = current_position(box1, transform1, rigidbody1);
+ Vector2 final_position2 = current_position(circle2, transform2, rigidbody2);
+
+ // Log final positions for debugging purposes
+ std::cout << "Final Position of Box: (" << final_position1.x << ", " << final_position1.y << ")" << std::endl;
+ std::cout << "Final Position of Circle: (" << final_position2.x << ", " << final_position2.y << ")" << std::endl;
+
+ // Calculate box half-extents
+ double half_width = box1.width / 2.0;
+ double half_height = box1.height / 2.0;
+
+ // Find the closest point on the box to the circle's center
+ double closest_x = std::clamp(final_position2.x, final_position1.x - half_width, final_position1.x + half_width);
+ double closest_y = std::clamp(final_position2.y, final_position1.y - half_height, final_position1.y + half_height);
+
+ // Calculate the distance squared between the circle's center and the closest point on the box
+ double distance_x = final_position2.x - closest_x;
+ double distance_y = final_position2.y - closest_y;
+ double distance_squared = distance_x * distance_x + distance_y * distance_y;
+
+ // Compare distance squared with the square of the circle's radius
+ return distance_squared <= circle2.radius * circle2.radius;
+}
+
+bool CollisionSystem::check_circle_circle_collision(const CircleCollider& circle1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2) {
+ // Get current positions of colliders
+ Vector2 final_position1 = current_position(circle1,transform1,rigidbody1);
+ Vector2 final_position2 = current_position(circle2,transform2,rigidbody2);
+
+ // Log final positions for debugging purposes
+ std::cout << "Final Position of Circle 1: (" << final_position1.x << ", " << final_position1.y << ")" << std::endl;
+ std::cout << "Final Position of Circle 2: (" << final_position2.x << ", " << final_position2.y << ")" << std::endl;
+
+ // Log rotation values for debugging (circles do not rotate, so this might not be needed for circles)
+ std::cout << "Rotation of Circle 1: " << transform1.rotation << " degrees" << std::endl;
+ std::cout << "Rotation of Circle 2: " << transform2.rotation << " degrees" << std::endl;
+
+ double distance_x = final_position1.x - final_position2.x;
+ double distance_y = final_position1.y - final_position2.y;
+ double distance_squared = distance_x * distance_x + distance_y * distance_y;
+
+ // Calculate the sum of the radii
+ double radius_sum = circle1.radius + circle2.radius;
+
+ // Check if the distance between the centers is less than or equal to the sum of the radii
+ return distance_squared <= radius_sum * radius_sum;
+}
+
+Vector2 CollisionSystem::current_position(const Collider& collider, const Transform& transform, const Rigidbody& rigidbody) {
+ // Function to convert degrees to radians
+ auto degrees_to_radians = [](double degrees) {
+ return degrees * (M_PI / 180.0);
+ };
+
+ // Get the rotation in radians
+ double radians1 = degrees_to_radians(transform.rotation);
+
+ // Calculate total offset with scale
+ Vector2 total_offset = (rigidbody.data.offset + collider.offset) * transform.scale;
+
+ // Rotate
+ double rotated_total_offset_x1 = total_offset.x * cos(radians1) - total_offset.y * sin(radians1);
+ double rotated_total_offset_y1 = total_offset.x * sin(radians1) + total_offset.y * cos(radians1);
+
+ // Final positions considering scaling and rotation
+ return(transform.position + Vector2(rotated_total_offset_x1, rotated_total_offset_y1));
+
+} \ No newline at end of file
diff --git a/src/crepe/system/CollisionSystem.h b/src/crepe/system/CollisionSystem.h
index 402ba64..a369ee9 100644
--- a/src/crepe/system/CollisionSystem.h
+++ b/src/crepe/system/CollisionSystem.h
@@ -16,10 +16,11 @@ public:
CollisionSystem();
void update();
private:
- bool check_collisions(const std::vector<Collider*>& colliders1, const std::vector<Collider*>& colliders2);
+ void 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& box, const CircleCollider& circle);
- bool check_circle_circle_collision(const CircleCollider& circle1, const CircleCollider& circle2);
+ 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 dc97c81..e82b493 100644
--- a/src/example/collision.cpp
+++ b/src/example/collision.cpp
@@ -7,11 +7,24 @@
#include <crepe/api/BoxCollider.h>
#include <crepe/api/Transform.h>
#include <crepe/system/PhysicsSystem.h>
+#include <crepe/system/RenderSystem.h>
+#include <crepe/util/log.h>
+
+#include <crepe/api/AssetManager.h>
+#include <crepe/api/Color.h>
+#include <crepe/api/Sprite.h>
+#include <crepe/api/Texture.h>
+#include <crepe/api/Transform.h>
+#include <crepe/api/Vector2.h>
+
+#include <chrono>
+#include <memory>
using namespace crepe;
using namespace std;
int main(int argc, char * argv[]) {
+ Color color(0, 0, 0, 0);
GameObject game_object1(0, "Name", "Tag", Vector2{10, 10}, 0, 1);
game_object1.add_component<Rigidbody>(Rigidbody::Data{
@@ -24,6 +37,10 @@ int main(int argc, char * argv[]) {
.offset = {0,0}
});
game_object1.add_component<BoxCollider>(Vector2{5, 5}, 5, 5);
+ // game_object1.add_component<Sprite>(
+ // make_shared<Texture>("/home/jaro/crepe/asset/texture/img.png"), color,
+ // FlipSettings{true, true});
+
GameObject game_object2(1, "Name", "Tag", Vector2{20, 0}, 90, 1);
game_object2.add_component<Rigidbody>(Rigidbody::Data{
@@ -36,7 +53,16 @@ int main(int argc, char * argv[]) {
.offset = {0,0}
});
game_object2.add_component<BoxCollider>(Vector2{5, 5}, 5, 5);
+ // game_object2.add_component<Sprite>(
+ // make_shared<Texture>("/home/jaro/crepe/asset/texture/img.png"), color,
+ // FlipSettings{true, true});
+
CollisionSystem coltest;
coltest.update();
+ // auto & sys = crepe::RenderSystem::get_instance();
+ // auto start = std::chrono::steady_clock::now();
+ // while (std::chrono::steady_clock::now() - start < std::chrono::seconds(5)) {
+ // sys.update();
+ // }
return 0;
}