我试着结合Lee Brimlow的blitting教程系列和Rex Van der spuy的“高级游戏设计与闪光”技术
我是一名开发人员,致力于使用flash制作的网络虚拟世界。我做了一个电话应用程序(类似于盗窃汽车游戏中的手机)。无论如何,当一条消息被发送时,我们想要播放这个疯狂的动画,一个信封飞来飞去,周围闪闪发光。它是滞后的(特别是在较旧的计算机上),所以我认为这是一个很好的机会使用blitting。然而,blitting动画实际上比普通的动画片段慢!到底发生了什么事? 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);
//“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:
int = 0; private 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();
它还使用BlitConfig存储有关Spritesheet吐出的信息,由TexturePacker
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()
{
}
}
}
答案 0 :(得分:0)
编辑: 知道这不是移动的,我的回答是无关紧要的。不过,我会把它留在那里,以防万一将来有人在移动设备上遇到麻烦。
关于这个具体问题,您每5ms运行一次计时器。首先,Timer准确的最低范围是> 15ms,因此永远不会是一个可行的解决方案。对于任何与在舞台上显示soemthing相关的计时器,你应该从不做不到一帧。 (1000/stage.framerate
。〜40ms的30fps应用程序)
对于blitting,目标是减少计算和渲染。你现在就设置这种方式的方式,看起来你每隔5ms就会出现一次。这实际上是MovieClip渲染频率的8倍。你应该减少你的blit频率。只有在实际进行了超出翻译的变更时才能执行此操作。经常这样做是有点过分而且它太慢的原因(再次,创建位图很慢)
通常,您不希望在AIR for Mobile应用程序中进行blit(我假设您正在进行操作,因为您提到了手机被初始化)。我不确定使用其他/本机SDK是否可以,但在AIR中避免使用它。
基本上,它归结为blitting的工作原理。 Blitting采用屏幕捕获并在舞台上显示而不是实际对象。总的来说,这很棒。这意味着您的显示对象,尤其是渲染速度较慢的向量,必须经常渲染。动画时特别好,因为每次以任何方式翻译对象时都会重新渲染,而不是位图。
但是,在移动平台上,创建该位图的速度非常慢。我从来没有研究过SDK如何创建Bitmaps,但是它并没有有效地做到这一点(它经常让我想知道它是否逐像素化)。在桌面上,这通常很好。有足够的CPU和足够的RAM来快速实现这一点。然而,在移动设备上,此刻并不存在奢侈品。因此,当您进行blit并创建该位图时,运行该进程需要一段时间。
高分辨率屏幕上的问题更加严重。我在今年1月到5月开发的应用程序选择性地使用blitting在GPU加速环境中使用过滤器。在iPad 2上,blitting将我的应用从30fps提升到了~24fps。没什么大不了的,用户不会注意到任何事情。然而,在带有视网膜显示屏的iPad 3上,它下降到10fps。当你想到它时,它是有道理的,因为视网膜iPad的像素是非视网膜iPad的4倍。
如果您确实想在手机上使用blitting,我建议您做一些事情:
View
到少于一帧(~40ms)才能在iPhone 4的发布模式下执行它所以一般情况下,在移动设备上使用blitting,因为位图创建很慢。