|
Depuis Flash 9 en ActionScript 3.0, une nouvelle propriété de MovieClip fait son apparition : currentLabels. Cette propriété est en fait un tableau d'objets contenant l'ensemble des étiquettes d'image (FrameLabel) disponibles sur un scénario (ou Timeline) ainsi que leur numéro. Une fonction globale cachée est également disponible : addFrameScript. Celle-ci permet d'ajouter du code sur une image clé du scénario dynamiquement.
Nous allons dans ce tutorial utiliser ces nouvelles possibilités pour déclencher de façon dynamique des méthodes (fonctions) de la classe document. Un graphiste pourra alors simplement déclencher un effet ou une méthode créée par un développeur dans la classe document, en nommant une image clé de son scénario portant le nom d'une méthode de la classe du document. Ce tutoriel s'adresse avant tout aux développeurs, qui souhaiteraient faciliter ou apporter un confort d'utilisation aux graphistes.
Niveau requis : Notions de programmation AS 3.0 / connaissance Flash et classe du document Auteur : Eric Ambrosi
Thèmes abordés : classe du document, manipulation du scénario par code
Notions abordées : classe du document, syntaxe crochet, { try / catch / finally } Logiciels : Flash CS3 Fichiers à télécharger : Un éditeur AS 3.0 tel que FlashDevelop
Qu'est-ce que la classe du document ?
Dans Flash CS3, nous avons désormais la possibilité de créer une classe du document correspondant au scénario principal de notre fla. Pour expliquer simplement les choses, la classe du document permet de gérer le code de notre site ou de notre application Flash dans un fichier ActionScript 3 séparé. Auparavant sous Flash 8, nous n'avions pas de solutions simples pour réaliser cela. Nous devions étendre MovieClip et avoir un clip conteneur principal. Pour créer un nouveau fichier .fla pointant vers une classe du document, ouvrez Flash CS3, créez un nouveau fichier .fla de type AS 3.0, puis dans le champ "classe du document" spécifiez un nom de classe. Pour ma part, je vais mettre "Document". Ce nom pointera vers la classe Document situé dans le fichier Document.as dans le même répertoire que notre .fla. Voici ce que vous devriez avoir :  Thibault et bien d'autres contributeurs en ont souvent parlé sur les forums, ou dans des tutoriaux vidéo et je ne m'étalerai donc pas sur le sujet, mais pour résumer : tout ce que nous écrivions jusqu'à maintenant (sous Flash 8) au sein du .fla à la première image clé vide, dans un calque nommé action, nous l'écrirons désormais sous Flash CS3 dans la classe du document. Passons maintenant à notre fameuse classe Document et voyons comment elle s'écrit. Quelques règles de la classe du document : - Toute classe est définie par le mot clef class. Cependant comme c'est une classe du document que nous écrivons, celle-ci est obligatoirement publique. Elle sera donc définie par l'attribut public.
- Le nom de la classe doit avoir le même nom (et la même casse) que le fichier .as, dans notre cas Document.
/** * ... * @author Eric Ambrosi
* @version 1.0 * */
//si vous voulez mettre cette classe dans un répertoire //il faut simplement préciser le nom du répertoire après package
package { //nous sommes obligés d'importer la classe MovieClip pour y faire référence import flash.display.MovieClip; //une classe document doit toujours être publique en AS 3.0 public class Document extends MovieClip { //définition d'une fonction constructeur //attention le constructeur doit avoir le même nom que la classe public function Document () //un constructeur est toujours public en AS 3.0 { trace ( this ); }
} }
Une fois la classe Document sauvegardée, lancez le compilateur de Flash CS3 depuis FlashDevelop via la touche F6. Il faut pour cela que Flash soit ouvert bien sûr. Vous devriez avoir un trace dans la fenêtre de sortie correspondant à ceci : [object Document] Notre trace s'effectue bien c'est la preuve que la classe document est bien chargée par Flash à la compilation. La propriété de MovieClip currentLabels
Désormais chaque MovieClip possède une propriété currentLabels renvoyant un tableau d'objets FrameLabel. Chaque objet FrameLabel possède une propriété frame correspondant au numéro de l'image clé nommée ainsi qu'une propriété name correspondant au nom de l'image clé. c'est cette propriété current Label de notre scénario que nous allons récupérer. package { import flash.display.Sprite; import flash.display.MovieClip;
public class Document extends MovieClip {
public function Document () { trace (this); //on trace la longueur du tableau d'image nommée trace (this.currentLabels.length);
//on utilise la nouvelle boucle for each afin d'accéder directement aux propriétés de chaque objet for each (var z:* in this.currentLabels) { trace ("nom de l'image :: "+z.name +" - numero de l'image :: "+z.frame ); } } } } Recompilez via F6, si vous n'avez mis aucune image clé nommée dans votre scénario principal la longueur du tableau sera de zéro et la boucle ne tracera rien, c'est logique... Création d'un scénario avec des étiquettes d'image
La prochaine étape consiste donc à créer un scénario avec des étiquettes d'image dont voici un exemple :
Recompilons notre .fla. Voici ce que vous devriez avoir en sortie : [object Document] 4 nom de l'image :: test - numero de l'image :: 1 nom de l'image :: bouncing - numero de l'image :: 15 nom de l'image :: aleapos - numero de l'image :: 30 nom de l'image :: fading - numero de l'image :: 45 Création et appel d'une méthode via la fonction non-documentée addFrameScriptL'AS 3.0 nous réserve encore une petite surprise : addFrameScript ( indexImage, nomDeFonction ). addFrameScript est une fonction globale non-documentée nous permettant d'ajouter du code à n'importe quelle image clé. Par exemple, nous allons ajouter l'appel d'une fonction nommée sayHello à chaque image clé comprise dans le tableau currentLabel. Pour l'instant cela n'a que peu d'intérêt car la fonction déclenchée est toujours la même, mais par la suite nous apellerons des fonctions correspondant aux noms de nos images clés. Voici notre constructeur de la classe mis à jour ainsi que la méthode sayhello :
public function Document () { trace (this); trace (this.currentLabels.length); for each (var z:* in this.currentLabels) { trace ("nom de l'image :: "+z.name +" - numero de l'image :: "+z.frame ); addFrameScript ( int(z.frame)-1, sayHello); //le premier paramêtre attend un index de tableau. //Autrement dit l'index de l'image 10 correspond à 9 pour addFrameScript //et l'index de l'image 1 du scénario correspond à 0 par exemple //Nous sommes donc obligés de soustraire 1 à ce que nous renvoie la valeur z.frame //le second paramètre est l'appel de la méthode sayHello qui sera ajouté à notre script à cette frame
} }
//fonction appelée à chaque image comportant une étiquette public function sayHello( ):void { trace ('salut'); }
A ce stade, votre fenêtre de sortie doit afficher "salut" lorsque la tête de lecteur passera sur les images 1-15-30-45. Création de fonctions de transitionVoici un certain nombre de fonctions de transition qui nous serviront d'exemples. A chaque fois que la tête de lecture passera sur une image nommée, on pourra déclencher ces fonctions si le nom de l'image correspond à un de nos noms de méthode dans la classe Document. Tout d'abord, créons nos méthodes.
Pour cette phase, vous devrez importer les classes de Tween développées par Robert Penner pour Flash CS3. import fl.motion.easing.Bounce; import fl.motion.easing.Linear; Afin de mieux appréhender les classes Tween de Flash, référez-vous à la documentation et à l'aide de flash, ces classes sont simples et vraiment pratiques. Voici les méthodes à rajouter dans la classe Document : //pour déclencher cette fonction, il faudra une image clé du même nom
public function bouncing( ):void {
//on parcourt la liste d'affichage de la scène for ( var i:Number = 0 ; i<this.numChildren; i++) { if ( this.getChildAt(i) is MovieClip ) { trace (this.getChildAt(i)); var monClip:MovieClip = MovieClip( this.getChildAt(i) ); var monTweenY:Tween = new Tween( monClip, "y", Bounce.easeOut, monClip.y, Math.random()*this.stage.stageHeight, 3 , true); } } }
//pour déclencher cette fonction, il faudra une image clé du même nom public function fading( ):void {
//on parcourt la liste d'affichage de la scene for ( var i:Number = 0 ; i<this.numChildren; i++) { //si un des enfants est de type MovieClip alors on crée un Tween afin de l'animer if ( this.getChildAt(i) is MovieClip ) { var monClip:MovieClip = MovieClip( this.getChildAt(i) ); var monTweenY:Tween = new Tween( monClip, "alpha", Linear.easeOut, monClip.alpha, Math.random(), 3 , true); } } }
Appel dynamique de méthodes au passage sur une image de scénario nommée Allez on s'accroche c'est la dernière ligne droite :) Il s'agit maintenant d'analyser le nom de chaque étiquette d'image. Si ce nom correspond à une méthode de la classe, alors nous glisserons l'appel de la méthode correspondante sur cette image via addFrameScript. Si par contre, le nom de l'image lue ne correspond à aucune méthode de notre classe Document, alors nous tracerons un message d'information en jetant une erreur. /** * ... * @author Eric Ambrosi * @version 1.0 * */
package {
import flash.display.MovieClip; import flash.display.SimpleButton; import flash.events.MouseEvent; import fl.transitions.Tween; import fl.motion.easing.Elastic; import fl.motion.easing.Bounce; import fl.motion.easing.Linear; public class Document extends MovieClip { public function Document () //un constructeur est toujours public en AS 3.0 //une classe document doit toujours être public en AS 3.0 { this.stage.frameRate = 30 ; for each (var z:* in this.currentLabels) { trace ("nom de l'image :: "+z.name +" - numero de l'image :: "+z.frame ); //permet de savoir si le code compris dans le try renvoi une erreur //si oui, on traite cette erreur par nous-mêmes au lieu de l'avoir à l'exécution //this[z.name] permet d'évaluer la fonction, la propriété ou l'objet présent
//dans this. Dans notre cas il s'agit de l'évaluation d'une méthode de this try { addFrameScript ( (int(z.frame)-1), this[z.name] ); } catch (pError:Error)//si l'évaluation du nom ne correspond à aucune méthode de this //alors on jette l'erreur sous forme d'alerte dans la fenêtre de sortie { trace('aucune fonction ne porte ce nom :: '+z.name); } finally { trace ("Rappel :: l'image numéro :: "+z.frame+" a pour nom "+z.name); } } //grace à la fonction non-documentée addFrameScript //nous pouvons déclencher une fonction spécifique lorsque //la tête de lecture atteint cette image //addFrameScript ( 9, hello ); //9 est un index de tableau d'images //et hello est le nom de l'étiquette ET de la méthode
}
//fonction appelée sur l'image 10, qui porte le nom d'étiquette bouncing public function bouncing( ):void { for ( var i:Number = 0 ; i<this.numChildren; i++) { if ( this.getChildAt(i) is MovieClip ) { trace (this.getChildAt(i)); var monClip:MovieClip = MovieClip( this.getChildAt(i) ); var monTweenY:Tween = new Tween( monClip, "y", Bounce.easeOut, monClip.y, Math.random()*this.stage.stageHeight, 3 , true); } } } public function fading( ):void { for ( var i:Number = 0 ; i<this.numChildren; i++) { if ( this.getChildAt(i) is MovieClip ) { trace (this.getChildAt(i)); var monClip:MovieClip = MovieClip( this.getChildAt(i) ); var monTweenY:Tween = new Tween( monClip, "alpha", Linear.easeOut, monClip.alpha, Math.random(), 3 , true); } } } }
}
Ca y est, tout est en place pour que notre petite appli fonctionne. Créez plein de MovieClip à partir de l'IDE dans un calque différent et lancez la bête . A chaque fois que la tête de lecture passera sur une image clé portant le nom d'une méthode de la classe Document, celle-ci sera exécutée car elle est ajoutée au code de l'image via la méthode addFrameScript. En conclusionCette technique est intéressante, cependant nous sommes limités au déclenchement de méthodes sur le scénario de la scène. En discutant de ce tutorial avec plusieurs contributeurs, nous nous sommes vite rendus compte qu'en production, les graphistes voudraient utiliser ce principe au sein de n'importe quel MovieClip imbriqué ou non et présent sur la scène. Je n'aborderai pas ici une solution détaillée :) mais voici comment je procèderai :
- Je suffixerai le nom des occurrences de clips auxquels je souhaiterai donner un comportement équivalent à celui de la scène. Par exemple, je donnerai comme nom d'occurrence monClip_effect.
- Ensuite au sein de ma classe Document, je ferai une boucle récursive sur l'ensemble des objets présent sur la scène pour connaître leur contenu.
- Si je tombe sur un objet de type MovieClip dont le nom d'occurrence finit par _effect alors je fais un addFrameScript sur les images clés de ce clip.
|