当前位置: 首页 > 文档资料 > HTML5 Canvas 实战 >

5.9 模拟粒子物理学

优质
小牛编辑
158浏览
2023-12-01

现在,我们已经介绍了经典物理学的基础,让我们把它们贯穿起来。本节,我们将通过模拟重力、边界条件、碰撞阻尼、地面摩擦力来模拟粒子物理运动。

模拟粒子物理运动
图5-9 模拟粒子物理运动

操作步骤

按照以下步骤,在画布中发射一个粒子,并观察其运动路径,先碰墙反弹,再在重力作用下渐渐落到地面,然后由于地面摩擦力的作用而慢慢停下来。

1. 链接到Animation类:

<head>
<script src="animation.js"> </script>

2. 定义applyPhysics()函数,该函数把粒子作为输入,并根据物理变量,如重力、碰撞阻尼、地面摩擦力,更新其位置和速度:

function applyPhysics(anim, particle){
  // 物理学全局变量
  var gravity  =  1500;  // pixels  / second^2
  var collisionDamper  =  0.8;  //  发生碰撞后速度将损失80%
  var floorFriction  =  100;  // pixels  / second^2
  var timeInterval  = anim.getTimeInterval();
  var canvas  = anim.getCanvas();
  //重力
  particle.vy  += gravity  * timeInterval  /  1000;
  //位置
  particle.y  += particle.vy  * timeInterval  /  1000; 
  particle.x  += particle.vx  * timeInterval  /  1000;
  //地面情况下
  if  (particle.y  >  (canvas.height  - particle.radius))  {
    particle.y  = canvas.height  - particle.radius;
    particle.vy  *=  -1;
    particle.vy  *= collisionDamper;
  }
  //地面摩擦力
  if  (particle.y  == canvas.height  - particle.radius)  {
    if  (particle.vx  >  0.1)  {
      particle.vx  -= floorFriction  * timeInterval  / 1000;
    }
    else if  (particle.vx  <  -0.1)  {
      particle.vx  += floorFriction  * timeInterval  /1000;
    }
    else  {
      particle.vx  =  0;
    }
  }
  //天花板情况下
  if  (particle.y  <  (particle.radius))  {
    particle.y  = particle.radius;
    particle.vy  *=  -1;
    particle.vy  *= collisionDamper;
  }
  //右墙情况下
  if  (particle.x  >  (canvas.width  - particle.radius))  {
    particle.x  = canvas.width  - particle.radius;
    particle.vx  *=  -1;
    particle.vx  *= collisionDamper;
  }
  //左墙情况下
  if  (particle.x  <  (particle.radius))  {
    particle.x  = particle.radius;
    particle.vx  *=  -1;
    particle.vx  *= collisionDamper;
  }
}

3. 实例化一个Animation对象,并获取画布上下文:

window.onload  = function(){
  var anim  = new Animation("myCanvas"); 
  var canvas  = anim.getCanvas();
  var context  = anim.getContext();

4. 使用位置,x、y方向上速度,半径初始化一个粒子对象:

  var particle  =  {
    x:  10,
    y: canvas.height  -  10, 
    vx:  600,  // px  / second
    vy:  -900,  // px  / second radius:  10
  };

5. 设置stage()函数,该函数把粒子对象传递给applyPhysics()函数来更新粒子的状态,清除画布,再绘制粒子:

anim.setStage(function(){
  // update
  applyPhysics(this, particle);
  // clear
  this.clear();
  // draw
  context.beginPath();
  context.arc(particle.x, particle.y, particle.radius,  0,  2  * Math.PI, false);
  context.fillStyle  = "blue"; 
  context.fill();
});

6. 启动动画:

  anim.start();
};
</script>
</head>

7. 在HTML文档的body部分嵌入canvas标签:

<body>
<canvas id="myCanvas" width="600" height="250" style="border:1px solid black;">
</canvas>
</body>

工作原理

要模拟粒子物理学,我们需要处理粒子在每一帧时的x、y位置,及x、y方向上的速度。理解粒子物理学的关键是要记住,粒子在一个系统中的运动,是由作用在该粒子上的所有力的合力决定的。在本例中,重力会把粒子往下拉;撞击到墙壁、天花板、地板时,会根据碰撞阻尼常数较低粒子的速度;当在地面上滚动时,地面摩擦力会较低粒子在水平方向上的速度。

一开始,在页面加载完成后,我们实例化一个Animation对象,并得到画布及其上下文对象。接下来,我们使用位置、初始速度、尺寸来初始化一个粒子。舞台上的演员(粒子)初始化完成后,我们可以设置stage()函数,该函数将更新粒子,清除画布,再在每个动画帧绘制粒子。

更新的逻辑发生在applyPhysics()函数中,该函数的参数是一个Animation对象(即particle对象)的引用。applyPhysics()遍历不同情况的列表来更新粒子的位置和速度。

调用applyPhysics()函数,并且粒子被更新之后,我们可以清除画布,然后简单绘制一个圆来绘制粒子,该圆的半径与粒子的半径相等。

最后,stage()函数被设置完成后,我们便可以调用start()方法启动动画了。

了解更多

如果你真的想弄点花样,你甚至可以外加其它的力,如空气阻力。根据普遍的经验,你给模拟粒子增加的力越多,其结果越逼真。你可以使用不同的初始位置和速度,看看不同的发射路径。

相关参考

  • 第2章 绘制圆