Javascript 为什么圆在碰撞(画布)上振动

Javascript 为什么圆在碰撞(画布)上振动,javascript,canvas,Javascript,Canvas,我一直在创建一个agar.io的克隆,我不明白为什么圆圈在彼此接触时开始振动。下面是我的代码: var 帆布, ctx, 宽度=内部宽度, 高度=内部高度, mouseX=0, mouseY=0; 变量 摄像机={ x:0,, y:0, 更新:功能(obj){ 此.x=对象x-宽度/2; 此.y=对象y-高度/2; } }, 玩家={ 质量:54,, x:0,, y:0, 斑点:[], 更新:函数(){ for(var i=0;i

我一直在创建一个agar.io的克隆,我不明白为什么圆圈在彼此接触时开始振动。下面是我的代码:

var
帆布,
ctx,
宽度=内部宽度,
高度=内部高度,
mouseX=0,
mouseY=0;
变量
摄像机={
x:0,,
y:0,
更新:功能(obj){
此.x=对象x-宽度/2;
此.y=对象y-高度/2;
}
},
玩家={
质量:54,,
x:0,,
y:0,
斑点:[],
更新:函数(){
for(var i=0;ithis.blobs[j].x){
this.blobs[i].x++;
}
if(this.blobs[i].ythis.blobs[j].y)){
this.blobs[i].y++;
}
}
}
}
}
这个.x+=(mouseX-width/2)/(width/2)*1;
此.y+=(鼠标-高度/2)/(高度/2)*1
},
拆分:函数(单元){
cell.mass/=2;
这个,滴,推({
x:cell.x,
y:手机,y,
质量:cell.mass
});
},
绘图:函数(){
for(var i=0;i
正文{
保证金:0;
填充:0;
}
请更新您的浏览器。
分隔圆圈 你的分离码不正确。使用它们之间的向量来获得新的位置

它们之间的向量 若要确定两个圆是否截取,请确定向量从一个到下一个的长度

两个圆圈

var cir1 = {x : 100, y : 100, r : 120}; // r is the radius
var cir2 = {x : 250, y : 280, r : 150}; // r is the radius
cir2
cir1

var vx = cir2.x - cir1.x;
var vy = cir2.y - cir1.y;
向量的长度

var len = Math.sqrt(x * x + y * y);
// or use the ES6 Math.hypot function
/* var len = Math.hypot(x,y); */
如果半径之和大于圆之间向量的长度,则圆重叠

if(cir1.r + cir2.r > len){ // circles overlap
使向量正常化 如果它们重叠,则需要将其中一个从另一个移开。有很多方法可以做到这一点,最简单的方法是沿着它们之间的直线移动一个圆

首先,通过除以向量长度,将向量从
cir1
标准化为
cir2

请注意,长度可以为零。如果发生这种情况,您将在进一步计算中得到
NaN
。如果你怀疑你可能会在同一个位置得到一个圆作为另一个最简单的方法来处理零移动一个圆一点

    // replace the two lines above with
    if(len === 0){ // circles are on top of each other
        vx = 1;  // move the circle (abstracted into the vector)
    }else{
        vx \= len;  // normalise the vector
        vy \= len;
    }
移动圆圈以仅接触 现在你有了1个单位长的归一化向量,你可以通过将两个标量乘以所需的长度,使其成为你需要的任意长度,在这种情况下,这两个标量是两个圆半径的总和

    var mx = vx * (cir1.r + cir2.r);  // move distance
    var my = vy * (cir1.r + cir2.r);
.仅使用以下方法之一

现在,您可以将其中一个圆定位到正确的距离,以便它们刚好接触

   // move cir1
   cir1.x = cir2.x - mx;
   cir1.y = cir2.y - my;

移动第二个圆

   cir2.x = cir1.x + mx;
   cir2.y = cir1.y + my;

移动两个圆,但必须首先找到两个圆之间的比例中心

   var pLen = cir1.r / (cir1.r + cir2.r); // find the ratio of the radii
   var cx = cir1.x + pLen * vx * len;  // find the proportional center between
   var cy = cir1.y + pLen * vy * len;  // the two circles     
然后将两个圆的半径从该点移开

   cir1.x = cx - vx * cir1.r;     // move circle 1 away from the shared center
   cir1.y = cy - vy * cir1.r;     
   cir2.x = cx + vx * cir2.r;     // move circle 2 away from the shared center
   cir2.y = cy + vy * cir2.r;     
演示 使用mods复制OP的代码片段,通过将第一个圆
blob1
从第二个圆
blob2
移开并假设它们永远不会在同一个点(不除以零)来解决问题

var
帆布,
ctx,
宽度=内部宽度,
高度=内部高度,
mouseX=0,
mouseY=0;
变量
摄像机={
x:0,,
y:0,
更新:功能(obj){
此.x=对象x-宽度/2;
此.y=对象y-高度/2;
}
},
玩家={
质量:54,,
x:0,,
y:0,
斑点:[],
更新:函数(){
for(var i=0;i   cir1.x = cx - vx * cir1.r;     // move circle 1 away from the shared center
   cir1.y = cy - vy * cir1.r;     
   cir2.x = cx + vx * cir2.r;     // move circle 2 away from the shared center
   cir2.y = cy + vy * cir2.r;