我在AS3中制作了一堆词。因为我将在移动设备上使用它,我想使用位图而不是Sprite。所以我创建了WordObjects,它有一个我可以访问的.bitmap属性。
我有以下代码,它触发click事件并循环遍历enterframe事件中的数组。这可能是一个坏主意,但我不确定如何做得更好。 (令人惊讶的是它在Flashbuilder中运行得很好,但在Flash CS5中慢慢爬行。)
有更好的方法吗?我只想要一种有效的方法来动画化位图数组。
private function clickhandler (e:MouseEvent){
this.addEventListener(Event.ENTER_FRAME, blowemup);
}
private function blowemup(e:Event){
var newPosition:Number;
for(var i:int=0; i<arrWordObjects.length; i++)
{
newPosition = updatePosition(arrWordObjects[i].bitmap);
arrWordObjects[i].bitmap.x += newPosition;
arrWordObjects[i].bitmap.y += getRandomNumber();
}
}
答案 0 :(得分:1)
您计划一次在舞台上有多少位图?
我使用air 2.6在我的iphone上以全速运行的舞台上播放了40个900x16px位图动画。
我在一个enterframe事件中使用了一个foreach循环,我在mouseclick上添加了一个,并在动画结束后删除了。
请记住为启用了gpu渲染的移动设备编译它。 (如果您使用的是air 2.6,则在您的app.xml中使用gpu)
这也值得一读,它解释了很多移动设备的性能 http://help.adobe.com/en_US/as3/mobile/WS901d38e593cd1bac-3d719af412b2b394529-8000.html
这是我所拥有的基本例子......
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
[SWF(frameRate="30", backgroundColor="#FF00FF")]
public class Test extends Sprite
{
private var fields:Vector.<Bitmap> = new Vector.<Bitmap>();
public function Test()
{
this.stage.scaleMode = StageScaleMode.NO_SCALE;
this.stage.align = StageAlign.TOP_LEFT;
for(var i:int = 0; i< 37; i++){
var bd:BitmapData = new BitmapData(960, 16, true, 0x000000);
bd.fillRect(new Rectangle(0, 0, 900, 16), Math.round( Math.random()*0xFFFFFFFF ));
var b:Bitmap = new Bitmap(bd);
b.x = 0;
b.y = i*16;
stage.addChild(b);
fields.push(b);
}
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
}
private var inertia:Boolean = false;
private var yCurrent:Number;
private var ySpeed:Number;
private var startY:Number;
private var cy:Number = 0;
private function onEnterFrame(e:Event):void{
if(!inertia){
ySpeed = (startY - yCurrent) ; // / 16;
startY = yCurrent
} else {
ySpeed *= 0.8;
if(ySpeed < 0.01 && ySpeed > -0.01){
inertia = false;
stage.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
}
}
cy += ySpeed;
if(cy > 640)
cy -= 640;
var ty:Number = cy;
for each(var tf:Bitmap in fields){
tf.y = ty;
ty += 16;
if(ty > 640)
ty -= 640;
}
}
private function onMouseDown(e:MouseEvent):void{
inertia = false;
startY = e.stageY;
yCurrent = e.stageY;
stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
private function onMouseMove(e:MouseEvent):void{
yCurrent = e.stageY;
}
private function onMouseUp(e:Event):void{
inertia = true;
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
}
}
答案 1 :(得分:1)
使用for each(Object in Array)
而不是标准的for
循环会产生巨大影响。
private function blowemup(e:Event):void
{
var newPosition:Number;
var i:ArrWordsObjectClass; // <-- don't know what the class for this is, just replace
for each(i in arrWordObjects)
{
newPosition = updatePosition(i.bitmap);
i.bitmap.x += newPosition;
i.bitmap.y += getRandomNumber();
}
}
键入for each
循环,意味着节省了大量时间,通常它会尝试计算每次迭代arrWordObjects[i]
的内容。
另外,请注意:使用一个ENTER_FRAME驱动函数并循环应用程序中要处理每个帧的所有内容比为对象应用数百个侦听器更有效。
我通常会创建一个包含ENTER_FRAME的处理程序类和一个存储我的对象的数组,如下所示:
package
{
import flash.events.Event;
import flash.display.Sprite;
public class Handler extends Sprite
{
// vars
public var elements:Array = [];
/**
* Constructor
*/
public function Handler()
{
addEventListener(Event.ENTER_FRAME, _handle);
}
/**
* Called on each dispatch of Event.ENTER_FRAME
*/
private function _handle(e:Event):void
{
var i:Element;
for each(i in elements)
{
i.step();
}
}
}
}
然后我为我想要处理的所有对象创建一个基类,包含上面调用的step()
函数。
package
{
import flash.display.DisplayObject;
public class Element extends Object
{
// vars
public var skin:DisplayObject;
/**
* Called on each dispatch of Event.ENTER_FRAME at Handler
*/
public function step():void
{
// override me
}
}
}
现在只需使用对象扩展Element:
package
{
import flash.display.Sprite;
public class MyThing extends Element
{
/**
* Constructor
*/
public function MyThing()
{
skin = new Sprite();
skin.graphics.beginFill(0);
skin.graphics.drawCircle(0,0,40);
skin.graphics.endFill();
}
/**
* Override step
*/
override public function step():void
{
skin.x += 4;
}
}
}
让一切顺利!:
var handler:Handler = new Handler();
var m:MyThing;
var i:uint = 0;
for(i; i<10; i++)
{
m = new MyThing();
m.y = Math.random()*stage.stageHeight;
handler.elements.push(m);
addChild(m.skin);
}
答案 2 :(得分:0)
我建议在注册ENTER_FRAME事件时在Adobe网站上编写自定义效果。您放在那里意味着只要程序运行,此代码将永远运行。如果你想停止效果或运行10帧并停止,那么你将不得不写更多的代码。如果要将其应用于多个实例,则会变得更加复杂。您将不得不解决自定义效果框架解决的问题。
我在这里阅读了如何编写自定义效果:
http://livedocs.adobe.com/flex/3/html/help.html?content=createeffects_1.html