簡體   English   中英

JavaScript Circle碰撞檢測錯誤

[英]JavaScript Circle Collision Detection Bug

我在做學校項目時所做的圓圈/球碰撞模擬中遇到了這個奇怪的錯誤。 我可能還會補充一點,我有點菜鳥,我已經編程了大約一年。

直到我在畫布上填充了很多圓圈之后,這些碰撞才能正常工作。 我真的不明白為什么。 25個圓圈可以正常工作,但是當我增加到50個時,圓圈開始變得越野車。

正如您在下面的鏈接中看到的那樣,經過一段時間並像瘋了似的旋轉后,圓圈開始相互依存,這不是我想發生的事情。

50個圓圈的示例: https : //dl.dropboxusercontent.com/u/9069602/circles/vers1/collisions.html

我的猜測是,隨着圓與圓之間的間距減小,圓彼此相接的風險更大,但似乎在開始模擬時它們具有足夠的間距。 我使用nextY / nextX位置變量在發生實際碰撞之前一幀計算碰撞。 這也可能是錯誤的來源。 我真的無法將矛頭指向開始調試。

這是50個圓的情況的代碼: https : //dl.dropboxusercontent.com/u/9069602/circles/vers1/circle.js

// Returns true if two circles are overlapping
function overlapDetection( circle1, circle2 ) {
    var returnValue = false;
    var dx = circle1.nextX - circle2.nextX;
    var dy = circle1.nextY - circle2.nextY;
    var distance = ( dx * dx + dy * dy );

    if ( distance <= ( circle1.radius + circle2.radius ) * ( circle1.radius + circle2.radius ) ) {
        returnValue = true;
    }
    return returnValue; 
}

function collide() {
    var circle;
    var testCircle;
    var returnValue = false;

    for ( var i = 0; i < circles.length; i += 1 ) {
        circle = circles[i];
        for ( var j = i + 1; j < circles.length; j += 1 ) {
            testCircle = circles[j];
            if ( overlapDetection( circle, testCircle ) ) {
                collideCircles( circle, testCircle );
                collideCircle1 = circle.id;
                collideCircle2 = testCircle.id;
                returnValue = true;
            }
        }
    }
    return returnValue;
}

function collideCircles( circle1, circle2 ) {

    var dx = circle1.nextX - circle2.nextX;
    var dy = circle1.nextY - circle2.nextY;
    var collisionAngle = Math.atan2( dy, dx );

    var speed1 = Math.sqrt( circle1.velocityX * circle1.velocityX + circle1.velocityY * circle1.velocityY );
    var speed2 = Math.sqrt( circle2.velocityX * circle2.velocityX + circle2.velocityY * circle2.velocityY );

    var direction1 = Math.atan2( circle1.velocityY, circle1.velocityX );
    var direction2 = Math.atan2( circle2.velocityY, circle2.velocityX );

    var rotatedVelocityX1 = speed1 * Math.cos( direction1 - collisionAngle );
    var rotatedVelocityY1 = speed1 * Math.sin( direction1 - collisionAngle );
    var rotatedVelocityX2 = speed2 * Math.cos( direction2 - collisionAngle );
    var rotatedVelocityY2 = speed2 * Math.sin( direction2 - collisionAngle );

    var finalVelocityX1 = ( ( circle1.mass - circle2.mass ) * rotatedVelocityX1 + ( circle2.mass + circle2.mass ) * rotatedVelocityX2 ) / ( circle1.mass + circle2.mass );
    var finalVelocityX2 = ( (circle1.mass + circle1.mass ) * rotatedVelocityX1 + ( circle2.mass - circle1.mass ) * rotatedVelocityX2 ) / ( circle1.mass + circle2.mass );

    var finalVelocityY1 = rotatedVelocityY1;
    var finalVelocityY2 = rotatedVelocityY2;

    circle1.velocityX = Math.cos( collisionAngle ) * finalVelocityX1 + Math.cos( collisionAngle + Math.PI / 2 ) * finalVelocityY1;
    circle1.velocityY = Math.sin( collisionAngle ) * finalVelocityX1 + Math.sin( collisionAngle + Math.PI / 2 ) * finalVelocityY1;
    circle2.velocityX = Math.cos( collisionAngle ) * finalVelocityX2 + Math.cos( collisionAngle + Math.PI / 2 ) * finalVelocityY2;
    circle2.velocityY = Math.sin( collisionAngle ) * finalVelocityX2 + Math.sin( collisionAngle + Math.PI / 2 ) * finalVelocityY2;

    circle1.nextX += circle1.velocityX;
    circle1.nextY += circle1.velocityY;
    circle2.nextX += circle2.velocityX;
    circle2.nextY += circle2.velocityY;
}

我希望我對這個問題很清楚。

提前致謝!

您的問題有兩個。

您的collideCircles(circle1, circle2)假設circle1circle2將在下一個坐標處發生碰撞,這由collide()保證,並且不會與當前坐標發生碰撞(請參閱如何計算collisionAngle ),這可能根本不正確。 這就是為什么您的圈子彼此重疊時會被“卡住”的原因。

如果說collideCircles(circle1, circle2)collideCircles(circle3, circle4)反彈circle2circle4以便它們的下一個坐標彼此collideCircles(circle1, circle2)則圓可以彼此collideCircles(circle1, circle2) 但是,碰撞檢測循環已經越過了它們,它們的碰撞不會被拾取,並且圓圈將快樂地彼此重疊。

假設您已經開發了鉸鏈接頭! =)實際上可能存在幾個問題。 例如:當您檢查自由空間時,另一個圓圈已經可以占據它; 我認為接下來是這種情況:假設有兩個圓圈

r=1; y =0;
circle1.x = 1, circle2.x =4;

檢查下一步:

circle1.canMoveToX(2) //=> true; coz border will move to x=3 it's empty at the moment;
circle2.canMoveToX(3)  // => true; coz border will move to x=2 it's empty at the moment;

在這一步,他們加入了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM