Actionscript 3 AS3电影剪辑比电影剪辑慢。为什么?

Actionscript 3 AS3电影剪辑比电影剪辑慢。为什么?,actionscript-3,flash,flash-builder,flash-cs5,blit,Actionscript 3,Flash,Flash Builder,Flash Cs5,Blit,我试着遵循李·布里姆洛(Lee Brimlow)的闪电战教程系列和雷克斯·范德斯皮(Rex Van der spuy)的“flash高级游戏设计”中的技术组合 我是一名开发人员,致力于flash制作的网络在线虚拟世界。我做了一个手机应用程序(工作原理类似于侠盗猎车手游戏中的手机)。不管怎样,当一条信息被发送时,我们想播放一个信封在周围飞来飞去,并在周围闪烁的疯狂动画。它是滞后的(尤其是在旧电脑上),所以我认为这将是一个使用blitting的好机会。然而,闪电动画实际上比普通电影播放得慢!!这到底

我试着遵循李·布里姆洛(Lee Brimlow)的闪电战教程系列和雷克斯·范德斯皮(Rex Van der spuy)的“flash高级游戏设计”中的技术组合

我是一名开发人员,致力于flash制作的网络在线虚拟世界。我做了一个手机应用程序(工作原理类似于侠盗猎车手游戏中的手机)。不管怎样,当一条信息被发送时,我们想播放一个信封在周围飞来飞去,并在周围闪烁的疯狂动画。它是滞后的(尤其是在旧电脑上),所以我认为这将是一个使用blitting的好机会。然而,闪电动画实际上比普通电影播放得慢!!这到底是怎么回事?闪电战只对移动设备更好,而实际上在计算机上更慢吗?也许我做错了什么。这是我的密码:

//这部分在初始化时发生

//**                
//---------------- 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);
//“闪电战”是我做的一门课。看起来是这样的:

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:
int=0; 私有变量计数: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吐出的spritesheet的信息

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


    }
}
编辑: 知道这不是移动的,我下面的回答是不相关的。不过,我会把它放在那里,以防将来有人在移动设备上遇到问题

关于这个具体问题,您每5毫秒运行一次计时器。首先,计时器准确度的最低范围是>15ms,因此这永远不是可行的解决方案。对于任何与在舞台上显示soemthing相关的计时器,您应该永远不要在少于一帧的时间内完成。(
1000/stage.framerate
对于每秒30帧的应用程序,帧速率约为40毫秒)

对于blitting,目标是减少计算和渲染。你现在设置这个的方式,看起来你是每5毫秒一次。这实际上是电影剪辑渲染频率的8倍多。你应该减少你暴躁的频率。只有当一个变化实际上已经超出了翻译的范围时才这样做。如果经常这样做,那就太过分了,原因是它太慢(同样,创建位图的速度很慢)


一般来说,您不希望在AIR for Mobile应用程序中使用blit(我假设您正在这样做,因为您提到了正在初始化的手机)。我不确定使用其他/本地SDK是否可以,但请避免在空中使用

从本质上讲,这取决于闪电战是如何运作的。Blitting采用屏幕截图,并在舞台上显示,而不是实际对象。总的来说,这很好。这意味着您的显示对象,尤其是渲染速度较慢的向量,渲染频率要低得多。它在设置动画时特别好,因为对象每次以任何方式转换时都倾向于重新渲染,而不是位图

然而,在移动平台上,创建位图的速度非常慢。我从来没有研究过SDK是如何创建位图的,但它并没有有效地创建位图(这常常让我怀疑它是否一个像素一个像素地创建位图)。在台式机上,这通常是好的。有足够的CPU和RAM来快速实现这一点。然而,在手机上,目前还没有这种奢侈品。因此,当您blit并创建位图时,运行该过程需要一段时间

这一问题在高分辨率屏幕上更加严重。今年1月至5月,我开发了一款应用程序,在GPU加速环境中选择性地使用了blitting来使用过滤器。在iPad2上,闪电游戏将我的应用程序从每秒30帧提升到每秒24帧。没什么大不了的,用户不会注意到的。然而,在带有视网膜显示器的iPad3上,它的速度下降到了10fps。想想看,这是有道理的,因为视网膜iPad的像素数是非视网膜iPad的4倍

如果您确实想在手机上使用blitting,我建议您做几件事:

  • 使用GPU渲染模式。没有它,你就没有机会。请注意,至少在pre AIR 3.7中,GPU模式下不支持过滤器。我不确定情况是否仍然如此。无论如何,您都应该避免在移动设备上使用过滤器,因为它们渲染速度非常慢
  • 确保测试发布模式应用程序。根据构建设置,调试模式和发布模式应用程序之间的差异可能很大,尤其是在iOS上。我刚刚开发的一个应用程序在调试模式下创建一个新的Flex
    View
    需要2-3秒,而在iphone4的发布模式下,创建这个新的Flex
    视图需要不到一帧(~40ms)
  • 少用闪电。只在绝对必要的地方做
  • 寻找简化显示列表的方法。让一个对象有40个子对象来创建一个按钮是很容易的。相反,寻找方法将其简化为更少的对象和更少的过滤器(即使移除过滤器需要添加另一个对象)。我不相信这将有助于实际的blitting过程,但它应该有助于在第一时间渲染对象

  • 所以,一般来说,在手机上少用blitting,因为位图创建速度很慢。

    它不在空中。这只是主权财富基金被上传到服务器上,在浏览器中播放,是的,在一台速度非常快的计算机上播放速度较慢。那么,你说“这部分发生在手机初始化时”肯定是骗人的。请看答案顶部的编辑是的,对不起。我通常用init()方法开始每个类;在构造器内部,所以“初始化手机”基本上意味着它在加载到世界上但在用户进行任何交互之前所做的所有事情。但在op中确实说这是一个网络虚拟世界。你确定使用普通的movieclips比blitting好吗??我以为斯塔琳基本上是在做闪电战。你有什么测试来比较这两者吗?