检查两个圆之间的距离

Checking Distance Between Two Circles

所以我有这段代码可以创建多个球,它们获得随机的 x、y 和速度,它们只是在屏幕上弹跳,这部分效果很好,但我想要更多。我一直在想办法让它们在相反的方向发生碰撞和反弹。我一直在试图弄清楚我做错了什么,但我已经花了大约 30 分钟才弄清楚,有什么建议吗?

var canvas = document.getElementById('gamecanvas');
var c = canvas.getContext('2d');

var ma = Math.random;
var mo = Math.round;

var ballcount = 5;
var balls = [];

function setup() {

    //canvas
    canvas.height = window.innerHeight;
    canvas.width = window.innerWidth;

    for (i = 0; i < ballcount; i++) {

        //ball setup
        r = mo(ma() * 40) + 10;
        y = mo(ma() * (canvas.height - r));
        x = mo(ma() * (canvas.width - r));
        vx = mo(ma() * 20) - 10;
        vy = mo(ma() * 20) - 10;
        balls[i] = { x, y, vx, vy, r };

    }
}

function gameloop() {

    //clear
    c.clearRect(0, 0, canvas.width, canvas.height);
    c.strokeStyle = 'white';

    //move
    for (i = 0; i < ballcount; i++) {

        balls[i].x += balls[i].vx;
        balls[i].y += balls[i].vy;

        //wall collision

        if (balls[i].x <= balls[i].r) {
            balls[i].x = balls[i].r;
            balls[i].vx *= -1;
        }
        if (balls[i].y <= balls[i].r) {
            balls[i].y = balls[i].r;
            balls[i].vy *= -1;
        }
        if (balls[i].x >= canvas.width - balls[i].r) {
            balls[i].x = canvas.width - balls[i].r;
            balls[i].vx *= -1;
        }
        if (balls[i].y >= canvas.height - balls[i].r) {
            balls[i].y = canvas.height - balls[i].r;
            balls[i].vy *= -1;
        }

        //ball collision
        for (j = 0; j < ballcount; j++) {
            if(i != j) {
                
                dx = balls[j].x - balls[i].x;
                dy = balls[j].y - balls[i].y;
                rs = balls[j].r + balls[i].r;
                
                if(Math.sqrt((dx * dx) - (dy * dy)) < rs) {
                    balls[i].vx *= -1;
                    balls[j].vx *= -1;
                }
            }
        }
    }

    //draw
    c.beginPath();
    for (i = 0; i < ballcount; i++) {

        c.moveTo(balls[i].x + balls[i].r, balls[i].y);
        c.arc(balls[i].x, balls[i].y, balls[i].r, 0, 7);

    }
    c.stroke();
}

setup();
setInterval(gameloop, 1000 / 60);
body {
    background-color: black;
    overflow: hidden;
    margin: 0;
}
<!DOCTYPE html>

<html>
    
    <head>
        
        <link rel="stylesheet" href="index.css">
        <title>Bslls</title>
        
    </head>
    
    <body id="body">
        <canvas id="gamecanvas"></canvas>
        <script src="index.js"></script>
        
    </body>
    
</html>

我过去曾尝试做类似的事情,我遇到了一些用 js 模拟物理的库,其中之一是 http://wellcaffeinated.net/PhysicsJS/。 这是一个简单的图书馆。

提示:

有两个子问题:找到碰撞点和反映轨迹。

要找到碰撞点,可以这样推理:

  • 将一个球膨胀另一个球的半径,让另一个球缩小为一个点;

  • 考虑小球与点的相对速度(即向量差),将小球移至原点

现在你有一个固定的圆和一个沿直线移动的点。您可以通过求解二次方程找到圆和线之间的第一个交点。最方便的是使用点运动的参数方程与圆的隐式方程。同样的价格,你得到会议时间。

为了反映轨迹,考虑交点圆的法线是入射方向和反射方向的平分线。在完美弹性冲击的情况下,反射后的速度与之前相同。

现在通过撤销初始变换,您可以找到两个球的交点和新方向。

一点向量微积分:-)

你必须检查两个球之间的距离是否小于它们的半径之和。


//let b1 be ball-1 and b2 be ball-2

var distance = Math.sqrt((b2.x - b1.x) ** 2 + (b2.y - b1.y) ** 2);
if(b1.r + b2.r <= distance) {

//colliding

}

但是在你的情况下,由于球在一个小space中移动得太快,你无法正确检测到碰撞。

也就是说,您的碰撞检测数学工作正常,问题是您无法在正确的时间检测到碰撞!

你的球会直线运动,所以考虑两个球在直线运动,你必须检查它们在相应运动线的任何部分时是否会碰撞。

将涉及一些更复杂的数学!