ActionScript 3.0动画基础-3
作者: egoldy性质: 翻译阅读次数: 11624发表时间: 2007-06-26 15:14:42声明: 此文章为未出版的keith peters的ActionScript 3.0 making things move中文版样章。为书中的第二章。webstudio会在中文版出版之际,友情提供论坛forum支持。转载请注明出处,谢谢! 2.5使用代码动画?
图2-3.逐帧动画? 当你在Flash中进入到图形或是元件符号中,可能情况会有些不同。Flash不能每一帧创建和保存一张新的图像,即使是在逐帧动画中。在每一帧 上,Flash保存着舞台上每个对象的位置,大小,颜色等等。因些,如果你有一个穿过屏幕的小球,那么每一帧将会保存当前帧上小球的位置。可能第一帧小球 位于距左边10像素的位置,第二帧可能就是15像素,如此这样。Flash 播放器读取到这些数据,根据这些描述来设置舞台,并且显示帧。根据这些,你可以得到另外一扩展后的流程,如图2-4所示。? 但是当你思考如何描述一个动态的,ActionScript动画时,它的流程看起来是这样的。如图 2-5.
图2-5. 脚本动画? 如你所见到的图2-5,没有第一帧,第二帧的概念等等。ActionScript动画一般可以做到,通常都是这样,只在一帧上发生。这里你可以开始了解我的说的循环。? 首先,你设置一个初始化状态。你可拖动一个影片剪辑到舞台上,如同你要创建一个补间动画。或都你可以只用代码描述整个场景。不管是哪种方法,你都要渲染和显示帧。? 接下来,应用你的规则。这个规则可以简化为,“这个小球向右移动5个像素,” 或者他们可以使用复杂的三角法来制作成许多线。本书中的范例将会涉及这些范围。? 应用规则将会得到一个新的状态—一个新的被渲染和显示的描述。然后不断重复的应用相同的规则。? 注意那是相同的一组规则被重复的使用。你不需要为第一帧设置一组规则,然后在为第二帧设置另一组规则,如此等等。因此,你的任务的是设置一组规则 它可以应付你场景中所有可能的情况。当发生了小球快速的移动右边并移出屏幕怎么办?你的规则需要考滤到它。你是否允用户使用鼠标与这些小球进行交互?你的 规则同样需要将它考滤进去。? 它看上去有些让人害怕,但实际上它并不是真的那么复杂。基本上你都可通过一个或两个规则创建一些非常简单的行为,当它们可以正常工作时,在加入其它的规则。? 这里面的”rules”规则,我一直这样叫它们,实际上就是指ActionScript声明。每一个规则可以是一个单一的声明或几个组合再或者是许多声明。在这个例子中小球向右移动5个像素,它的规则看上去如下样子: ball.x = ball.x + 5; 你只是指出了小球的x位置(水平方向),增加5,来产生一个新的x位置。你可以更简单写在如下代码: ball.x += 5; +=操作符只是将右边的值增加到左边的变量中。并将结果指定给变量。? var dx:Number = mouseX - ball.x; var dy:Number = mouseY - ball.y; var ax:Number = dx * spring; var ay:Number = dy * spring; vx += ax; vy += ay; vy += gravity; vx *= friction; vy *= friction; ball.x += vx; ball.y += vy; graphics.clear(); graphics.lineStyle(1); graphics.moveTo(ball.x,ball.y); graphics.lineTo(mouseX,mouseY); 现在不要提心它们是什么意思,只要知道Flash将需要运行这样的代码来生成每一个新的帧。? for(i = 0; i < 500; i++){ ball.x = i; } 它看上去非常的简单。变 量i的初始值为0,小球影片剪辑放在舞台上x轴0的位置。i++会使变量i在循环时每次都增加1,从0到1到2,3,4,如此等等,每执行一次,值就会指 定给ball.x,让它从舞台的左右移动它到右边。当i达到500时,i<500的声明就会变成false,循环就会停止。?
图 2-6.为什么你不能使用for来动画? 你确实应用了规则并且移动了小球的位置,创建的500次的新场景。但是直到循环结束时它才得以显示。这是因为Flash只是在最后一帧的时候才更新了场景。这是非常重要的一点。? 这里是每一帧执行动作的顺序:? 1.在舞台上放置好所有物体的位置,包括任何级别,任何层,载入影片剪辑,如此等等。? 2.执行那一帧上所有需要被调用的ActionScript,包括任何层或级别上的任何影片剪辑或按钮,或是嵌套的影片剪辑,无论有多深。? 3.检查是否有时间来显示帧。如果你设置了帧频为每秒20帧,Flash将检测是否在至少50毫秒的时间可以显示一个帧。如果可以,它将显示刚刚渲染的这一帧并且移动到下一个帧。如果不可以,它将等待直到正确的时间数量都过去。? 你需要知道一些关于时间因素的问题。首先,帧频率从来都是不精确的(即便是现在的Flash Player 9影片)。不要指望他们会有严格准确的时间。第二,很可能出现渲染或ActionScript执行的时间超过分配给每一帧的时间。你不必担心你的脚本会被 裁切掉,而Flash会在移到上面的第三步之前完成脚本的执行(第二部),尽管它会慢于帧频率。Flash其实会在指定的帧上为完成你的脚本等待15秒。 它将会显示出一行提示信息”一个脚本导致了播放器运行缓慢……”等信息。? 在前面的范例中,Flash在进入到下一帧之前,在等待For 循环的结束,并且它只在去往下一帧之前才更新屏幕。这就是为什么你只看到了一个跳跃,而不是移动。? 因此,你所需要做的就是通过帧打破这种循环,因此你需要回到如图2-5所示的流程。? 2.5.2帧循环? 因为这本书并不是讲关于处理时间线和单独某一帧上的内容,所以我不打算给出一个确切的帧循环的例子;而在这里,我只是描述这个概念。如果你使用的是Flash CS3 IDE,它可能是一个很的教学来真正的开始你自已的范例。? 说到帧循环的思路我们要回到早期版本的Flash,当时ActionScript并不象今天这样强大。它的思路是将一些代码放在一个指定的帧上, 然后在另一个帧上放一个语句,通常是gotoAndPlay,它可以让播放头回到前一帧上。这样就在两帧之间形成了一个无穷的循环,每当播放头播放到有代 码的帧时,就会执行帧上的代码。? 比较重要需要注意的是因为它有两帧,代码被执行,屏幕被更新和显示,以及播放头的移动。这样屏幕会在每次重复执行代码时刷新,你就得到了动画。? 例如,在你的舞台上有一个影片剪辑名为ball。那么第一帧上的代码应是象这样: ball.x ++; 第二帧的代码这样: gotoAndPlay(1); 实际上,在这个例子中第二帧可以什么也没有,因为时间默认状态下会自动的回放。? onClipEvent(eventName){ // 代码写在这里 } 除了onClipEvent(eventName)之外,还有on(eventName),这个”on”事件还作用于鼠标和键盘动作,如按下(press)和松开(release)。? onClipEvent(load){ // 初始化代码 } enterFrame事件发生在Flash每次准备开如渲染下一帧时,即便是只有一帧的影片。例如,如果帧频率设为每秒钟20帧,enterFrame将 会大约每隔50豪秒运行一次。这个enterFrame 剪辑事件就是你经常应用“规则(ruler)”或动作代码的位置,因为你有两个需求:重复代码和每次执行后的重新显示。它看上去如下: onClipEvent(enterFrame){ // 动作代码 } 这样,你将一个影片剪辑放置在时间线上,然后将下面的代码加在上面(注意这里是早期的AS 1语法): onClipEvent(load){ this._x = 100; this._y = 100; } onClipEvent(enterFrame){ this._x += 5; } 另外,本书中的范例并没有使用这种设置方式(因为它不在是AS3语言中的一部分),但是有三个要点需要注意,初始化,重复动作,和屏幕刷新,它将是你在任何系统中制作任何动画的一部分。? addEventListener(Event.ENTER_FRAME,onEnterFrame); 如果你去查看Event.ENTER_FRAME的属性值,会发现它其实就是一个简单的字符串“enterFrame”。现在,你可能会想这种方式同样会 非常容易写成Event.ENTOR_FRAME。但是这里的改进是如果你写错了,你的程序将拒绝编译并会正确的告诉你在Event类中没有那样的属性。 它不但会精确的指示出你错在第几行,而且也会精确到这一行的哪一个单词上。它可以说好的不能再好了,除非有一天编译器可以更改你的错误,并且能为你写代 码。? mySpriteButton.addEventListener(MouseEvent.MOUSE_DOWN,onSpritePress); 最后需要注意的事情是它不象之前版本的ActionScript,必须要用指定的事件处理函数名称如onEnterFrame,在AS3中当你加入侦听者 时,你可以为你的事件处理函数命名任意的名称。在enterFrame的范例中,我使用onEnterFrame做为一个处理者(handler),那只 是因为它比较适合我并且习惯于这样使用它。在AS3中,onEnterFrame已不在是固定不变的。我可以很随意的将enterFrame处理函数命名 为move,run或doSomethingColl。然而按照惯例,事件处理函数通常是以on开头,后面跟随着事件的描述和可能来自于哪儿,如 onStartButtonClick,,onConfigXMLLoad, 或 onRocketCrash。还有一些人喜欢在事件名称后面加上Handler后缀来做为事件处理函数名称----例 如,enterFrameHandler。 那么,这只是一个偏好的问题,最重要的事情是保持一致性,你只要能做到一看到它就知道它是事件处理函数即可。? removeEventListener(Event.ENTER_FRAME,onEnterFrame); 这就是在告诉对象从自身的侦听指定事件的侦听者列表中移除侦听者,因此它将不会在接受到其它任何的提醒。? package { import flash.display.Sprite; import flash.events.MouseEvent; public class EventDemo extends Sprite { private var eventSprite:Sprite; public function EventDemo() { init(); } private function init():void { eventSprite = new Sprite(); addChild(eventSprite); eventSprite.graphics.beginFill(0xff0000); eventSprite.graphics.drawCircle(0,100); eventSprite.graphics.endFill(); eventSprite.x = stage.stageWidth / 2; eventSprite.y = stage.stageHeight / 2; eventSprite.addEventListener(MouseEvent.MOUSE_DOWN,onMouseDown); eventSprite.addEventListener(MouseEvent.MOUSE_UP,onMouseUp); } private function onMouseDown(event:MouseEvent):void { trace("mouse down"); } private function onMouseUp(event:MouseEvent):void { trace("mouse up"); } } } 怎么理解呢?init函数的最主要的作用是创建一个精灵(sprite),然后在里面绘制一个圆形,然后将它对齐在舞台的中心。最重的是最后两行。这个类 将它自已加入作为一个侦听者,来侦听两个事件,MOUSE_DOWN和MOUSE_UP。注意它们是MouseEvent类的属性,MouseEvent 类必须要先导入。作为处理者(handlers,也有人称为句柄),你传入onMouseDown和onMouseUp函数,他们要放在后面。处理者 (handler)通常接收传过来的一个包含事件信息的对象。简单讲,它将包括一些对象触发事件的信息。在本例中的鼠标事件,它包括在事件发生时鼠标的位 置,哪个鼠标按键被按下,等等信息。对于键盘事件,它将包括在事件过程中哪个键子被按下;其它按键的状态,如Ctrl,Alt,和Shift键。可以参考 帮助文件来查看各种事件类型所包括的信息。? package { import flash.display.Sprite; import flash.events.Event; public class FirstAnimation extends Sprite { private var ball:Sprite; public function FirstAnimation() { init(); } private function init():void { ball = new Sprite(); addChild(ball); ball.graphics.beginFill(0xff0000); ball.graphics.drawCircle(0,40); ball.graphics.endFill(); ball.x = 20; ball.y = stage.stageHeight / 2; ball.addEventListener(Event.ENTER_FRAME,onEnterFrame); } private function onEnterFrame(event:Event):void { ball.x++; } } } Init函数创建一个名为ball的精灵(sprite)并且设置了事件侦听者。onEnterFrame函数用来实现动画,移动小球,之后屏幕会被刷新。它并不是很复杂,但是这是本书中所有其它内容的基础,所以要很好的理解它。? 好,我们已经涉及了很多的关于如何架构ActionScript动画的内容。解释了如何应用规则来不断的重复运行,以及如何在应用了程序规则后更 新屏幕来产生运动错觉。但是你能用它来移动什么呢?目前为止,你已经可以移动一个精灵(sprite),但是目前的所有代码只是简单应用在一个影片剪辑 上。下一步,我们将研究如何创建精灵和影处剪辑并使用显示列表(display list)来使用显示。? 未完待续 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |