簡體   English   中英

多邊形碰撞檢測實現

[英]Polygon collision detection implementation

我正在嘗試編寫自己的分離軸定理的實現,但要使其盡可能准確地工作卻有些麻煩。 我不能肯定地說,但是看起來像是當形狀周圍的假想框像第一個形狀發生碰撞時發生碰撞。 但是第二種形狀效果很好。

這是正方形的頂點數據(精確坐標):

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

這是測試形狀1(相對於鼠標)的頂點數據:

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

最后是測試形狀2(相對於鼠標)的頂點數據:

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

為了澄清起見,平移的坐標是經過測試的坐標,並且這些圖形的形狀已經按照所示的順序進行了坐標測試。

在此處輸入圖片說明

這是實際功能。

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;
}

如果您需要,我會嘗試其他形狀的。

這是我的axisOverlap函數。

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

我想到了!

我開始在紙上畫數字線,意識到問題是我的軸計算不正確。 要計算垂直向量,您需要交換x和y坐標 ,然后將其求反,我完全忘記了交換坐標。

新密碼

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