铁三角适合听什么悔适合在臣士养吗

新浪广告共享计划>
广告共享计划
第三章&三角学应用Ⅰ&[FL车在臣]
第三章&三角学应用
从这一章开始,我们将学习三角学,并在第五章开始应用到动画技术中,其实在下一章的绘图技术中就会接触到。如果你已经对三角学有所了解或渴望学习动画方面的知识,那么可以跳过开始这部分,待日后遇到不懂的问题时,再回来学习。我们用到的90%的三角学都需要
Math.sin 和 Math.cos
这两个函数。在我写本书的第一版时,曾说过,除了在中学学习过的那些代数和几何外(而且由于时间久远大多都记不清了),我没有接受过正规的数学培训,最初在本章中的内容都是来自于各种书籍,网站或是其它网络资源,这是因为这部分知识并不难,既然我能够学会,那么你也一定可以的。而现在我已经完成了大学代数和微积分课程,对于三角学也有了更为全面和系统的了解。我可以很荣幸地说,这一章的内容非常好,因为对于这个学科有了更为深入的了解,所以很多地方可以解释得更为清楚。
什么是三角学(Trigonometry)
三角学是一门研究三角形与其边和角关系的学科。当我们观察一个三角形时,发现它有三条边和三个角(因此称为三角),而且在这些边和角之间存在着一些特殊的关系。例如,增大其中的任何一个角,那么该角所对应的边就会增长(假设其它两条边长度不变),同时,其它两个角会变小,实际上,究竟它们变化了多少,加以计算后就可以得出一个比例。在一个三角形中,如果其中有一个角为90度,那么就称为直角三角形,并在该角的夹角处标出一个正方形(垂足),只有在直角三角形才会这样。学习直角三角形中存在的关系要比推导基本公式简单得多,这使得直角三角形成为一种非常有用的结构,本章及该书后面的内容大多都是直角三角形。
角是三角学最主要的研究对象,让我们先来解决这个问题。角是由两条相交线构成的图形,或是两条相交线之间的那部分空间,空间远大,夹角越大。事实上,两条相交的线会形成四个角,见图
图3-1 两条线形成四个角
弧度制(radian)与角度制(degress)
弧度制与角度制是角度测量中的两种特殊制度。我们大概对于角度制最为熟悉,甚至闭着眼都能画出45度或90度的角。圆的360度体系已经成为了一种文化,人们常说“180度转弯”就是指“转到相反的方向”,这里并不是指转弯的方向,而是指一种相反的观点。我们所讨论的角度,对于计算机来说,就是弧度。所以,不管你是否喜欢,都要对弧度制有所了解。
1弧度约等于57.2958度。你也许会问“这符合逻辑吗?”确实有其逻辑所在。一个圆,360度,计算出的弧度为6.2832。仍然没有任何意义?好,想一下圆周率派
Pi(π) 约等于 3.1416,而一个圆(6.2832弧度)就等于2 pi。我们知道 360 度相当于 2 pi,180 度相当于
pi,90 度相当于 pi/2,等等。图3-2 给出一些常用的弧度制。
图3-2 弧度与角度
从现在起我们就要开始使用弧度制了,而且今后会遇到很多用弧度表示度的情况。
&&& 影片剪辑和 Sprite
影片的 rotation
属性都要使用角度制,而且属性非常会经常使用。例如,一辆汽车需要旋转到运动的方向,如果使用三角学计算运动方向,那么所得到的角度是以弧度制表示的,而汽车的旋转则需要使用角度制。相反,如果要指定某个对象向某个方向前进,就要获得它的旋转(rotation)角度,而这是用角度制表示的,如果要在三角函数中使用它就一定要转换为弧度制。
角度制,还应用在滤镜上,如果使用投影滤镜(drop shadow
filter),来为物体投射45度的阴影,就需要指定其角度而非弧度,不论是在 Flash IED 中还是使用 ActionScript
代码都一样。
为什么在一个编程体系里有两种截然不同的制度呢?也许这就是Flash双重性。一方面,这是设计人员的工具,在 Flash IDE
中拥有所有的绘图和变形工具,可以绘制出漂亮的图形。如果你对一名设计员说把你制作的 logo
文字旋转一个弧度,你肯定会遭白眼。另一方面,Flash 也是一个开发工具,更像一种编程语言,ActionScript
用户使用弧度制。总之,不论你是否喜欢都要使用到它们,而且还需要掌握角度制与弧度制间的相互转换。以下是公式:
弧度(radians) = 角度(degrees) * Math.PI /180
角度(degrees) = 弧度(radians) * 180 / Math.PI
在学习本书的过程中,会遇到很多公式。无论哪里,遇到需要记忆的公式时,我都会指出来,希望大家能够识记,这里是第一个公式。每次需要用到这些公式时,可以查找一下,但不会得到现成的代码,因为这些代码都需要用手敲进去。我使用
ActionScript 写这些公式,比如使用 Math.PI 要比使用 pi
或其它字符要好,因为这和我们输入的代码是一致的。
180度大约等于3.14…弧度。换句话讲,半圆为 pi 个弧度,整圆为 2 pi个弧度,一个弧度大概为 57.29…度。
&&& 在讨论角度时,就要提到
Flash 坐标系。如果我们习惯于数学坐标系,那么对于 Flash 坐标系可能会有些不习惯,因为在这里一切是颠倒(upside
down)的。在标准坐标系中,用X表示水平轴,用Y表示垂直轴,Flash 也是一样。当
x=0,y=0时,坐标(0,0)通常显示在中心位置,X为正数时在右边,X为负数时在左边,Y为正数时在上边,Y为负数时在下边,如图
3-3 所示。
图3-3 标准坐标系
&&& 然而 Flash
是基于视频屏幕的坐标系,0,0
点为左上角,如图3-4。X值从左向右不断增大,但Y轴是相反的,正值向下,负值向上。这个系统有其历史根源,与屏幕扫描建立图像的原理一样,从左到右,从上到下。
图3-4 Flash 坐标系
我们可以想像成一个普通的坐标系,只是要把Y轴颠倒过来,并把屏幕中心迁移到屏幕的左上角。下面就来说说角。在一般的坐标系中,角度是以逆时针计算的,并以0度为起点向正X轴引一条线,如图3-5所示。
图3-5 普通的角度
在 Flash 中是颠倒的,如图3-6所示。顺时针旋转角度为正角。逆时针就意味着为负角。
图3-6 Flash 的角度
三角形的边
对于三角形的边,没有太多可说的,但它们都有各自的术语。以直角三角形为例,如图3-7所示,每条边都有各自的名称,与90度角相接的两条边称为直角边(legs),相对的边称为斜边,它总是那个最长的边。
图3-7 直角三角形各部分
刚才说到对边时,说它是与该角不相接的边。说到邻边时,说它是与角相接的边。在很多例子中,都是与其余两个不是90度的角打交道。在三角形中最有趣的就是角与边的关系,这些关系对于动画制作非常有用,下面就让我们来看看。
&&& ActionScript
拥有一套用于计算不同三角关系的三角函数:正弦,余弦,正切,反正弦,反余弦和反正切。下面我们就开始定义和使用这些函数,而后还会介绍它们的实际应用。
正弦(Sine)
下面是三角学的第一个部分。一个角的正弦值等于该角的对边与斜边的比,在 ActionScript中,使用 Math.sin(angle)
函数来表示。图3-8
所示为一个30度角的正弦。对边长为1,斜边长为2,两条边的比为1比2,或记作1/2或0.5,因此,我们可以说30度角的正弦值为0.5,下面在
Flash 中测试一下:
trace(Math.sin(30));
图3-8 角的正弦值为对边/斜边
&&& 输出结果为
&0.862,为什么会这样,能够找出原因吗?这是因为我们忘记了将结果转换为弧度制。我敢说你以后会常犯这种错误(我也一样),所以一定要小心。以下是正确的写法:
trace(Math.sin(30 * Math.PI / 180));
成功!输出 0.5
&&& 还可能得到
这样的值,这并不是程序的错误,而是由于二进制计算机常以浮点形式表示数值。但这个值已经非常接近了,所以就认为它等于0.5。
可以把一个三角形想象为角度为30,两条边长分别为1和2,然后把它移到普通坐标系中,不要忘了, Flash
坐标系的Y轴向下,角度是顺时针的。所以,对边和角度都是相反的,见图3-9。
图3-9 在 Flash 坐标系中创建相同的角
因此,比例也变成了-1/2,我们就称它为-30度角的正弦值。同时,把表达式改为:
trace(Math.sin(-30 * Math.PI / 180));
好的,不会很痛苦吧?下面再来看一个三角函数:余弦。
余弦(Cosine)
&&& 在 Flash 中,使用
Math.cos(angle) 就可以计算余弦值,余弦的定义为角的邻边与斜边之比。见图 3-10。
图3-10 角的余弦值为邻边/斜边
图3-10中的角度与图3-9中的相同,这次在图中直接加入了邻边的长度 1.73。角的余弦值为 1.73/2,或
0.865。因此,我们可以说-30度角的余弦值为 0.865,下面测试一下:
trace(Math.cos(-30 * Math.PI / 180));
与使用正弦函数一样,只不过这次调用的是 Math.cos 函数,这次输出结果为 0.439,非常接近
0.865。之所以会有所不同,是因为我把邻边的值取整了。真正的长度应该近似于1.88,用这个数除以2,那么结果就非常接近-30度的余弦值。到现在为止,我们所说的都是左下方的角(degrees)。下面来看看右上方的角,首先,需要重新在坐标系中定位该角,这里的坐标系是指
Flash 坐标系,见图3-11。
图3-11 观查对角(opposite angle)
该角的正弦值为对边与斜边之比,或1.73/2(0.865),余弦值为邻边与斜边之比,1/2(0.5)。因此就得出,一个角的余弦值等于另一个角的正弦值,请注意它们之间是相互关联,成比的。
正切(Tangent)
另一个重要的三角函数是正切,用 Flash 表示为
Math.tan(angle)。它反应的是对边与邻边之间的关系如图3-12所示。
图3-12 角的正切值为对边/邻边
&&& 两者的比例为
-1/1.73 或 -0.578,直接在 Flash 中进行验证,会得到更准确的结果:
trace(Math.tan(-30 * Math.PI / 180));
&&& 输出结果为
&0.626,证实了前面的计算。在 ActionScript
中,这个函数并不常用,而使用正弦和余弦的时候要多一些。另外,反正切函数却是非常有用的,后面会讲到,这里请大家记住正切函数的比例关系。
反正弦(Arcsine)和反余弦(Arccosine)
与正切相似,反正弦和反余弦在一般的 Flash
动画中很少使用。然而,我们还是要学习一下它们的用法,实际上就是正弦和余弦函数的反函数。换句话讲,就是输入一个比例值,返回一个角度值(以弧度表示)。
ActionScript 函数中记作 Math.asin(ratio) 和
Math.acos(ratio)。下面让来测试一下,我们已经知道30度角的正弦值为0.5,所以0.5的反正弦值应为30度,检验一下:
trace(Math.asin(0.5) * 180 / Math.PI);
别忘记将结果转换为角度制,才能得到角度制30度,而不是弧度制0.523。
我们知道,30度角的余弦值大约为 0.865,下面以同样的方法来测试一下:
trace(Math.acos(0.865) * 180 / Math.PI);
&&& 得到结果为
30.1。如果把30度的余弦值输入得更准确,那么所得的结果也会更为精确。怎么样,不难吧?
反正切(Arctangent)
大家可能都猜到了,反正切简单地说就是正切函数的反函数。我们只要输入对边与邻边的比值,就可以得到相应的角度。
&&& 在 Flash
中有两个函数可计算反正切。第一个就是像前面介绍过的函数一样
Math.atan(ratio),只需提供对边与邻边的比例值。例如,前面学过30度角的正切值约为0.577。试一下:
trace(Math.atan(0.577) * 180 / Math.PI);
输出结果是一个近似30的数,不是非常直观易懂吗,为什么还需要另一个函数呢?下面请看图3-13,让它来回答:
图3-13 四个象限上的角
如图3-13所示,有四个不同的角:A,B,C,D。角A和B,在X轴上为正数,角C和D在X轴上为负数,同样,角A和D在Y轴上为负数,而角B和C在Y轴上为正数。因此,四个内角的比例分别为:
A: &1/2 (&0.5)
B: 1/2 (0.5)
C: 1/ &2 (&0.5)
D: &1/ &2 (0.5)
对边与邻边之比为0.5,输入Math.atan(0.5),并转换为角度制,结果大约为
26.57,那么究竟所指的是角B还是角D呢?两个比例都为0.5那样就无法分辨了,看似是个小问题,但对于日后的工作确有很大的影响。
&&& 下面有请
Math.atan2(y,x),这是 Flash 的另一个反正切函数,它比
Math.atan(ratio)要有用得多。实事上,只需要学会这个函数的用法就可以了,函数中包括两个参数:对边长度与邻边长度。有时常会误写成
x,y,请注意应该是 y,x。请看如下示例,输入 Math.atan2(1,2),然后记住这个结果:
trace(Math.atan2(1, 2) * 180 / Math.PI);
输出结果为 26.,这正是角B的度数。下面再输入-1/-2(角D),再来试试:
trace(Math.atan2(-1, -2) * 180 / Math.PI);
出乎意料的结果&153..为什么会这样?图3-14能给你解释。
图3-14 一个角的两种表示方法
从角D自身的底边开始,它确实为26.57度,但别忘了 Flash 的角度是从 X 轴的正半轴顺时针计算的。因此,从 Flash
的角度来衡量,则该角被视为-153.43度。下面就要开始在 Flash 中实践和应用三角学了。
旋转(Rotation)
&&& 我们想让一个影片剪辑或
影片通过旋转来指向鼠标的位置,这将是个挑战。旋转(rotation)将成为我们工具箱中非常的工具,可以应用于游戏制作,鼠标追踪,界面设计等。
下面看一个示例。也可以根据以下步骤或打开文档类 RotateToMouse.as 和 Arrow.as(与本书中其它代码一同在
下载),这些是已写好的代码。首先,需要让物体旋转,它可以是一个在 Sprite
中绘制的箭头(Arrow)。事实上,如果我们要反复应用到这个箭头,可以把它制作成一个类:
&import flash.display.S
&public class Arrow extends Sprite {
&&public function Arrow() {
&&&init();
&&public function init():void
&&&graphics.lineStyle(1,0,1);
&&&graphics.beginFill(0xffff00);
&&&graphics.moveTo(-50,-25);
&&&graphics.lineTo(0,-25);
&&&graphics.lineTo(0,-50);
&&&graphics.lineTo(50,0);
&&&graphics.lineTo(0,50);
&&&graphics.lineTo(0,25);
&&&graphics.lineTo(-50,25);
&&&graphics.lineTo(-50,-25);
&&&graphics.endFill();
&&& 这里使用到了绘图 API
(会在下一章介绍)来绘制箭头。无论何时需要一个箭头,只需写一句 new
Arrow()即可,在图3-15中可看到显示结果。当绘制一些图像并进行旋转时,要注意它的指向,默让地指向右边,X的正半轴,这就是它旋转到0度时的状态。
我们先要创建一个Arrow类的实例,放致于舞台中心,并让它指向鼠标的方向,如图3-16。
图3-15 使用绘图API绘制的箭头
图3-16 下一次需要计算的值
很熟悉吗?与我们之前所讲的三角形相同,只不过多加入了鼠标与箭头的坐标。鼠标的位置只需使用 mouseX 和 mouseY
属性即可获得,同样,使用x,y属性,获得箭头的位置。使它们的值相减,就得到了两条边的长度。现在只需要使用
Math.atan2(dy,dx) 就可以求出夹角,然后把结果转换为角度制,最后让箭头的 rotation
属性等于这个夹角。代码如下:
var dx:Number = mouseX - arrow.x;
var dy:Number = mouseY - arrow.y;
var radians:Number = Math.atan2(dy, dx);
arrow.rotation = radians * 180 / Math.PI;
当然,为了使之形成一个动画,还需要加入循环。如同前一章提到的,使用事件处理函数将会是最好的选择,请使用 enterFrame
事件。以下是这个完整的文档类:
&import flash.display.S
&import flash.events.E
&public class RotateToMouse extends Sprite {
&&private var arrow:A
&&public function RotateToMouse()
&&&init();
&&private function init():void
&&&arrow=new
&&&addChild(arrow);
&&&arrow.x=stage.stageWidth
&&&arrow.y=stage.stageHeight
&&&addEventListener(Event.ENTER_FRAME,onEnterFrame);
&&public function
onEnterFrame(event:Event):void {
dx:Number=mouseX - arrow.x;
dy:Number=mouseY - arrow.y;
radians:Number=Math.atan2(dy,dx);
&&&arrow.rotation=radians
* 180 / Math.PI;
&&& 请确认
RotateToMouse.as 文件与 Arrow.as 文件在同一目录下,以 RotateToMouse 作为文档类,并为它创建
SWF。怎么样?就像施了魔法一样!假设如果我们没有 Math.atan2
这个函数,就要先通过,dy除以dx求出对边与邻边的比值,然后再写入 Math.atan 函数。下面用 Math.atan 函数来代替
Math.atan2 函数来试一下,代码如下:
var radians = Math.atan(dy / dx);
试试这种写法,马上就会发现问题。如果鼠标位于箭头的左侧,箭头不会指向鼠标,并与鼠标相背离。能说说为什么吗?回到有 A,B,C,D
四个角的图(图3-13),不要忘记角A和C拥有相同的比值,角B和D也是一样。这样一来, Flash
就无法知道所指的是哪个角,所以只能得到A与或角B。如果,鼠标处于D角区域,Flash
会回到B角区域并把箭头指向这个角度。毫无疑问,这时 Math.atan2 的好处就显示出来了,书中会经常用到这个函数。
大家肯定听说过正弦波,也一定见过图3-17所示的图形。
图3-17 正弦波形
那么为什么要把正弦函数与正弦图像两个不相干的东西联系到一起呢?如果将0到360度(或着0到2pi)代入到正弦函数中,那么就会得到这个正弦函数图像。从左到右代表所使用的角度值,而图中y坐标变化,代表这些角的正弦值。
图3-18中,标出了一些特殊的角度,我们可以看到0度的正弦值为0,90度或pi/2的正弦值为1,180度或pi的正弦值又回到0,270度或3/2pi的正弦值为-1,360度的正弦值为0。下面用
Flash 来试一下正弦波形,把以下代码放入文档类的框架中进行测试:
for (var angle:Number = 0; angle & Math.PI * 2;
angle += .1) {
&trace(Math.sin(angle));
从现在起,要开始习惯只使用弧度制。除了使用 rotation 或其它只使用角度制的属性外,要开始学着不去使用角度制。
图3-18 正弦图像值
在这个例子中,角度从0开始,每次递增0.1直到大于 Math.PI*2
为止,并输出该角的正弦值。看一下输出结果,我们发现角度是从0开始,增加到1后,开始减小,减少到-1时,再回归至0。这些值不会真正准确地到达1或0,因为每次增加0.1,所以永远不会得到pi或pi/2的整数倍。
平滑的上下运动
&&& 如何使用
Math.sin(angle) 呢?如果想让物体上下或左右移动,那么就要用到这个函数。考虑:使用 0~1~-1~0
的变化来实现这个动画,并且反复地使用这个波形。
活动域仅仅是从1到-1,不能看出效果,所以要把这些数值放大一些,比如扩大100倍。这样就拥有了一个从100到-100的波形,并且连绵不断。在下面这个文档类
Bobbing.as 中,要使用一个在 Ball 类中定义的 Sprite 影片,请看代码:
&import flash.display.S
&public class Ball extends Sprite {
&&private var
&&private var color:
&&public function
Ball(radius:Number=40, color:uint=0xff0000) {
&&&this.radius =
&&&this.color =
&&&init();
&&public function init():void
&&&graphics.beginFill(color);
&&&graphics.drawCircle(0,
0, radius);
&&&graphics.endFill();
当这个类被实例化后,就能绘制出一个圆。我们还可以自行给出圆的半径(radius)和颜色(color)。如果不给这些参数的话,就会使用默认的参数:半径为40,颜色为红色(这是AS3.0新增的功能)。这个类非常简单,但却非常有用,今后在书中会经常用到,所以大家一定要掌握。
&&& 文档类创建一个 Ball
类的实例,并加入到舞台上,再为它增加一个 enterFrame 侦听器,这样就可以让小球上下移动了。
&import flash.display.S
&import flash.events.E
&public class Bobbing extends Sprite {
&&private var ball:B
&&private var angle:Number =
&&public function Bobbing()
&&&init();
&&private function init():void
&&&ball = new
&&&addChild(ball);
&&&ball.x =
stage.stageWidth / 2;
&&&addEventListener(Event.ENTER_FRAME,
onEnterFrame);
&&public function
onEnterFrame(event:Event):void {
&&&ball.y =
stage.stageHeight / 2 + Math.sin(angle) * 50;
&&&angle +=
首先,需要一个角度属性(angle)初始值为0。在 onEnterFrame
方法中,使用该角的正弦值并扩大50倍。这样一来,取值的范围就变成了50到-50。再在这个值上加舞台高度的一半,数值就变为从250到150(设舞台高度为400像素),用这个值作为小球的Y坐标,最后为下一次循环增加0.1个弧度,这样就完成了小球平滑的上下运动。每一次循环的值都不相同,我们发现如果将0.1变为另一个数值的话,就改变了小球运动的速度。角度(angle)变化的快慢与
Math.sin 从1到-1变化的速度成正比。很明显,改变50这个值,就改变了小球移动的距离,而改变
stage.stageHeight / 2
的值,就改变了小球运动时围绕的位置。我们还可以给出一些抽象的值作为变量,代码如下(只给出需要改变或增加的部分):
// at the top of the class:
private var angle:Number = 0;
private var centerY:Number = 200;
private var range:Number = 50;
private var speed:Number = 0.1;
// and the handler function:
public function onEnterFrame(event:Event):void {
&ball.y = centerY + Math.sin(angle) *
&angle += speed;
在运动代码中没有使用具体的数值,真是次非常好的练习,以后应尽量这样做。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。新浪广告共享计划>
广告共享计划
第三章&三角学应用Ⅱ&[FL车在臣]
线性垂直运动
&&& 在 Wave1.as
文件中,加入了线性垂直运动,只是为我们制作动画增加一些灵感。以下是这个文件的代码:
&import flash.display.S
&import flash.events.E
&public class Wave1 extends Sprite {
&&private var ball:B
&&private var angle:Number =
&&private var centerY:Number =
&&private var range:Number =
&&private var
xspeed:Number = 1;
&&private var yspeed:Number =
&&public function Wave1() {
&&&init();
&&private function init():void
&&&ball = new
&&&addChild(ball);
&&&ball.x =
&&&addEventListener(Event.ENTER_FRAME,
onEnterFrame);
&&public function
onEnterFrame(event:Event):void {
&&&ball.y =
centerY + Math.sin(angle) *
&&&angle +=
使用正弦值作为一种工具,不仅仅只用于控制物理位置。在 Pulse.as
文件中,使用一个值来影响小球的缩放,实现一个心跳的效果,代码如下:
&import flash.display.S
&import flash.events.E
&public class Pulse extends Sprite {
&&private var ball:B
&&private var angle:Number =
&&private var
centerScale:Number = 1;
&&private var range:Number =
&&private var speed:Number =
&&public function Pulse() {
&&&init();
&&private function init():void
&&&ball = new
&&&addChild(ball);
&&&ball.x =
stage.stageWidth / 2;
&&&ball.y =
stage.stageHeight / 2;
&&&addEventListener(Event.ENTER_FRAME,
onEnterFrame);
&&public function
onEnterFrame(event:Event):void {
&&&ball.scaleX
= ball.scaleY = centerScale +
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
Math.sin(angle) *
&&&angle +=
原理是一样的,centerScale表示100%的缩放比, range 表示范围, speed 表示速度。不仅如此,正弦波还在
alpha,rotation 等属性中应用。
再给大家一种思想:设置两套数值 angle1 和
angle2,为它们各自增加一个中心点(center)和速度(speed)值。用一个正弦波作为一种属性,另一个正弦波作为另一种属性,比如位置或缩放。我不敢保证能够得到什么有用的结果,但这样做的话,就等于让这些函数自由发挥作用。
&&& 从 Random.as
文档类开始,这里面拥有两个角度(angle),两个速度(speed)和两个中心点(center),将其中一个角(angle1)作为小球的X坐标,另一个角(angle2)作为Y坐标。运行程序时,就像只虫子在房间里飞,虽然这些数字都是预先定义好的,但结果却没有什么规律可言。代码如下:
&import flash.display.S
&import flash.events.E
&public class Random extends Sprite {
&&private var ball:B
&&private var
angleX:Number = 0;
&&private var angleY:Number =
&&private var centerX:Number =
&&private var centerY:Number =
&&private var range:Number =
&&private var
xspeed:Number = .07;
&&private var yspeed:Number =
&&public function Random()
&&&init();
&&private function init():void
&&&ball = new
&&&addChild(ball);
&&&ball.x =
&&&addEventListener(Event.ENTER_FRAME,
onEnterFrame);
&&public function
onEnterFrame(event:Event):void {
= centerX + Math.sin(angleX) *
&&&ball.y =
centerY + Math.sin(angleY) *
&&&angleX +=
&&&angleY +=
&&& 最后,在
Wave2.as 中,不再使用小球,转而使用绘图API来绘制正弦波形。代码如下:
&import flash.display.S
&import flash.events.E
&public class Wave2 extends Sprite {
&&private var angle:Number =
&&private var centerY:Number =
&&private var range:Number =
&&private var xspeed:Number =
&&private var yspeed:Number =
&&private var
&&private var
&&public function Wave2() {
&&&init();
&&private function init():void
&&&graphics.lineStyle(1,
&&&graphics.moveTo(0,
&&&addEventListener(Event.ENTER_FRAME,
onEnterFrame);
&&public function
onEnterFrame(event:Event):void {
&&&angle +=
centerY + Math.sin(angle) *
&&&graphics.lineTo(xpos,
下一章我们会详细讲述绘图API,大家也应该有兴趣来执行一下这个文件,观察一下绘制出的波形。注意,由于 Flash
的Y轴是反向的,所以绘制出的波形也是颠倒的。
目前为止我们已经掌握了正弦波,下面再来看看它的兄弟,余弦波。与正弦波的形成相同,只不过是使用余弦函数代替了正弦函数而已。如果你还记得前面所说的正弦和余弦是怎样一种相反关系的话,就能理解,它们只是波形都相同,只是所处位置不同了。图3-19
为余弦波图像:
图3-19 余弦波形
可见,余弦图像中0度和2pi度(或360度)的值都为1,从1开始经过 0,-1,0,
最后回到1。所以,它与正弦曲线相同,只不过位置发生了一点偏移。
在执行物体移动的动画时,完全可以使用余弦来代替正弦。实际上,余弦和正弦协同工作时,才能形成一个更加有用的功能:使物体沿圆形运动,如图3-20。
图3-20 物体沿圆形运动时的几个点
如图3-20所示,以图中的圆为例,盯住右侧的那直角条边(y),然后开始对它进行旋转,我们发现这条边正在被倒置。这条边的中心点就是圆心,而它的运动范围就是这个圆的半径。就像在第一个正弦实验中一样,我们可以计算出这条边的长度:角的正弦值乘以半径。在这里,使用正弦函数非常合适,当我们从侧面观察这个圆时,就可以算出
y 的长度——对边的长度。如果把这个圆放倒,再来观察它,发现角是在向前向后或向左向右移动的。这时,可以使用余弦函数计算出 x
的长度——邻边的长度。重要的一点是,两个的夹角都是相同的,而不像 Random.as 那个例子中使用不同的角度计算 x,y
坐标。这里我们只需要记住用正弦函数计算 y ,用余弦函数计算 x。下面请看 ActionScript 代码:
&import flash.display.S
&import flash.events.E
&public class Circle extends Sprite {
&&private var ball:B
&&private var
angle:Number = 0;
&&private var centerX:Number =
&&private var centerY:Number =
&&private var
radius:Number = 50;
&&private var speed:Number =
&&public function Circle()
&&&init();
&&private function init():void
&&&ball = new
&&&addChild(ball);
&&&ball.x =
&&&addEventListener(Event.ENTER_FRAME,
onEnterFrame);
&&public function
onEnterFrame(event:Event):void {
= centerX + Math.cos(angle) *
&&&ball.y =
centerY + Math.sin(angle) *
&&&angle +=
大家可以自己写这个例子,也可以打开 Circle.as 作为文档类。执行后发现,获得了一个完美的圆。这段代码的精华就是使用余弦来确定
x 坐标,使用正弦来确定 y 坐标,你应该对他们的关系非常了解了。在 Flash 中,只要提到 x
,你就应该马上想到余弦,并且还能联想到 y 使用正弦。请在最后这段代码上多花些时间,它将是 ActionScript
动画工具箱中最有用的工具之一。
椭圆运动&&&
想要获得一个椭圆该怎么办呢,其实很简单,问题就在于半径。如果让x和y运动的大小相同,那么就得到一个圆。如果想得到一个椭圆形,我们只需要在计算x和y位置时使用不同的半径值:
radiusX 和 radiusY
。从严格的几何观点来看,使用这两个名称实在不怎么好,但是它们确实非常简单易懂,也非常好记非常直观,所以我还是坚持使用这两个变量名。下面看看它们是如何配合的,见
&import flash.display.S
&import flash.events.E
&public class Oval extends Sprite {
&&private var ball:B
&&private var angle:Number =
&&private var centerX:Number =
&&private var centerY:Number =
&&private var
radiusX:Number = 200;
&&private var radiusY:Number =
&&private var speed:Number =
&&public function Oval() {
&&&init();
&&private function init():void
&&&ball = new
&&&addChild(ball);
&&&ball.x =
&&&addEventListener(Event.ENTER_FRAME,
onEnterFrame);
&&public function
onEnterFrame(event:Event):void {
= centerX + Math.cos(angle) * radiusX;
&&&ball.y =
centerY + Math.sin(angle) * radiusY;
&&&angle +=
&&& 这里, radiusX
为200,意味着小球在距离 centerX 200个像素内左右运动。 radiusY
为100,意味着小球上下运动的范围只有100像素,这样就得到了一个不匀称的圆。
最后,介绍一下勾股定理。虽然并不能算是三角学中正式的一部分,但是它与我们这个学科还是有一些关系的,并且还涉及到一个将来会经常使用的公式,所以在这里介绍它非常合适。
勾股定理是很久以前一个希腊人发明。这个定理是说 A的平方 + B的平方 = C的平方
,听起来好像是儿歌,如果大家之前学过这个定理,那么交流起来效果最好。
深入探讨一下,另一种对该定理的叙述是:直角三角形的两条直角边的平方和等于斜边的平方,这句话真正说到点子上了。请看图3-21所示直角三角形。
两条直角边A和B长度为3和4,斜边C长度为5。毕达哥拉斯(Pythagoras)先生告诉我们 A2 +
B2 = C2 。加入一些数字来检验一下,32 + 42 = 52,计算出 9
+ 16 = 25。是的,非常正确。
图3-21 一个直角三角形
如果大家已经知道了这个口决,那么勾股定理只不过就是一种有趣的关系。如果中知道其中两条边的长度,那么勾股定理就派上用场了,可以用它很快地求出第三条边的长度。在
Flash 中,最常见的情况是我们只知道两条直角边的长度要求出斜边的长度。比如,求出两点间的距离。
两点间距离
&&& 假设在舞台上有两个
Sprite 影片,想要求出它们之间的距离。这是勾股定理在 Flash 中最为常见的应用。那么如何实现呢?已知两个 Sprite 的
x,y 坐标,把第一个影片的位置称为x1,y1,另一个影片的位置称为 x2,y2,见图3-22。
图3-22 两个物体间的距离是多少?
如果你在本章中看了太多的直角三角形,那么很容易就把图3-22看成一个直角三角形,而那条距离线(distance)就是三角形的斜边。在图3-23中,加入了这个三角形并填入了数字。
图3-23 变成一个直角三角形
dx为两个影片之间的x轴,dy为它们之间的y轴。用x2减x1就得到了dx的值:58 & 50 =
8,同样,用y2-y1等于6得到dy的值。现在使用勾股定理,将dx,dy的平方相加,就得到了距离(distance)的平方。
&&& 换言之,62 +
82 = dist2,相当于 36 + 64(=100) = dist2。基础代数学讲过可以通过开平方把它转化为 =
dist。这样一来,就可以得出两个影片之间的距离为 10。
现在,把它抽像成一个公式,这样的话,今后再遇到同样的问题,就可以直接使用这个公式了。有两个位置 x1,y1 和 x2,y2,先计算出
x 的距离和 y 的距离,然后求出它们的平方和,最后求出平方根,下面请看 ActionScript 写法:
dx = x2 & x1;
dy = y2 & y1;
dist = Math.sqrt(dx*dx + dy*dy);
请特别注意这些代码,它们将是我们工具箱中又一个最好的工具。前两句是获得x,y轴上的距离。最后一句分为三个步骤:计算每个值的平方,把它们相加,求出平方根。下面进行一下实践,文档类
Distance.as ,创建了两个 Sprite 影片,并随机摆放,最后计算出它们之间的距离。
&import flash.display.S
&public class Distance extends Sprite {
&&public function Distance()
&&&init();
&&private function init():void
sprite1:Sprite = new Sprite();
&&&addChild(sprite1);
&&&sprite1.graphics.beginFill(0x000000);
&&&sprite1.graphics.drawRect(-2,
-2, 4, 4);
&&&sprite1.graphics.endFill();
&&&sprite1.x =
Math.random() * stage.stageW
&&&sprite1.y =
Math.random() * stage.stageH
sprite2:Sprite = new Sprite();
&&&addChild(sprite2);
&&&sprite2.graphics.beginFill(0xff0000);
&&&sprite2.graphics.drawRect(-2,
-2, 4, 4);
&&&sprite2.graphics.endFill();
&&&sprite2.x =
Math.random() * stage.stageW
&&&sprite2.y =
Math.random() * stage.stageH
&&&var dx:Number
= sprite1.x - sprite2.x;
&&&var dy:Number
= sprite1.y - sprite2.y;
dist:Number = Math.sqrt(dx * dx + dy * dy);
&&&trace(dist);
编译执行这个动画后,就得到了两个影片之间的距离。每次执行,两个影片的位置都会不同。不论它们处于什么位置,我们所获得的距离都是正数。有趣吧,但是还不够动态,在下面这个示例,可以实时地获得影片的距离,请试一下这个文档类,MouseDistance.as:
&import flash.display.S
&import flash.events.MouseE
&import flash.text.TextF
&public class MouseDistance extends Sprite {
&&private var
&&private var
textField:TextF
&&public function MouseDistance()
&&&init();
&&private function init():void
&&&sprite1 = new
&&&addChild(sprite1);
&&&sprite1.graphics.beginFill(0x000000);
&&&sprite1.graphics.drawRect(-2,
-2, 4, 4);
&&&sprite1.graphics.endFill();
&&&sprite1.x =
stage.stageWidth / 2;
&&&sprite1.y =
stage.stageHeight / 2;
&&&textField =
new TextField();
&&&addChild(textField);
&&&stage.addEventListener(MouseEvent.MOUSE_MOVE,
onMouseMove);
&&public function
onMouseMove(event:MouseEvent):void {
&&&graphics.clear();
&&&graphics.lineStyle(1,
&&&graphics.moveTo(sprite1.x,
sprite1.y);
&&&graphics.lineTo(mouseX,
&&&var dx:Number
= sprite1.x - mouseX;
&&&var dy:Number
= sprite1.y - mouseY;
dist:Number = Math.sqrt(dx * dx + dy * dy);
&&&textField.text
= dist.toString();
&&& 在这里dx和dx的值是用
的位置减去当前鼠标位置得出的,dist的值放入一个文本框中进行显示,并在影片和鼠标之间绘制一条线(在下一章绘图API中会学到)。最后,将所有这些代码放到处理函数
onMouseMove
中,每次鼠标移动时进行刷新。测试一下这个文件,并移动鼠标,鼠标与影片剪辑之间会连接上一条线,并实时读取线的长度。
后面的章节中,在学到碰撞检测时,我们会发现内置的碰撞检测(hit
testing)方法存在着先天不足,然后会看到使用勾股定理公式完成基于距离(distance-based)碰撞检测方法。它还非常适合用于计算重力或弹力等,因为这些力的大小与两个物体之间的距离成正比。
本章重要公式
现在我们已经有了一个全新的工具箱,同时又多了不少工具,全部所有的工具将会在第19章列出,那么让我们看看现在都有了哪些工具。注意,这些公式非常地抽象和简化,里面不包括数据类型和变量定义,在类中使用这些公式时,是否使用这些给出的句型取决于你。
基本三角函数的计算:
角的正弦值 = 对边 / 斜边
角的余弦值 = 邻边 / 斜边
角的正切值 = 对边 / 邻边
角度制与弧度制的相互转换:
弧度 = 角度 * Math.PI / 180
角度 =&弧度 *&180 /
向鼠标旋转(或向某点旋转):
// substitute mouseX, mouseY with the x, y point to rotate to
dx = mouseX - sprite.x;
dy = mouseY - sprite.y;
sprite.rotation = Math.atan2(dy, dx) * 180 / Math.PI;
创建波形:
// assign value to x, y or other property of sprite or movie
// use as drawing coordinates, etc.
public function onEnterFrame(event:Event){
value = center + Math.sin(angle) *
创建圆形:
// assign position to x and y of sprite or movie clip,
// use as drawing coordinates, etc.
public function onEnterFrame(event:Event){
xposition = centerX + Math.cos(angle) *
yposition = centerY + Math.sin(angle) *
创建椭圆:
// assign position to x and y of sprite or movie clip,
// use as drawing coordinates, etc.
public function onEnterFrame(event:Event){
xposition = centerX + Math.cos(angle) * radiusX;
yposition = centerY + Math.sin(angle) * radiusY;
计算两点间距离:
// points are x1, y1 and x2, y2
// can be sprite / movie clip positions, mouse coordinates,
dx = x2 & x1;
dy = y2 & y1;
dist = Math.sqrt(dx*dx + dy*dy);
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 道士向和尚忏悔 的文章

 

随机推荐