加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

转 第三章 三角学应用(2)(as3.0)

发布时间:2020-12-15 06:44:16 所属栏目:百科 来源:网络整理
导读:反正切(Arctangent) ? ? ? 大家可能都猜到了,反正切简单地说就是正切函数的反函数。我们只要输入对边与邻边 的比值,就可以得到相应的角度。 ? ? ? 在 Flash 中有两个函数可计算反正切。第一个就是像前面介绍过的函数一样 Math.atan(ratio),只需提供对边与

反正切(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.565051177078,这正是角 B 的度数。下面再输入-1/-2(角 D),再来试试:
trace(Math.atan2(-1,-2) * 180 / Math.PI);
出乎意料的结果–153.434948822922.为什么会这样?图 3-14 能给你解释。



图 3-14 一个角的两种表示方法
????? 从角 D 自身的底边开始,它确实为 26.57 度,但别忘了 Flash 的角度是从 X 轴的正半
轴顺时针计算的。因此,从 Flash 的角度来衡量,则该角被视为-153.43 度。下面就要开
始在 Flash 中实践和应用三角学了。
旋转(Rotation)
????? 我们想让一个影片剪辑或 Sprite 影片通过旋转来指向鼠标的位置,?? 这将是个挑战。旋
转(rotation)将成为我们工具箱中非常的工具,可以应用于游戏制作,鼠标追踪,界面设计
等。
????? 下面看一个示例。也可以根据以下步骤或打开文档类 RotateToMouse.as 和
Arrow.as(与本书中其它代码一同在 www.friendsofed.com 下载),这些是已写好的代码。
首先,需要让物体旋转,它可以是一个在 Sprite 中绘制的箭头(Arrow)。事实上,如果我
们要反复应用到这个箭头,可以把它制作成一个类:
package {
? import flash.display.Sprite;
? public class Arrow extends Sprite {
?? public function Arrow() {
???? init();
?? }
?? public function init():void {
???? graphics.lineStyle(1,1);
???? graphics.beginFill(0xffff00);
???? graphics.moveTo(-50,-25);
???? graphics.lineTo(0,-50);
???? graphics.lineTo(50,0);
???? graphics.lineTo(0,50);
???? graphics.lineTo(0,25);
???? graphics.lineTo(-50,-25);
???? graphics.endFill();
?? }
? }
}
????? 这里使用到了绘图 API (会在下一章介绍)来绘制箭头。无论何时需要一个箭头,只需
写一句 new Arrow()即可,在图 3-15 中可看到显示结果。当绘制一些图像并进行旋转时,
要注意它的指向,默让地指向右边,X的正半轴,这就是它旋转到 0 度时的状态。
????? 我们先要创建一个Arrow类的实例,放致于舞台中心,并让它指向鼠标的方向.



图 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 事件。以下是这个完整的文档类:
package {
? import flash.display.Sprite;
? import flash.events.Event;
? public class RotateToMouse extends Sprite {
?? private var arrow:Arrow;
?? public function RotateToMouse() {
???? init();
?? }
?? private function init():void {
???? arrow=new Arrow ;
???? addChild(arrow);
???? arrow.x=stage.stageWidth / 2;
???? arrow.y=stage.stageHeight / 2;
???? addEventListener(Event.ENTER_FRAME,onEnterFrame);
?? }
?? public function onEnterFrame(event:Event):void {
???? 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;
?? }
? }
}
??? 请确认 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 就无法知道所指的是哪个角,所以
????????????????? 如果,鼠标处于D角区域,Flash 会回到B角区域并把箭头指向这个角度。
只能得到A与或角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 影片,请看代码:
package {
? import flash.display.Sprite;
? public class Ball extends Sprite {
?? private var radius:Number;
?? private var color:uint;
?? public function Ball(radius:Number=40,color:uint=0xff0000) {
???? this.radius = radius;
???? this.color = color;
???? init();
?? }
?? public function init():void {
???? graphics.beginFill(color);
???? graphics.drawCircle(0,radius);
???? graphics.endFill();
?? }
? }
}
????? 当这个类被实例化后,就能绘制出一个圆。我们还可以自行给出圆的半径(radius)和颜
色(color)。如果不给这些参数的话,就会使用默认的参数:半径为 40,颜色为红色(这是
AS3.0 新增的功能)。这个类非常简单,但却非常有用,今后在书中会经常用到,所以大家
一定要掌握。
????? 文档类创建一个 Ball 类的实例,并加入到舞台上,再为它增加一个 enterFrame 侦听
器,这样就可以让小球上下移动了。
package {
? import flash.display.Sprite;
? import flash.events.Event;
? public class Bobbing extends Sprite {
?? private var ball:Ball;
?? private var angle:Number = 0;
?? public function Bobbing() {
???? init();
?? }
?? private function init():void {
???? ball = new Ball();
???? 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 += .1;
?? }
? }
}
首先,需要一个角度属性(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) * range;
? angle += speed;
}
在运动代码中没有使用具体的数值,真是次非常好的练习,以后应尽量这样做。

?

线性垂直运动
????? 在 Wave1.as 文件中,加入了线性垂直运动,只是为我们制作动画增加一些灵感。以下
是这个文件的代码:
package {
? import flash.display.Sprite;
? import flash.events.Event;
? public class Wave1 extends Sprite {
?? private var ball:Ball;
?? private var angle:Number = 0;
?? private var centerY:Number = 200;
?? private var range:Number = 50;
?? private var xspeed:Number = 1;
?? private var yspeed:Number = .05;
?? public function Wave1() {
???? init();
?? }
?? private function init():void {
???? ball = new Ball();
???? addChild(ball);
???? ball.x = 0;
???? addEventListener(Event.ENTER_FRAME,onEnterFrame);
?? }
?? public function onEnterFrame(event:Event):void {
???? ball.x += xspeed;
???? ball.y = centerY + Math.sin(angle) * range;
???? angle += yspeed;
?? }
? }
}

?

?

心跳运动
????? 使用正弦值作为一种工具,不仅仅只用于控制物理位置。在 Pulse.as 文件中,使用一
个值来影响小球的缩放,实现一个心跳的效果,代码如下:
package {
? import flash.display.Sprite;
? import flash.events.Event;
? public class Pulse extends Sprite {
?? private var ball:Ball;
?? private var angle:Number = 0;
??? private var centerScale:Number = 1;
?? private var range:Number = .5;
?? private var speed:Number = .1;
?? public function Pulse() {
???? init();
?? }
?? private function init():void {
???? ball = new Ball();
???? 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) * range;
???? angle += speed;
?? }
? }
}
原理是一样的,centerScale 表示 100%的缩放比, range 表示范围, speed 表示速度。不
仅如此,正弦波还在 alpha,rotation 等属性中应用。

?


双角波形
??? 再给大家一种思想:设置两套数值 angle1 和 angle2,为它们各自增加一个中心点
(center)和速度(speed)值。用一个正弦波作为一种属性,另一个正弦波作为另一种属性,
比如位置或缩放。我不敢保证能够得到什么有用的结果,但这样做的话,就等于让这些函数
自由发挥作用。
??? 从 Random.as 文档类开始,这里面拥有两个角度(angle),两个速度(speed)和两个中
心点(center),将其中一个角(angle1)作为小球的 X 坐标,另一个角(angle2)作为 Y 坐标。
运行程序时,就像只虫子在房间里飞,虽然这些数字都是预先定义好的,但结果却没有什么
规律可言。代码如下:

package {
? import flash.display.Sprite;
? import flash.events.Event;
? public class Random extends Sprite {
?? private var ball:Ball;
??? private var angleX:Number = 0;
??? private var angleY:Number = 0;
??? private var centerX:Number = 200;
??? private var centerY:Number = 200;
?? private var range:Number = 50;
??? private var xspeed:Number = .07;
??? private var yspeed:Number = .11;
?? public function Random() {
???? init();
?? }
?? private function init():void {
???? ball = new Ball();
???? addChild(ball);
???? ball.x = 0;
???? addEventListener(Event.ENTER_FRAME,onEnterFrame);
?? }
?? public function onEnterFrame(event:Event):void {
???? ball.x = centerX + Math.sin(angleX) * range;
???? ball.y = centerY + Math.sin(angleY) * range;
???? angleX += xspeed;
???? angleY += yspeed;
?? }
? }
}

?

绘制波形 ???? 最后, Wave2.as 中, ?????????? 在??????????? 不再使用小球,转而使用绘图 API 来绘制正弦波形。代码如下: package { ?import flash.display.Sprite; ?import flash.events.Event; ?public class Wave2 extends Sprite { ? private var angle:Number = 0; ? private var centerY:Number = 200; ? private var range:Number = 50; ? private var xspeed:Number = 1; ? private var yspeed:Number = .05; ? private var xpos:Number; ? private var ypos:Number; ? public function Wave2() { ??? init(); ? } ? private function init():void { ???? xpos = 0; ???? graphics.lineStyle(1,1); ???? graphics.moveTo(0,centerY); ???? addEventListener(Event.ENTER_FRAME,onEnterFrame); ?? } ?? public function onEnterFrame(event:Event):void { ???? xpos += xspeed; ???? angle += yspeed; ???? ypos = centerY + Math.sin(angle) * range; ???? graphics.lineTo(xpos,ypos); ?? } ? } } ????? 下一章我们会详细讲述绘图 API,大家也应该有兴趣来执行一下这个文件,观察一下绘 制出的波形。注意,由于 Flash 的 Y 轴是反向的,所以绘制出的波形也是颠倒的。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读