0

我在 AS3 中为一堆单词制作动画。因为我将在移动设备上使用它,所以我想使用位图而不是 Sprites。所以我创建了 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();

        }
    }
4

3 回答 3

1

你打算一次在舞台上放多少张位图?

我有 40 个 900x16px 位图在舞台上使用 air 2.6 在我的 iphone 上全速运行。

我在 enterframe 事件中使用了一个 foreach 循环,我在鼠标单击时添加了该循环,并在动画完成后将其删除。

请记住在启用 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);
        }

    }
}
于 2011-05-04T21:31:32.563 回答
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);
}
于 2011-05-05T00:04:37.653 回答
0

我建议在注册 ENTER_FRAME 事件时在 Adob​​e 的网站上编写自定义效果。您在此处放置的内容意味着只要程序正在运行,此代码将永远运行。如果您想停止效果或运行 10 帧并停止,那么您将不得不编写更多代码。如果要将其应用于多个实例,它会变得更加复杂。您将不得不解决自定义效果框架解决的问题。

我会在这里阅读如何编写自定义效果:

http://livedocs.adobe.com/flex/3/html/help.html?content=createeffects_1.html

于 2011-05-04T21:14:31.240 回答