aboutsummaryrefslogtreecommitdiff
path: root/src/crepe/system/CollisionSystem.h
blob: 6334ba1187f57162e9463b1366cba39218dab85a (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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
#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>>;

	//! A enum that is used to tell the pair of the collider stor in a std::pair.
	enum class ColliderStorType {
    BOX_BOX,
    CIRCLE_CIRCLE,
    BOX_CIRCLE,
    CIRCLE_BOX,
	};

	/**
		* \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: //generic

	/**
	 * \brief Returns a type of the colliders combined into a pair.
	 * 
	 * This function uses the holds_alternative to determine what both colliders are.
	 * This caluclated value is returned so get can be savely used.
	 *
	 * \param collider1 Variant of collider. Can be a box or circle collider
	 * \param collider2 Variant of collider. Can be a box or circle collider
	 *
	 * \return collider pair type.
	 */
	ColliderStorType check_collider_type(const collider_stor& collider1,const collider_stor& collider2);

	/**
	 * \brief Calculates the position of the Collider
	 * 
	 * Using the \c Collider offset, \c Transform position and \c Rigidbody offset the place of the collider is calculated.
	 *
	 * \param collider_offset Collider offset value.
	 * \param transform Transform of same gameobject as collider.
	 * \param rigidbody Rigidbody of same gameobject as collider. 
	 *
	 * \return Postion of collider.
	 */
	vec2 current_position(vec2 collider_offset, const Transform& transform, const Rigidbody& rigidbody);

private:// handeling

	/**
	 * \brief Calculates the position of the Collider
	 * 
	 * Using the \c Collider offset, \c Transform position and \c Rigidbody offset the place of the collider is calculated.
	 *
	 * \param collider_offset Collider offset value.
	 * \param transform Transform of same gameobject as collider.
	 * \param rigidbody Rigidbody of same gameobject as collider. 
	 *
	 * \return Postion of collider.
	 */
	void collision_handler_request(CollidedInfoStor& data1,CollidedInfoStor& data2);

	/**
	 * \brief Calculates the move back value and direction of the Collision
	 * 
	 * Uses data from both gameobjects to calculate the value of the gameobject to move out of other collider. 
	 *
	 * \param data1 Has data about the first gameobject of the collision
	 * \param data2 Has data about the second gameobject of the collision
	 * \param type Type of collider pair used for variant
	 *
	 * \return Move back value and direction for first gameobject
	 */
	std::pair<vec2,Direction> collision_handler(CollidedInfoStor& data1,CollidedInfoStor& data2 ,ColliderStorType type);

	/**
	 * \brief Calculates the move back value for box box collision
	 * 
	 * Uses both collider and positions to calculate move back value 
	 *
	 * \param box_collider1 First boxcollider of collision
	 * \param box_collider2 Second boxcollider of collision
	 * \param position1 Position of first boxcollider
	 * \param position2 Position of second boxcollider
	 *
	 * \return Move back value and direction for first gameobject
	 */
	vec2 box_box_move_back(const BoxCollider& box_collider1,const BoxCollider& box_collider2,vec2 position1,vec2 position2);

	/**
	 * \brief Determines what collision handler is called
	 * 
	 * If the object is static is does nothing.
	 * If the object is dynamic and collides with not static object it calls the script collision handeler.
	 * If the object is dynamic and collides with static it handles it and calls the script collision handeler.
	 *
	 * \param info Collision info of both gameobjects
	 */
	void determine_collision_handler(CollisionInfo& info);

	/**
	 * \brief handles static collision
	 * 
	 * Moves the object back out of static gameobject.
	 * If bounce is active change velocity.
	 *
	 * \param info Collision info of both gameobjects
	 */
	void static_collision_handler(CollisionInfo& info);
private: // detection
	
	/**
	 * \brief Checks if there is an collision between two colliders
	 * 
	 * Does not use the type of a collider to determine if there is collision.
	 * uses variant with comment data to determine if even collision needs to be checked.
	 *
	 * \param colliders Holds all colliders
	 *
	 * \return Move back value and direction for first gameobject
	 */
	std::vector<std::pair<CollidedInfoStor,CollidedInfoStor>> check_collisions(std::vector<collider_stor> & colliders);

	/**
	 * \brief Calls the correct check collision function.
	 * 
	 * Uses the type to check what colliders are used, converts the colliders and calls the check function.
	 *
	 * \param collider1 First collider
	 * \param components1 Transform and rigidbody from first object
	 * \param collider2 Second collider
	 * \param components2 Transform and rigidbody from second object
	 * \param type Type of collider pair
	 *
	 * \return status of collision
	 */
	bool check_collision(const collider_stor& collider1,std::pair<std::reference_wrapper<Transform>, std::reference_wrapper<Rigidbody>> components1,const collider_stor& collider2,std::pair<std::reference_wrapper<Transform>, std::reference_wrapper<Rigidbody>> components2,CollisionSystem::ColliderStorType type);
	
	/**
	 * \brief Check collision for box on box collider
	 *
	 * \param box1 First collider
	 * \param box2 Second collider
	 * \param transform1 Transform of first object
	 * \param transform2 Transform of second object
	 * \param rigidbody1 Rigidbody of first object
	 * \param rigidbody2 Rigidbody of second object
	 *
	 * \return status of collision
	 */
	bool check_box_box_collision(const BoxCollider& box1, const BoxCollider& box2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2);
	
	/**
	 * \brief Check collision for box on circle collider
	 *
	 * \param box1 First collider
	 * \param circle2 Second collider
	 * \param transform1 Transform of first object
	 * \param transform2 Transform of second object
	 * \param rigidbody1 Rigidbody of first object
	 * \param rigidbody2 Rigidbody of second object
	 *
	 * \return status of collision
	 */
	bool check_box_circle_collision(const BoxCollider& box1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2);

	/**
	 * \brief Check collision for circle on circle collider
	 *
	 * \param circle1 First collider
	 * \param circle2 Second collider
	 * \param transform1 Transform of first object
	 * \param transform2 Transform of second object
	 * \param rigidbody1 Rigidbody of first object
	 * \param rigidbody2 Rigidbody of second object
	 *
	 * \return status of collision
	 */
	bool check_circle_circle_collision(const CircleCollider& circle1, const CircleCollider& circle2, const Transform& transform1, const Transform& transform2, const Rigidbody& rigidbody1, const Rigidbody& rigidbody2);
};

} // namespace crepe