2009-10-13 8 views
1

Fondamentalement, j'essaie simplement de créer une classe AnimatedBitmap haute performance. J'ai étudié certaines classes AnimatedBitmap basées sur Sprite qui utilisent des timers et des variantes de BitmapData.copyPixels() ou BitmapData.draw(), mais celles-ci ne semblent pas aussi rapides que l'échelonnement des assets sur un scénario MovieClip et laisser jouer la timeline.Est-il possible d'assembler une timeline movieclip dynamique avec ActionScript 3?

Alors, que penser im est une classe qui étend MovieClip et possède une fonctionnalité le long des lignes du pseudo-code suivant:

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);    
     } 
    } 

Est-ce une course de fous?

+0

Il est certainement possible. Pourquoi ne pas essayer et voir si c'est un fatser? –

Répondre

3

bien, l'idée est cool, mais je suppose que, vous ne pouvez pas aller juste et sauter à un cadre inexistant, puis ajouter du contenu (au moins je ne réussissais pas) ...

j'ai deux idées pour vous:

  • compiler un clip vide suffisamment longue (avec suffisamment de cadres pour faire ce que vous voulez, ou les multiples, avec des longueurs étant une puissance de 2 (vous aurez pas plus de 50% de frais généraux)) . répartissez vos bitmaps sur les images, puis utilisez MovieClip::addFrameScript pour ajouter un gotoAndPlay(0) à la dernière image.
  • créer un swf à l'exécution, en utilisant une bibliothèque appropriée, comme hxformat (ok, vous aurez besoin de haXe pour cela, mais c'est quelque chose que je suggère de toute façon, si vous êtes vraiment en performance), et le charger avec Loader::loadBytes . Je suis sûr qu'il existe des bibliothèques similaires pour as3 (vous voudrez probablement utiliser l'encodeur png de corelib pour pouvoir intégrer les tranches dans le swf). Le mieux serait, pour créer un MovieClip, contenant l'animation désirée comme un atout, de sorte que vous chargiez le clip une fois, récupérez la classe puis instanciez (rend l'opération synchrone).

bien sûr, vous pouvez combiner les deux, créant simplement un clip vide lors de l'exécution, puis le remplir avec des données bitmap ...

à part ça, je l'aurais d'autres suggestions:

  • Mettez toutes les coupes en une seule image-objet et utilisez DisplayObject::visible pour faire l'affaire.
  • faire la conversion sur le serveur à partir duquel vous distribuez le swf (peut-être injecter à l'aide swfmill ou si)
  • départ banana slice

Je voudrais aussi noter que les méthodes décrites à l'aide que vous BitmapData::copyPixels ou BitmapData::draw, s'il est bien implémenté, fonctionne généralement mieux au détriment de la mémoire ... c'est parce que le rendu, l'anticrénelage, la mise en cache, l'écrêtage et bien d'autres choses ne sont pas optimaux ... il y a eu une discussion ici dernièrement ... vous voudrez peut-être le chercher ...

Eh bien, bonne chance ...;)


modifier: bien, je suis d'accord, ce n'est pas vraiment agréable, même si la mise en visibilité est presque sans frais (tant que vous ne forcez pas rendu juste après) ...

de toute façon ...l'astuce est de garder une trace du dernier objet visible, comme ceci:

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

} 

et voici un code à tester:

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); 

+0

Merci pour la réponse. J'ai fait un essai et mon approche était à peu près exactement ce que vous avez recommandé. Le seul problème est que addchild/removeChild n'est pas limité à l'image clé sur laquelle le code s'exécute. J'ai donc dû utiliser cette bête (qui était tout aussi mauvaise que Bitmapdata.copyPixels: (both onEnterFrame) function publique onEnterFrame (e: Event): void { \t if (_bitmapDataVector == null || _bitmapDataVector.length <1) {\t retour; \t} \t for (var i: int = 1; i <= numChildren; i ++) { \t \t if (i = currentFrame) { \t \t \t getChildAt (i-1) .visible = faux, \t \t \t continuer \t \t \t} \t \t getChildAt (i-1) .visible = true; \t \t \t \t \t}} –

+0

Désolé: \t \t fonction publique onEnterFrame (e: Event): void { \t \t \t if (_bitmapDataVector == null || _bitmapDataVector.length <1) {\t retour; \t} \t \t \t for (var i: int = 1; i <= numChildren; i ++) { \t \t \t \t if (! I = currentFrame) { \t \t \t \t \t getChildAt (i-1) .visible = faux; \t \t \t \t \t continuent \t \t \t \t \t} \t \t \t \t getChildAt (i-1) .visible = true; \t \t \t \t \t \t \t}} \t \t –

Questions connexes