Domanda

Con ActionScript3 per Flash Player 9+, qual è il modo più bello per chiamare una funzione "una tantum", dopo esattamente un fotogramma?

Sono consapevole della classe Timer ed è usi, e il metodo di callLater su Flex Chimp (che, sfogliando la fonte, non sembra molto efficiente in questo scenario). Sono anche a conoscenza di setTimeout (in flash.utils).

La classe Timer e l'utilità setTimeout sono entrambi basati tempo, così come avremmo garantire che la nostra funzione verrà chiamato dopo esattamente un fotogramma?

Dal mio test limitati sembra che funzioni passate al setTimeout solo eseguito dopo almeno un telaio (provare a impostare il ritardo a 0). Ma questo non è garantito.

Naturalmente, abbiamo potuto ascoltare per gli eventi Event.ENTER_FRAME da un DisplayObject, ma che sembra eccessivo per una volta-off ritardato chiamata di funzione.

È stato utile?

Soluzione

Flex aveva lo scopo di astrarre la natura frame-based di Flash Player in modo da non trovare molto per aiutare voi con il vostro problema. L'approccio migliore è quello di ascoltare per ENTER_FRAME come lei suggerisce. Se questo è eccessivo (e io non sono sicuro perché si pensa che è), è possibile creare una classe di supporto che prende un DisplayObject e funzione come argomenti, che verrà automaticamente aggiungere / rimuovere il listener di eventi ENTER_FRAME per voi.

public class NextFrameCommand() {

    private var functionToCall : Function;

    public function NextFrameCommand(dObj: DisplayObject, func : Function) {
        functionToCall = func;
    }

    public function start() : void {
        dObj.addEventListener(Event.ENTER_FRAME, onEnterFrame);
    }

    private function onEnterFrame(e : Event) : void {
        e.target.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
        functionToCall.call();
    }

}

Non ho ancora testato che il codice ma si spera che si ottiene l'idea ....

Altri suggerimenti

Giocando con le soluzioni fornite da Theo e brd6644 ci sono venuto con questo. Esso consente a più funzioni (con parametri) mettere in coda ed eseguiti in ordine al fotogramma successivo.

public class DelayedFunctionQueue
{
    protected var queue:Array;
    protected var dispatcher:Sprite;

    public function DelayedFunctionQueue()
    {
        queue = new Array();
        dispatcher = new Sprite();
    }

    public function add( func:Function, ... args ):void
    {
        var delegateFn:Function = function():void
        {
            func.apply( null, args );
        }
        queue.push( delegateFn );
        if ( queue.length == 1 )
        {
            dispatcher.addEventListener( Event.ENTER_FRAME, onEF, false, 0, true );
        }
    }

    protected function onEF( event:Event ):void
    {
        dispatcher.removeEventListener( Event.ENTER_FRAME, onEF, false );
        queue = queue.reverse();
        while ( queue.length > 0 )
        {
            var delegateFn:Function = queue.pop();
            delegateFn();
        }
    }
}

Potrebbe essere utile a qualcuno.

Un modo sarebbe quello di vedere quanti fotogrammi al secondo il progetto è impostato per e lasciare che il ritardo funzione setTimeout per il tempo 1 fotogramma all'interno di tale impostazione.

Così, se il progetto è impostato a 24 fotogrammi al secondo, si ritarda per 42 millisecondi in setTimeout.

var timerSprite:Sprite = new Sprite();

timerSprite.addEventListener(Event.ENTER_FRAME, oneFrameHandeler);

function oneFrameHandeler(e:Event):void
{
   timerSprite.removeEventListener(Event.ENTER_FRAME, oneFrameHandeler);
   timerSprite = null;

   trace("one frame later!")
}

ENTER_FRAME non è eccessivo - qualcosa di simile è breve e facile

addEventListener(Event.ENTER_FRAME, function(e:Event):void
{
    removeEventListener(Event.ENTER_FRAME, arguments["callee"]);
    onceOffFunction();
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top