aboutsummaryrefslogtreecommitdiff
path: root/src/crepe
diff options
context:
space:
mode:
Diffstat (limited to 'src/crepe')
-rw-r--r--src/crepe/Collider.cpp2
-rw-r--r--src/crepe/Collider.h6
-rw-r--r--src/crepe/api/BoxCollider.cpp7
-rw-r--r--src/crepe/api/BoxCollider.h15
-rw-r--r--src/crepe/api/CMakeLists.txt4
-rw-r--r--src/crepe/api/CircleCollider.cpp6
-rw-r--r--src/crepe/api/CircleCollider.h9
-rw-r--r--src/crepe/api/Rigidbody.h2
-rw-r--r--src/crepe/api/Vector2.cpp4
-rw-r--r--src/crepe/api/Vector2.h3
-rw-r--r--src/crepe/system/CollisionSystem.cpp275
-rw-r--r--src/crepe/system/CollisionSystem.h25
12 files changed, 349 insertions, 9 deletions
diff --git a/src/crepe/Collider.cpp b/src/crepe/Collider.cpp
index bbec488..0706371 100644
--- a/src/crepe/Collider.cpp
+++ b/src/crepe/Collider.cpp
@@ -2,4 +2,4 @@
using namespace crepe;
-Collider::Collider(game_object_id_t id) : Component(id) {}
+Collider::Collider(game_object_id_t id, Vector2 offset) : Component(id), offset(offset) {}
diff --git a/src/crepe/Collider.h b/src/crepe/Collider.h
index 827f83d..54695b1 100644
--- a/src/crepe/Collider.h
+++ b/src/crepe/Collider.h
@@ -1,14 +1,14 @@
#pragma once
#include "Component.h"
+#include "api/Vector2.h"
namespace crepe {
class Collider : public Component {
public:
- Collider(game_object_id_t id);
-
- int size;
+ Collider(game_object_id_t id, Vector2 offset);
+ Vector2 offset;
};
} // namespace crepe
diff --git a/src/crepe/api/BoxCollider.cpp b/src/crepe/api/BoxCollider.cpp
new file mode 100644
index 0000000..eafbdb2
--- /dev/null
+++ b/src/crepe/api/BoxCollider.cpp
@@ -0,0 +1,7 @@
+#include "BoxCollider.h"
+#include "../Collider.h"
+
+using namespace crepe;
+
+
+BoxCollider::BoxCollider(game_object_id_t game_object_id,Vector2 offset, double width, double height) : Collider(game_object_id,offset), width(width), height(height) {}
diff --git a/src/crepe/api/BoxCollider.h b/src/crepe/api/BoxCollider.h
new file mode 100644
index 0000000..357c979
--- /dev/null
+++ b/src/crepe/api/BoxCollider.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "Vector2.h"
+#include "../Collider.h"
+
+namespace crepe {
+
+class BoxCollider : public Collider {
+public:
+ BoxCollider(game_object_id_t game_object_id,Vector2 offset, double width, double height);
+ double width;
+ double height;
+};
+
+} // namespace crepe
diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt
index 53b3041..07341e2 100644
--- a/src/crepe/api/CMakeLists.txt
+++ b/src/crepe/api/CMakeLists.txt
@@ -18,6 +18,8 @@ target_sources(crepe PUBLIC
Vector2.cpp
Camera.cpp
Animator.cpp
+ BoxCollider.cpp
+ CircleCollider.cpp
EventManager.cpp
EventHandler.cpp
IKeyListener.cpp
@@ -48,6 +50,8 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES
SceneManager.hpp
Camera.h
Animator.h
+ BoxCollider.h
+ CircleCollider.h
EventManager.h
EventManager.hpp
EventHandler.h
diff --git a/src/crepe/api/CircleCollider.cpp b/src/crepe/api/CircleCollider.cpp
new file mode 100644
index 0000000..04a4995
--- /dev/null
+++ b/src/crepe/api/CircleCollider.cpp
@@ -0,0 +1,6 @@
+#include "CircleCollider.h"
+
+using namespace crepe;
+
+
+CircleCollider::CircleCollider(game_object_id_t game_object_id,Vector2 offset, int radius) : Collider(game_object_id,offset), radius(radius) {}
diff --git a/src/crepe/api/CircleCollider.h b/src/crepe/api/CircleCollider.h
index e77a592..29a9c1e 100644
--- a/src/crepe/api/CircleCollider.h
+++ b/src/crepe/api/CircleCollider.h
@@ -1,14 +1,15 @@
#pragma once
+
+#include "Vector2.h"
+
#include "../Collider.h"
namespace crepe {
class CircleCollider : public Collider {
public:
- CircleCollider(game_object_id_t game_object_id, int radius)
- : Collider(game_object_id),
- radius(radius) {}
- int radius;
+ CircleCollider(game_object_id_t game_object_id,Vector2 offset, int radius);
+ double radius;
};
} // namespace crepe
diff --git a/src/crepe/api/Rigidbody.h b/src/crepe/api/Rigidbody.h
index 68481f4..b9edec2 100644
--- a/src/crepe/api/Rigidbody.h
+++ b/src/crepe/api/Rigidbody.h
@@ -75,6 +75,8 @@ public:
bool use_gravity = true;
//! if object bounces
bool bounce = false;
+ //! offset of all colliders
+ Vector2 offset;
};
public:
diff --git a/src/crepe/api/Vector2.cpp b/src/crepe/api/Vector2.cpp
index 09b3fa3..947c49e 100644
--- a/src/crepe/api/Vector2.cpp
+++ b/src/crepe/api/Vector2.cpp
@@ -54,4 +54,8 @@ bool Vector2::operator!=(const Vector2 & other) const {
return !(*this == other);
}
+double Vector2::dot(const Vector2& other) const {
+ return this->x * other.x + this->y * other.y;
+}
+
} // namespace crepe
diff --git a/src/crepe/api/Vector2.h b/src/crepe/api/Vector2.h
index 5a57484..90d9d57 100644
--- a/src/crepe/api/Vector2.h
+++ b/src/crepe/api/Vector2.h
@@ -42,6 +42,9 @@ public:
//! Checks if this vector is not equal to another vector.
bool operator!=(const Vector2 & other) const;
+
+ //!
+ double dot(const Vector2& other) const;
};
} // namespace crepe
diff --git a/src/crepe/system/CollisionSystem.cpp b/src/crepe/system/CollisionSystem.cpp
index 55e0fdc..ac35026 100644
--- a/src/crepe/system/CollisionSystem.cpp
+++ b/src/crepe/system/CollisionSystem.cpp
@@ -1,7 +1,280 @@
+#include <cmath>
+#include <algorithm>
+#include <cstddef>
+#include <tuple>
+#include <utility>
+#include <variant>
+
#include "CollisionSystem.h"
+#include "../ComponentManager.h"
+#include "../api/BoxCollider.h"
+#include "../api/CircleCollider.h"
+#include "../api/Vector2.h"
+#include "../api/Rigidbody.h"
+#include "../api/Transform.h"
+
+#include "Collider.h"
+#include "iostream"
+
using namespace crepe;
CollisionSystem::CollisionSystem() {}
-void CollisionSystem::update() {}
+void CollisionSystem::update() {
+ ComponentManager & mgr = ComponentManager::get_instance();
+ std::vector<std::reference_wrapper<BoxCollider>> boxcolliders = mgr.get_components_by_type<BoxCollider>();
+ 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) {
+ call_collision_handler(collision_pair.first,collision_pair.second); // First collider
+ call_collision_handler(collision_pair.second,collision_pair.first); // First collider
+ }
+
+ if(collided.empty()) {
+ std::cout << "No objects collided" << std::endl;
+ }
+}
+
+void CollisionSystem::call_collision_handler(const CollidedInfoStor& data1,const CollidedInfoStor& data2){
+
+ // Check collision type and get values for handler
+ game_object_id_t first = 0,second = 0;
+ if (std::holds_alternative<BoxCollider>(data1.collider)) {
+ if (std::holds_alternative<BoxCollider>(data2.collider)) {
+ const BoxCollider& box_collider1 = std::get<BoxCollider>(data1.collider);
+ const BoxCollider& box_collider2 = std::get<BoxCollider>(data2.collider);
+ first = box_collider1.game_object_id;
+ second = box_collider2.game_object_id;
+ }
+ else {
+ const BoxCollider& box_collider = std::get<BoxCollider>(data1.collider);
+ const CircleCollider& circle_collider = std::get<CircleCollider>(data2.collider);
+ first = box_collider.game_object_id;
+ second = circle_collider.game_object_id;
+ }
+ }
+ else {
+ if (std::holds_alternative<CircleCollider>(data2.collider)) {
+ const CircleCollider& circle_collider1 = std::get<CircleCollider>(data1.collider);
+ const CircleCollider& circle_collider2 = std::get<CircleCollider>(data2.collider);
+ first = circle_collider1.game_object_id;
+ second = circle_collider2.game_object_id;
+ }
+ else {
+ const CircleCollider& circle_collider = std::get<CircleCollider>(data1.collider);
+ const BoxCollider& box_collider = std::get<BoxCollider>(data2.collider);
+ first = circle_collider.game_object_id;
+ second = box_collider.game_object_id;
+ }
+ }
+
+ // check rigidbody type
+ if(data1.rigidbody.data.body_type != Rigidbody::BodyType::STATIC)
+ {
+ // If second body is static move back
+ if(data2.rigidbody.data.body_type == Rigidbody::BodyType::STATIC) return;
+ //call static handler (is bounce true?)
+
+ // call script handler
+ }
+}
+
+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;
+ //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 collisions
+ for (size_t i = 0; i < boxcolliders.size(); ++i) {
+ // Fetch components for the first box collider
+ if(!boxcolliders[i].get().active) continue;
+ int game_object_id_1 = boxcolliders[i].get().game_object_id;
+ Transform& transform1 = mgr.get_components_by_id<Transform>(game_object_id_1).front().get();
+ if(!transform1.active) continue;
+ Rigidbody& rigidbody1 = mgr.get_components_by_id<Rigidbody>(game_object_id_1).front().get();
+ if(!rigidbody1.active) continue;
+
+ // Check CircleCollider vs CircleCollider
+ for (size_t j = i + 1; j < boxcolliders.size(); ++j) {
+ if(!boxcolliders[j].get().active) continue;
+ // Skip self collision
+ int game_object_id_2 = boxcolliders[j].get().game_object_id;
+ if (game_object_id_1 == game_object_id_2) continue;
+
+ // Fetch components for the second box collider
+ Transform & transform2 = mgr.get_components_by_id<Transform>(boxcolliders[j].get().game_object_id).front().get();
+ if(!transform2.active) continue;
+ Rigidbody & rigidbody2 = mgr.get_components_by_id<Rigidbody>(boxcolliders[j].get().game_object_id).front().get();
+ if(!rigidbody2.active) continue;
+ // Check collision
+ if (check_box_box_collision(boxcolliders[i], boxcolliders[j], transform1, transform2, rigidbody1, rigidbody2)) {
+ collisions_ret.emplace_back(std::make_pair(
+ CollidedInfoStor{boxcolliders[i], transform1, rigidbody1},
+ CollidedInfoStor{boxcolliders[j], transform2, rigidbody2}
+ ));
+ }
+ }
+
+ // Check BoxCollider vs CircleCollider
+ for (size_t j = 0; j < circlecolliders.size(); ++j) {
+ if(!circlecolliders[j].get().active) continue;
+ // Skip self collision
+ int game_object_id_2 = circlecolliders[j].get().game_object_id;
+ if (game_object_id_1 == game_object_id_2) continue;
+
+ // Fetch components for the second collider (circle)
+ Transform & transform2 = mgr.get_components_by_id<Transform>(circlecolliders[j].get().game_object_id).front().get();
+ if(!transform2.active) continue;
+ Rigidbody & rigidbody2 = mgr.get_components_by_id<Rigidbody>(circlecolliders[j].get().game_object_id).front().get();
+ if(!rigidbody2.active) continue;
+
+ // Check collision
+ if (check_box_circle_collision(boxcolliders[i], circlecolliders[j], transform1, transform2, rigidbody1, rigidbody2)) {
+
+ collisions_ret.emplace_back(std::make_pair(
+ CollidedInfoStor{boxcolliders[i], transform1, rigidbody1},
+ CollidedInfoStor{circlecolliders[j], transform2, rigidbody2}
+ ));
+ }
+ }
+ }
+ // Check CircleCollider vs CircleCollider
+ for (size_t i = 0; i < circlecolliders.size(); ++i) {
+ if(!circlecolliders[i].get().active) continue;
+ // Fetch components for the first circle collider
+ int game_object_id_1 = circlecolliders[i].get().game_object_id;
+ Transform & transform1 = mgr.get_components_by_id<Transform>(circlecolliders[i].get().game_object_id).front().get();
+ if(!transform1.active) continue;
+ Rigidbody & rigidbody1 = mgr.get_components_by_id<Rigidbody>(circlecolliders[i].get().game_object_id).front().get();
+ if(!rigidbody1.active) continue;
+
+ for (size_t j = i + 1; j < circlecolliders.size(); ++j) {
+ if(!circlecolliders[j].get().active) continue;
+ // Skip self collision
+ int game_object_id_2 = circlecolliders[j].get().game_object_id;
+ if (game_object_id_1 == game_object_id_2) continue;
+
+ // Fetch components for the second circle collider
+ Transform & transform2 = mgr.get_components_by_id<Transform>(circlecolliders[j].get().game_object_id).front().get();
+ if(!transform2.active) continue;
+ Rigidbody & rigidbody2 = mgr.get_components_by_id<Rigidbody>(circlecolliders[j].get().game_object_id).front().get();
+ if(!rigidbody2.active) continue;
+
+ // Check collision
+ if (check_circle_circle_collision(circlecolliders[i], circlecolliders[j], transform1, transform2, rigidbody1, rigidbody2)) {
+ collisions_ret.emplace_back(std::make_pair(
+ CollidedInfoStor{circlecolliders[i], transform1, rigidbody1},
+ CollidedInfoStor{circlecolliders[j], transform2, rigidbody2}
+ ));
+ }
+ }
+ }
+ return collisions_ret;
+}
+
+bool CollisionSystem::check_box_box_collision(const BoxCollider& box1, const BoxCollider& box2, 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(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;
+
+ // 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;
+
+
+ // Calculate half-extents (half width and half height)
+ double half_width1 = box1.width / 2.0;
+ double half_height1 = box1.height / 2.0;
+ double half_width2 = box2.width / 2.0;
+ double half_height2 = box2.height / 2.0;
+
+ // 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
+}
+
+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::max(final_position1.x - half_width, std::min(final_position2.x, final_position1.x + half_width));
+ double 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
+ 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));
+
+}
diff --git a/src/crepe/system/CollisionSystem.h b/src/crepe/system/CollisionSystem.h
index 1e9f1aa..9a72948 100644
--- a/src/crepe/system/CollisionSystem.h
+++ b/src/crepe/system/CollisionSystem.h
@@ -1,11 +1,36 @@
#pragma once
+#include "Collider.h"
+#include "api/Rigidbody.h"
+#include "api/Transform.h"
+#include "api/BoxCollider.h"
+#include "api/CircleCollider.h"
+#include <tuple>
+#include <vector>
+#include <variant>
+
namespace crepe {
+
class CollisionSystem {
+private:
+ using collider_stor = std::variant<BoxCollider, CircleCollider>;
+private:
+ struct CollidedInfoStor {
+ collider_stor collider; // Store either BoxCollider or CircleCollider
+ Transform transform; // Transform data
+ 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);
};
} // namespace crepe