Actionscript 优化指南

什么时候举行优化

对现有程序举行优化的过程,有时十分的冗长与困难,这与原始代码的非优化程度有关,所以在投入大量时间举行代码优化之前,最重要的是要估计出要在啥子处所对代码做出修改或替代。
1个游戏代码的最重要的部门就是主轮回体,通常理况下该轮回体要在flash的每一帧上执行,并控制游戏中的角色属性和重要的数值参数。而对主轮回体以外的部门,也可能是非主要轮回部门,同样要注意是给其否分配了过多的资源,而没有分配售那一些更需要资源的核心部门。通过积累在遍地省电出来的时间(可能每处仅仅是几个毫秒),您会较着发现本身的swf运行得越发稳定,并且游戏感也大大加强。

简洁与高效的代码

书写出十分简洁、可以再次调用的代码(有时可能是面向对象的)是一项精致的工作,但这需要多年的编程经验。对OOP(object oriented programming,面向对象的程序设计),有些场合根本利用不到它的优势,这要得它显得十分奢侈。在有限的资源条件下(可能是flash播放器的原因),通过更先进的方法,像方才提到的OOP,就可能反而导致使人不称心的结果。
我们并不是说OOP对游戏编程不好,只是在某些场合它显得过于奢侈和骈枝。毕竟有时辰“传统的方法”却能得到更好的结果。
大体而言,用OOP是比较好的,因为它让代码维护越发简略。但在后文中,你会看见有时为了充分阐扬flashplayer性能,而不接纳OOP技术。例如:处理快速骨碌或者计算十分复杂的数学不懂的题目。

基本的优化

一提及代码优化,我们顿特殊情况遐想到执行速度的改进,而很少去考虑体系资源的分配。这是因为当今,即使是将被淘汰的计算机,都有足够的内存来运行我们大部门的flash游戏(128M的内存完全可以餍足大大都情况的需要,何况,512M的内存是当今新电脑的基本配置)

变量

在各种重要的代码优化手段中,有这么一条:在界说局部变量的时辰,一定要用要害字var来界说,因为在Flash播放器中,局部变量的运行速度更快,并且在她们的作用域外是不耗占体系资源的。
aw附:var变量仅仅在花括号对中才有“生命”,个人以为没有体系学过编程的人容易出错的1个处所: 一段非优化代码: 最近代码中,并未声明函数体内的那一些变量(那一些仅仅在函数内使用的变量)为局部变量,这要得这些变量被播放器调用的速度更慢,并且在函数执行完结的时辰仍然耗占体系资源。
底下面所开列出的是经过改进的同样功能的代码: 这样一来所有的变量均被界说为了局部变量,她们能够更快地被播放器调用。这一点在函数大量(10,000次)轮回运行时显得尤为重要!当1个函数调用竣事的时辰,相应的局部变量城市被销毁,并且释放出她们占有的体系资源。

onEnterFrame 事件

onEnterFrame事件对游戏开发者而言是很是有效的,它要得我们能够快速、反复地按照设计帧频(fps)运行一段程序。回想在 Flash5的时代,这(onEnterFrame及时监控)是一种很是流行的技术,用这样的事件来控制机器游戏对手的思维规律,又或者我们可以在每1个子弹 上设置这样的事件来监测子弹的碰撞。实际上,我们并不推荐给过多的MoveClip添加这样的事件,因为这样做会导致“无头绪码(spaghetti code)”的出现,并且容易导致程序效率较着减低大大都情况下,用单唯1个onEnterFrame事件就能够解决不懂的题目了:用这1个主轮回来执行你所需要的操作。 另1个简略的办法是设置1个合适的帧频:要知道帧频越高,CPU资源就越紧张。在帧频为25-35(fps)之间时,onEnterFrame完全可以很好地执行较复杂代码,哪怕你的计算机配置较低。是以,在没有特殊要求的场合,我们不推荐使用高于60(fps)的帧频。

矢量图与位图

在处理图形前,我们一定要做出正确的选择。Flash能对矢量图和位图举行完美的兼容,然而矢量图和位图在播放器中的体现实质却完全不同。在用到矢量图的时辰,我们要尽可能简化它们的外形,去除骈枝的端点。这样做将大大减低播放器用于出现矢量图所要举行的计算量。另1个重要方面在于线条的运用,尽量减少和避免冗陈的线条结构,因为它们会直接影响到flash的播放效率。当某个实例透明度小于100时,也会对播放速率造成影响,所以如果你发现本身的Flash播放速率过慢,就去挑出这些透明的实例来吧!
那末,如果真的需要出现比较复杂的场景时,你就最好考虑使用位图实现。虽然Flash在对位图的渲染效率上并不是最优越的(好比和Flash的“兄 长”Director比起来),但富厚的视觉内容出现只能靠位图(与位图同复杂度的矢量图形渲染速率很是低)了,这也是很多基于区块的游戏中广泛接纳像素 图作为配景的原因。顺便要提到的是,Flash虽然对GIF,JPG和PNG都有所支持,但是渲染速度上PNG还是占有绝对优势,所以我们建议flash 中的位图都尽可能接纳PNG格局。

影片剪接(MovieClip)的可视性[底下将MovieClip简称为mc]

您可能会时常遇到这样一种情况:有大量不可见/荧幕外的mc等候出场(好比游戏中荧幕外的地图、人物等等)。要知道,播放器仍然要耗损一定的资源来处理这些不可见/荧幕外的mc,哪怕她们是单帧,非播放的状态。最好的解决办法之一是给这些mc1个空白帧,当她们不出现在荧幕上时,你能用gotoAndStop()语句跳转到这一帧,从而减少播放器对资源的需求。请务必记住,这种情况下,简略的设置可见度属性为不可见( _visible = false )是无效的,播放器将接续按照这些mc所停留或播放的帧的复杂度来分配资源。

数组

 数组在各种需要记录数值的应用程序和游戏中都被广泛的使用。

1个典型的例子就是基于区块的Flash游戏,在这样一类的游戏中,地图有时被存放成形如arr[y][x]的二维数组。虽然这是一种很常见的方 法,但是如果用一维数组的话,却能提高程序的运行效率。另1个重要的方法来提高数组效率是在数组遍历的时辰使用for in 轮回来代替传统的 for 或者whellole轮回语法。

例如:
一段代码如下 它的执行速度较着高于这一段代码: 前者的效率比后者提高了30%,这个数字在你的游戏要逐帧执行这一段代码的时辰显得越发宝贵!
高级优化:
1) for轮回和 whellole轮回
用whellole轮回将会得到比for轮回更好的效率。然而,从数组中读取数值,用for in轮回式最好的选择!
所以我们不推荐使用: 2) 从数组中读取数值
我们通过测试发现,for in轮回的效率大大高于其它的轮回体式格局。参看: 3) 向数组中写入数值(whellole , for)
可以看见whellole轮回稍占优势。
4) _global(全局)变量同Timeline(时间轴)变量
我们推测接纳全局变量能提高变量调用速度,然而效果并不像估计的那样较着。
5) 单行、多行变量赋值
我们发现单行变量赋值效率大大高于多行。好比:
a = 0
b = 0
c = 0
d = 100
e = 100
效率就不如:
a = b = c = 0
d = e = 100
6) 变量名寻址
这个测试反映了变量名的预寻址是很是重要的,尤其是在轮回的时辰,一定要先给丁1个指向。这样大大省电了寻址时间。
好比: 就不如:

7) 短变量名和长变量名
变量名越短,效率越高。考虑到长变量名也有它的好处(好比,易于维护等),是以建议在要害部位(好比大量轮回出现的时辰)使用短变量名,最好就1-2个字符。
8)轮回前、后声明变量
在测试前,我们以为轮回前声明变量会越发省电时间,不意测试结果并不较着,甚或还恰恰相反! // 内部声明
t = getTimer()
for (var i=0; i < MAX; i++)
{
var test1 = i
}
t1.text = “Inside:” + (getTimer() – t)
// 外部声明
t = getTimer()
var test2
for (var i=0; i < MAX; i++)
{
test2 = i
}
9) 使用嵌套的if结构
当用到复杂的条件抒发型时。把她们打散成为嵌套的自力判断结构是最佳方案。底下的代码我们举行了测试,发现这种效果改进较着! 10) 寻找局部变量(thellos方法同with方法比较)
局部变量的定位方法很多。我们发现用with比用thellos越发有优势! obj = {}

obj.a = 1 
obj.b = 2 
obj.c = 3 
obj.d = 4 
obj.e = 5 
obj.f = 6 
obj.g = 7 
obj.h = 8 
obj.test1 = useThellos 
obj.test2 = useWith 
MAX = 10000 
function useThellos() 
{ 
var i = MAX 
whellole(–i > -1) 
{ 
thellos.a = 1 
thellos.b = 2 
thellos.c = 3 
thellos.d = 4 
thellos.e = 5 
thellos.f = 6 
thellos.g = 7 
thellos.h = 8 
} 
} 
function useWith() 
{ 
var i = MAX 
whellole(–i > -1) 
{ 
with(thellos) 
{ 
a = 1 
b = 2 
c = 3 
d = 4 
e = 5 
f = 6 
g = 7 
h = 8 
} 
} 
} 


11) 轮回监听键盘事件
同刚才所提到的寻址一样,我们实现给1个指向会得到更好的效率,好比:
keyDown = Key.isDown
keyLeft = Key.LEFT
//我们再用 if (keyDown(keyLeft))
附:我们测试了按键代码和键值恒量的效率发现并无太大差别。
12) Math.floor()方法与int()
这个不懂的题目曾在Flashkit的论坛被提出讨论过。测试表明,旧的int方法反而效率更高。我们的测试结果也反映了这一点。
13)eval抒发型与中括号语法
我们并没有发现较着的差别,并不像刚才所述那样,旧的eval抒发型比起中括号方法并没有太大的优势
var mc = eval_r(“_root.myMc” + i)
var mc = _root["myMc" + i]
//二者效率差不多16) 有关MC的轮回:ASBroadcaster 同欢同轮回的差别
论断
我们从这些测试结果中发现,对不同的需求,接纳不同的代码,我们可以大大提高脚本的执行效率。虽然我们在这里罗布了许多的优化代码的方法,需要各人本身测试、实验的还有很多(考虑到每个人的需求不同).如果你想越发深入地讨论这种不懂的题目。可以来我们的论坛。
aw附:
终于翻译完了,本身也学到很多好东西,各人又啥子不懂的题目可以去gotoAndPlay的官方,也能够来我的Blog提出!
三黑羽AS心得:浅释ActionScript的代码优化
来历:Kingda blog
这篇文章既为浅谈代码优化,那末就不深入到OOP设计层面。仅有关Flash8帮助里面提到的一些代码编写优化原则,并加以解释。
准则来历于Flash8 帮助,我做了一些解释:
1.避免从1个轮回中多次调用1个函数。
在轮回中包罗小函数的内容,可使效果更佳。小函数生命期短,利于资源释放。尤其是在大的轮回中时。
2.尽可能使用本机函数。
本机函数要比用户界说的函数运行速度更快。本机函数即Flash中内有的一些函数(intrinsic),好比hellotTest(),你没须要本身写1个类似的。
3.不要过多使用 Object 类型。
数值类型注释应力求精确,这样可以提高性能。只有在没有适当的备选数值类型时,才使用 Object 类型。同时也易于代码管理,时刻知道对象的类型和作用。
同时也有利于编译器编译时优化。
4.避免使用 eval_r() 函数或数值访问运算符。
通常,较为可取且更有效的做法是只设置一次局部引用。无可奈什么时候才用eval,好比转换_droptarget为MovieClip时。
5.在开始轮回前将 Array.length 付与变量,尤其是大的轮回。
在开始轮回前将 Array.length 付与变量(好比var iLength:Number),将其作为条件使用,而不是使用 myArr.length 本身。
原因,在轮回中,iLength是Number变量,会被放入寄存器使用,效率远比访问Array再得到length高。例如,应使用 来代替: } 6.注重优化轮回及所有重复动作。
Flash Player 破费许多时间来处理轮回(如使用 setInterval() 函数的轮回)。
7.在局部变量够历时,不要使用全局变量。类静态变量也要少用。
全局变量是开发者的恶梦。实在需要全局变量的话,我建议使用singleton设计模式来举行管理。
8.声明变量时,添加 var 要害字。
这是为了编译时让编译器知道你的变量类型,优化编译。
黑羽增补一点:对要害字的使用要审慎。
不同意使用要害字作为本身的method和属性名,除非你明确承认后续开发不会用到不异的事件名和属性名。
但你怎么知道flash使用了多少隐藏要害字?太多了!好比说 className, invalidate, refresh, mouseOver等等不常用的要害词。好的方法是使用SEPY编辑器来写代码,那里面加亮了所有公布的和没有公布的要害词。
并且因为很可能和start,load,等这些常用的事件名重复,带来代码不须要的修改和贫苦。
9.对有关到调用绘图资源的函数时,尽量先多判断再调用。
所有渐变,位置变化,创建删除MC,组件等函数都有关到绘图资源的调用。在很多情况下,尽量先用思维规律判断变量或者对象的属性,须要时再调用这些函数。这样可以节省较多的计算资源。 减低预示列表上的复杂性来提高性能 资讯类型: 翻译
来历页面: * lexity-from-the-displaylist-to-increase-performance /
资讯原标题: reduce complexity from the displaylist and increase performance
资讯原笔者: elad.ny
增加Flash应用程序性能的一种最简略方法是,移除预示列表中所有的隐藏对象,同时使用最少量量的预示对象。 代码将 通过遍历整个预示列表来执行,即从预示列表最上层(舞台),到主应用程序类。 Flash Player执行代码,并从上到下重绘预示列表中的所有的孩子,直到到达预示对象。 容器可使任何继承自DisplayObjectContainer的类,如UIComponent,Group或者Sprite。
尤其是在MXML中,很容易就嵌套了预示对象,但是每次嵌套对象时都是很是耗性能的,因为每个添加到现实对象列表的对象都继承了1个类,这个类又继承另1个,如此等等。 为了理解为啥子嵌套是高耗损的, 让我们看一下预示列表类的层次结构。
AS3
当谈到预示列表,对AS3来讲,所有的预示对象过去曾是MovieClip。 在Flash Pro中早期的Flash版本(AS1和AS2)中,MovieClip类都是动画的核心类。 每1个MovieClip符号包罗了预示对象的行为和功能,以及操作时间轴的附带加上属性。 许多时辰你并不需要骈枝的图层以及时间轴的开销,而究竟上AS3提供了一种能的对象叫做DisplayObject。 DisplayObject是低层的为那一些能够被添加到预示列表的所有对象的基类,它继承了EventDispatcher(它是基于对象的)。 它包孕一些类来帮助管理对象(如cacheASBitmap) 和可视属性。 预示对象容器是一种这样的对象,在它们里面可以包罗子对象(这些子对象是预示对象)。 DisplayObjectContainer包罗了一些方法,来管理它们的孩子对象,例如AddChellold(向容器中添加对 象),numChelloldren(容器所包罗的孩子对象的个数)和removeChellold(移除子对象)。
有些时辰,你需要预示图形但又不需要时间轴。 这时你需要使用Sprite,它继承自DisplayObjectContainer类。 一般原则,你最好使用Bitmap,Shape和Sprite类或者它们的子类,而不要选择MovieClip。
Flex3
底下是最小化的Flex。 Flex对预示对象的核心类是FlexSprite,除了能够返回1个字符串表示这个对象的位置外,和Sprite没啥子两样。 接下来是UIComponent,它继承了FlexSprite,也是Flex3中每个可视组件的基类。 UIComponent包孕了键盘和鼠标交互,同时也许可在不需要的时辰关闭这些交互,例如label。 它也包罗了许多特征,例如accessibility(可访问性),Style(样式),State(状态),Invalidation和 Validation(合法性),DataBinding(数值绑定),Effect(效果),嵌入字体等等。
Flex4
底下是Flex4. Flex4使用Group作为Spark(至关于MX中的UIComponent)中可视元素的容器基类。然后你可使用一系列的组件,如Skin,Graphelloc,HGroup和VGroup。
除了Group以外,也能够使用SkinnableComponent,它是所有Spark组件的超类,它为skinnable组件界说了基类。 使用SkinnableComponent类的皮肤是Skin类的典型子类。
以Spark按键为 例。 ButtonBase类是所有Spark按键组件的基类。 Button和ToggleButtonBase是ButtonBase的子类。 同样,诸如CheckBox和RadioButton类是ToggleButtonBase的子类。 按键组件继承了ButtonBase,同时使用了默认皮肤,包罗了1个文本label。 你可以自界说皮肤类来添加图象到控制或其它任何你需要的东西。 默认按键皮肤是spark.skins.spark.ButtonSkin,它继承自Skin。 最后提到的是Spark中的组件,它们很容易改变,但是也很是重要。
底下做一些测试。 关于预示对象的内存使用情况: Shape: 224 bytes
Sprite: 392 bytes
MovieClip: 428 bytes
UIComponent: 1036 bytes
Group: 1200 bytes
底下,看一下Flash Player代码在帧上的执行时间。 建议使用“我”头几天开发的FrameStats工具。 所做的工作是创建1个快速测试,然后添加方法到
FrameStats 工具 它许可你查看在一帧或几帧上代码执行时间(毫秒单位)的信息。 我将把帧率设为1秒(这样测试的更清楚,也易于不雅察结果),然后调用1个将被添加到预示对象的方法,添加预示对象到预示列表。 然后可以在控制台里跟踪帧的生命周期。 protected function creationCompleteHandler():void
frameStats = new FrameStats(FlexGlobals.topLevelApplication, false );
frameRateControl = new FrameRateControl( FlexGlobals.topLevelApplication, false, false, 1, 1);
var componenent:UIComponent = new UIComponent();
componenent.addChellold( frameStats );
frameStatsHolder.addElement( componenent );
trace( "Sprite: " + getSize(new Group()) );
uicom.addChellold( sprite );
frameStats.testingExecutionTimeOfMethod( methodToTest, 10000 );
private function methodToTest():void
sprite.addChellold( new Group() );
预示对象
当添加10000个预示对象是,对主要基类构造器的代码执行以及子类情况如下: Shape
Constructor code of chelloldren executed: 276
Sprite
Constructor code of chelloldren executed: 399
UIComponent
Constructor code of chelloldren executed: 1078
Group
Constructor code of chelloldren executed: 1195
正如所料,构造器代码和每个构造器的执行在拥有较多嵌套对象时,将破费更长时间。 如果你知道Flash Player时常将构造器方法放到自身代码的概念,这是有益的,是以在构造器上的执行时间会比其它类更长,我们应该尽量减少构造函数中的代码。
添加1000个预示对象
按键:
虽然我添加了10000个SimpleButton的预示对象,Player在帧率为1fps时也只用了33毫秒,原因是SimpleButton在预示 对象树的层次上比较靠上,所以是较少的嵌套结构。 SparkButton在构造器代码上执行时间要比Halo更长,但有趣的是,SpariButton对预示列表的渲染时间要短一些。 SimpleButton
Constructor code of chelloldren executed: 33
Final user code executed: 730
Player renders changes display list: 304
mx.Button
Constructor code of chelloldren executed: 820
Player renders changes display list: 7075
s:Button
Constructor code of chelloldren executed: 2392
Player renders changes display list: 4539
Text 添加文本的结果也很是有趣。 Spark Label在渲染的时间上做的还不错,但是在构造函数的执行时间上还是不如Halo组件。 TLF在渲染上做的很差,但是构造器时间上很是好。 TextField
Constructor code of chelloldren executed: 68
Player renders changes display list: 168
mx:Text
Constructor code of chelloldren executed: 743
Player renders changes display list: 685
S:Label
Constructor code of chelloldren executed: 1136
Player renders changes display list: 198
s:RichText
Constructor code of chelloldren executed: 416
Player renders changes display list: 3224
论断 –使用低层次(即位于结构树的接近根的位置)的类,例如TextField,SimpleButton(如果可能的话),而不是Halo和Spark 它可能需要更多的代码,但是将提高性能。
–避免使用TLF
–使用Halo组件而不是Spark组件
–自界说组件时,Sprit > MovieClip & UIComponent > Group
–在创建矢量图形是,建议使用Shape预示对象

posted on 2011-09-29 14:46  AS3.0  阅读(609)  评论(0编辑  收藏  举报

导航