20、《每周一点canvas动画》——桌球运动(2)

1. 二维碰撞解析

2. 代码实现

3. 粒子系统

4. 总结

2.代码优化

...
var vx0Final = ((ball0.mass - ball1.mass)*ball0.vx + 2 * ball1.mass * ball1.vx)/(ball0.mass +ball1.mass);
var vx1Final = ((ball1.mass - ball0.mass)*ball1.vx + 2 * ball0.mass * ball0.vx)/(ball0.mass +ball1.mass);
...



var vxTotal = ball0.vx - ball1.vx;         //速度方向相反所以相减
var vx0Final = ((ball0.mass - ball1.mass) * ball0.vx + 2 * ball1.mass * ball1.vx)/(ball0.mass + ball1.mass);      //只计算其中的一个速度
var vx1Final = vxTotal + vx0Final;        //另一个速度


3.代码实现

function ballCollsion(ball0, ball1){

dy = ball1.y - ball0.y,
dist = Math.sqrt(dx*dx + dy*dy); //用于距离的碰撞检测

//计算物体间的夹角，并得出坐标旋转所需要的sin,cos值
var angle = Math.atan2(dy, dx),
sin = Math.sin(angle),
cos = Math.cos(angle),
//ball0旋转后的坐标
x0 = 0,
y0 = 0,
//ball1旋转后的坐标
x1 = dx * cos + dy * sin,
y1 = dy * cos - dx * sin,
//ball0 旋转后的速度
vx0 = ball0.vx * cos + ball0.vy * sin,
vy0 = ball0.vy * cos - ball0.vx * sin,
//ball1 旋转后的速度
vx1 = ball1.vx * cos + ball1.vy * sin,
vy1 = ball1.vy * cos - ball1.vx * sin,

vxTotal = vx0 - vx1;
//带入公式计算碰撞后的速度
vx0 = ((ball0.mass - ball1.mass) * vx0 + 2 * ball1.mass * vx1) /(ball0.mass + ball1.mass);
vx1 = vxTotal + vx0;
x0 += vx0;
x1 += vx1;

var x0Final = x0 * cos - y0 * sin,
y0Final = y0 * cos + x0 * sin,
x1Final = x1 * cos - y1 * sin,
y1Final = y1 * cos + x1 * sin;
//调整球体实际上位于屏幕的位置
ball1.x = ball0.x + x1Final;
ball1.y = ball0.y + y1Final;
ball0.x = ball0.x + x0Final;
ball0.y = ball0.y + y0Final;
//素的旋转回去
ball0.vx = vx0 * cos - vy0 * sin;
ball0.vy = vy0 * cos + vx0 * sin;
ball1.vx = vx1 * cos - vy1 * sin;
ball1.vy = vy1 * cos + vx1 * sin;
}
}


4.粒子系统

   for(var ballA, i=0, len = numBalls - 1; i<len; i++){

ballA = balls[i];

for(var ballB, j=i+1; j<numBalls; j++){
ballB = balls[j];
checkCollision(ballA, ballB); //物体间的碰撞处理
drawLine(ballA, ballB);  //物体间连线画线
}
}

function drawLine(ball0, ball1){
var dx = ball1.x - ball0.x,
dy = ball1.y - ball0.y,
dist = Math.sqrt(dx*dx + dy*dy); //计算物体间的距离

if(dist < long){ //小于long画线
context.save();
context.strokeStyle = "rgba(255,255,255,0.3)";
context.beginPath();
context.moveTo(ball0.x, ball0.y);
context.lineTo(ball1.x, ball1.y);
context.closePath()
context.stroke()
context.restore();
}
}

function rotate(x, y, sin, cos, reverse){
return {
x: (reverse)?(x*cos + y*sin):(x*cos - y*sin),
y: (reverse)?(y*cos - x*sin):(y*cos + x*sin)
}
}


5.总结

//遵循动量守恒和能量守恒的碰撞后的速度大小
v0Final = ((m0 - m1)*v0 + 2*m1*v1) / (m0 + m1);
v1Final = ((m1 - m0)*v1 + 2*m0*v0) / (m0 + m1);

//精简版
var vxTotal = vx0 - vx1;
vx0 = ((ball0.mass - ball1.mass)*vx0 + 2*ball1.mass*vx1)/(ball0.mass + ball1.mass);
vx1 = vxTotal + vx0;

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120