aboutsummaryrefslogtreecommitdiff
path: root/src/crepe/system/CollisionSystem.h
blob: 44fff4e19c33820df5543e02c941eb7214f2bd15 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#pragma once

#include <vector>
#include <variant>

#include "api/Rigidbody.h"
#include "api/Transform.h"
#include "api/BoxCollider.h"
#include "api/CircleCollider.h"
#include "api/Vector2.h"

#include "Collider.h"
#include "System.h"

namespace crepe {


//! A system responsible for detecting and handling collisions between colliders.
class CollisionSystem : public System {
public:
	using System::System;
private:
	
	//! A variant type that can hold either a BoxCollider or a CircleCollider.
	// using collider_stor = std::variant<BoxCollider, CircleCollider>;
	using collider_stor = std::variant<std::reference_wrapper<BoxCollider>, std::reference_wrapper<CircleCollider>>;

	/**
		* \brief A structure to store the collision data of a single collider.
		* 
		* This structure stores the collider type, its associated transform, and its rigidbody.
		*/
	struct CollidedInfoStor {
		//! Store either BoxCollider or CircleCollider
		collider_stor collider; 
		Transform& transform;
		Rigidbody& rigidbody;
	};
	
	//! Enum representing movement directions during collision resolution.
	enum class Direction {
    NONE,
    X_DIRECTION,
    Y_DIRECTION,
    BOTH
	};

public:
	/**
		* \brief A structure representing the collision information between two colliders.
		* 
		* This structure contains both colliders, their associated transforms and rigidbodies,
		* as well as the movement vector to resolve the collision.
		*/
	struct ColliderInfo {
		const Collider& collider;
		Transform& transform;
		Rigidbody& rigidbody;
	};
	/**
		* \brief A structure representing detailed collision information between two colliders.
		* 
		* This includes the movement data required to resolve the collision.
		*/
	struct CollisionInfo{
    ColliderInfo first;
    ColliderInfo second;
		vec2 move_back_value;
		Direction move_back_direction = Direction::NONE;
	};

public:

	//! Updates the collision system by checking for collisions between colliders and handling them.
	void update() override;

private:
	/**
		* \brief Handles a collision between two colliders.
		* 
		* This function calculates the necessary response to resolve the collision, including
		* moving the objects back to prevent overlap and applying any velocity changes.
		*
		* \param data1 The collision data for the first collider.
		* \param data2 The collision data for the second collider.
		*/
	void collision_handler(CollidedInfoStor& data1,CollidedInfoStor& data2);
	
	/**
		* \brief Resolves the movement of two box colliders that are colliding.
		* 
		* This function calculates the smallest overlap (along the X or Y axis) and determines
		* the move-back vector to prevent overlap.
		*
		* \param box_collider1 The first box collider.
		* \param box_collider2 The second box collider.
		* \param final_position1 The final position of the first box collider.
		* \param final_position2 The final position of the second box collider.
		* \return The move-back vector to resolve the collision.
		*/
	vec2 box_box_collision_move_back(const BoxCollider& box_collider1,const BoxCollider& box_collider2,vec2 position1,vec2 position2);

	/**
		* \brief Determines the appropriate collision handler based on the rigidbody types of the colliding objects.
		* 
		* This function checks if the second object is static, and if so, it calls the static collision handler.
		* Otherwise, it triggers a collision event.
		*
		* \param info The collision information containing the colliders, transforms, rigidbodies, and move-back data.
		*/
	void determine_collision_handler(CollisionInfo& info);

	/**
		* \brief Handles the collision with a static object.
		* 
		* This function resolves the collision by moving the object back and applying any bounce or stop behavior.
		*
		* \param info The collision information containing the colliders, transforms, rigidbodies, and move-back data.
		*/
	void static_collision_handler(CollisionInfo& info);
private: //detection
	
	/**
		* \brief Checks for collisions between box colliders and circle colliders
		* and returns the collision pairs that need to be resolved.
		* 
		* \param boxcolliders A vector of references to all box colliders.
		* \param circlecolliders A vector of references to all circle colliders.
		* \return A vector of pairs containing collision information for the detected collisions.
		*/
	std::vector<std::pair<CollidedInfoStor,CollidedInfoStor>> check_collisions(const std::vector<std::reference_wrapper<BoxCollider>>& boxcolliders, const std::vector<std::reference_wrapper<CircleCollider>>& circlecolliders);
	
	/**
		* \brief Checks for a collision between two box colliders.
		* 
		* This function checks if two box colliders overlap based on their positions and dimensions.
		*
		* \param box1 The first box collider.
		* \param box2 The second box collider.
		* \param transform1 The transform component of the first box collider.
		* \param transform2 The transform component of the second box collider.
		* \param rigidbody1 The rigidbody component of the first box collider.
		* \param rigidbody2 The rigidbody component of the second box collider.
		* \return True if the two box colliders overlap, otherwise false.
		*/
	bool check_box_box_collision(const BoxCollider& box1, const BoxCollider& box2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2);
	
	/**
		* \brief Checks for a collision between a box collider and a circle collider.
		* 
		* This function checks if a box collider overlaps with a circle collider based on their positions
		* and dimensions.
		*
		* \param box1 The box collider.
		* \param circle2 The circle collider.
		* \param transform1 The transform component of the box collider.
		* \param transform2 The transform component of the circle collider.
		* \param rigidbody1 The rigidbody component of the box collider.
		* \param rigidbody2 The rigidbody component of the circle collider.
		* \return True if the box collider and circle collider overlap, otherwise false.
		*/
	bool check_box_circle_collision(const BoxCollider& box1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2);
	
	/**
		* \brief Checks for a collision between two circle colliders.
		* 
		* This function checks if two circle colliders overlap based on their positions and radii.
		*
		* \param circle1 The first circle collider.
		* \param circle2 The second circle collider.
		* \param transform1 The transform component of the first circle collider.
		* \param transform2 The transform component of the second circle collider.
		* \param rigidbody1 The rigidbody component of the first circle collider.
		* \param rigidbody2 The rigidbody component of the second circle collider.
		* \return True if the two circle colliders overlap, otherwise false.
		*/
	bool check_circle_circle_collision(const CircleCollider& circle1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2);
	
	/**
		* \brief Gets the current position of a collider by combining its transform and rigidbody data.
		* 
		* This function calculates the current position of the collider by considering its transform and 
		* rigidbody velocity.
		*
		* \param collider The collider whose position is being determined.
		* \param transform The transform component associated with the collider.
		* \param rigidbody The rigidbody component associated with the collider.
		* \return The current position of the collider as a vec2.
		*/
	vec2 current_position(const Collider& collider, const Transform& transform, const Rigidbody& rigidbody);
};

} // namespace crepe