[AS3] – Déclenchement dynamique de fonctions

 Depuis Flash CS3 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 :

Définition d'une classe de document

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.
?View Code ACTIONSCRIPT3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*
*
* @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
		//un constructeur est toujours public en AS 3.0
		public function Document()
		{
			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.

?View Code ACTIONSCRIPT3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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 :

scénario image clé

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 addFrameScript

L’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 :

?View Code ACTIONSCRIPT3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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 transition

Voici 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 :

?View Code ACTIONSCRIPT3
1
2
3
4
5
//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

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.

?View Code ACTIONSCRIPT3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/*
*
* @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
	{
		//un constructeur est toujours public en AS 3.0
		//une classe document doit toujours être public en AS 3.0
		public function Document()
		{
			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

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 conclusion

Cette 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.
Bookmark and Share

Une réponse Souscrire aux commentaires


  1. fenetre pvc

    peut on tester le z.frame avec le this.currentframe ???

    ça n’a pas l’air de marcher

    24 juil 2010 @ 0:58

Répondre