飞闪物理──用Flash做物理课件之力的合成与分解

IT商界

  上一篇我们介绍了平抛运动的演示,包括运动方程的建立、坐标的描述和轨迹的记录。这里我们将上期平抛运动实例作品和源Flash文件提供出来以供参考。

  实例:http://www.cpcw.com/download/soft/37/flash1.swf

  源文件:http://www.cpcw.com/download/soft/37/flash1.fla

  同样,我们在《飞闪物理》这个Flash课件制作系列中,都会在每个教程的下期报纸中提供作品和源Flash文件的下载以供大家学习和参考。

  今天我们要制作一个交互式的演示课件,在拖动力的箭头末端时改变矢量平行四边形,用来形象地说明矢量合成与分解的平行四边形定则。该课件也可以用于数学中“向量合成”部分的教学。

  实例:力的合成与分解(见图)

  分 析

  由于力是典型的矢量,在计算机中模拟的时候,我们需要用坐标来表示力的矢量。

  设力的终点坐标为(x1,y1),的终点坐标为(x2,y2),合力的终点坐标为(x,y),我们规定以影片剪辑元件的中心为原点和所有力的始点,那么力的坐标就等于其终点坐标。

  根据矢量运算法则有:

  力的合成:x1+x2=x;y1+y2=y

  根据两点间距离的公式,力的大小

  F1与F的夹角余弦值cosθ=

  元件制作及程序编写

  在主场景中,将影片尺寸改为620×500,在时间轴中选中第1帧,在“动作”窗口中输入脚本(其中,draging变量指示是否在拖曳中,ondrg变量指示正在拖曳哪一个力,1为F1,2为F2,0为合力):

  draging=false;

  ondrg=0;

  //初始化变量

  制作三个影片剪辑元件Arrow1、Arrow0、Arrow2(如图1),分别标以不同的颜色,并记下它们的颜色号(以便在后面画线的时候保证颜色一致)。注意:务必使箭头有颜色填充的部分位于影片剪辑的中心点处,否则拖动时会出现问题。

  新建一个影片剪辑元件Main,把刚才画好的三个元件依次拖进去,并在属性栏中分别命名为a1、ar、a2。在下方用文字工具画一个约600×100的文本框,将其属性修改为“动态文本”,字号设为19,并在属性栏“变量”(Variable)框中填入prompt(与“prompt”变量关联)。布置好后的元件如图2。

  选中ar,在动作窗口中输入其脚本:

  on (press){

  startDrag(ar,true);//当鼠标按下时开始拖曳

  _root.draging=true;//改变标记变量为正在拖曳,_root表示指向主场景

  _root.ondrg=0;//指示拖曳的是合力

  }

  on(release){

  stopDrag();//当鼠标释放时停止拖曳

  _root.draging=false;//改变标记变量为已停止拖曳

  }

  a1的脚本:

  on (press){

  startDrag(a1,true);

  _root.draging=true;

  _root.ondrg=1;

  }

  on(release){

  stopDrag();

  _root.draging=false;

  }

  a2的脚本:

  on (press){

  startDrag(a2,true);

  _root.draging=true;

  _root.ondrg=2;

  }

  on(release){

  stopDrag();

  _root.draging=false;

  }

  Main元件第1帧的动作脚本:

  reDraw();

  function reDraw(){//定义重画矢量平行四边形的函数

  fac=180/Math.PI;//定义角弧度转换因数

  if (_root.ondrg<>2) {//如果不是在拖拽F2

  a2._x=ar._x-a1._x;

  a2._y=ar._y-a1._y;

  }

  else//如果拖曳的是F2

  {

  ar._x=a1._x+a2._x;

  ar._y=a1._y+a2._y;

  }

  a1._rotation=Math.atan2(a1._y,a1._x)*fac;

  ar._rotation=Math.atan2(ar._y,ar._x)*fac;

  a2._rotation=Math.atan2(a2._y,a2._x)*fac;

  //将箭头根据力的角度转向

  with (this) { //声明下面的操作对象为本元件

  clear();

  beginFill (0x99CCFF,50);//开始填充F1与合力之间的区域

  lineStyle(3.5,0xFF9900,100); //使用与ar相同的颜色

  moveTo(0,0);

  lineTo(ar._x,ar._y) //画合力

  lineStyle(3.5,0xFF3300,100); //使用与a1相同的颜色

  moveTo(0,0);

  lineTo(a1._x,a1._y) //画F1

  lineStyle(1,0x0099FF,100);

  lineTo(ar._x,ar._y); //画合力与F1终点的连线

  endFill();//至此,以上三条线构成的封闭图形已被填充

  beginFill (0xFFFFCC,50);//开始填充F2与合力之间的区域

  lineStyle(3.5,0x33CC66,100); //使用与a2相同的颜色

  moveTo(0,0);

  lineTo(a2._x,a2._y)//画F2

  lineStyle(1,0xFFCC00,100);

  lineTo(ar._x,ar._y);//画合力与F2终点的连线

  endFill();//完成填充

  }

  f1=Math.sqrt(a1._x*a1._x+a1._y*a1._y)/10;

  f2=Math.sqrt(a2._x*a2._x+a2._y*a2._y)/10;

  fr=Math.sqrt(ar._x*ar._x+ar._y*ar._y)/10;//根据两点间距离公式计算力的大小,每10像素代表1牛顿

  ang1=Math.acos((a1._x*ar._x+a1._y*ar._y)/(Math.sqrt(a1._x*a1._x+a1._y*a1._y)*Math.sqrt(ar._x*ar._x+ar._y*ar._y  )*fac;

  ang2=Math.acos((a2._x*ar._x+a2._y*ar._y)/(Math.sqrt(a2._x*a2._x+a2._y*a2._y)*Math.sqrt(ar._x*ar._x+ar._y*ar._y  )*fac;

  //分别计算F1、F2与合力的夹角

  prompt="F1="+f1+"N F2="+f2+"N F合="+fr+"N\rF1与合力夹角="+ang1+"° F2与合力夹角="+ang2+"°\rF1与F2夹角="+(ang1+ang2)+"°";//输出提示信息,\r为换行符号

  }

  在Main元件的时间轴中选中第2、3帧的位置,按F6新建关键帧。

  第2帧的脚本:

  if (_root.draging){//如果在拖曳中那么调用reDraw()函数重画

  reDraw();

  }

  第3帧的脚本:

  gotoAndPlay(2);

  最后,把Main元件拖进主场景中,并加上说明文字和标题,这个课件就完成了。

  使用说明:1.拖动F1末端不改变合力,相应改变F2

  2.拖动合力末端不改变F1,相应改变F2

  3.拖动F2末端不改变F1,相应改变合力

  要点提示

  (1)点(.)语法:上一节中我们使用了setProperty来改变属性,实际上,在对象名称明确的前提下,可以直接使用b1._x=100这样的语句来改变属性。“.”的前面是目标路径,即要访问的属性、方法、函数、变量存在的路径,这个路径可以是影片剪辑、父层对象(_parent),或主场景(_root),以及其他对象(如Math,String);后面是要访问的属性等的名称。

  (2)_rotation属性:设置/返回对象旋转的角度值,以水平向右为起始边,顺时针方向为角的正方向,逆时针为负方向。取值范围:-180~180°

  (3)beginFill(<color>,<alpha>);

  endFill();

  这两个语句对它们之间的语句所画的图形进行填充,color和alpha分别设置了填充的颜色和透明度。

  (4)startDrag(<object>,<lockcenter>,<left>,<top>,<right>,<bottom>);

  这个语句表示可以开始拖曳对象,前面两项分别是要拖曳的对象,是否将鼠标锁定在元件中心(建议为true,否则可能会在拖曳过程中鼠标远离元件,从而无法感应鼠标是否放开而停止拖曳),后面四项分别是可以拖曳的范围的左、上、右、下的坐标。

  stopDrag();停止拖曳对象。

  (5) Math对象下的数学函数和常数

  Math.atan2(y,x);角始边、正方向的定义与_rotation属性相同,返回以(x,y)为终边上一点坐标、正切值为y/x的角的弧度。

  Math.cos(x),Math.sqrt(x);分别求x的余弦值

  Math.PI;返回常数π的值

  (6)function <name>(<parameter1>,<parameter2>….) {

  …

  }

  定义一个函数,这样可以避免重复编写代码,只是在需要用到该代码的时候调用该函数即可。

  小结与拓展

  通过这一个课件我们学习了如何制作一个能够通过鼠标拖曳直接控制的交互式课件。拖曳的方法使用非常广泛,可以用来制作模拟实验程序,比如用于把某一个仪器组装到指定的位置。而根据拖曳到的位置通过帧的播放实时刷新的方法,也是经常会用到的。