diff options
| -rw-r--r-- | src/crepe/system/CollisionSystem.cpp | 156 | ||||
| -rw-r--r-- | src/crepe/system/CollisionSystem.h | 7 | ||||
| -rw-r--r-- | src/example/collision.cpp | 26 | 
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;  } |