是否可以使用ActionScript 3组合动态影片剪辑时间轴?

时间:2009-10-13 22:44:35

标签: actionscript-3

基本上我只是想创建一个高性能的AnimatedBitmap类。我已经调查了一些基于Sprite的AnimatedBitmap类,它们使用了定时器和BitmapData.copyPixels()或BitmapData.draw()的一些变体,但这些似乎并不像简单地错开MovieClip时间轴上的资产那么快让时间线发挥。

所以我认为是一个扩展MovieClip的类,并且具有以下伪代码的特征:

    public function contstructTimeline(frameContent:Vector<BitmapData>):void {
        //Iterate through the frameContent vector and add a bitmap to each keyframe....I do NOT want bitmaps to persist beyond the frame they have been added to.
        var thisBitmap:Bitmap;
        for(var i:int = 0 ; i < frameContent.length; i++){
            gotoAndStop(i);
            thisBitmap = new Bitmap(frameContent[i]);
            addChild(thisBitmap);               
        }
    }

这是一个傻瓜差事吗?

1 个答案:

答案 0 :(得分:3)

好吧,这个想法很酷,但我想,你不能只是去跳到一个不存在的框架,然后添加内容(至少我没有成功)......

我有两个想法:

  • 编译一个足够长的空剪辑(有足够的帧来做任何你喜欢的,或多个,长度为2的幂(因此你的开销不超过50%))。将您的位图展开在框架上,然后使用MovieClip::addFrameScript在最后一帧添加gotoAndPlay(0)
  • 在运行时创建一个swf,使用一个合适的库,hxformat(好吧,你需要Haxe,但不管怎么说,如果你真的进入,那就是我的建议性能),并用Loader::loadBytes加载它。我确定as3有类似的库(你可能想要使用corelib的png编码器,这样你就可以将切片嵌入到swf中)。最好的是,创建一个动画片段,包含所需的动画作为资源,所以你加载剪辑一次,抓住类然后实例化(使操作同步)。

当然,您可以将两者结合起来,只需在运行时创建一个空剪辑,然后用位图数据填充它......

除此之外,我还有其他建议:

  • 将所有切片放入一个精灵中,然后使用DisplayObject::visible来完成这个操作。
  • 在您分发swf的服务器上进行转换(可能使用swfmill左右注入)
  • 查看banana slice

我还要注意,您使用BitmapData::copyPixelsBitmapData::draw描述的方法,如果实施得当,通常会以内存为代价执行得更好...这是因为Flash播放器渲染,抗锯齿,缓存,裁剪和许多其他事情都不是最优的......最近有一个关于这个的讨论...你可能想要搜索它......

那么,祝你好运......;)


编辑嗯,我同意,这不是很好,虽然设置可见性几乎是免费的(只要你之后不强制渲染)......

无论如何......诀窍是跟踪最后一个可见对象,如下所示:

package  {
    import flash.display.*;
    import flash.events.Event;
    public class SliceBitmap extends Sprite {
        private var _currentFrame:uint = 0;
        private var _totalFrames:uint;
        private var _playing:Boolean;
        public function SliceBitmap(slices:Array) {
            for each (var slice:BitmapData in slices) 
                this.addChild(new Bitmap(slice)).visible = false;
            this.getChildAt(0).visible = true;
            this._totalFrames = slices.length;
            this.play();
        }
        private function onEnterFrame(e:Event):void {
            this.goto((this._currentFrame + 1) % this._totalFrames);
        }
        private function goto(frame:uint):void {
            if ((frame < 0) && (frame >= this._totalFrames)) throw "this should be handled";
            this.getChildAt(this._currentFrame).visible = false;
            this.getChildAt(this._currentFrame = frame).visible = true;
        }   
        public function play():void { this.playing = true; }
        public function stop():void { this.playing = false; }
        public function get playing():Boolean { return _playing; }
        public function set playing(value:Boolean):void {
            if (this._playing != value) {
                if (this._playing = value) 
                    this.addEventListener(Event.ENTER_FRAME, onEnterFrame, false, int.MAX_VALUE);
                else 
                    this.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
            }
        }
        public function gotoAndPlay(frame:uint):void {
            this.goto(frame);
            this.play();
        }
        public function gotoAndStop(frame:uint):void {
            this.goto(frame);
            this.stop();
        }           
    }

}

这里有一些要测试的代码:

var slices:Array = [];
for (var i:int = 0; i < 20; i++) {
    var b:BitmapData = new BitmapData(200, 200, true);
    b.perlinNoise(4, 4, 4, i, true, false, 7, true);
    slices.push(b);
}
this.addChild(new SliceBitmap(slices);