1

我正在开发一款游戏,旨在作为“原生”应用程序和桌面网络浏览器部署在手机上。

由于在多个平台上工作,Flash 及其嵌入式 AIR 似乎是一个不错的解决方案。但是哦。

现在仅使用 4 关键帧动画剪辑(将它们添加到舞台,更新它们在每一帧上的位置,并最终删除它们)会使游戏在桌面屏幕上显示大约 30 个时变慢,在我的 Android 上显示大约 20 个时(三星 i9000 - 2.3.3)。我可能需要更多。

因此,我尝试通过重绘位图区域并将我的 MovieClips 转换为存储在我的 Flash 库中的 bitmapDatas spritesheets 来进行闪烁。桌面上的结果很棒,具有完美、流畅的动画,即使有数百个对象。但是在移动设备上的结果很糟糕,即使在屏幕上仅显示一个对象,CPU 或 GPU 渲染时,FPS 也会下降到 15。

因为我的游戏在“旧”设备上运行显然很好,如果我想达到接近或高于 50 的帧速率,此时使用 Flash 和 AIR 是一个坏主意吗?

用flash开发手游时,有什么技巧,或者必不可少的做法吗?在这种情况下,我们必须避免任何常见的错误吗?

4

2 回答 2

1

实际上,您可以在 Adob​​e Air 中通过非常复杂的 Flash 矢量动画获得 30fps 到 50fps。

不该做什么:

  1. 不要将预制的“缓存为位图”复选框用于任何动画。当应用于静态矢量图像时,这是一个很棒的功能,因为它将其转换为静态位图。如果动画以除了在 x 或 y 轴上平移影片剪辑之外的任何方式进行动画处理,则您的动画实际上会更慢,并且缓存为打开的位图。

  2. 不要做blitting。Blitting 可以使游戏在 Flash 中快速运行,但在 Adob​​e air 中它会使它们变慢。您想要的是放置在舞台上的位图对象,而不是被传送到舞台上的 bitmapData 对象。

因此,您可以做的是抓取一个 swf 或 Movieclip,运行对象的每一帧并将每一帧转换为位图。然后,将每个位图保存到一个数组中。然后,要播放动画,从数组中检索位图并将它们按顺序放置在舞台上。在我的测试中,我能够在 Android 平板电脑上以超过 40fps 的速度运行全屏、24 帧动画。

代码示例如下。它会慢慢缓存位图,完成,然后立即开始以更高的速率播放。如果需要,您可以在动画缓存时隐藏动画。当您不再需要动画时,清除数组以释放内存。

package scripts.animation{
    import flash.display.MovieClip;
    import flash.events.*;
    import flash.display.Stage;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.*;
    import flash.events.Event;


    public class spriteSheetMaker extends MovieClip {
        private var pWidth:int=0;
        private var pHeight:int=0;
        private var regX:int=0;
        private var regY:int=0;
        private var swfObj:MovieClip = null;
        private var pFrame:int=0;
        private var pFrames:int=0;
        private var pSheetArray:Array=[];
        private var pSheetInfo:Array=[];
        private var pAnimating:Boolean = false;
        private var pAnimationCycle:int = 0;
        //-------------------------------------------------------
        //-------------------------------------------------------
        //init
        //-------------------------------------------------------
        //-------------------------------------------------------
        public function spriteSheetMaker ():void {
            startGrab();
        }
        //-------------------------------------------------------
        //-------------------------------------------------------
        //swf is loaded, find out how many frames are in, dimentions etc, and start animation
        //-------------------------------------------------------
        //-------------------------------------------------------
        public function startGrab ():void {
            swfObj=this.animation;
            swfObj.x = 0;
            //swfObj.y = 0;
            pFrames=swfObj.totalFrames;
            pFrame=0;
            pSheetInfo=[this.name,pWidth,pHeight];
            pSheetArray.push (pSheetInfo);
            pAnimating = false;
            this.addEventListener (Event.ENTER_FRAME,cycleSwfAnim);
        }
        //-------------------------------------------------------
        //-------------------------------------------------------
        //load the next frame of the animation and convert it
        //-------------------------------------------------------
        //-------------------------------------------------------
        private function cycleSwfAnim (event:Event):void {
            pFrame++;
            if (pFrame < pFrames + 2) {
                swfObj.gotoAndStop (pFrame);
                grabBitmap ();
            } else {
                stopGrab ();
            }
        }
        //
        private function stopGrab():void{
            this.removeEventListener (Event.ENTER_FRAME,cycleSwfAnim);
            trace("Sheet = " + pSheetArray);
            swfObj.parent.removeChild(swfObj);
            swfObj=null;
            startAnimationPlayback();
        }
        //-------------------------------------------------------
        //-------------------------------------------------------
        //Convert fram (vector, bitmap, whatever is on the frame) into a bitmadata object
        //-------------------------------------------------------
        //-------------------------------------------------------
        private function grabBitmap ():void {
            pWidth=this.width;
            pHeight=this.height;
            var bmd:BitmapData=new BitmapData(pWidth,pHeight,true,0x00FFFFFF);
            bmd.draw (swfObj);
            var bm:Bitmap = new Bitmap();
            bm.bitmapData = bmd;
            pSheetArray.push (bm);
        }
        //-------------------------------------------------------
        //-------------------------------------------------------
        //Play animation
        //-------------------------------------------------------
        //-------------------------------------------------------
        private function startAnimationPlayback():void{
            this.addEventListener (Event.ENTER_FRAME,animate);
            pFrame =0;
        }
        //
        private function animate(event:Event):void{
            pFrame++;
            if (pFrame>pSheetArray.length){
                pFrame = 1;
            }
            var bm:Bitmap = pSheetArray[pFrame];
            if (bm != null){
                if (this.numChildren>0){
                    this.removeChildAt(0);
                }
                this.addChild(bm);
            }
        }
    }
}
于 2016-03-15T00:58:22.603 回答
0

结合 GPU 渲染,您可以使用 cacheAsBitmap 和 cacheAsBitmapMatrix 获得一些改进,但对于任何远程复杂的东西,很可能仍然无法让您接近 60fps。

如果您想在移动设备上获得真正的性能,您可能需要查看 Starling 框架 (http://gamua.com/starling/)。它完全将合成和渲染转移到 GPU,同时保持对象模型和显示列表非常接近标准 Flash 等效项。即使在一代或两代旧硬件上,性能也非常快(很容易达到 60fps)。

于 2012-09-05T10:49:35.930 回答