我正在开发一款旨在作为“原生”应用和桌面网络浏览器部署在手机上的游戏。
自从在多个平台上工作以来,Flash及其嵌入式AIR似乎是一个非常好的解决方案。但是呃 - 哦。
目前仅使用4-keyframed影片剪辑(将它们添加到舞台,更新每个帧上的位置,最终删除它们)会使游戏在桌面屏幕上显示约30个时减慢,当显示时约20个我的Android(三星i9000 - 2.3.3)。我可能需要更多。
所以我尝试通过重绘我的位图区域,并将我的MovieClip转换为存储在我的Flash库中的bitmapDatas spritesheets来进行blittering。桌面上的结果很棒,动画完美,流畅,即使有数百个对象也是如此。但是移动设备上的结果非常糟糕,即使屏幕,CPU或GPU上只显示一个对象,FPS也会下降到15。
因为我的游戏在“旧”设备上工作显然会很好,如果我想达到接近或超过50的帧速率,那么目前使用Flash和AIR是一个坏主意吗?
使用闪存开发手机游戏时是否需要使用任何提示或不可或缺的做法?在这种情况下,我们必须避免任何常见的错误吗?
答案 0 :(得分:1)
使用非常复杂的Flash矢量动画,您实际上可以在Adobe Air中获得30fps到50fps。
什么不该做:
不要使用预制的"缓存作为位图"任何动画的复选框。当应用于静态矢量图像时,这是一个很好的功能,因为它将其转换为静态位图。如果动画以除了在x或y轴上平移影片剪辑之外的任何方式进行动画处理,则动画实际上将是SLOWER,并且缓存为位图打开。
不要做blitting。 Blitting可以让游戏在Flash中快速发展,但在Adobe Air上它会使它们变慢。你想要的是放置在舞台上的位图对象,而不是在舞台上嵌入的bitmapData对象。
所以,你可以做的是抓取swf或Movieclip,并运行对象的每一帧并将每个帧转换为位图。然后,将每个位图保存到一个数组中。然后,要播放动画,请从数组中检索位图并将它们按顺序放在舞台上。在我的测试中,我能够以超过40fps的速度在Android平板电脑上运行全屏,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);
}
}
}
}
答案 1 :(得分:0)
你可以通过cacheAsBitmap和cacheAsBitmapMatrix与GPU渲染相结合来获得一些改进,但是对于任何远程复杂的东西来说,仍有可能无法让你接近60fps。
如果您想在移动设备上获得真正的性能,您可能需要查看Starling框架(http://gamua.com/starling/)。它完全将合成和渲染移动到GPU,同时保持对象模型和显示列表非常接近标准Flash等价物。即使在一代或两个旧硬件上,性能也非常快(60fps容易实现)。