2017-09-07 13 views
1

openflのプリローダーの基本クラスとして組み込みのNMEPReloaderを使用しています。preloaderでのOpenFLアニメーションは、常に最初にステルスする

class AttractAnimation extends Sprite 
{ 
var currentFrame:Int; 
var previousFrame:Int; 
var bitmapFrames:Array<Bitmap>; 
var loadScreenTimer:Timer; 

public function new() 
{ 
    super(); 
    currentFrame = 0; 
    previousFrame = -1; 
    bitmapFrames = new Array<Bitmap>(); 
} 

public function assignBitmapData(bitmapData : Array<BitmapData>){ 
    for(bmap in bitmapData){ 
     var frame = new Bitmap(null, flash.display.PixelSnapping.AUTO, true); 
     frame.bitmapData = bmap; 
     pushFramesAsBitmap(frame); 
    } 
} 
public function pushFramesAsBitmap(frameAsBitmap:Bitmap) { 
    bitmapFrames.push(frameAsBitmap); 

    frameAsBitmap.visible = false; 
    addChild(frameAsBitmap); 
} 

public function startAnimation(fps:Int) { 
    var milliseconds:Float = 1000/fps; 
    loadScreenTimer = new Timer(milliseconds, 10); 
    loadScreenTimer.addEventListener(TimerEvent.TIMER, updateAnimation); 
    loadScreenTimer.start(); 
} 

    private function updateAnimation(e : TimerEvent):Void { 
     if (currentFrame > bitmapFrames.length -1) { currentFrame = 0; } 
     if (previousFrame != -1) { 
      bitmapFrames[previousFrame].visible = bitmapFrames[previousFrame].__combinedVisible = false; 
     } 
     bitmapFrames[currentFrame].visible = bitmapFrames[currentFrame].__combinedVisible = true; 
     previousFrame = currentFrame; 
     currentFrame++; 
    } 

} 

は何イム私はplayAnimationそれは本当に悪い吃音で呼び出すときに見て、私はアニメーションを再生次回はそれがスムーズに演じて何Imはフレームでアニメーションフレームを再生していること

アルファを0に設定してアニメーションを再生しようとしましたが、1に戻して再生していましたが、この場合は2回目は吃音になります。

同じ私は別の表示オブジェクトの後ろに移動する場合、アニメーションを再生し、それを描画順序の前面に移動すると、それはもう一度吃音になります。

私はそれが吃音せずにこのアニメーションを再生できる方法はありますか?

答えて

1

個々の画像の代わりにスプライトシートを使用して、吃音を止めることができました。

私は2番目のアニメーションを追加して名前を変更しました。ビットマップ配列の代わりにタイルシートを使用するようになりました。

私は提案されたonEnterFrameの変更を含めるために、以下の回答を再度更新しました。スプライトシートは吃音を取り除いていますが、アニメーションはエンターフレームのイベントでははるかにスムーズです。

class AnimatedSprite extends Sprite 
{ 
public var currentFrame:Int; 

private var loadScreenTimer:Timer; 
private var tiles: Array<Int>; 
private var tilesheet : Tilesheet; 

private var fps : Int; 
private var mDeltaTime:Float = 0; //the current delta time for time-based updates 
private var mTime:Float; //a variable containing the current time since the last frame change 


public function new(framesPerSecond : Int, looping : Bool = false) 
{ 
    super(); 
    currentFrame = 0; 
    fps = framesPerSecond; 
} 

//public methods 
public function assignBitmapData(bitmapData : BitmapData, tileData : Array<Rectangle>) : Void { 
    tilesheet = new Tilesheet(bitmapData); 
    tiles = new Array<Int>(); 

    for(i in 0...tileData.length){ 
     tiles.push(tilesheet.addTileRect(tileData[i])); 
    } 
    mTime = 0; 
} 

public function playAnimation() : Void { 
    trace("playAnimation"); 
    visible = true; 
    currentFrame = 0; 
    addEventListener(Event.ENTER_FRAME, onEnterFrame, false, 0, true); 
} 

//private methods 
private function endAnimation(?e : TimerEvent) : Void { 
    removeEventListener(Event.ENTER_FRAME, onEnterFrame); 
    graphics.clear(); 
    trace("end animation"); 
    currentFrame = 0; 
    mTime = 0; 
} 

private function onEnterFrame(e:Event):Void 
{ 
    trace("enter frame"); 
    var currentTime = Lib.getTimer(); //get the current time 
    var elapsed:Float = (currentTime - mDeltaTime); //calculate the time since the last update 
    mDeltaTime = currentTime; 

    mTime += elapsed; //add the elapeed time to mTime 
    if (mTime >= 1000/fps) //if it is time to change frame... 
    { 
     mTime = 0; 
     graphics.clear(); 
     tilesheet.drawTiles(this.graphics, [0, 0, tiles[currentFrame], 1, 1]); 
     trace("Draw frame : " + currentFrame); 
     if (currentFrame == tiles.length-1) endAnimation(); 

     currentFrame++; 
    } 
} 
} 
1

実装が非常に簡単で、多くの外部APIに依存しないため、タイマーが原因である可能性があります。プリローダは実際にはすべてを優先してロードしているので、それを隠すか防御するための措置を講じない限り遅れが予想されます。遅れのため、タイマーイベントが複数回連続して発生する可能性があります。この結果、視覚的なバグや吃音が発生します。

まず、タイマーの代わりにenterFrameイベントリスナーを使用してください。これは、すべてではないにしても大部分のデザインでは間違った選択です。

//Using this event listener 
addEventListener(Event.ENTER_FRAME, OnUpdateAnimation); 

//which would call this function every frame 
function OnUpdateAnimation(e:Event):Void 
{ 
    //calculate delay since last frame 
    //play next frame 
} 

第2に、ビットマップの配列を使用する代わりに、単一のビットマップとビットマップデータの配列を使用します。小さなアニメーションではあまり変わらないはずですが、これはより良い方法であり、パフォーマンスの向上に役立ちます(プリローダーなど)。

ここに、スプライトを拡張するアニメーションクラスの新しい実装があります。テストされていませんが、宣伝されたとおりに動作するはずです。通常、オブジェクトごとにEnterFrameリスナを使用するのは良い方法ではないことに注意してください。通常、更新可能なすべてのオブジェクトをループするメインの更新機能があります。しかし、この場合、十分です。

class Animation extends Sprite 
{ 

    private var mBitmapDataList:Array<BitmapData>; //a list of bitmapdata 
    private var mBitmap:Bitmap; //the bitmap that will contain all bitmapdata 
    private var mCurrentIndex:Int; //the currently displayed bitmapdata 
    private var mFrameLength:Float; //the duration of a frame in miliseconds 
    private var mDeltaTime:Float = 0; //the current delta time for time-based updates 

    private var mTime:Float; //a variable containing the current time since the last frame change 
    public function new(aFrameLength:Float) 
    { 
     super(); 
     mFrameLength = aFrameLength; 
     mBitmapDataList = new Array<BitmapData>(); 
     mBitmap = new Bitmap(); 
     addChild(mBitmap); //add the bitmap to the scene 
         //(it will display nothing as no bitmapdata is set) 
     mCurrentIndex = 0; 
    } 

    //add a bitmapdata instead of a complete bitmap object 
    public function addBitmapData(aBD:BitmapData):Void 
    { 
     mBitmapDataList.push(aBD); 
    } 

    public function play():Void 
    { 
     addEventListener(Event.ENTER_FRAME, onEnterFrame, false, 0, true); 
    } 

    private function onEnterFrame(e:Event):Void 
    { 
     var currentTime = Lib.getTimer(); //get the current time 
     var elapsed:Float = (currentTime - mDeltaTime); //calculate the time since the last update 
     mDeltaTime = currentTime; 

     mTime += elapsed; //add the elapeed time to mTime 
     if (mTime >= mFrameLength) //if it is time to change frame... 
     { 
      mTime = 0; 
      mCurrentIndex++; 
      if (mCurrentIndex == mBitmapDataList.length) mCurrentIndex = 0; 
      mBitmap.bitmapData = mBitmapDataList[mCurrentIndex]; //change it 
     } 
    } 
} 

このようにして、吃音の極端な場合でも、最初のフレームだけがスキップされます。また、一部のターゲットでは、まだロードされていないイメージを表示できないことに注意してください。別の解決策は、資産<assets path="assets" embed="false"/>を埋め込み、OpenFLの資産クラスを使用してロードすることです(私の謙虚な意見では、プリローダーを捨て去ります)。

PS:mと変数のプレフィックスをお許しください。 mはメンバー変数、aは引数です。

+0

ありがとうございました。画像のスプライトシートを使って解決できました。私は行って、提供されたソリューションを使用しました。 –

+0

私はあなたのEnterFrameイベントの実装にもよく切り替えるでしょう –

関連する問題