TimeInterval : gestion des intervalles de temps
Par -Alexandre LEGOUT aka LAlex- le 12 octobre 2004, 14:55 - AS2 - Lien permanent
Comme je le précisais dans mon précédent post, je suis en train de m'attaquer au redéveloppement de certaines classes fournies par Macromedia. Cela commence par la fameuse OnEnterFrameBeacon, fournissant un point d'accés central à l'évenement onEnterFrame de MovieClip. La seule différence entre ma version et celle de MM est son nom, (devenue pour l'occasion FrameBeacon, c'est bien suffisant :P), l'utilisation de EventDispatcher, et la création d'un constructeur privé, histoire d'être bien sûr qu'on ne puisse pas l'instancier. ![]()
Viennent ensuite les classe de type ITimeInterval que sont MSInterval et FrameInterval.
Ces deux classes servent à gérer des intervalles de temps, soit en millisecondes, soit en nombre de frames. Elle diffuse régulièrement un évenement onTime à ses écouteurs. Le but est ici d'uniformiser l'execution d'instructions à intervalles réguliers, comme cela peut exister avec un setInterval. L'utilité de ces classes réside dans plusieurs points :
- Une interface commune, permettant de modifier facilement à l'execution le type d'intervalle.
- La possibilité d'executer un évenement toutes les n frames, comme c'est le cas en millisecondes avec setInterval.
- La possiblité de définir un nombre maximum d'itérations de l'intervalle
- La possiblité d'arrêter un intervalle en cours de route, et de le reprendre où il en était
- La possibilité de synchroniser plusieurs instructions en leur attribuant la même instance d'un intervalle
Voici un exemple d'utilisation :import com.lalex.transitions.*;
class Diaporama {
private var _itv:ITimeInterval;
// Constructeur et méthodes ...
// Si un intervalle existait déjà, on l'arrete et on le désabonne
public function setInterval(itv:ITimeInterval) {
if (_itv != null) {
_itv.stop();
_itv.removeListenerEvent("onTime", this);
}
_itv = itv;
_itv.addListenerEvent("onTime", this);
}
public function onTime() {
nextImage();
}
public function start() {
_itv.start();
}
}
/** Utilisation */
var diapo:Diaporama = new Diaporama();
diapo.addImage("image1.jpg");
diapo.addImage("image2.jpg");
// On crée un intervalle de 500 ms.
var ms:ITimeInterval = new MSInterval(500);
// La même instruciton pour changer d'image toutes les 20 frames
// var ms:ITimeInterval = new FrameInterval(20);
diapo.setInterval(ms);
diapo.start();
A noter que pour obtenir l'équivalent d'un onEnterFrame, il suffit de créer un FrameInterval sans paramètre (ou avec 1 en premier paramètre).
Le seul probleme important vient du fait que les destructeurs ne sont pas gérés, et qu'un delete d'une instance non stopée peut laisser tourner un processus orphelin ... :\
La classe Tween utilisant les intervalles de temps viendra prochainement ... ![]()
Commentaires
Entre toi et pet je m'en sort plus.
Je croule sous le boulot et je suis frusté de ne pas pouvoir tout tester.
A force de Bookmarker, j'ai des liens dans tt les sens.
Je vais devoir prendre une semaine de coner pour récuperer ce retard
C'est génial, merci les mecs
Il est vrai que là ça devient devient de plus en plus compliqué de suivre.....
Va falloir penser à faire une classe qui rallonge la durée d'une journée aussi
En tout cas merci
Hello

mais au moins il ne me gène plus. Qu'en penses tu ? 
Je vais essayer de pas les lire trop vite pour voir ce que je ferai tout seul et pour comparer aprés avec les tiennes
Merci en tout cas 

Question ? pourquoi tu gardes une profondeur positive pour ton clip dans ta frame FrameBeacon ?
Pour ma part cela m'embrouillait d'avoir cette profondeur positive... du moins pour utiliser _root.getNextHighestDepth() ... du coup j'ai passé le clip en profondeur négative. Je ne sais pas si c'est super propre
PS : sinon tes classes sont exactements du style de ce que j'allais mettre en place très bientôt ...
bye
Pourquoi ne pas vérifier lors du broadcast que l'objet existe bien et que s'il n'existe pas le supprimer des écouteurs et que lorsqu'il n'y a plus d'écouteurs, supprimer l'interval ?
@SamSam > Je ne parle pas des écouteurs, mais bien de l'instance de MSInterval ou FrameInterval ...
@eka > Je me suis contenté de reprendre OnEnterFrameBeacon, et de baisser la profondeur de 1. De toutes façons, je ne programme quasiment jamais sur _root, mais dans un clip qui contient tout !
++ ^_^
Moi non plus mais parfois pour les tests.. lol cela peut arriver et là problème et cela fait perdre un peu de temps pour trouver d'où viens le bug... c'est un peu comme ce foutu bug avec le focusManager quand on utilise les composants MM 2004 lol .. il y a des trucs que je saisi pas sur les finesses des choix des équipes de macromédia, un peu comme tu le disais avec le AsBroadcaster qui est boudé et remplacé par un BroadcasterMX peut imaginatif ?? Etrange
Dans ce cas pourquoi ne pas stocker dans un tableau en statique les instances, à la manière d'un singleton, càd que l'on ne crée pas directement une instance mais plutot MSInterval.getNewInstance(ms:Number):MSInterval;
De cette manière :
1- lors du broadcast si une instance n'as pas d'écouteur > MSInterval.removeInstance(o:MSInterval):Void;
2- removeInstance stoppe toujours l'interval avant de supprimer l'instance.
Faudrait utiliser une Collection peut être dans ton cas SamsamTS
(voir classes du package mx.utils de remoting)
Voilà, une collection c'est le terme que je cherchais
(Jamais vu cette classe d'ailleurs)
Moi je donne des idées après LAlex il fait comme il veut
L'idéal serait quand même la gestion des destructeurs, ca serait le pied...
hello
J'utilise dans mon travail la classe Gdispatcher de GrantSkinner qui ressemble comme 2 gouttes d'eau (ou presque) à EventDispatcher donc je vais pas la mettre ici 
En réfléchissant .. sur ma mise en place un peu perso des classes Motion et Tween de Penner... j'ai un peu poussé la classe onEnterFrameBeacon en m'inspirant de beaucoup de ce que tu as fais avec ta classe FrameBeacon.
J'utilise au passage une classe BasicArray issue d'une discussion avec petpex au sujet d'un élémént de son FrameWork PixLib et de cette vieille discussion que j'avais eu avec neoLao à l'époque sur MSN
Voilà en gros l'idée :
interface de la classe BasicArray
/* ---------- IBasicArray 1.0.0La classe BasicArrayInterface Name : IBasicArray
Package : net.eka.core.interfaces
Version : 1.0.0
Date : 2004-10-16
Author : ekameleon
URL : <a href="http://www.ekameleon.net" rel="nofollow">http://www.ekameleon.net</a>
Mail : <a href="mailto:contact@ekameleon.net" rel="nofollow">contact@ekameleon.net</a>
Description
Interface de la classe BasicArray
---------- */
interface net.eka.core.interfaces.IBasicArray {
function getIndex ( o ) : Number ;
function exists (o) : Boolean ;
function push(o) : Boolean ;
function remove(o) : Boolean ;
}
/* -------------------------------------------------------------------------et enfin la classe FrameBeacon :Name : BasicArray
Package : net.eka.core
Version : 1.0.0
Date : 2004-10-19
Author : ekameleon
URL : <a href="http://www.ekameleon.net" rel="nofollow">http://www.ekameleon.net</a>
Mail : <a href="mailto:contact@ekameleon.net" rel="nofollow">contact@ekameleon.net</a>
-------------------------------------------------------------------------
DESCRIPTION
-------------------------------------------------------------------------
Classe permettant de créer des classes qui héritent de Array
-------------------------------------------------------------------------
THANKS
-------------------------------------------------------------------------
Francis Bourre : <a href="http://www.tweenpix.net/" rel="nofollow">http://www.tweenpix.net/</a>
------------------------------------------------------------------------- */
import net.eka.core.interfaces.IBasicArray ;
class net.eka.core.BasicArray extends Array implements IBasicArray {
function BasicArray () {
splice.apply(this, [0, 0].concat(arguments));
}
public function getIndex( o ) : Number {
var l:Number = this.length;
while ( --l > -1 ) if (this[l] == o) return l ;
return -1 ;
}
public function exists(o) : Boolean {
return getIndex(o) != -1 ;
}
public function push(o) : Boolean {
if (!exists(o)) {
super.push(o) ;
return true ;
} else return false;
}
public function remove(o) : Boolean {
var i:Number = getIndex(o) ;
if (i > -1) {
splice(i, 1);
return true;
} else return false;
}
}
/* -------------------------------------------------------------------------Name : FrameBeacon
Package : net.eka.transitions
Version : 1.0.0
Date : 2004-10-19
Author : ekameleon
URL : <a href="http://www.ekameleon.net" rel="nofollow">http://www.ekameleon.net</a>
Mail : <a href="mailto:contact@ekameleon.net" rel="nofollow">contact@ekameleon.net</a>
-------------------------------------------------------------------------
DESCRIPTION
-------------------------------------------------------------------------
Classe permettant d'appliquer un événement onEnterFrame sur n'importe quelle classe.
-------------------------------------------------------------------------
STATICS METHODS
-------------------------------------------------------------------------
initialize ()
getList()
Renvoi la liste (type BasicArray) des objets qui écoutent MovieClip
getTarget()
Renvoi la cible du clip qui sert de support pour créer l'événement onEnterFrame global
Par défaut _root est renvoyé
setTarget( o )
Défini la cible du clip servant de support à l'événement onEnterFrame.
L'utilisation de cet méthode invoque automatiquement la méthode clear()
Paramètre : un objet
clear ()
Détruit tous les événements ainsi que la liste des écouteurs.
addEventFrameBeacon ( o )
Ajoute un objet à la liste des écouteurs de la classe MovieClip
Paramètre : un objet
Renvoi : true si l'ajout d'un objet réussi, sinon false.
removeEventFrameBeacon ( o ) : Boolean
supprime un objet à la liste des écouteurs de la classe MovieClip
Si la list est vide alors la boucle infinie est détruite.
Paramètre : un objet
Renvoi : true si la suppression réussie, sinon false.
-------------------------------------------------------------------------
THANKS
-------------------------------------------------------------------------
<a href="http://www.lalex.com/blog/" rel="nofollow">LAlex</a>
<a href="http://www.tweenpix.net/" rel="nofollow">Francis Bourre</a>
------------------------------------------------------------------------- */
import net.event.GDispatcher ;
import net.eka.core.BasicArray ;
class net.eka.transitions.FrameBeacon {
private static var _list:BasicArray ;
private static var _target:MovieClip ;
private static var _eMC:MovieClip ;
static function initialize () : Void {
if (!_eMC) {
GDispatcher.initialize (_global.MovieClip) ;
_eMC = getTarget().createEmptyMovieClip ("_eframe", -9999);
_eMC.onEnterFrame = function () {
updateAfterEvent () ;
_global.MovieClip.dispatchEvent ({type:"onEnterFrame", target:this}) ;
}
}
}
static function getList():BasicArray { return _list }
static function getTarget() :MovieClip { return _target || _root }
static function setTarget(mc:MovieClip) :Void {
clear () ;
_target = mc ;
}
static function clear () : Void {
if (_list != undefined) _list = undefined ;
_eMC.swapDepths (getTarget().getNextHighestDepth()) ;
_eMC.removeMovieClip () ;
_eMC = undefined ;
}
static function addEventFrameBeacon ( o ) : Boolean {
var bool:Boolean = _list.exists(o) ;
if (bool) return false ;
else {
if (_list == undefined) _list = new BasicArray ;
initialize () ;
var bool:Boolean = _list.push (o) ;
MovieClip.addEventListener ("onEnterFrame", o) ;
return true ;
}
}
static function removeEventFrameBeacon ( o ) : Boolean {
var bool:Boolean = _list.remove(o) ;
if (bool) {
MovieClip.removeEventListener ("onEnterFrame", o) ;
var l:Number = _list.length ;
if (l<1 || l == undefined) clear () ;
}
return bool ;
}
}
utilisation dans flash :
import net.eka.transitions.FrameBeacon ;
_global.Classe1 = function () {
this.cpt = 0 ;
FrameBeacon.addEventFrameBeacon ( this ) ;
}
Classe1.prototype.onEnterFrame = function () {
if (++ this.cpt> 25) {
trace ("stop Class1") ;
FrameBeacon.removeEventFrameBeacon( this) ;
} else {
trace ("Class1 : " + this.cpt) ;
}
}
_global.Classe2 = function () {
this.cpt = 0 ;
FrameBeacon.addEventFrameBeacon ( this ) ;
}
Classe2.prototype.onEnterFrame = function () {
if (++ this.cpt> 25) {
trace ("stop Class2") ;
FrameBeacon.removeEventFrameBeacon( this) ;
} else {
trace ("Class2 : " + this.cpt) ;
}
}
var instance1 = new Classe1 () ;
var instance2 = new Classe2 () ;
L'intérêt donc est qu'ici à la fin quand plus aucun objet n'écoute MovieClip pour intercepter l'événement onEnterFrame .. le clip qui sert de support à l'événement global est détruit avec sa boucle, ce qui permet de libérer à mon avis pas mal de ressource sur les vieilles machines.
Voilà
Oups .. j'ai fait n'importe quoi avec les balises bbcode AS !! désolé
Fil des commentaires de ce billet