简体   繁体   English

多边形碰撞检测实现

[英]Polygon collision detection implementation

I'm trying to write my own implementation of separating axis theorem but I'm have some trouble getting it to work as accurately as I want. 我正在尝试编写自己的分离轴定理的实现,但要使其尽可能准确地工作却有些麻烦。 I can't say for sure, but it looks like it's saying there's a collision when an imaginary box around the shapes collide like in the first shape. 我不能肯定地说,但是看起来像是当形状周围的假想框像第一个形状发生碰撞时发生碰撞。 But the second shape works perfectly. 但是第二种形状效果很好。

Here's the vertex data for the square (exact coordinates): 这是正方形的顶点数据(精确坐标):

vertsx = [ 200, 220, 220, 200 ]
vertsy = [ 220, 220, 200, 200 ]

Here's the vertex data for test shape 1 (relative to mouse): 这是测试形状1(相对于鼠标)的顶点数据:

vertsx = [ -10,   0,  10, 10, -10 ]
vertsy = [ -10, -50, -10, 10,  10 ]

And lastly here's the vertex data for test shape 2 (relative to mouse): 最后是测试形状2(相对于鼠标)的顶点数据:

vertsx = [ -10,   0,  10, 10, -10 ]
vertsy = [ -10, -20, -10, 10,  10 ]

Just for clarification the translated coordinates are the ones that are tested and these have shapes have been tested with the coordinates ordered as shown. 为了澄清起见,平移的坐标是经过测试的坐标,并且这些图形的形状已经按照所示的顺序进行了坐标测试。

在此处输入图片说明

Here's the actual function. 这是实际功能。

function collisionConvexPolygon ( vertsax, vertsay, vertsbx, vertsby ) {
    var alen = vertsax.length;
    var blen = vertsbx.length;
    // Loop for axes in Shape A
    for ( var i = 0, j = alen - 1; i < alen; j = i++ ) {
        // Get the axis
        var vx =    vertsax[ j ] - vertsax[ i ];
        var vy = -( vertsay[ j ] - vertsay[ i ] );
        var len = Math.sqrt( vx * vx + vy * vy );

        vx /= len;
        vy /= len;

        // Project shape A
        var max0 = vertsax[ 0 ] * vx + vertsay[ 0 ] * vy, min0 = max0;
        for ( k = 1; k < alen; k++ ) {
            var proja = vertsax[ k ] * vx + vertsay[ k ] * vy;

            if ( proja > max0 ) {
                max0 = proja;
            }
            else if ( proja < min0 ) {
                min0 = proja;
            }
        }
        // Project shape B
        var max1 = vertsbx[ 0 ] * vx + vertsby[ 0 ] * vy, min1 = max1;
        for ( var k = 1; k < blen; k++ ) {
            var projb = vertsbx[ k ] * vx + vertsby[ k ] * vy;

            if ( projb > max1 ) {
                max1 = projb;
            }
            else if ( projb < min1 ) {
                min1 = projb;
            }
        }
        // Test for gaps
        if ( !axisOverlap( min0, max0, min1, max1 ) ) {
            return false;
        }
    }
    // Loop for axes in Shape B (same as above)
    for ( var i = 0, j = blen - 1; i < blen; j = i++ ) {
        var vx =    vertsbx[ j ] - vertsbx[ i ];
        var vy = -( vertsby[ j ] - vertsby[ i ] );
        var len = Math.sqrt( vx * vx + vy * vy );

        vx /= len;
        vy /= len;

        var max0 = vertsax[ 0 ] * vx + vertsay[ 0 ] * vy, min0 = max0;
        for ( k = 1; k < alen; k++ ) {
            var proja = vertsax[ k ] * vx + vertsay[ k ] * vy;

            if ( proja > max0 ) {
                max0 = proja;
            }
            else if ( proja < min0 ) {
                min0 = proja;
            }
        }
        var max1 = vertsbx[ 0 ] * vx + vertsby[ 0 ] * vy, min1 = max1;
        for ( var k = 1; k < blen; k++ ) {
            var projb = vertsbx[ k ] * vx + vertsby[ k ] * vy;

            if ( projb > max1 ) {
                max1 = projb;
            }
            else if ( projb < min1 ) {
                min1 = projb;
            }
        }
        if ( !axisOverlap( min0, max0, min1, max1 ) ) {
            return false;
        }
    }
    return true;
}

I'll try other shapes if you need me to. 如果您需要,我会尝试其他形状的。

Here's my axisOverlap function. 这是我的axisOverlap函数。

function axisOverlap ( a0, a1, b0, b1 ) {
    return !( a0 > b1 || b0 > a1 );
}

I figured it out! 我想到了!

I began plotting number lines on paper and realized the problem was that my axes weren't calculated correctly. 我开始在纸上画数字线,意识到问题是我的轴计算不正确。 To calculate a perpendicular vector you need to swap the x and y coordinates and THEN invert one, I completely forgot to swap the coordinates. 要计算垂直向量,您需要交换x和y坐标 ,然后将其求反,我完全忘记了交换坐标。

The new code 新密码

var vx =    vertsay[ i ] - vertsay[ j ];
var vy = -( vertsax[ i ] - vertsax[ j ] );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM