Блиттинг AS3 медленнее, чем мувиклип. Почему?

Я попытался следовать комбинации серии руководств Ли Бримлоу по блитингу и техники Рекса Ван дер Спуи «Расширенный игровой дизайн с помощью flash».

Я разработчик, работающий над виртуальным веб-миром, созданным во флэш-памяти. Я сделал приложение для телефона (работает аналогично телефону в играх grand theft auto). В любом случае, когда сообщение отправлено, мы хотим воспроизвести эту сумасшедшую анимацию конверта, летящего вокруг и трансформирующегося с блестками вокруг него. Он зависал (особенно на старых компьютерах), поэтому я подумал, что это отличный шанс использовать блиттинг. Однако анимация блитинга на самом деле воспроизводится медленнее, чем обычный мувиклип!! Что, черт возьми, здесь происходит? Блиттинг лучше только для мобильных устройств и на самом деле медленнее на компьютерах? Может быть, я делаю что-то не так. Вот мой код:

// ЭТА ЧАСТЬ ПРОИСХОДИТ, КОГДА ТЕЛЕФОН ИНИЦИАЛИЗИРУЕТСЯ

//**                
//---------------- Blitting stuff ----------------------------------
// add this bitmap stage to the display list so we can see it
            _bitmapStage = new BitmapData(550, 400, true, 0xD6D6D6);


        _phoneItself.addChild(new Bitmap(_bitmapStage));

        var _spritesheetClass:Class = getDefinitionByName("ESpritesheet_1") as Class;
        _spritesheet = new _spritesheetClass() as BitmapData;

        _envelopeBlit = new BlitSprite(_spritesheet, BlitConfig.envelopeAnimAry , _bitmapStage);
        _envelopeBlit.x = -100;
        _envelopeBlit.y = 0;

        _envelopePlayTimer = new Timer(5, 0);
        _envelopePlayTimer.addEventListener(TimerEvent.TIMER, onEnterTimerFrame);
        _envelopeBlit.addEventListener("ENV_ANIM_DONE", onEnvAnimFinished);

// "BlitSprite" - это класс, который я создал. Это выглядит так:

package com.fs.util_j.blit_utils
{
    import flash.display.BitmapData;
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.geom.Point;
    import flash.geom.Rectangle;

    public class BlitSprite extends EventDispatcher
    {

        private var _fullSpriteSheet:BitmapData;
        private var _rects:Array;
        private var _bitmapStage:BitmapData;

        private var pos:Point = new Point ();
        public var x:Number = 0;
        public var y:Number = 0;

        public var _animIndex:

интервал = 0; частная переменная _count:int = 0;

    public var animate:Boolean = true;
    private var _whiteTransparent:BitmapData;
    private var _envelopeAnimAry:Array;
    private var _model:Object;



    public function BlitSprite(fullSpriteSheet:BitmapData, envelopeAnimAry:Array, bitmapStage:BitmapData, model:Object = null) 
    {
        _fullSpriteSheet = fullSpriteSheet;
        _envelopeAnimAry = envelopeAnimAry;
            _bitmapStage = bitmapStage;
            _model= model;

            init();
        }

        private function init():void
        {
//          _whiteTransparent = new BitmapData(100, 100, true, 0x80FFffFF);

            this.addEventListener("ENV_ANIM_DONE", onEvnAnimDone);

        }       

        protected function onEvnAnimDone(event:Event):void
        {

        }       

        public function render():void
        {

//          pos.x = x - _rects[_animIndex].width*.5;
//          pos.y = y - _rects[_animIndex].width*.5;

//          if (_count % 1 == 0 && animate == true)
//          {

//              trace("rendering");

                if (_animIndex == (_envelopeAnimAry.length - 1) )
                {
//                  _animIndex = 0;
                    dispatchEvent(new Event("ENV_ANIM_DONE", true));
                    animate = false;
//                  trace("!!!!animate over " + _model.animOver);

//                  if (_model != null)
//                  {
//                      _model.animOver = true;
//                  }

//                  trace("!!!!animate over " + _model.animOver);

                }

                else 
                {
                    _animIndex++;
                }


                pos.x = x + _envelopeAnimAry[_animIndex][1];
                pos.y = y + _envelopeAnimAry[_animIndex][2];


                _bitmapStage.copyPixels(_fullSpriteSheet, _envelopeAnimAry[_animIndex][0], pos, null, null, true);

        }



    }
}




// THIS PART HAPPENS WHEN PHONE'S SEND BUTTON IS CLICKED


                _envelopeBlit.animate = true;
                _envelopeBlit._animIndex = 0;
                _darkSquare.visible = true;
                _envelopePlayTimer.addEventListener(TimerEvent.TIMER, onEnterTimerFrame);
                _envelopePlayTimer.start();

он также использует BlitConfig, в котором хранится информация о спрайт-листе, выдаваемом TexturePacker.

    package com.fs.pack.phone.configuration
    {
        import flash.geom.Rectangle;

        public final class BlitConfig
        {




            public static var _sending_message_real_20001:Rectangle = new Rectangle(300,1020,144,102);
            public static var _sending_message_real_20002:Rectangle = new Rectangle(452,1012,144,102);
            public static var _sending_message_real_20003:Rectangle = new Rectangle(852,852,146,102);
            public static var _sending_message_real_20004:Rectangle = new Rectangle(2,1018,146,102);
            public static var _sending_message_real_20005:Rectangle = new Rectangle(702,822,148,102);
.
.
.
public static var _sending_message_real_20139:Rectangle = new Rectangle(932,144,1,1);

    public static var envelopeAnimAry:Array = [

                // rectangle, x offset, y offset
            [ _sending_message_real_20001, 184,155],
            [ _sending_message_real_20002, 184,155],
            [ _sending_message_real_20003, 183,155],
            [ _sending_message_real_20004, 183,155],
.
.
.
[ _sending_message_real_20139, 0,0]
        ]



        public function BlitConfig()
        {
        }


    }
}

person Fans    schedule 30.08.2013    source источник


Ответы (1)


РЕДАКТИРОВАТЬ: Зная, что это не мобильный телефон, мой ответ ниже не имеет значения. Однако я оставлю его там на тот случай, если у кого-то возникнут проблемы с блиттингом на мобильных устройствах в будущем.

Что касается этого конкретного вопроса, вы запускаете свой таймер каждые 5 мс. Во-первых, самый низкий диапазон точности таймера составляет> 15 мс, поэтому это никогда не будет жизнеспособным решением. Для любого таймера, относящегося к отображению чего-либо на сцене, вы должны никогда не делать это меньше одного кадра. (1000/stage.framerate. ~40 мс для приложения со скоростью 30 кадров в секунду)

Целью блитинга является сокращение вычислений и рендеринга. То, как вы это настроили прямо сейчас, похоже, что вы блитите каждые 5 мс. На самом деле это более чем в 8 раз чаще, чем рендеринг MovieClip. Вам следует уменьшить частоту блитов. Делайте это только тогда, когда изменение действительно было сделано за пределами перевода. Делать это чаще, чем это, излишне и причина, по которой это так медленно (опять же, создание растровых изображений происходит медленно)


Как правило, вы не хотите запускать приложение AIR for Mobile (что, как я предполагаю, вы делаете, поскольку вы упомянули об инициализации телефона). Я не уверен, что можно делать это с помощью других/родных SDK, но избегайте этого в AIR.

По сути, все сводится к тому, как работает блиттинг. Блиттинг делает снимок экрана и отображает его на сцене, а не на реальном объекте. В общем, это здорово. Это означает, что ваши экранные объекты, особенно векторы, которые рендерятся медленно, должны рендериться гораздо реже. Это особенно хорошо при анимации, потому что объект имеет тенденцию к повторному рендерингу каждый раз, когда он каким-либо образом транслируется, но не растровое изображение.

Однако на мобильных платформах создание этого растрового изображения происходит невероятно медленно. Я никогда не изучал, как SDK создает растровые изображения, но он делает это неэффективно (это часто заставляет меня задуматься, делает ли он это попиксельно). На десктопах это вообще нормально. Существует много процессора и много оперативной памяти, чтобы сделать это быстро. Однако на мобильных устройствах такой роскоши пока нет. Поэтому, когда вы копируете и создаете это растровое изображение, для запуска этого процесса требуется некоторое время.

Проблема усугубляется на экранах с высоким разрешением. Приложение, которое я разрабатывал с января по май этого года, выборочно использовало блиттинг для использования фильтров в среде с ускорением на GPU. На iPad 2 скорость моего приложения увеличилась с 30 кадров в секунду до ~ 24 кадров в секунду. Ничего страшного, пользователь ничего не заметит. Однако на iPad 3 с дисплеем Retina скорость снизилась до 10 кадров в секунду. Это имеет смысл, если подумать, поскольку у iPad с сетчаткой в ​​4 раза больше пикселей, чем у iPad без сетчатки.

Если вы хотите использовать блиттинг на мобильных устройствах, я рекомендую несколько вещей:

  1. Используйте режим рендеринга GPU. Без него у вас нет шансов. Имейте в виду, что, по крайней мере, до AIR 3.7 фильтры не поддерживались в режиме графического процессора. Я не уверен, что это все еще так. Тем не менее, вам следует избегать использования фильтров на мобильных устройствах, так как они очень медленно отображаются.
  2. Обязательно протестируйте приложение в режиме выпуска. В зависимости от настроек сборки разница между режимом отладки и режимом выпуска приложения может быть существенной, особенно в iOS. Приложение, которое я только что разработал, сократилось с 2-3 секунд, чтобы создать новый Flex View в режиме отладки, до менее кадра (~ 40 мс), чтобы сделать это в режиме выпуска на iPhone 4.
  3. Используйте блиттинг экономно. Делайте это только там, где это абсолютно необходимо
  4. Ищите способы упростить свой список отображения. Легко иметь объект с 40 дочерними элементами для создания кнопки. Вместо этого ищите способы упростить это до меньшего количества объектов и фильтров (даже если удаление фильтра требует добавления другого объекта). Я не верю, что это поможет в самом процессе копирования, но в первую очередь должно помочь с рендерингом объектов.

В общем, используйте блиттинг на мобильных устройствах с осторожностью, потому что создание растровых изображений происходит медленно.

person Josh    schedule 30.08.2013
comment
В ЭЙРЕ его нет. Это просто swf-файлы, загружаемые на сервер для воспроизведения в браузере, и да, здесь это происходит медленнее на очень быстром компьютере. - person Fans; 30.08.2013
comment
Тогда вы говорите, что ЭТА ЧАСТЬ ПРОИСХОДИТ, КОГДА ТЕЛЕФОН ИНИЦИАЛИЗИРУЕТСЯ. Смотрите мое редактирование в верхней части ответа - person Josh; 30.08.2013
comment
Да извини. Обычно я начинаю каждый класс с метода init(); внутри конструктора, поэтому инициализация телефона в основном означает все, что он делает, когда загружается в мир, но до любого взаимодействия с пользователем. Однако в описании говорится, что это виртуальный онлайн-мир WEB. - person Fans; 30.08.2013
comment
Вы уверены, что использование обычных мувиклипов лучше, чем копирование?? Я думал, что Старлинг в основном занимается блиттингом. У вас есть какие-нибудь тесты, которые сравнивают эти два? - person Fans; 23.09.2013