Почему настольное приложение AIR работает медленнее, чем автономный Flash Player?

#flash #actionscript-3 #performance #air

#flash #actionscript-3 #Производительность #air

Вопрос:

следующая программа создает фон, состоящий из двух слоев — растрированной заливки и повторяющейся растровой заливки с режимом многократного наложения сверху. при нажатии окно переключается между полноэкранным и оконным режимами, соответствующим образом настраивает размер фона, а затем становится черным с помощью Tweener.

когда я запускаю программу непосредственно с помощью автономного Flash Player (10.2), анимация плавного перехода происходит очень плавно как в полноэкранном, так и в оконном режимах. но когда я запускаю приложение как приложение AIR (2.5), исчезающая анимация заметно отстает, становится прерывистой.

я разработал приложение с использованием Flash Professional CS5. я пробовал публиковать со всеми 3 вариантами аппаратного ускорения (None, Direct, GPU), но разницы нет. я считаю, что код оптимизирован настолько, насколько это возможно для анимации отображаемых объектов путем преобразования их в растровые изображения.

я запускаю код как на автономном Flash Player 10.2, так и на AIR 2.6 (хотя приложение опубликовано с пакетом SDK 2.5) в Mac OS X 10.6.7 с 27-дюймовым iMac с частотой 3,06 ГГц Intel Core 2 Duo и 4 ГБ оперативной памяти. у меня нет доступа к тестированию в Windows или Linux.

ниже приведен основной класс документа и прикреплен в формате embedded .png, который я использовал («Background.png») в коде.

 package
{
//Imports
import com.caurina.transitions.Equations;
import com.caurina.transitions.Tweener;
import flash.display.Bitmap;
import flash.display.BlendMode;
import flash.display.BitmapData;
import flash.display.PixelSnapping;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageDisplayState;
import flash.display.StageScaleMode;
import flash.events.MouseEvent;
import flash.filters.BlurFilter;
import flash.geom.Matrix;

//SWF Metadata Tag
[SWF (width = "1000", height = "500", frameRate = "60", backgroundColor = "0x000000")]

//Class
public class FullScreenFadeTest extends Sprite
    {
    //Constants
    private static const MIN_WINDOW_WIDTH:uint = 480;
    private static const MIN_WINDOW_HEIGHT:uint = 320;
    private static const BLUR_AMOUNT:uint = 150;

    //Variables
    [Embed (source = "Background.png")]
    private var ImageAsset:Class;

    private var backgroundFillShape:Shape;
    private var backgroundFillBitmap:Bitmap;
    private var backgroundFillBitmapData:BitmapData;
    private var backgroundTexture:Shape;
    private var canvas:Sprite;
    private var faderShape:Shape;
    private var faderBitmap:Bitmap;
    private var faderBitmapData:BitmapData;
    private var fader:Sprite;

    //Constructor
    public function FullScreenFadeTest()
        {
        stage.scaleMode = StageScaleMode.NO_SCALE;
        stage.align = StageAlign.TOP_LEFT;

        init();
        }

    //Initialize
    private function init():void
        {
        backgroundFillShape = new Shape();
        backgroundFillShape.graphics.beginFill(0x7F7F7F, 1.0);
        backgroundFillShape.graphics.drawRect(-(MIN_WINDOW_WIDTH   BLUR_AMOUNT * 2) / 2, -(MIN_WINDOW_HEIGHT   BLUR_AMOUNT * 2) / 2, MIN_WINDOW_WIDTH   BLUR_AMOUNT * 2, MIN_WINDOW_HEIGHT   BLUR_AMOUNT * 2);
        backgroundFillShape.graphics.endFill();
        backgroundFillShape.graphics.beginFill(0xFFFFFF, 1.0);
        backgroundFillShape.graphics.drawEllipse(-MIN_WINDOW_WIDTH * 0.75 / 2, -MIN_WINDOW_HEIGHT * 0.5 / 2, MIN_WINDOW_WIDTH * 0.75, MIN_WINDOW_HEIGHT * 0.5);
        backgroundFillShape.graphics.endFill();
        backgroundFillShape.filters = [new BlurFilter(BLUR_AMOUNT, BLUR_AMOUNT, 3)];

        backgroundFillBitmapData = new BitmapData(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT);
        backgroundFillBitmapData.draw(backgroundFillShape, new Matrix(1, 0, 0, 1, MIN_WINDOW_WIDTH / 2, MIN_WINDOW_HEIGHT / 2));

        backgroundFillBitmap = new Bitmap(backgroundFillBitmapData, PixelSnapping.NEVER, true);
        backgroundFillBitmap.width = stage.stageWidth;
        backgroundFillBitmap.height = stage.stageHeight;

        backgroundTexture = new Shape();
        backgroundTexture.graphics.beginBitmapFill(backgroundFillBitmapData = (new ImageAsset()).bitmapData);
        backgroundTexture.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
        backgroundTexture.graphics.endFill();
        backgroundTexture.blendMode = BlendMode.MULTIPLY;

        canvas = new Sprite();
        canvas.addChild(backgroundFillBitmap);
        canvas.addChild(backgroundTexture);

        faderShape = new Shape();
        faderShape.graphics.beginFill(0x000000, 1.0);
        faderShape.graphics.drawRect(0, 0, 1, 1);
        faderShape.graphics.endFill();

        faderBitmapData = new BitmapData(1, 1);
        faderBitmapData.draw(faderShape);

        faderBitmap = new Bitmap(faderBitmapData, PixelSnapping.NEVER);
        faderBitmap.width = stage.stageWidth;
        faderBitmap.height = stage.stageHeight;

        fader = new Sprite();
        fader.addChild(faderBitmap);
        fader.alpha = 0.0;

        addChild(canvas);
        addChild(fader);

        stage.addEventListener(MouseEvent.CLICK, toggleDisplayState);
        }


    //Toggle Display State
    private function toggleDisplayState(evt:MouseEvent):void
        {
        if  (!Tweener.isTweening(fader))
            {
            if  (stage.displayState == StageDisplayState.NORMAL)
                stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
                else
                stage.displayState = StageDisplayState.NORMAL;

            backgroundTexture.graphics.clear();
            backgroundTexture.graphics.beginBitmapFill(backgroundFillBitmapData);
            backgroundTexture.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
            backgroundTexture.graphics.endFill();

            backgroundFillBitmap.width = fader.width = stage.stageWidth;
            backgroundFillBitmap.height = fader.height = stage.stageHeight;

            fader.alpha = 1.0;

            Tweener.addTween(fader, {time: 1.0, delay: 1.0, transition: Equations.easeInOutCubic, alpha: 0.0});
            }
        }
    }
}
  

Фон

Комментарии:

1. Вы уверены, что частота кадров составляет 60 кадров в секунду? SWF-тег может не соблюдаться AIR. Вы можете установить stage.frameRate, чтобы быть уверенным.

2. я добавил настройку stage.frameRate в коде, но, к сожалению, это не помогло. также ранее в IDE было установлено значение 60,0 кадров в секунду. хорошая идея. удалось ли вам скомпилировать приведенный выше код для подтверждения аналогичных результатов? еще одна вещь — я пытался использовать TweenLite вместо Tweener, но результаты были теми же.

3. Я не использую Flash CS, но я перенес ваш код в MXML AIR app и добавил счетчик кадров в секунду. Я вижу почти 60 кадров в секунду со случайными минимумами на отдельных кадрах при переключении режима экрана.

4. вы используете ОС Windows? я только что установил SWFProfiler. программа работает со скоростью 60 кадров в секунду. начиная с автономного Flash Player 10.2, при переключении из оконного режима в полноэкранную анимацию постепенного исчезновения кадров в секунду падает примерно до 35 кадров в секунду — это намного ниже, но все равно плавно. однако в приложении AIR во время анимации полноэкранного режима скорость снижается примерно до 12 кадров в секунду!!! во время затухания на моем Mac оно заметно прерывистое, а затем после анимации снова ускоряется до 60 кадров в секунду.

5. Я тестировал на Windows XP и AIR 2.0. Для AIR доступен SDK 2.6, это что-нибудь меняет?