当前位置: 首页 > 图文教程 > Flash动画 > ActionScript > Flash as入门(17):Math类三角函数

ActionScript
FLASH 3D相册之利用BitmapData类制作
Flash 脚本游戏开发教程 第一课
Flash 脚本游戏开发教程第二课
Flash 脚本游戏开发教程第三课
Flash 脚本游戏开发教程第四课
Flash 脚本游戏开发教程第五课
Flash 脚本游戏开发教程第六课
Flash 脚本游戏开发教程第七课
Flash 脚本游戏开发教程第八课
Flash AS实现的蝌蚪摆尾动画的教程
从基础开始深入学Flash AS3教程(4)(译文)
从基础开始深入学Flash AS3教程(5)(译文)
从基础开始深入Flash AS3教程(2)(译文)
从基础开始深入学Flash AS3教程(3)(译文)
Flash AS3对单个图片进行角色动作化处理
从基础开始深入Flash AS3教程(1)(译文)
Flash教程:if条件语句的用法
Flash AS教程:_visible属性的详细讲解
Flash AS教程:图片环绕旋转效
Flash教程:trace()的使用

ActionScript 中的 Flash as入门(17):Math类三角函数


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2010-03-20   浏览: 384 ::
收藏到网摘: n/a

本例继续讲解AS的基础知识,今天我们来学习Flash AS入门系列教程第七课:影片剪辑第11节三角函数,Math类为我们提供了很多数学计算函数,今天我们来了解一下三角函数,对Flash的AS编程有兴趣的朋友可以到论坛与作者交流。

三角函数

Math类为我们提供了很多数学计算函数,今天我们来了解一下三角函数。三角函数是研究三角形的边与角的关系的学科。希望不要看到这个题目就开跑,不要怕,往下看,你会复习到初中所学的三角课程,同时你会感觉到三角函数会很简单。当然所要介绍的只是正弦,余弦和反正切三个常用的函数。

Flash为什么要研究三角函数呢?看看下面的图:

在flash坐标体系中(即舞台上),放上一个点a,然后通过a点将a点的x,y长度画出来,并将两条线的端点连起来,你看一个直角三角形出现了。这样三角函数就有研究头了。这个三角形跟这个点有什么关系呢?最明显的就是这个三角形的两条直角边b,c确定了a点的位置。除了两条直角边以外,还有斜边d,还有一个角e, (另外两个角我们不研究)。这些边和角之间的关系就是三角函数。我们说过只研究三个函数:
sin(e) = c/d; 对边除以斜边
cos(e) = b/d; 邻边除斜边
e = atan(c/b)
而flash为我们提供了一个更为合理的反正切函数:atan2(y,x)
即: e = atan2(y,x)
从上面的图中可以看出,实际上b就等于点a的x,c就等于点a的y.这换一下,就成:
sin(e)=y/d;
cos(e) = x/d;
将这两个式子变一下就成:
y = d*sin(e);
x=d*cos(e);
对这两个式子,需要说明的是:角e在三角函数的运行中必须使用弧度制,这与我们习惯的角度制有所不同,所以我们需要记住角度弧度转换的公式:
[cose]角度弧度转换公式:
角度 = 弧度*180/Math.PI;
弧度 = 角度*Math.PI/180;[/code]
PI是园周率,即3.14159,它属于Math类写法为:Math.PI.三角函数也属于Math类。所以上面的公式正确写法是:
x= d*Math.cos(e) e为弧度表示
y=d*Math.sin(e)

三角函数的知识差不多复习这么多就行了,是不是很简单呢?

园周运动:

上面介绍的三角函数有什么用呢?我们还是来看看前面那个图,如果直角三角形的斜边长度固定不变,让角e不断地加大,会是个什么效果呢?很容易理解它出现的是下面的效果:

点a在做园周运动。看起来有点意思了哈。怎样让它做园周动运的呢?要让对象移动需要改变对象的x,y值,上面的公式已经给了我们计算这两个值的方法:
x= d*Math.cos(e)
y=d*Math.sin(e)

做园周运动时直角三角形的斜边长度d不变,其实我们早已看出来了,斜边实际就上园周的半径。将角e不断增大,从而产生不同的x,y值,将这些值赋给点a对象,就形成了园周运动了。在上例中,我们将点a做成MC,实例名称为:ball_mc,h 上例的代码为:
var d = 100; //半径为100
var centerx = Stage.width/2;
var centery = Stage.height/2;确定园心的位置在舞台中心
var zl=10;//设一个增量,即角e每次增加10度。
var i=1;
onEnterFrame =function(){
ball_mc._x=centerx+d*Math.cos(i*zl*Math.PI/180);//再次提醒三角函数要用弧度
ball_mc._y =centery+d*Math.sin(i*zl*Math.PI/180);
i++;
if(i>36){//这个条件语句可以不要,但那样i会无限度增大,我觉得不好,所以在i>36时,即转完1周时,让i=1。
i=1;
}
}
上面已经完成了三角函数的第一个应用:园周运动。

园周运动公式:
MC._x = 园心x+半径*Math.cos(i*增量*Math.PI/180);
MC._y = 园心x+半径*Math.sin(i*增量*Math.PI/180);
i++;

你非常高兴,因为你已经会让对象做园周运动了,你很快就想到了要做一个月亮围绕地球运转的效果。但问题出现了,月亮的运轨迹好象是椭园的。不要作急,我们来比较一下园和椭园的区别,很快我们发现椭园与园的区别就是x轴半径和y轴的半径不相等。于是乎,椭园运动公式出来了。

椭园运动公式:
MC._x = 园心x+x轴半径*Math.cos(i*增量*Math.PI/180);
MC._y = 园心x+y轴半径*Math.sin(i*增量*Math.PI/180);
i++;

恭喜,你现在连椭园运动都会了。我们再来研究一下,看看三角函数还能搞点什么名堂。

上面说过,要研究三个三角函数,上面只用了两个,好象还有个flash专用的反正切函数:atan2.这个函数是根据某点的x,y值计算出该点与x轴之间的角度:
e = Math.atan2(y,x);

能不能算出两点之间的角度偏差呢?还是来看看图:

 

在图中有两个点a和b,将两个点用一根线连起来,通过a点作y轴平行线,通过b点作x轴平行线,这样三根线就组成了一个直角三角形。有了三角形就好办了,我们的三角函数就该上场了。先来分析一下这个直三角形,不难看出,三角形的两条直角边实际就是两点的坐标差,分别是:(x1-x2)和(y1-y2).而角e就是是两点间的角度差。有了角度差,就想如果将b点旋转一个角差,那么b点的方向就与a点一样了。如果将a点换为鼠标,在鼠标移动时始终计算b点与鼠标的角差,然后让b点旋转这个角差,这样b点会一直指向鼠标跑都跑不脱。效果如下:

代码:
onEnterFrame = function(){
var dx = _xmouse - jt_mc._x;
var dy = _ymouse - jt_mc._y;
var angle = Math.atan2(dy,dx)*180/Math.PI;
jt_mc._rotation = angle;
}

跟随鼠标旋转公式:
onEnterFrame = function(){
var dx = _xmouse - MC._x;
var dy = _ymouse - MC._y;
var angle = Math.atan2(dy,dx)*180/Math.PI;
MC._rotation = angle;
}

这里要注意两点:1. atan2(dy,dx)是dy在前,dx在后,这一点容易搞错。2.由atan2()计算出的角度是弧度,而我们要设置_rotation属性要用角度,所以要用180/Math.PI;弧度转为角度。硬是妖怪得很,一会转过去,一会转过来。

现在你又想出了新花样了,光是跟着鼠标转还不行,还跑过去抓住它。还是看上面那个图,b点要到a点,是不是b点的x加上(x1-x2), b点的y加上(y1-y2)就行了呢。但即然是跟跟随肯定不能一步到位,要不就不是跟随了,而是帖在一起了,也就是说趋于直角三角形的斜边一能一步到位,而是一点一点地增加,这就需在设一个增量。根据前面的三角函数公式就可算出每次增加的x和y的量了。
vx = 增量*Math.cos(e);
vy = 增量*Math.sin(e);

将b点的x,y不停地加上这个vx,vy,b点就不停地向a点靠近了。

效果:

代码:
var speed = 3;
onEnterFrame = function(){
var dx = _xmouse - jt_mc._x;
var dy = _ymouse - jt_mc._y;
var angle = Math.atan2(dy,dx)*180/Math.PI;
jt_mc._rotation = angle;
jt_mc._x += speed*Math.cos(angle);
jt_mc._y += speed*Math.sin(angle);
}

鼠标跟随公式:
var speed = 一个数字;
onEnterFrame = function(){
var dx = _xmouse - MC._x;
var dy = _ymouse - MC._y;
var angle = Math.atan2(dy,dx)*180/Math.PI;
MC._rotation = angle;
MC._x += speed*Math.cos(angle);
MC._y += speed*Math.sin(angle);
}

将本节介绍的内容与上节介绍的绘图方法结合,可以绘制出很多图形,如园,椭园,正,余弦波形等。这个留给大家研究。下面做一个经典的练习,图片旋转,制作方法来源于网络:

下面是我的鼠绘作品的一个算是展示吧:

我选了6张作品,导入到库中。然后,新建一个MC,共6个关键帧,每个关键帧,放一张图片,大小统一调为150x200.然后在库中右击MC>“连接”,点中“为ActionSpript运行时导出“前的钩,在标识符一栏内输入:imge.

回到主场景,打开帧动作面板,输入:

var r = 200;
var v = 1;
for (var i = 1; i<=6; i++) {
attachMovie("imge", "mc"+i, i);
_root["mc"+i].gotoAndStop(i);
_root["mc"+i].cita = i*60;
_root["mc"+i]._y = 200;
}
onEnterFrame = function () {
v = (275-_root._xmouse)/25;
for (var i = 1; i<=6; i++) {
with (_root["mc"+i]) {
cita += v;
_alpha = 50+(100+100*Math.sin(cita/180*Math.PI))/4;
_xscale = 100*Math.sin(cita/180*Math.PI)*_alpha/100;
_yscale = 75+(100+100*Math.sin(cita/180*Math.PI))/8;
_x = 75+r-r*Math.cos(cita/180*Math.PI);
}
_root["mc"+i].swapDepths(Math.round(_root["mc"+i]._xscale));
}
};

代码分析:

首先通过一个for循环,将图片元件加载6次,每一次加载后,让它停在不同的帧上,这样舞台上实际上就有6张不同的图片了,这是一个非常有趣的方法,值得学习。同时为每张图片设置了一个不同的初始量Cita,共6张图片,一个园周是360度除以6等于60,这样6张图片被设为i*60,即均匀分布。最后将图片的y坐标固定在200,因为图的旋转实际就是图片从左到右往返运动而已,y坐标是不变的。
for (var i = 1; i<=6; i++) {
attachMovie("imge", "mc"+i, i);
_root["mc"+i].gotoAndStop(i);
_root["mc"+i].cita = i*60;
_root["mc"+i]._y = 200;
}
接下来的代码可能不是太好理解,请记住一点,正弦,余弦函数的值是从1到-1来回变化的,这一点很重要,在下面的代码中充分地运用了这个原理。通过 onEnterFrame事件使动画不断重复,每重复一次,每一个图片的Cita加上鼠标x坐标与舞台中线的差值除25,也就是说设置了一个增量,所以这 25可以自行改变,值越大转得越慢。
onEnterFrame = function () {
v = (275-_root._xmouse)/25;
for (var i = 1; i<=6; i++) {
with (_root["mc"+i]) {
cita += v;

接下来设置图片的透明度,来理解一下这句:
_alpha = 50+(100+100*Math.sin(cita/180*Math.PI))/4;
首先看:Math.sin(cita/180*Math.PI)这个函数的值上面说了是从1到-1来回变化的。那么100*Math.sin(cita /180*Math.PI)10到-100来回变化,100+100*Math.sin(cita/180*Math.PI))就是200到0之间的变化了,(100+100*Math.sin(cita/180*Math.PI))/4就是50到0之间变化了,50+ (100+100*Math.sin(cita/180*Math.PI))/4;就是50到100之间变化了。这一句的作用就是使透明度在正面时为 100,转到背面时为50.
接下来:
_xscale = 100*Math.sin(cita/180*Math.PI)*_alpha/100;
100*Math.sin(cita/180*Math.PI)的值是100到-100,_xscale属性设为-100时的效果是水平翻转,这就形成了在正面的背面方向不一样的效果,也行成了在两端时的翻转效果。*_alpha/100;应该是让图片的正反面与透明度同步。
下一句:
_yscale = 75+(100+100*Math.sin(cita/180*Math.PI))/8;
算得出来这是让图片的高在75到100之间变化,即在背面时高度要小一些。
下一句:
_x = 75+r-r*Math.cos(cita/180*Math.PI);
可以算出等号后面的式子值为75到475之间变化,这就确平方和了图片在75到475间左右移动。
最后一句:
_root["mc"+i].swapDepths(Math.round(_root["mc"+i]._xscale));
深度交换,让图片在最大时(正面),在最上面,以形成正面图片遮住背面图片的效果。