简体   繁体   中英

Problems with circle to circle collision in clusters

I am making a game, similar to agar.io, and am working on adding collision to my gameobjects, which all consist of circles. The collision system works pretty well sometimes, but as soon as I get more than 2 in a tight cluster things start getting very glitchy and jittery. Even occasionally when only having 2 they jump arround sporadically. I think the fact that I am trying to move these cells while checking for the collisions is part of the problem, but thats hard to test for.

I am working with Sockets.io, Node.js, and a drawing library called P5.js. The collision is all being handled server side, but the movement of the cells is handled client side.

On the server, the collision code

socket.on('update', msgUpdate)
    function msgUpdate(data){
    var cell

    //finds the cell that we want to update
    for(var si=0; si<cells.length; si++){   
        if(socket.id + data.di == cells[si].id){
        cell = cells[si];               
        }       
    }

    //the collision system
    for(var i = cells.length-1; i>=0; i--){
        var dx = cell.x - cells[i].x;
        var dy = cell.y - cells[i].y;
        var distance = Math.sqrt(dx * dx + dy * dy);
        if(distance < cell.r + cells[i].r && cell.r > cells[i].r){
            var unitX = dx/distance;
            var unitY = dy/distance;

            cell.x = cells[i].x + (cell.r + cells[i].r + 1) * unitX;
            cell.y = cells[i].y + (cell.r + cells[i].r + 1) * unitY;
       }
    }
}

On the client

//myCells is an array of Cell objects, all of which you control
for(var i = myCells.length-1; i>=0; i--){
    myCells[i].move();
    var data = {
        x: myCells[i].pos.x,
        y: myCells[i].pos.y,
        r: myCells[i].r,
        c: myCells[i].c,
        di: myCells[i].id
    }
    socket.emit('update', data);
}

And the client side movement script, within the Cell object


this.move = function(){
    for(var ii = myCells.length-1; ii>=0; ii--){
        var velocity = createVector(mouseX - width/2 + (myCells[ii].pos.x - this.pos.x), mouseY-height/2 + (myCells[ii].pos.y - this.pos.y));
    }
    var sub = this.r * 0.03;
    velocity.setMag((6 - sub));
    this.pos.add(velocity);
}

The client could send inputs(mouse position) and all the tracking is handled by the server and the server answer back the positions of where to draw things. That way you broadcast an update when all the cells are check for collision and it can be at periodically (like frame rate). The client only task is to render the given data and tell the position of the mouse.

Also, I would recommend avoiding creating new variables in loops.

    let dx;
    let dy;
    let distance;
    let i;
    let unitX;
    let unitY;
    //the collision system
    for(i = cells.length-1; i>=0; i--){
        dx = cell.x - cells[i].x
        dy = cell.y - cells[i].y;
        distance = Math.sqrt(dx * dx + dy * dy);
        if(distance < cell.r + cells[i].r && cell.r > cells[i].r){
            unitX = dx/distance;
            unitY = dy/distance;

            cell.x = cells[i].x + (cell.r + cells[i].r + 1) * unitX;
            cell.y = cells[i].y + (cell.r + cells[i].r + 1) * unitY;
       }
    }

Reusing variable help the performance of the code. Garbage collection and instantiation can be costly in loops.

Another tip to accelerate the check could be to check first if comparing the x and y distance with the radius. This avoids doing square root that can be also costly and not precise.

example if

c1.y=0
c1.x=0
c1.r=10

c2.y=0
c2.x=1000
c2.r=10

then they do not intersect

if(cell.r + cells[i].r < dx || cell.r + cells[i].r < dy ){
 //No intersection
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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