首页 专题 H5案例 前端导航 UI框架

canvas动画包教不包会:撞球物理

作者:TG 日期: 2016-11-15 字数: 6526 阅读: 907
前面经过十章的学习,相信你已经可以实现很多动画了。在这一章中,我们要来学习较为复杂的物理知识(对于还记得物理老师教的知识的伙伴应该不难),当然,不仅仅是学习物理概念,而且是要在动画中实现。

这一章的内容:
  • 质量
  • 动量
  • 动量守恒

1、质量
在前面的章节中,我们介绍很多运动相关的知识:速度、加速度、向量、摩擦力、反弹、缓动、弹动及重力,可是,我们都没有考虑物理质量对运动的影响,在现实生活中,质量对运动的影响是很大的。

在物理上,质量是指物体保持运动速度的能力。物体的质量越大,就越难以改变物体的运动状态(减速、加速或改变方向)。在地球上,我们通常认为质量就代表物体有多重。物体的质量越大,重量也就是越大。

质量与加速度、外力也有关系。物体的质量越大,就需要对它施加越大的外力来产生一定的加速度(这在生活中很明显,比如:推动一辆自行车和推动一辆汽车需要的力的差别是巨大的),方程式如下:

F = m × a


2、动量
动量是指运动物体的作用效果,它是物体的质量与速度的乘积。动量用字母p来表示,质量用m表示,公式如下:

p = m × v

这意味着,一个质量小、速度大的物体可以和另一个质量大、速度小的物体拥有差不多的动量。

注意:由于速度是一个向量(方向和大小),所以动量也是一个向量,方向与速度向量的方向相同。

3、动量守恒
前面我们已经介绍过碰撞检测以及碰撞后产生的效果。动量守恒是制作真实的碰撞效果的基本原理。

假如已知碰撞前每个物体的质量以及速度大小和方向,我们就能计算出它们碰撞后的速度大小和运动方向,这就是动量守恒的作用。

在物理上,有一个“动量守恒定理”的概念,它的意思是:系统在碰撞前的总动量等于系统在碰撞后的总动量。这里的系统又指的是什么呢?是指一些拥有动量的物体的集合。在这章中,我们只考虑两个物体碰撞后的反应,所以系统就是物体A和物体B。

从动量公式和动量守恒定理中,我们可以得出下面的公式1(相对两个物体object0和object1):

(m0 × v0) + (m1 × v1) = (m0 × v01) + (m1 × v11)

v01v11分别是object0和object1碰撞后的速度,要求得这两个速度向量,我们还必须借助动能公式:

EK = m × v^2 × 0.5 

v^2是v的平方积。
系统在碰撞前后的动能也是相同的,得到公式2

(0.5 × m0 × v0^2) + (0.5 × m1 × v1^2) = (0.5 × m0 × v01^2) + (0.5 × m1 × v11^2)

由上面的公式1公式2,我们可以得出:

v01 = ((m0 - m1) × v0 + 2 × m1 × v1) ÷ (m0 + m1);


v11 = ((m1 - m0) × v1 + 2 × m0 × v0) ÷ (m0 + m1);

看着这些公式,是不是明白我一开始为什么说复杂了吧,不过,都坚持学到了第11章,一定要hold住,胜利mm就在前面!

3.1 单轴上的动量守恒
这里我们继续用Ball类,给它添加了一个质量属性:

function Ball(x, y, radius) {   

  this.x = x;   

  this.y = y;   

  this.radius = radius;   

  this.angle = 0;   

  this.vx = 0;   

  this.vy = 0;   

  this.mass = 1;   

};

接下来,我们创建位于同一水平线的两个质量、速度都不相同的小球ball0ball1(忽略y轴)。我们已经知道计算碰撞后的速度公式,所以创建一个获取速度的方法getFinalSpeed(),传入两个球对象作为参数。

function getFinalSpeed(ballA,ballB){   

  var mass = ballA.mass + ballB.mass;   

  var vx01 = ((ballA.mass - ballB.mass) * ballA.vx + 2 * ballB.mass * ballB.vx) / mass;   

  var vx11 = ((ballB.mass - ballA.mass) * ballB.vx + 2 * ballA.mass * ballA.vx) / mass;   

  return {   

    vx01: vx01,   

    vx11: vx11   

  };   

};

我们需要知道何时碰撞,然后计算最终速度:

if(Math.abs(dist) < (ball0.radius + ball1.radius)) {   

  var vFinal = getFinalSpeed(ball0,ball1);   

  ball0.vx = vFinal.vx01;   

  ball1.vx = vFinal.vx11;   

};


实例:

没有加入任何阻力,所以会一直碰撞下去。


3.2 双轴上的动量守恒

单轴上的动量守恒比较简单,因为两个速度向量都在x轴上,我们可以直接加减它们的值,但是双轴上的动量守恒就相对复杂了,先看下图:










目录