《3.0 动画基础.docx》由会员分享,可在线阅读,更多相关《3.0 动画基础.docx(19页珍藏版)》请在课桌文档上搜索。
1、3.0动画基础3.0动画基础/s/articlelist_1053530897_3_l.html类和面对对象编程类(ClaSS)和面对对象(ObjeCtOriented),对于有些读者来说可能还没接触过而有些读者可能已经在AS(或其它语言)中运用类很多年了,为了让大家都能学会,我会扼要的介绍一下这些基础学问。就算是AS2的OOP专家也希望能略读下这一段,因为AS3.0的工作原理的确发生了很大的变更。假如你说你从没用过类,那你就错了,只要你在Flash中写过代码,那么事实上就已经运用了类。类可以简洁理解为一种对象,MovieClip就是影片剪辑的类,而文本框、影片剪辑、按钮、字符串和数值等都有它
2、们自己的类。一个类最基本的两个部分:属性(数据或信息),行为(动作或它能做的事)。属性(ProPerty)指用于保存与该类有关的信息变量,行为(BehaVior)就是指函数,假如一个函数是这个类中的一部分,那么我们就称它为方法(Method)。一个基本的类:常用Flash的挚友都知道,我们可以在库中创建一个元件,用这个元件可以在舞台上创建出很多的实例。与元件和实例的关系相同,类就是一个模板,而对象(犹如实例)就是类的一个特别表现形式。下面来看一个类的例子:packagepublicclassMyClasspublicvarmyProperty:Number=100;publicfunction
3、myMethod()tracedamhere);先来说明一下这段代码。在这里有些新的学问,对于AS2老手也如此:包的声明。包(PaCkage),作用就是把相关的类进行分组。知道这一点就够了,我们不再进行深化的探讨,本书的示例甚至不会用到包。Package这个关键字和一对大括号是必需有的,我们理解为默认包,紧随其后的就是类的定义。另一个变更是AS3.0中的类拥有了访问关键字。访问关键字是指:一个用来指定其它代码是否可访问该代码的关键字。public(公有类)关键字指该类可被外部任何类的代码访问。本书中全部示例的类都是public的。在深化学习了AS3.0后,我们会发觉不是全部类都是公有的,甚至还
4、有多重的类,这些内容超出了本书的谈论范围Q本例中我们可以看到,这个类的名字为MyClass,后面跟一对大括号。在这个类中有两种要素,一个是名为myProperty的变量,另一个是名为myMethod的函数。包(PaCkage)包主要用于组织管理类。包是依据类所在的书目路径所构成的,并可以嵌套多层。包名所指的是一个真正存在的文件夹,用.进行分隔。例如,有一个名为Utils的类,存在于文件夹com/friendsofed/makingthingsmove/中(运用域名作为包名是一个不成文的规定,目的是保证包名是唯一的)。这个类就被写成com.friendsofed.makingthingsmove
5、.Utils0在AS2中,运用整个包名来创建一个类,例如:classcom.friendsofed.makingthingsmove.Utils)在AS3中,包名写在包的声名处,类名写类的声名处,例如:packagecom.friendsofed.makingthingsmovepublicclassUtils导入(1.nPort)想象一下,每次要运用这个类的方法时都要输入com.friendsofed.makingthingsmove.Utils,是不是太过烦琐太过死板了。别担忧,import语句可以解决这个问题。在这个例子中,可以把下面这句放在package中类定义的上面:importco
6、m.friendsofed.makingthingsmove.Utils;C构造函数(COnStrUCtor)构造函数是指一个名字与类名相同的方法。当该类被实例化时,该函数会被自动调用,也可以传入参数,例如:首先,创建一个类:packagepublicclassMyClasspublicfunctionMyClass(arg:String)trace(constructed);trace(youpassed+arg);然后,假设工作在FlashCS3IDE(集成开发环境)中,在时间轴上创建该实例:varmyInstance:MyClass=newMyClass(hello);结果输出:cons
7、tructedyoupassedhello继承(InheritanCe)一个类可以从另一个类中继承(inherit)和扩展(extend)而来这就意味着它获得了另一个类全部的属性和方法(除了那些被private掩盖住的属性)。所生成的子类(派生类)还可以增加更多的属性和方法,或更改父类(基类)已有的属性或方法。要分别创建两个类来实现(两个独立的.as文件),例如:packagepublicclassMyBaseClasspublicfunctionsayHello():voidtrace(HellofromMyBaseClass);packagepublicclassMySubClassext
8、endsMyBaseClasspublicfunctionSayGoodbye():voidtrace(GoodbyefromMySubClass);不要遗忘,每个类都必需在其自身的文件中,文件名为该类的类名,扩展名.as,所以必须要有MyBaseClass.as文件和MySubClass.as文件。因此,在运用FlashCS3IDE时,保存的F1.A文件,要与这两个类在同一个文件夹。下面代码会生产两个实例,把它写入时间轴看看会发生什么:varbase:MyBaseClass=newMyBaseClass();base.sayHello();varSubiMySubClass=newMySub
9、Class();sub.sayHello();sub.SayGoodbyeO;第一个实例没什么可说的,值得留意的是其次个实例中的SayHello方法,虽然在MySubClass中没有定义SayHello,但它却是继承自MyBaseClass类的。另一个值得留意的是,增加了一个新的方法SayGoodbye,这是父类所没有的。下面说说,在子类中如何变更一个父类中已存在的方法。在AS2中,我们可以只须要重新定义这个方法就可以了。而在AS3中,则必需明确地写出override关键字,来进行重新定义。packagepublicclassMySubClassextendsMyBaseClassoverri
10、depublicfunctionSayHello():voidtrace(HolafromMySubClass);publicfunctionSayGoodbye():voidtrace(GoodbyefromMySubClass);请留意,原来的SayHello方法被重写,再调用MySubClass后,就有了新的信息。另外,私有成员也不能被重写,因为它们只能被它们自身的类访问。MovieClipZSprite子类我们可以自己写一个类,然后让另一个类去继承它。在AS3中,全部代码都不是写在时间轴上的,那么它们一起先都要继承自MovieClip或SpriteoMovieClip类是影片剪辑对象属
11、性和方法的ActionScript模板。它包括我们所熟识的属性如:影片的x,y坐标,缩放等,这些在AS3中的变更不大。AS3还增加了Sprite类,通常把它理解为不在时间轴上的影片剪辑。很多状况下,只运用代码操作对象,并不涉刚好间轴和帧,这时就应当运用Sprite这个轻型的类。假如一个类继承自MovieClip或Sprite,那么它会自动拥有该类全部的属性和方法,我们还可以为这个类增加特别的属性和方法。例如,嬉戏设计一个太空船的对象,我们希望它拥有一个图形,并且在屏幕的某个位置移动,旋转,并为动画添加enterFrame侦听器,还有鼠标、键盘的侦听等。这些都可以由MovieClip或Sprit
12、e来完成,所以就要继承自它们。同时,还可以增加一些属性如:速度(SPeed)、油量(fuel)、损坏度(damage),还有像起飞(takeff)坠落(crash)射击(shoot)或是自毁(selfDestruct)等方法。那么这个类或许是这样的:packageimportflash,display.Sprite;publicclassSpaceShipextendsSpriteprivatevarSpeedrNumber=O;privatevardamage:Number=O;privatevarfuel:Number=100O;publicfunctiontakeff():void/.p
13、ublicfunctioncrash():void/.publicfunctionshoot():void/publicfunctionSelfDestructO:void/.留意,首先要导入flash,display包中的Sprite类,假如要导入MovieClip类,同样也须要导入这个相同的包flash,display.MovieClip类。创建文档类(DOCUInentclass)现在我们对类已经了肯定的了解,接下来,看看假如真正地运用它。有时候我常说基于AS3的SWF是多么的重要,这是因为AS3引入了一个全新的概念,文档类(documentclass)o一个文档类就是一个继承自Spri
14、te或MovieClip的类,并作为SWF的主类。读取SWF时,这个文档类的构造函数会被自动调用。它就成为了我们程序的入口,任何想要做的事都可以写在上面,如:创建影片剪辑,画图,读取资源等等。假如在FlashCS3IDE中写代码,可运用文档类,也可以选择接着在时间轴上写代码。但假如运用FlexBuilder2或免费FlexSDK,那里没有时间轴,唯一的方法就是写在类中。这些工作一切都围围着强大的文档类而绽开,没有它就没有SWFo以下是一个文档类的框架:packageimportflash,display.Sprite;publicclassTestextendsSpritepublicfunc
15、tionTest()init();privatefunctioninit():void/写代码处假如你看过前面的部分,不会认为这是个新学问,只不过是把他们放在了一起而已。运用默认包,导入并继承Sprite类。构造函数只有一句,调用init方法。当然,也可以把全部代码写在构造函数里,但是要养成一个好习惯,就是尽量削减构造函数中的代码,所以把代码写到了另一个方法中。本书会给大家很多代码块进行测试,那时要像上面这个例子一样把代码块放入init方法中,这样在影片编译执行时,就会调用init中的代码。下面我们要起先学习如何连接文档类和SWFo运用FlashCS3IDE(集成开发环境)FlashCS3ID
16、E是实现文档类的最便利的工具。把上述的类选择一个文件夹进行保存,文件名为TeSt.as。打开FlashCS3,创建一个F1.A文件,保存到一这个类相同的书目下。确认F1.A默认发布设置为FlashPlayer9及AS3.O0在属性面板中,我们留意到出现了一个名为文档类(DoCUmentClass)的区域(图2-1)o只需输入类名:Test0图2-1设置文档类请留意,我们输入的是类名,而不是文件名。所以这里不须要输入扩展名.as0假如这个类包涵在一个包中,那么就须要输入类的完整路径例如:com.friendsofed.chapter2.Testo程序动画下面,再来学习一些AS3编程的基本原理。假
17、如你已经选择好了一个开发环境,那么就动身吧。让我们进入ActionScript动画世界。动画的执行过程几乎全部的程序动画都包括几种不同的执行过程。对于逐帧动画来说,意味着创建和存储一组连续的位图,每一帧都是一幅图像,只须要进行显示即可,见图2-3o图2-3逐帧动画当我们在Flash中运用图形或元件时,事情就发了微妙的变更。这时,Flash不会为每一帧创建和存储新的位图。对于每一帧而言,Flash存储的是舞台上每个对象的位置,大小,颜色等等。比如,一个小球在屏幕上移动,每一帧只存储小球的在该帧上的位置,第1帧小球的位置在左边第10个像素,第2帧或许就在第15个像素,等等。Flash播放器(Fla
18、ShPIayer)读取这些信息,再依据这些信息的描述来渲染舞台并显示该帧。依据这些变更扩展一下流程图,见图2-4o图2-4渲染并显示帧我是这样描述一个动态程序动画的,见图2-5图2-5脚本动画如图2-5所示,没有第1帧、第2帧的概念,脚本动画通常只由一帧完成。下面我们就来看看动画的执行过程。首先,建立初始化。舞台中放入一个影片剪辑,再创建补间动画,或运用代码来描述整个场景。总之,最终都要对该帧进行渲染及显示。然后,应用自定义规则。规则可以像让球向右移动5像素这样简洁,也可以是由几十条困难的三角函数组成。运用自定义规则会产生新的描述再依据这些描述进行渲染及显示,并不断地应用这个规则。请留意,同一
19、规则被一遍又一遍地执行,而不是对第1帧用一套规则,而对第2帧又运用另一套规则。所以难度就在于,一套规则要处理全部可能出现的状况。要是球向右移动得过远,超出了舞台怎么办?你的这套规则就要解决这个问题。是否还希望用户通过鼠标来操作小球?那么你的规则也要把它考虑进去。听起来很困难,其实不然,这里所说的规则,事实上就是ActionScript代码。每套规则都可由一行或多行代码组成。下面是小球向右移动5像素的例子:ball.X=ball,x+5;这句话是说无论小球X坐标(水平轴)在哪里,都在原来的X位置上增加5像素,并把该坐标作为它的新X坐标。也可简化为:ball.X+=5;+=操作符:把右边的值与左边
20、的变量相加,相加的结果再赋值给该变量。以下是更多的高级规则,日后会学到:vardx:Number=mouseX-ball,x;vardy:Number=mouseY-ball,y;varax:Number=dx*spring;varay:Number=dy*spring;vx+=ax;vy+=ay;vy+=gravity;vx*=friction;vy*=friction;ball,x+=vx;ball.y+=vy;graphics,clear();graphics.IineStyle(1);graphics.moveTo(ball,x,ball,y);graphics.IineTo(mous
21、eX,mouseY);这段现在看不懂没关系,大家只要知道Flash会在每一帧中生成这段代码,并不断地执行。怎样让它循环执行?看看我第一次的尝试,这也是很多AS初学者都会犯的错误。这是在很多程序设计语言中都存在的循环结构,如for和whileo用循环结构使代码重复执行,这就是我曾写的那段:for(i=0;i500;i+)ball,x=i;看起来相当简洁。变量i从O起先,所以小球X坐标移动到0舞台最左边。i让i的值每次增长1,KP:01234,每次这个值都会做为ball.X的值,把小球从左向右移动。当值为500时,表达式i500值为假(false),循环结束。假如你也犯过同样的错误,就会知道,小球
22、没有在舞台上发生移动只是一下子出现在了舞台的右边而已。为什么没有移动到中间的那些点上?其实它移动了,只是我们没有看到,因为我们没有让Flash去刷新屏幕。图2-6为另一个流程图,看看实际都发生了什么。图2-6为什么循环结构无法产生动画事实上我们运用自定义规则使球移动到指定位置,并创建了500次新的场景。但在循环结束之前没有给出显示,这是因为Flash只在每一帧结束后才进行一次刷新只在每一帧结束后才进行一次刷新,这点很重要。以下是Flash进入帧的动作依次:在舞台上放置全部的对象,不论在何级,何层,或是否为加载的影片。执行帧上全部的Action脚本(ACtionSCript),不论在何级,何层,
23、不论处于影片剪辑还是按钮中,也不论它嵌套在何处。推断是否到了该显示的时候。假如设置帧频为20帧/秒,Flash最少要等上一帧显示后50毫秒后再进行下一次显示,显示了该帧后,就要编译和进入下一帧。假如帧频没有到20帧/秒,那么要等待到正确的时间再去执行。定时时间存在着一些问题。首先,众所周知帧频是不精确的(即使在Flash9中),不要依靠它作为精确的定时器。其次,在大量的编译和AS执行花费的时间会超出规定的时间。尽管如此,我们也不必担忧自己的脚本会被砍掉一部分。在进入第3步之前,Flash会完成全部可执行代码(第2步),即使须要延缓帧频也要完成。Flash为了能完成脚本,甚至会等上15秒。在上面
24、的例子中,Flash等待循环结束,然后进入下一帧,只在跳转到下一帧时进行屏幕的刷新。这就是为什么我们看到的是跳动而不是移动。因此,要想完成移动,我们所要做的就是打散这个循环,请回过头参考图2-5o帧循环帧循环的理念,存在于Flash最早的版本中,那时ActionScript还不像今日那么强大。把代码写入关键帧,并在下一帧中写入像gotoAndPlay这样的语句,使播放头(PIayhead)回到前一帧。这样两帧之间就形成了一个无限循环,每当播放头到了代码帧上时,就会执行那些代码。例如,在舞台上有一个实例名为ball的影片剪辑。第一帧的代码就像这样:ball.X+;其次帧的代码如下:gotoAnd
25、Play(l);事实上其次帧不须要做任何事,只是让时间轴自动回到第一帧而以。另一个版本是建立三个帧,第一帧进行初始化,写入只执行一次的代码,不进行循环。其次帧才是主要的执行代码,第三帧只写gotoAndPlay(2);这个方法在早期Flash版本中常被运用,虽然有点过时,但是同样可以精彩地完成任务。立刻我们还要学到更敏捷更强大的设置方法,但今后你会发觉其实原理上是一样的。影片事务影片事务在AS3中彻底的消逝了,这真是件好事。但还要捎带提一下,回顾Flash5的时代,只有帧循环和影片剪辑事务两种选择。影片事务指代码干脆写在影片剪辑上,而不是帧上。如何实现影片事务,首先选择舞台上的影片剪辑,然后打
26、开动作面板并将代码写在上面,这些代码只对该影片剪辑有效。全部代码必需写在事务块中,比如:OnClipEvent(eventName)/codegoeshere)对于OnClipEvent(eventName),作用于eventName(某种事务)。对于on类型事务则必需指定鼠标或键盘事务,如按下(PreSS)和释放(release)。事务名称(eventName)是指很多Flash影片事务之一,所谓事务就是在影片中发生的事。事务分为两种:系统事务和用户事务。系统事务指发生在如计算机,Flash,或影片上的事务,比如调取数据,调取信息,或播放帧等。用户事务是指用户所做的一些事,基本上就是鼠标和键
27、盘两种。影片事务运用得最多的就是load和enterFrame这两个。1.oad事件会在影片第一次出现在舞台上时才执行,且只执行一次。所以说特别适合在这里面写入初始化代码。只要把代码写在大括号间即可:OnClipEvent(Ioad)/initializationcode我们可以把带有如下代码的影片剪辑放入时间轴上(留意:此处为AS1写法):OnClipEvent(load)this._x=100;this._y=100;OnClipEvent(enterFrame)this._x+=5;本书示例中的代码不运用这种写法(因为它已经不是一种语言了),但不论运用何种方法,初始化(initializ
28、ation),重复动作(repeatingactions)和屏幕刷新(SCreenrefresh)都是特别重要的。事务及事务处理FlashMX的ActionScrpt发生了重要的变更,这些转变与革新为Flash成为真正的富客户端程序(RIA)奠定了基础。其中一个就是全新的事务结构,在编写特别困难的行为时比之前的版本好用很多。FlashMX之前的版本,只能把代码放在影片和按钮的OnClipEvent(eventName)或on(eventName)这两种事务处理方法中。这就意味着,在设计的时候就要把影片剪辑放到舞台上,并把代码写入影片剪辑中。MX的事务结构并不完备,但与之前版原来说已经有了长足的
29、进步,并允许我们在任何时候访问任何事务,或是停止处理任何事务,或是动态变更某个事务的行为,可以想象这有多么的强大和敏捷。要想了解事务,就要明白下面几条概念:侦听器(Iintener)与处理函数(handler),这两个名字很贴切,侦听器就是侦听事务的对象,处理函数是一个用于处理所要发生的事务的函数。侦听与处理在ActionScript的发展过程中进行过很多次演化,在AS2中就有很多不同的实现方法。为了避开混乱,我很推崇AS3,因为它简化了这个过程,使事务处理变得更便利更一样。事务侦听器与处理函数前面说过,侦听器是一个用于侦听事务的对象。我们可以设计一个类,通过调用addEvent1.isten
30、er函数为某事务指定一个侦听器。输入要侦听的事务名称以及要执行处理的函数名称。看一个例子:addEvent1.istener(enterFrame,OnEnterFrame);在力口入事务侦听器时,可运用可选参数,本书中不会用到;对于大多数的应用程序来说,会运用以上这种写法就够用了。请留意事务名enterFrame为字符串型,戏称它为魔力字符串(MagicString)o为什么这么叫?假如你误输入成了entorFrame,尽管没有这个事务名称,编译器也会编译执行它,会发觉事务处理函数没有执行。但AS3仍会对其进行处理,除了运用魔力字符串以外,还可以运用事务类(EVentCIaSS)的属性。例如
31、:addEvent1.istener(Event.ENTERFRAME,OnEnterFrame);事实上Event.ENTER_FRAME的值就是enterFrame这个字符串。那么这个属性也可能输错就像Event.ENTOR_FRAME,但这种方法好在,假如输入错误了,程序会拒绝编译,并提示你在事务类中不存在该属性。编译器会提示发生错误的行及准确的字符。所以,最好运用这种方法,除非编译器会帮我们修正错误或编写代码。除此之外,还有其它的事务类型如:MouseEvent.M0USE_D0WN,KeyboardEvent.KEY_D0WN,TimerEvent.TIMER等。这些都由Inouse
32、Down,keyDown,timer这样的简洁字符串来表示,假如你记不住这些字符串,那么最好就去运用事务类的属性。另一个重点是,运用addEvent1.istener函数干脆调用类中的函数。有时,须要侦听另一个对象产生的事务,例如,有一个名为mySpriteButton的Sprite影片(SPrite):影片或按钮,能完成按钮的动作。当用户点击它的时候就会产生mouseDown(鼠标按下)事务。侦听该Sprite影片的mouseDown事务,就要调用该对象的addEvent1.istener方法,如下:mySpriteButton.addEvent1.istener(MouseEvent.MO
33、USEDOWN,onSpritePress);最终一点,必须要有事务处理函数如OnEnterFrame,在AS3中,可以随意地为事务处理函数命名,这点与以前的ActionScript不同。在enterFrame示例中,运用OnEnterFrame做事务处理函数,是因为我们习惯运用这个名称。在AS3中,OnEnterFrame已不再是关键字,当然也可以为这个处理函数命名为move,run,或是doSomethingCool0然而,我们已经习惯运用on表示事务起先,后面跟一些描述词如OnStartButtonClick,OnConfigXM1.1.oad或OnRoketCrasho有些挚友喜爱在事
34、务名后面加上Handler作为后缀,如:enterFrameHand1er,这只是个人偏好问题。侦听器用于侦听事务,但对于一个侦听器来说,或许会同时侦听很多事务。在系统内部,一个事务对象拥有一个包括了全部对象及自身的侦听器的列表。假如一个对象能够产生多种不同类型的事务,如mouseDown,mouseUp,mouseMove等,那么它就拥有一个侦听器列表,其中包括它所涉及的全部类型的事务。无论触发何种事务,都会检索一遍列表,然后使列表中的每个对象都知道所发生的事务。另一种对事务的描述是,将其看作一个加入到事务行列的侦听器成员。产生事务的对象将它所产生的事务公布给全部成员,当你不再须要这个对象进
35、行侦听时,可以令其停止侦听或运用removeEvent1.istener方法解除该成员;就是告知对象从侦听器列表中删除该侦听器,这样一来,他就不会再接收信息了。让我们看看这段代码,下面是一段在舞台中创建Sprite影片,并进行绘图,然后再为其添加侦听器的代码:packageimportflash,display.Sprite;importflash,events.MouseEvent;publicclassEventDemoextendsSpriteprivatevareventSprite:Sprite;publicfunctionEventDemoOinit();privatefuncti
36、oninit():voideventSprite=newSprite();addChiIdCeventSprite);eventSprite.graphics.beginFill(OxffOOOO);eventSprite.graphics.drawCircle(0,0,100);eventSprite.graphics.endFill();eventSprite.X二stage.StageWidth/2;eventSprite.y=stage.StageHeight/2;eventSprite.addEvent1.iStener(MouseEvent.MOUSEDOWN,OnMouseDow
37、n);eventSprite.addEvent1.iStener(MouseEvent.MOUSEUP,onMouseUp);privatefunctionOnMouseDown(event:MouseEvent):voidtrace(mousedown);privatefunctionOnMouseUp(event:MouseEvent):voidtrace(mouseup);在初始化函数(init)中创建一个Sprite影片,并在里面画圆,置于舞台中心,最终两句是为它添加两个侦听器,侦听鼠标按下(MOUSE_DOWN)和鼠标弹起(MOUSE_UP)这两个事务。它们是MouseEvent类的两个属性,而这个类必须要导入。最终定义两个处理函数OnMouseDown和OnMOUSeUp。由事务对象调用事务处理函数,通常还会包括一些事务信息。在处理鼠标事务时,就包括触发该事务时鼠标位置的信息如:鼠标点击在按钮上。对于键盘事务,就要包括按下键时的信息如Ctrl,Alt,Shift等。把上述示例保存为EventDemo.as文件,并选择一种前面讲过的编译方式。当运行SWF时,就会看到每次点击或图形时,都会输出pressed或releasedo