2
\$\begingroup\$

I am having a bit of difficulty detecting collisions properly with separating axis theorem. My code seems to be giving a lot of false alarms. Also, I've looked into implementing sliding collisions with the data from the theorem.

This is the resource I used for this algorithm: https://stackoverflow.com/questions/115426/algorithm-to-detect-intersection-of-two-rectangles?rq=1

This is my code for detecting collisions:

// Note .boundingBox is a set of four vertices for each rectangle. It is:
// [Bottom Right, Bottom  Left, Top Left, Top Right]

// Also .edge is the set of four edges for each rectangle. It goes:
// [Bottom, Left, Top, Right]

// Only take two edges of each rectangle since two edges share each axis
var edges = this.edges.slice( 0, 2 ).concat( polygon.edges.slice( 0, 2 ) );

// Loop through the axes of both rectangles
for ( var i = 0; i < edges.length; i++ )
{
    var oppositeSides = true,

        // Convert the edge to an axis by finding its normal,
        // then convert the axis to a unit vector
        magnitude = i % 2 === 0 ? 50 : 25,
        normal = {
            x: -edges[ i ].y / magnitude,
            y: edges[ i ].x / magnitude
        },

        // Take one point on the current shape and find its projection onto the axis
        currentPoint = i < 2 ? this.boundingBox[ i ] : polygon.boundingBox[ i - 2 ],
        nextPoint = i < 2 ? this.boundingBox[ i + 2 ] : polygon.boundingBox[ i ],
        shape1Vector = {
            x: nextPoint.x - currentPoint.x,
            y: nextPoint.y - currentPoint.y
        },
        shape1DotProduct = shape1Vector.x * normal.x + shape1Vector.y * normal.y,
        shape1DotProductSign = shape1DotProduct >= 0;

    // Take all the points on the other shape and project their distance
    // onto the axis. If their dot product sign is opposite to the point
    // on the same shape, then there must be no collision
    for ( var j = 0; j < 4; j++ )
    {
        nextPoint = i < 2 ? polygon.boundingBox[ j ] : this.boundingBox[ j ];

        var shape2Vector = {
                x: nextPoint.x - currentPoint.x,
                y: nextPoint.y - currentPoint.y,
            },
            shape2DotProduct = shape2Vector.x * normal.x + shape2Vector.y * normal.y,
            shape2DotProductSign = shape2DotProduct >= 0;

        if ( shape2DotProductSign === shape1DotProductSign )
            oppositeSides = false;
    }

    if ( oppositeSides )
        return true;
}

return false;

Now for handling the sliding collisions, I attempted to project the rectangle's velocity vector onto the axis where there is the least overlap, then multiply that scalar dot product by the unit vector of the axis, but that seems to result in strange behaviour where the velocity goes to insane velocities.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.