Javascript - Circle-Circle Collision Issue

2019-02-19 12:28发布

I am making a game in HTML5, Canvas, and this is my code for resolving collision between two moving circles:

function resCCCol(a, b) {
    var dx = a.x - b.x;
    var dy = a.y - b.y;

    var dist = dx * dx + dy * dy;

    var vx = b.vx - a.vx;
    var vy = b.vy - a.vy;

    var dot = dx * vx + dy * vy;

    if (dot > 0) {
        var scale = dot / dist;

        var cx = dx * scale;
        var cy = dy * scale;

        var mass = a.r + b.r;

        var cw1 = 2 * b.r / mass;
        var cw2 = 2 * a.r / mass;

        a.vx += cw1 * cx
        a.vy += cw1 * cy
        b.vx -= cw2 * cx
        b.vy -= cw2 * cy
    }
}

If I set the coordinates so that the circles overlap but still have their velocity both at 0, the circles won't push out each other, that is the problem. How do I fix this?

EDIT: Fiddle: http://jsfiddle.net/yP7xf/2/, click "Glitch it!" to see the glitch, as you see they won't separate.

3条回答
beautiful°
2楼-- · 2019-02-19 12:43

When two circles overlap with no velocity your resCCCol() method won't work since dot is 0. Even if you change the if statement to execute on dot >= 0, you're still left with 0 velocity.

if (dot > 0) { //dot === 0
    var scale = dot / dist; //scale === 0

    var cx = dx * scale; //cx === 0
    var cy = dy * scale; //cy === 0

    var mass = a.r + b.r;

    var cw1 = 2 * b.r / mass;
    var cw2 = 2 * a.r / mass;

    a.vx += cw1 * cx // 0
    a.vy += cw1 * cy // 0
    b.vx -= cw2 * cx // 0
    b.vy -= cw2 * cy // 0
}

You should handle cases when dot === 0. The easiest way is to simply give them a set velocity when the velocity is 0:

if (dot > 0) { 
    ... 
} else {
    a.vx = 1;
    a.vy = 1;
    b.vx = -1;
    b.vy = -1;
}

This, of course, will only propel them away from each other towards opposite corners of the screen, but you could easily implement something that better adheres to the laws of physics (ignoring the fact that two objects can't take up the same space).

查看更多
再贱就再见
3楼-- · 2019-02-19 12:54

I'm not sure what the purpose of dot is (maybe I'm missing some maths knowledge here), but two circles colliding happens if dist < sum(radii). Should this occur, you should deflect the circles, but ensure they have at least some small speed to ensure they separate.

查看更多
成全新的幸福
4楼-- · 2019-02-19 13:00

It's not entirely clear what the best way to handle this would be, and I think it would be better to make sure you don't end up in this situation in the first place (by making sure they don't ever overlap with zero velocity), but a quick and dirty fix is to check dot === 0 and if so, give them some velocity. For example:

if (dot === 0) {
    // numbers pulled completely out of thin air...
    a.vx = 0.5;
    a.vy = 0.5;
    b.vx = -0.5;
    b.vy = -0.5;
}

http://jsfiddle.net/yP7xf/5/

Now what velocity should you give them? That's something you'll need to work out. Probably you want them to move apart so you can probably calculate some vector based on a line from the center of one to the center of the other and send one in one direction along that vector and the other in the other at whatever speed you think is appropriate. But if they are laid exactly on top of each other (centers at the same point), then you'll need to account for that case too.

查看更多
登录 后发表回答