Thursday, January 10, 2019

2D Collision Detection Pt 1

Rectangle - Rectangle Collision Detection
For rectangle - rectangle collisions, a collision can be determined if there is an overlap in both dimensions.

Pseudo Code
bool Overlap(float _minA, float _maxA, float _minB, float _maxB)
{
    return _minB <= _maxA && _minA <= _maxB;
}

bool RectsCollide(Rect _rectA, Rect _rectB)
{
    float aLeft = _rectA.origin.x;
    float aRight = aLeft + _rectA.size.x;
    float bLeft = _rectB.origin.x;
    float bRight = bLeft + _rectB.size.x;

    float aBottom = _rectA.origin.y;
    float aTop = aBottom + _rectA.size.y;
    float bBottom = _rectB.origin.y;
    float bTop = bBottom + _rectB.size.y;

    return Overlap(aLeft, aRight, bLeft, bRight) && Overlap(aBottom, aTop, bBottom, bTop);
}

Circle - Circle Collision Detection
To detect circle-circle collisions, we must compare the distance between their centers and the sum of both circles radii. If the distance is less than the sum then there is a collision.

Pseudo Code
bool CircleCollide(Circle _circA, Circle _circB)
{
    float radiusSum = _circA.radius + _circB.radius;
    Vector2 distance = SubtractVectors(_circA.center, _circB.center);
    return VectorLength(distance) <= radiusSum;
}

Line - Line Collision Detection
Lines are endless and therefore there are only two scenarios where lines don't collide: when they are parallel and not equivalent.

Pseudo Code
Vector2 RotateVector90(Vector2 _vector)
{
    return new Vector2(-_vector.y, _vector.x);
}

bool ParallelVectors(Vector2 _vectorA, Vector2 _vectorB)
{
    Vector2 rotatedA = RotateVector90(_vectorA);
    return DotProduct(rotatedA, _vectorB) == 0;
}

bool EqualVectors(Vector2 _vectorA, Vector2 _vectorB)
{
    return (_vectorA.x - _vectorB.x == 0) && (_vectorA.y - _vectorB.y == 0)
}

bool EquivalentLines(Line _lineA, Line _lineB)
{
    if (!ParallelVectors(_lineA.direction, _lineB.direction))
    {
        return false;
    }

    Vector2 distance = SubtractVectors(_lineA.base, _lineB.base)
    return ParallelVectors(distance, a.direction);
}

bool LinesCollide(Line _lineA, Line _lineB)
{
    if (ParallelVectors(_lineA.direction, _lineB.direction))
    {
        return EquivalentLines(_lineA, _lineB);
    }
    else
    {
        return true;
    }
}

The function ParallelVectors() allows us to check for parallelism between two vectors and we know that if the returned value from a calculated dot product is 0 then the two vectors have a 90° angle between themselves. So we rotate one of the vectors by 90° and check their dot product to find out if they are parallel.

Equivalence in this scenario doesn't mean that the two lines are equal, in fact it means that the two lines have a parallel direction to each other and one of the base points is somewhere on the other line.

The function EquivalentLines() checks for parallelism, so if the lines are parallel we need to find out if the a base point of one line lies on the other line. This means that the distance vector is parallel to either lines.

The function LineCollide() checks if they are parallel and if that is the case then returns their equivalence. If they are not parallel then they do collide.

No comments:

Post a Comment