Цикл в enterframe? - PullRequest
       37

Цикл в enterframe?

0 голосов
/ 05 мая 2011

Я оживляю кучу слов в AS3.Поскольку я собираюсь использовать это на мобильном устройстве, я хочу использовать растровые изображения, а не спрайты.Итак, я создал 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();

        }
    }

Ответы [ 3 ]

1 голос
/ 05 мая 2011

Сколько растровых изображений вы планируете иметь на сцене за один раз?

У меня было 40 900x16px растровых изображений, которые анимировались на сцене на полной скорости и работали на моем iphone с использованием воздуха 2.6.

Я использовал цикл foreach в событии enterframe, который я добавил по щелчку мышью и удалил после завершения анимации.

Не забудьте скомпилировать его для мобильного телефона с включенным рендерингом gpu.(gpu в вашем app.xml, если вы используете air 2.6)

Это тоже стоит прочитать, это многое объясняет о производительности для мобильных устройств 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 голос
/ 05 мая 2011

Что-то, что будет иметь огромное значение, - это использование 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
        }
    }
}

Теперь просто расширьте Элемент своими объектами:

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);
}
0 голосов
/ 05 мая 2011

Я бы посоветовал посмотреть на создание пользовательского эффекта на веб-сайте Adobe для регистрации события ENTER_FRAME. То, что вы там поместили, означает, что этот код будет работать вечно, пока работает программа. Если вы хотите остановить эффект или запустить на 10 кадров и остановить, вам придется написать больше кода. Это становится еще более сложным, если вы хотите применить это к нескольким экземплярам. Вам придется решать проблемы, которые решает инфраструктура пользовательских эффектов.

Я бы прочитал, как написать пользовательские эффекты здесь:

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

...