Collisions
Why:
Whether it is for 2D or 3D games, collisions are used a lot.
Even the oldest games, like Tetris and Pacman, have some sort of collisions.
After all this time, developers have found ways to simulate even more complex collisions :
- Box2D is opensource and was made by Erin Catto, but is not 3D
- PhysX was made by NVidia, but was discontinued
- Bullet, a 3D opensource collision library
- Chaos, recently developed by Unreal Engine
- Havok, used by Nintendo, Ubisoft, and others, but being premium
- Jolt Physics, a new 3D opensource used Horizon Forbidden West
- And more…
However, since the old days, new ways to represent shapes are being used:
- 2D boxes, moving freely (example : Mario)
- 2D Sprite pixels, for pixel to pixel collisions
- Complex 2D shapes, with multiple points
- 3D triangles, the mainstream way to represent 3D models
- Sign Distance Functions, being mathematical expressions of a shape
- And even more…
The way to handle collisions is still evolving.
Some games also require custom collisions to be optimal.
Example : Minecraft only requires collisions between boxes and cylinders. The collision between chunks don’t even have to be tested.
How:
The collisions will be implemented that way (unless if specified otherwise):
struct ShapePair
{
Shape* shape1;
Shape* shape2;
};
class CollisionDetector
{
std::vector<Shape> registeredShapes;
BroadPhase broadPhase;
NarrowPhase narrowPhase;
void Register(const Shape& shape)
{
broadPhase.Register(shape);
}
void Unregister(const Shape& shape)
{
broadPhase.Unregister(shape);
}
void SimulateCollisions()
{
// A container of potentially colliding pairs
// Could return a std::vector, std::list, etc
auto& pairs = broadPhase.GetPotentiallyCollidingPairs();
for (ShapePair& pair : pairs)
{
CollisionInfo collisionInfo;
if (narrowPhase.AreShapesColliding(pair.shape1, pair.shape2, collisionInfo))
{
RunPhysicalResponse(pair.shape1, pair.shape2, collisionInfo);
}
}
}
};