0

Lee Brimlow のブリッティング チュートリアル シリーズと、Rex Van der spuy の「フラッシュを使用した高度なゲーム デザイン」のテクニックの組み合わせに従ってみました。

私は、フラッシュで作成された Web オンライン仮想世界に取り組んでいる開発者です。電話アプリケーションを作成しました (グランド セフト オート ゲームの電話と同じように機能します)。とにかく、メッセージが送信されると、封筒が飛んで周りをキラキラと変化するクレイジーなアニメーションを再生したいと考えています。(特に古いコンピューターでは) ラグがあったので、ブリッティングを使用する絶好の機会だと思いました。ただし、ブリッティング アニメーションは、実際には通常のムービークリップよりも遅く再生されます!! ここで一体何が起こっているのですか?ブリッティングはモバイルデバイスでのみ優れており、実際にはコンピューターでは遅いですか? たぶん私は何か間違ったことをしています。これが私のコードです:

// この部分は、電話が初期化されたときに発生します

//**                
//---------------- 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; プライベート var _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();

また、TexturePacker によって吐き出されたスプライトシートに関する情報を保存する BlitConfig も使用します。

    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()
        {
        }


    }
}
4

1 に答える 1

0

編集:これはモバイルではないことを知っているので、以下の私の答えは無関係です。ただし、将来誰かがモバイルでブリッティングに問題が発生した場合に備えて、そこに残しておきます.

この特定の質問に関しては、5 ミリ秒ごとにタイマーを実行しています。まず、タイマーの精度の最低範囲は 15 ミリ秒を超えるため、実行可能なソリューションにはなりません。ステージ上で何かを表示することに関連するタイマーについては、1 フレーム未満にしないでください( 1000/stage.framerate. 30fps アプリの場合は ~40ms)

ブリッティングの目的は、計算とレンダリングを減らすことです。この設定方法では、5 ミリ秒ごとにブリットしているように見えます。これは、実際には MovieClip のレンダリングの 8 倍以上の頻度です。ブリットの頻度を減らす必要があります。翻訳を超える変更が実際に行われた場合にのみ行ってください。それ以上頻繁に行うのはやり過ぎであり、それが非常に遅い理由です (繰り返しますが、ビットマップの作成は遅いです)。


一般に、AIR for Mobile アプリケーションでは blit を実行したくありません (電話機が初期化されていると述べたので、blit を実行していると思います)。他の/ネイティブ SDK を使用して実行してもよいかどうかはわかりませんが、AIR では使用しないでください。

基本的に、それはブリッティングがどのように機能するかにかかっています。ブリッティングはスクリーン キャプチャを取得し、実際のオブジェクトではなくステージ上に表示します。一般的に、これは素晴らしいことです。これは、表示オブジェクト、特にレンダリングが遅いベクターは、レンダリングの頻度を大幅に減らす必要があることを意味します。オブジェクトは、ビットマップではなく何らかの方法で変換されるたびに再レンダリングされる傾向があるため、アニメーション化する場合に特に適しています。

ただし、モバイル プラットフォームでは、そのビットマップの作成は非常に遅くなります。SDK がビットマップを作成する方法を調べたことはありませんが、効率的ではありません (ピクセルごとに作成するのかどうか疑問に思うことがよくあります)。デスクトップでは、これは通常問題ありません。これを迅速に行うための十分な CPU と RAM があります。ただし、モバイルでは、現時点ではそのような贅沢はありません。そのため、そのビットマップをブリットして作成すると、そのプロセスの実行に時間がかかります。

この問題は、高解像度の画面で悪化します。今年の 1 月から 5 月にかけて開発したアプリでは、GPU アクセラレーション環境でフィルターを使用するためにブリッティングを選択的に使用しました。iPad 2 では、ブリッティングによりアプリが 30fps から ~24fps になりました。大したことではなく、ユーザーが気付くものではありません。ただし、Retina ディスプレイを搭載した iPad 3 では、10fps まで低下しました。Retina iPad のピクセル数は非 Retina iPad の 4 倍であるため、考えてみれば当然のことです。

モバイルでブリッティングを使用したい場合は、いくつかのことをお勧めします。

  1. GPU レンダリング モードを使用します。それがなければ、チャンスはありません。少なくとも AIR 3.7 より前では、フィルターは GPU モードでサポートされていないことに注意してください。今もそうなのか不安です。ただし、レンダリングが非常に遅いため、モバイルでのフィルターの使用は避ける必要があります。
  2. リリース モードのアプリケーションを必ずテストしてください。ビルド設定によっては、特に iOS では、デバッグ モードとリリース モードのアプリの違いが大きくなる可能性があります。私が開発したばかりのアプリは、iPhone 4 でデバッグ モードで新しい Flex を作成するのに 2 ~ 3 秒かかってViewいましたが、リリース モードでは 1 フレーム未満 (約 40 ミリ秒) になりました。
  3. ブリッティングは控えめに使用してください。どうしても必要なところだけにする
  4. 表示リストを簡素化する方法を探してください。ボタンを作成するために 40 個の子を持つオブジェクトを持つのは簡単です。代わりに、それをより少ないオブジェクトとより少ないフィルターに単純化する方法を探してください (フィルターを削除するには、別のオブジェクトを追加する必要がある場合でも)。これが実際のブリッティング プロセスに役立つとは思いませんが、そもそもオブジェクトのレンダリングには役立つはずです。

したがって、一般的に、ビットマップの作成は遅いため、モバイルではブリッティングを控えめに使用してください。

于 2013-08-30T17:53:52.217 に答える