-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathcollisiondetector.h
250 lines (174 loc) · 7.25 KB
/
collisiondetector.h
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
/*
Created by Fabrizio Di Vittorio ([email protected]) - <http://www.fabgl.com>
Copyright (c) 2019-2022 Fabrizio Di Vittorio.
All rights reserved.
* Please contact [email protected] if you need a commercial license.
* This library and related software is available under GPL v3.
FabGL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
FabGL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FabGL. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
/**
* @file
*
* @brief This file contains fabgl::CollisionDetector class definition
*/
#include <stdint.h>
#include <stddef.h>
#include "fabglconf.h"
#include "displaycontroller.h"
namespace fabgl {
class CollisionDetector;
class QuadTree;
struct QuadTreeObject {
QuadTree * owner;
QuadTreeObject * next;
Sprite * sprite;
QuadTreeObject(QuadTreeObject * next_, Sprite * sprite_)
: owner(nullptr), next(next_), sprite(sprite_)
{
}
};
#define QUADTREE_LEVEL_SPLIT_THRESHOLD 3
enum QuadTreeQuadrant {
TopLeft,
TopRight,
BottomLeft,
BottomRight,
None,
};
typedef void (*CollisionDetectionCallback)(void * callbackObj, Sprite * spriteA, Sprite * spriteB, Point collisionPoint);
class QuadTree {
public:
QuadTree(CollisionDetector * collisionDetector, QuadTree * parent, QuadTreeQuadrant quadrant, int x, int y, int width, int height);
void insert(QuadTreeObject * object);
static void remove(QuadTreeObject * object);
//void dump(int level = 0);
QuadTreeObject * detectCollision(QuadTreeObject * object, CollisionDetectionCallback callbackFunc = nullptr, void * callbackObj = nullptr);
bool isEmpty();
void detachFromParent();
static void update(QuadTreeObject * object);
private:
QuadTreeQuadrant getQuadrant(QuadTreeObject * object);
void createQuadrant(QuadTreeQuadrant quadrant);
bool objectsIntersect(QuadTreeObject * objectA, QuadTreeObject * objectB);
bool objectIntersectsQuadTree(QuadTreeObject * object, QuadTree * quadTree);
bool checkMaskCollision(QuadTreeObject * objectA, QuadTreeObject * objectB, Point * collisionPoint);
static bool objectInRect(QuadTreeObject * object, int x, int y, int width, int height);
CollisionDetector * m_collisionDetector;
QuadTree * m_parent;
QuadTreeQuadrant m_quadrant;
int m_x;
int m_y;
int m_width;
int m_height;
QuadTreeObject * m_objects;
int m_objectsCount;
QuadTree * m_children[4]; // index is Quadrant
};
/**
* @brief A class to detect sprites collisions.
*
* CollisionDetector uses a Quad-tree data structure to efficiently store sprites size and position and quick detect collisions.<br>
* CollisionDetector is embedded in Scene class, so usually you don't need to instantiate it.
*/
class CollisionDetector {
friend class QuadTree;
public:
/**
* @brief Creates an instance of CollisionDetector.
*
* CollisionDetector is embedded in Scene class, so usually you don't need to instantiate it.
*
* @param maxObjectsCount Specifies maximum number of sprites. This is required to size the underlying quad-tree data structure.
* @param width The scene width in pixels.
* @param height The scene height in pixels.
*/
CollisionDetector(int maxObjectsCount, int width, int height);
~CollisionDetector();
/**
* @brief Adds the specified sprite to collision detector.
*
* The collision detector is updated calling CollisionDetector.update() or CollisionDetector.updateAndDetectCollision().<br>
* The number of sprites cannot exceed the value specified in CollisionDetector constructor.
*
* @param sprite The sprite to add.
*/
void addSprite(Sprite * sprite);
/**
* @brief Removes the specified sprite from collision detector.
*
* @param sprite The sprite to remove.
*/
void removeSprite(Sprite * sprite);
/**
* @brief Detects first collision with the specified sprite.
*
* It is necessary to call CollisionDetector.update() before detectCollision() so sprites position and size are correctly updated.
*
* @param sprite The sprite to detect collision.
* @param removeCollidingSprites If true the collided sprites are automatically removed from the collision detector.
*
* @return The other sprite that collided with the specified sprite.
*/
Sprite * detectCollision(Sprite * sprite, bool removeCollidingSprites = true);
/**
* @brief Detects multiple collisions with the specified sprite.
*
* It is necessary to call CollisionDetector.update() before detectCollision() so sprites position and size are correctly updated.
*
* @param sprite The sprite to detect collision.
* @param callbackFunc The callback function called whenever a collision is detected.
* @param callbackObj Pointer passed as parameter to the callback function.
*/
void detectCollision(Sprite * sprite, CollisionDetectionCallback callbackFunc, void * callbackObj);
/**
* @brief Updates collision detector.
*
* When a sprite changes its position or size it is necessary to update the collision detector.<br>
* This method just updates the detector without generate collision events.
*
* @param sprite The sprite to update.
*/
void update(Sprite * sprite);
/**
* @brief Updates collision detector and detect collision with the specified sprite.
*
* When a sprite changes its position or size it is necessary to update the collision detector.<br>
* This method updates the detector and detects collisions.
*
* @param sprite The sprite to update and to check for collisions.
* @param removeCollidingSprites If true the collided sprites are automatically removed from the collision detector.
*
* @return The other sprite that collided with the specified sprite.
*/
Sprite * updateAndDetectCollision(Sprite * sprite, bool removeCollidingSprites = true);
/**
* @brief Updates collision detector and detect multiple collisions with the specified sprite.
*
* When a sprite changes its position or size it is necessary to update the collision detector.<br>
* This method updates the detector and detects multiple collisions.
*
* @param sprite The sprite to update and to check for collisions.
* @param callbackFunc The callback function called whenever a collision is detected.
* @param callbackObj Pointer passed as parameter to the callback function.
*/
void updateAndDetectCollision(Sprite * sprite, CollisionDetectionCallback callbackFunc, void * callbackObj);
//void dump();
private:
QuadTree * initEmptyQuadTree(QuadTree * parent, QuadTreeQuadrant quadrant, int x, int y, int width, int height);
QuadTree * m_rootQuadTree;
QuadTree * m_quadTreePool;
int m_quadTreePoolSize;
QuadTreeObject * m_objectPool;
int m_objectPoolSize;
};
} // end of namespace