Collision System - hikawi/cc-sakura GitHub Wiki
Just like any game, this game also needs a system for checking for collisions.
Collision System
The ccsakura engine provides a simple 2D collision detection system (See engine/collision.h). This document provides a high-level overview for the system.
Core Concepts
The collision system is built upon a hierarchy of collider objects, each representing a distinct geometric shape for collision detection.
The collision Struct
When a collision check is performed, the result is encapsulated in a collision struct:
is_colliding: A boolean value (trueif a collision occurred,falseotherwise).depth: Adoubleindicating the penetration depth. This value represents how much the two colliders are overlapping. A positive value means overlap.normal: Avec2dthat defines the direction of the minimum separation needed to resolve the collision.
Collider Types
The engine supports the following 2D collider shapes:
aabb_collider(Axis-Aligned Bounding Box): A rectangular shape that is always aligned with the X and Y axes. Defined by itscenterandextents(half-width and half-height).obb_collider(Oriented Bounding Box): A rectangular shape that can be rotated to any angle. Defined by itscenter,extents, andangle.circle_collider: A circular shape. Defined by itscenterandradius.capsule_collider: A shape consisting of a line segment with a radius around it, effectively a "rounded rectangle" or two circles connected by a rectangle. Defined by two endpoints (p1,p2) and aradius.
Performing Collision Checks
To check for a collision between two objects, you will typically use the collides() method available on any collider object.
// Example: Checking collision between two AABBs
aabb_collider box1(center1, extents1);
aabb_collider box2(center2, extents2);
collision result = box1.collides(box2);
if (result.is_colliding) {
// A collision occurred!
// result.depth tells you how much they overlap.
// result.normal tells you the direction to push box1 to separate it from box2.
// E.g., box1.shift(result.normal * result.depth);
}
Understanding the Normal Vector
The normal vector returned by colliderA.collides(colliderB) consistently points from colliderA (the object on which collides was called) away from colliderB (the object passed as the argument).
This direction is critical for collision resolution. If you were to apply a force to separate the objects, colliderA would be pushed along result.normal, and colliderB would be pushed along -result.normal.
Collider Interaction Matrix
The engine provides specific collision algorithms for each pair of collider types. Some interactions leverage existing algorithms by transforming one or both colliders into a more straightforward representation.
| Collider Collision Type | Brief Description |
|---|---|
aabb_collider vs. aabb_collider |
Direct AABB vs AABB algorithm. |
aabb_collider vs. obb_collider |
Internally treats AABB as OBB with 0 angle, then uses OBB vs OBB. |
aabb_collider vs. circle_collider |
Direct AABB vs Circle algorithm. |
aabb_collider vs. capsule_collider |
Direct AABB vs Capsule algorithm. |
obb_collider vs. aabb_collider |
Internally treats AABB as OBB with 0 angle, then uses OBB vs OBB. |
obb_collider vs. obb_collider |
Direct OBB vs OBB (SAT) algorithm. |
obb_collider vs. circle_collider |
Transforms Circle into OBB's local space, then uses AABB vs Circle. |
obb_collider vs. capsule_collider |
Transforms Capsule into OBB's local space, then uses AABB vs Capsule. |
circle_collider vs. aabb_collider |
Reuses AABB vs Circle algorithm. |
circle_collider vs. obb_collider |
Reuses OBB vs Circle algorithm. |
circle_collider vs. circle_collider |
Direct Circle vs Circle algorithm. |
circle_collider vs. capsule_collider |
Direct Circle vs Capsule algorithm. |
capsule_collider vs. aabb_collider |
Reuses AABB vs Capsule algorithm. |
capsule_collider vs. obb_collider |
Reuses OBB vs Capsule algorithm. |
capsule_collider vs. circle_collider |
Reuses Circle vs Capsule algorithm. |
capsule_collider vs. capsule_collider |
Direct Capsule vs Capsule algorithm. |
This table shows that while a direct algorithm might exist for a pair (e.g., AABB vs. AABB), in other cases, one collider might be transformed or delegate the check to another collider type's algorithm to simplify the calculation (e.g., OBB vs. Circle transforms the circle to treat the OBB as an AABB in its local space).