Forums Développement Multimédia

Les formations Mediabox
Les formations Mediabox
Compatible ActionScript 3. Cliquer pour en savoir plus sur les compatibilités.Par Nataly, le 31 décembre 2011

Variables, fonctions, syntaxe
Objets, méthodes, propriétés…
Clics et événements souris sur les boutons et les clips
Champs texte et objet String
Structures de contrôle alternatives : if
Manipuler un movieClip
• Structures de contrôle alternatives : switch
• Structures de contrôle répétitives : for - while
Liste d'affichage, imbrication et profondeur des objets
Liste d'affichage, gestion dynamique des objets (ici)
Les tableaux

Ajouter et supprimer des clips dynamiquement

Parfait ! On sait maintenant manipuler les enfants d'un clip (et de n'importe quel objet de type DisplayConteneur \o/) reste à pouvoir les supprimer ou en ajouter et on va commencer à pouvoir jouer, vraiment;)

Ajouter une instance de symbole à un clip en cours d'exécution du code - dynamiquement donc, selon la terminologie en vigueur - c'est l'équivalent codé de glisser un symbole, “à la main”, depuis la bibliothèque jusqu'au clip ouvert dans le panneau scène.

J'ai dit “glisser un symbole” pour aller vite, mais on est d'accord que les symboles de bibliothèque ne sont que des moules - en quelque sorte - à partir desquels on fabrique autant de clips semblables qu'il nous chante.
Dans le panneau Propriétés, ces clips sont appelés de façon générique occurrence, c'est absolument synonyme de instance.

Ajouter un enfant : addChild

Avant d'ajouter un enfant à un clip, encore faut-il que cet enfant existe… Ben oui, pardon d'énoncer des évidences [pas taper].

Pour ajouter une instance de symbole on va donc commencer par la créer puis, quand ça nous dira, on l'ajoutera.
J'insiste dès tout de suite sur ce non-détail, parce qu'il est important d'avoir en tête qu'un objet existant n'est pas forcément affiché 1). Inversement un objet sorti de la liste d'affichage n'est pas pour autant supprimé… Eh oui :-? On y reviendra…

Exporter pour ActionScript

Pour créer, dynamiquement, une instance de symbole il faut avoir préparé le terrain via le panneau propriété du symbole en question, en cochant la case 'Exporter pour ActionScript'

Voilà, mieux que Jourdain, on vient de fabriquer une classe qui hérite de MovieClip. Rappelez-vous l'arbre d'héritage des objets d'affichage.
Quand on coche la fameuse case, Flash tout seul comme un grand et sans rien nous en dire de plus, fabrique en arrière boutique une classe portant le nom saisi dans le champ Classe qui hérite de la classe MovieClip (qui elle même appartient à la grande famille des objets d'affichage de flash : flash.displayObject).

Créer l'instance : new

Créer une instance de n'importe quelle classe ça se fait toujours pareil (c'est ce qui est reposant avec le code, quand on a compris un principe on le décline pour tout ;)) :

• 1) Déclarer et typer la variable qui va représenter l'objet :

var nomDeLinstance:NomDeLaClasse;

• 2) Valoriser la variable d'un nouvel objet.
C'est le mot clef new qui permet de générer un nouvel objet, suivit du nom de la classe dont l'objet est issu :

nomDeLinstance = new NomDeLaClasse();

Souvent on écrit tout sur la même ligne, c'est ce qu'on va faire avec notre cercle :

var leCercle:Mv_Cercle= new Mv_Cercle();

A ce stade, si on teste le fichier, apparemment rien ne se passe. Ne vous y laissez pas prendre : l'instance a bien été créée, seulement elle n'est pas encore affichée.
Le clip représenté par la variable leCercle existe pour flash, il “vit” dans les limbes mais on ne le voit pas parce qu'il n'a pas encore été ajouté à la liste d'affichage.

Pour les St Thomas

Et si le dire, le répéter, l'affirmer ne suffit pas à vous convaincre (ce que je comprends bien ;)), alors tentez l'expérience suivante : fabriquez un autre symbole qui joue un son. Ne vous compliquez pas : une forme répétée sur quelques images (histoire d'y voir quelque chose le cas échéant) et un son très court joué sur une image quelconque, ça par exemple ('pô pu m'empêcher de jouer avec l'outil déco).


Si vous en posez une instance sur la scène (et que vous testez) ça fait du bruit au rythme de la boucle.

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

Très bien, supprimons cette instance, c'était juste pour être sûrs - et créons une instance en code, comme de normal 2) :

var c:Mv_Feu= new Mv_Feu();

Quand on teste, on ne voit pas la boule de feu mais… on l'entend ! Preuve est faite ;)

Ajouter l'instance : addChild, addChildAt

Pour ajouter une instance à la liste d'affichage d'un conteneur (DisplayObjectContener), on utilise sa méthode addChild :

unDisplayObjectContener.addChild(unObjetDaffichage);

Appliqué au symbole Mv_Cercle, ça donnera donc pour en ajouter une instance sur le scénario principal : (code complet)

var leCercle:Mv_Cercle= new Mv_Cercle();
leCercle.x=100;// tant qu'à faire, autant le disposer où on veut tout de suite
leCercle.y= 50;
this.addChild(leCercle);
Ici, je valorise les propriétés x et y avant d'ajouter la nouvelle instance, on aurait pu le faire après sans que ça change quoi que ce soit, mais profitez en pour vous convaincre du fait que, affiché ou non, un objet d'affichage expose toutes ses propriétés3).

Vous l'avez noté, la méthode addChild ajoute un enfant au plus haut niveau disponible du conteneur ce qui revient à dire au premier plan. Vous pouvez choisir d'ajouter un enfant dans un conteneur au niveau de profondeur de votre choix, il faut alors avoir recours à la méthode addChildAt, en lui passant un objet d'affichage et une profondeur :

unDisplayObjectContener.addChild(unObjetDaffichage, niveauProfondeur);

Par exemple le code ci-dessous ajoute une instance du symbole Mv_Arbre en arrière plan dans un clip nommé foret :

var unArbre:Mv_Arbre= new Mv_Arbre()
unArbre.x=… // coordonnée x
unArbre.y=… // coordonnée y
foret.addChildAt(unArbre, 0);

Pour vous dégourdir les doigts

Dans la série qui ne sert à rien, facile :

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

Indices :
N'allez pas chercher des choses qu'on n'aurait pas vues encore4), il suffit ici d'écouter, sur la scène, les événements souris. On a vu ensemble les célèbres CLICK et autres ROLL_OVER, mais n'hésitez pas à vous reporter à la doc (ou au panneau action de l'environnement auteur) pour voir si il n'y en aurait pas d'autres tout aussi intéressants5).

Au nombre des propriétés bien utiles des DisplayObjects (donc du scénario principal, donc de 'this') il y a mouseX et mouseY qui donnent les coordonnées du pointeur sur l'objet considéré.

Dans la même série (presque) aussi facile :

Si vous savez ajouter un cercle à l'endroit où se trouve la souris, vous savez ajouter un cercle qui change de couleur… Sans se compliquer, avec ce qu'on sait…
L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

Indices :
Un clip peut comporter plusieurs images (c'est même l'intérêt ;)) et on sait envoyer la tête de lecture où on veut.
Une variable compteur (int) pourrait très bien stocker un numéro d'image courante…

Sources exemple 1 : les cercles tout bêtes (CS3)
Vous y trouverez aussi, en commentaires, la correction d'un exo à venir (celui-ci)
Sources exemple 2 : les cercles arc en ciel (CS3)

Créer un clip vide

Non, ce n'est pas absurde de créer un clip vide, c'est même souvent bien utile pour gérer l'ajout et la suppression dynamique d'instances. En effet, il est bien plus simple de supprimer un conteneur et tous ses enfants que supprimer, une par une, une armée d'instances.
Vous voulez distribuer des cartes sur un plateau (des pions, des personnages, des éléments de décors…) et les supprimer à chaque nouvelle partie ? Plutôt qu'identifier une par une les instances concernées et leur appliquer la méthode qui va bien (on y arrive, juste après) il est franchement plus simple d'avoir pris le temps de fabriquer un conteneur dédié et de le supprimer avec tous ses enfants au moment opportun.
Créer un conteneur dédié, c'est fabriquer une instance de clip vide et l'ajouter (où bon nous semblera).

Un clip vide, c'est un clip “tout court”, donc une instance de l'objet (classe) MovieClip, et vous savez déjà vous y prendre : déclarer la variable, la typer, la valoriser d'un nouvel objet à l'aide du mot clé new, puis l'ajouter :

var plateau:MovieClip= new MovieClip(); // une instance de MovieClip (forcément vide ;))
addChild(plateau); // équivalent à this.addChild(plateau)

Supprimer un enfant : removeChild

Pas utile de ménager plus longtemps un suspens insoutenable : pour supprimer (retirer) une instance de l'affichage on utilise la méthode removeChild appliquée à son conteneur6) :

leConteneur.removeChild(unEnfant);
Attention :
removeChild ne supprime pas une instance, au sens où l'objet n'est pas détruit, il se contente de l'ôter de l'affichage.

Si vous voulez vous en convaincre, ressortez la boule-de-feu-qui-fait-du-bruit et vérifiez que même une fois un removeChild appliqué à son contenant, on l'entend toujours exploser (même si on ne la voit plus)

Oui, mais alors… Comment supprimer vraiment une instance ?
On ne peut pas.
Voilà, c'est comme ça. Il faut laisser flash s'en charger, quand ça lui chantera O.O
C'est le ramasse-miettes7), un processus interne sur lequel on n'a pas la main qui s'en charge quand les ressources viennent à manquer.

La seule chose qu'on puisse faire, c'est sortir les poubelles ;) comprendre donner toutes les chances à l'objet en question d'être supprimé, et pour ça il faut qu'il ne soit plus attaché à rien et que plus rien n'y soit attaché. Je dis attaché, ça n'a pas de sens informatique, le parler juste voudrait que je conjugue les verbes référencer et souscrire.
Allez je le fais (parler juste ;)) :

Un objet est éligible au ramasse miettes quand plus aucune variable ne le référence et quand plus aucun écouteur n'y est souscrit.

Une variable c'est une laisse

Les variables c'est la première chose qu'on a vue, il y a bien longtemps déjà, et - forcément - je n'ai pas tout dit à leur sujet. C'est le principe de la mayonnaise : ne pas verser toute l'huile d'un coup, sans quoi ça s'effondre en une pitoyable soupe. Pareil pour les connaissances, il faut y aller molo sans quoi, la soupe c'est dans la tête qu'on la fait ;)

Je vous ai donc raconté qu'une variable représente quelque chose et qu'elle peut être utilisée en lieu et place de ce quelque chose - ce qui est toujours vrai… ouf ! ;)

Une autre analogie que j'emploie souvent c'est celle de la laisse : une variable c'est une ficelle accrochée à une donnée (objet, valeur), je tire la ficelle, je chope la donnée ou l'objet.
Bien sûr je peux y accrocher successivement différentes choses - pourvu que ce soit toujours du même type - et je peux aussi ne rien avoir du tout au bout de la laisse.
Quand on écrit :

var unClip:MovieClip;

On a une “laisse à clips”, avec rien au bout. D'ailleurs ça nous le dit si on “trace” :

trace(unClip);
null

Pour revenir à ce qui nous intéresse : quand vous avez retiré de l'affichage une instance (removeChild), pour qu'elle soit éligible au ramasse-miettes encore faut-il la détacher de sa “laisse”. Ça se fait en affectant à la variable considérée la valeur null.

var unClip:Mv_Truc= new Mv_truc();
conteneur.addChild(unClip);
 
// traitements
// un peu plus loin :
 
conteneur.removeChild(unClip); // plus affiché mais toujours existant
unClip=null; // toujours existant, mais pourra être nettoyé quand le ramasse-miettes passera ds le coin

A vous de jouer

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

C'est quoi le principe ?
J'ai déjà éventé la ruse : vous vous doutez bien que pour effacer on ne va pas parcourir toute la liste d'affichage pour en supprimer les instances colorées. Le plus simple c'est encore de les ajouter, non pas au scénario principal comme on l'avait précédemment fait, mais à un clip dédié (vide à l'origine). Le bouton effacer se contente de supprimer le clip en question et d'en créer un autre, tout prêt à se voir ajouter à son tour des pastilles colorées…

Extraits :

var conteneur:MovieClip= new MovieClip();// un clip vide pour "y dessiner"
this.addChild(conteneur);// on l'ajoute tout de suite
function ajoutePiece():void {
	var c:Mv_Cercle= new Mv_Cercle();
	cpt = cpt%200+1;
	c.gotoAndStop(cpt);
	c.x = mouseX;
	c.y = mouseY;
	conteneur.addChild(c);// la suele différence avec la version précédente c'est qu'on ajoute au conteneur dédié
}

Le bouton Effacer :

• La première ligne supprime de la liste d'affichage le clip référencé par la variable conteneur.
• La deuxième ligne associe un nouveau clip vide à la même variable, l'ancien est donc déréférencé (attention, le clip -et tous ses enfants- existe toujours, on l'a juste “lâché dans les limbes”), et comme il n'est plus “accroché à sa laisse” il sera supprimé par le ramasse-miettes.
• La troisième ligne ajoute ce clip vide au scénario principal. Puisqu'il est référencé par la variable conteneur, la fonction ajoutePiece continue de “fonctionner”.

btEfface.addEventListener(MouseEvent.CLICK,qdEfface);
function qdEfface(me:MouseEvent):void {
	this.removeChild(conteneur);// supprimer de l'affichage le clip référencé par la variable
	conteneur= new MovieClip(); // associer un nouveau clip (un autre, le précédent existe toujours)
	this.addChild(conteneur);
}

Oui, mais non !, s'énerve Ronchon, ça ne marche pas !

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

Hé oui… Il y a un piège :-P
Que se passe-t-il ? Le survol du bouton est bien reconnu (il change de couleur), c'est le clic qui n'est pas pris, d'ailleurs ça se voit aussi : le bouton ne devient jamais noir (couleur de l'état enfoncé). C'est bien normal : au moment où on clique c'est d'abord un événement mouseDown qui est diffusé par le bouton. La scène - sur laquelle on a monté un écouteur - “l'entend”, la fonction enfonce est invoquée et c'est une pastille qui vient se mettre sous le pointeur empêchant le bouton de diffuser un événement click.

Il faut donc invalider la fonction enfonce quand l'événement mouseDown est diffusé par le bouton, dit autrement : savoir sur qui on a cliqué et empêcher enfonce de faire son boulot si c'est le bouton qui a reçu le clic…
La propriété eventPhaseça vous dit quelque chose ? ;)

Dans notre cas on a accroché un écouteur à Stage.
Le croquis illustre l'imbrication des objets d'affichage de l'animation.

Cliquez sur la scène ou sur le bouton pour voir la propagation de l'événement.

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

• Quand on clique n'importe où sur la scène, d'abord l'événement descend (phase 1) et n'est pas écouté (argument capture vaut faux par défaut), il arrive à la scène qui a diffusé l'événement (on est en phase 2), il est entendu (l'écouteur est sur Stage) : eventPhase vaut 2.

• Quand on clique sur le bouton, d'abord l'événement descend (phase 1) et n'est pas écouté (argument capture vaut faux par défaut), il arrive sur le bouton qui l'a diffusé (phase 2) “rebondit” et remonte (phase 3) en arrivant à la scène il est entendu : eventPhase vaut 3.

function enfonce(me:MouseEvent):void {
	trace(me.eventPhase)
	if (me.eventPhase==3) {
	// phase de remontée (bubble) ce n'est donc pas la scène qui diffuse l'événement mais un enfant (le bouton donc)
	return;
	}
	stage.addEventListener(MouseEvent.MOUSE_MOVE,bouge);
	ajoutePiece();
}



Vous trouverez dans la section blog la version vidéo de cette démo



Attention aux ressources

Si maintenant je vous propose ça :

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

voire ça :

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.


Woho ! Trop facile :)
C'est exactement la même chose que le cercle un peu plus haut, s'exclame un enthousiaste, si ce n'est qu'au lieu de contenir un bête cercle sur une image, le clip cette fois porte une étoile interpolée. La belle affaire !

Et zou c'est parti, on duplique/modifie le fichier et …

Voilà que pour certains, ça ne fait pas tout à fait ce qu'on attendait :

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.
En soi c'est rigolo, mais c'est pas ce qu'on attendait…

Il faut, bien sûr penser à mettre un stop() après la dernière image de l'interpolation afin que la lecture du clip ne boucle pas indéfiniment.

Mais ça ne suffit pas, loin de là. Tous ces clips, qu'on ne voit plus et qui s'accumulent, c'est pas propre du tout, ça va finir par tenir de la place, pour rien. Le mieux c'est de les supprimer, puisqu'on n'en veut plus.
Quand je dis les supprimer, j'entends utiliser un removeChild, et bien entendu que vous n'allez pas écrire, après la dernière image de l'interpolation : MovieClip(root).conteneur.removeChild(this); ce serait bien trop “rigide” : ça implique qu'on les ajoute obligatoirement à un clip nommé conteneur…
Somme toute, le clip conteneur, c'est surtout - et systématiquement par la force même des choses - le parent du clip considéré… On écrira donc :

parent.removeChild(this);


Non, non. On ne remplace pas le stop() par la ligne en question. Il faut les deux, mon capitaine.
Rappelez vous la boule de feu qu'on entendait exploser même si elle n'était pas affichée… “pas encore affiché” ou “plus affiché”, c'est pareil ;)
Un objet, qu'il soit dans la liste d'affichage ou non, mène sa vie dès lors qu'il a été créé, et du coup consomme des ressources aussi longtemps que le ramasse miettes n'est pas passé. C'est pourquoi il convient de ne pas laisser “tourner” inutilement des processus, pas plus la lecture du scenario que d'éventuels appels récurrents à coup d'enterFrame par exemple, dont vous avez peut-être déjà entendu parler.

Quand vous supprimez un objet d'affichage via removeChild, arrêtez systématiquement la lecture (stop) et supprimez les écouteurs qui y sont associés (removeEventListener).



Un objet classe depuis une chaîne de caractères

Une autre chose qui peut être bien utile, c'est créer une instance de classe depuis le nom de la classe considérée, une chaîne donc.

On utilisera la fonction getDefinitionByName :

var classCercle:Class = getDefinitionByName("Mv_Cercle") as Class;
var cercle= new classCercle();
addChild(cercle);

Pour aller vite illustrons de l'exemple basique d'un damier. On veut distribuer des clips en lignes/colonnes pour faire un damier. Dit du point de vue qui nous intéresse, il faut ajouter une fois une instance d'un symbole Mv_Case0, la fois suivante une instance de Mv_Case1, et recommencer…


L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

S'il s'agissait toujours du même symbole, disons Mv_Case0, vous sauriez faire :

var nbCol:int=5;
var nbLig:int=3;
var nbTot:int=nbLig*nbCol;
 
for (var i:int=0; i<nbTot; i++) {
	var laCase:Mv_Case0=new Mv_Case0();
	laCase.y=int(i/nbCol)*laCase.height;
	laCase.x=i%nbCol*laCase.width;
	addChild(laCase);
}

Pour ceux qui n'ont pas encore apprivoisé le modulo, un détour par ce petit billet sur le blog 'Annexe' s'impose ;)

Bien sûr, avec cette consigne minimaliste vous pourriez être tentés d'utiliser un if et de valoriser dans chacune de ses branches la variable laCase, genre :

	if (i%2==0) {
		 laCase=new Mv_Case0()  ;
	} else {
		 laCase=new Mv_Case1()  ;
	}

… mais ce n'est pas le but :D, je vous laisse faire utiliser notre nouvel outil : getDefinitionByName ;)

var nbCol:int=5;
var nbLig:int=3;
var nbTot:int=nbLig*nbCol;
 
for (var i:int=0; i<nbTot; i++) {
 
	// avec le modulo on a les numéros pairs ->0 les impairs ->1
	var classRef:Class=getDefinitionByName("Mv_Case"+i%2) as Class;
 
	// pour rappel : avec toujours le symbole Mv_Case0 on aurait écrit :
	// var laCase:Mv_Case0=new Mv_Case0();
	var laCase= new classRef();
 
	laCase.y=int(i/nbCol)*laCase.height;
	laCase.x=i%nbCol*laCase.width;
	addChild(laCase);
}





Et puis du coup… vous pouvez décliner l'exercice du tout début8). Celui où le toujours même cercle était ajouté en suivant le mouvement de la souris. Disons que cette fois on veut ajouter au hasard l'instance d'un symbole ou d'un autre… C'est une alternative bien pratique à la solution qui consiste à installer les visuels sur des images différentes et de s'y rendre à coup de gotoAndStop (on l'utilise pour faire neiger dans un autre tuto)

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.



Dupliquer : retrouver le nom de classe d'une instance

Quelle est la classe dont est issue une instance ? C'est une question dont la réponse peut nous être utile quand on souhaite dupliquer une instance.
Imaginez que vous souhaitiez dupliquer une instance en cliquant dessus par exemple (en vrai, ici c'est un glissé-lâché9) ).

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.
En fin de compte il s'agit ni plus ni moins que de créer une nouvelle instance depuis la même classe que celle du clip considéré, il suffit donc de la connaître, cette classe.
La classe dont est issu un objet, on l'obtient avec la fonction getQualifiedClassName à qui on passe le clip considéré. Elle renvoie une chaine et comme maintenant on est outillés de la fonction getDefinitionByName pour récupérer la classe elle même10).

Vous avez tout ce qu'il faut pour vous essayer :)
Indice :
Soyez économes de votre énergie (et des ressources), n'allez pas ajouter un écouteur par instance…

• Remarquez que sur la démo j'ai appliqué quelques propriétés de base aux instances, la coccinelle est rétrécie, une bestiole est inclinée, l'autre encore est un peu transparente… et les duplicatas sont affectés des mêmes modifications.

Si on ne fait rien de particulier (en code) le duplicata ne reflète pas l'état du clip modèle, il a ses dimensions d'origine par exemple, et c'est bien normal, les dimensions et autre inclinaison, en langage AS ce sont des propriétés : scaleX, scaleY, rotation, alpha….
Quand je parle de dupliquer, c'est pour aller vite, mais ce qu'on fait c'est seulement créer une nouvelle instance, on ne recopie pas la première, on lit tout bêtement son nom de classe pour l'utiliser… Pensez donc à appliquer à la nouvelle instance toutes les propriétés “du modèle” que vous souhaitez reproduire.

stage.addEventListener(MouseEvent.MOUSE_DOWN,enfonce,true);// on écoute la phase de capture sur la scène, donc ses enfants
stage.addEventListener(MouseEvent.MOUSE_UP,lache);
var clip_c:MovieClip;// le clip courant (le duplicata)
 
function enfonce(me:MouseEvent):void {
	var leClip:MovieClip=MovieClip(me.target);// le modèle
	var nomClasse:String=getQualifiedClassName(leClip);// le nom de la classe en chaine
	var classRef:Class=getDefinitionByName(nomClasse) as Class;// l'objet Classe
	clip_c= new classRef();
	clip_c.x=mouseX; // sous la souris
	clip_c.y=mouseY;
	clip_c.scaleX=leClip.scaleX; // dimensions
	clip_c.scaleY=leClip.scaleY;
	clip_c.rotation=leClip.rotation;// inclinaison
	clip_c.alpha=leClip.alpha;// transparence
 
	addChild(clip_c);
	stage.addEventListener(MouseEvent.MOUSE_MOVE,bouge);
 
}
function lache(me:MouseEvent):void {
	stage.removeEventListener(MouseEvent.MOUSE_MOVE,bouge);
}
function bouge(me:MouseEvent):void {
// suit la souris
	clip_c.x=mouseX;
	clip_c.y=mouseY;
}

addChild, d'autres cordes à son arc

Déplacer d'un conteneur à un autre

Quand on a recours à la méthode addChild (ou addChildAt) pour la première fois avec une instance nouvellement créée (new) cette instance est ajoutée à la liste d'affichage (du contenant considéré). Dans les faits, on voit la nouvelle instance “s'afficher”.
Ça c'est clair. Mais qu'en est-il si on utilise addChild sur un contenant en lui passant un clip déjà affiché (déjà contenu dans une liste d'affichage) ? Hé bien elle fait sont boulot - la méthode : elle affiche le clip là où on le lui demande. De fait, elle le déplace d'un contenant à un autre, en une pov' ligne, sans avoir à supprimer ou mémoriser quoi que ce soit11).
Et ce, bien sûr, que l'instance en question ait été ajoutée dynamiquement ou non.
Essayez :
(les pastilles rouges passent d'un contenant à l'autre sur clic)

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

Vous constatez, sans vous en étonner, que les propriétés x et y sont conservées… Normal : on s'est contenté d'ajouter l'objet à une autre liste d'affichage, encore heureux que flash ne se soit pas mêlé de modifier les propriétés au passage !
Pour enfoncer le clou, la pastille du bas est l'objet d'une rotation12) qu'elle conserve de contenant en contenant13).

Par ailleurs, bien sûr que si le contenant de destination a subit des modifications, les clips qu'on y déplace subissent les mêmes modifications (ici scaleY pour le contenant du bas)

contOrigine.addEventListener(MouseEvent.CLICK,qdClicOrigine,true);
function qdClicOrigine(me:MouseEvent):void {
	contenant2.addChild(MovieClip(me.target));
}
 
// et c'est là qu'on voit bien l'intérêt du troisième paramètre ;)
contenant2.addEventListener(MouseEvent.CLICK,qdClicContenant2,true);
function qdClicContenant2(me:MouseEvent):void {
	contDeforme.addChild(MovieClip(me.target));
}
 
contDeforme.addEventListener(MouseEvent.CLICK,qdCliccontDeforme,true);
function qdCliccontDeforme(me:MouseEvent):void {
	contOrigine.addChild(MovieClip(me.target));
}
Si cette histoire de phase de capture vous reste obscure et que vous pensez encore que c'est se compliquer pour rien, essayez donc de virer ce troisième paramètre et cliquez sur le fond (jaune) du contenant ;)

Déplacer au premier plan

Du coup, si on utilise addChild “depuis un conteneur sur lui même” (en y ajoutant une instance déjà contenue par lui), eh bien on se contente de remonter l'instance en question au premier plan. C'est une bonne alternative à la méthode setChildIndex, comparez :

// facile à lire et écrire
contenant.addChild(contenant.leClip);
// moins facile… ;)
contenant.setChildIndex(contenant.leClip,contenant.numChildren-1);

A retenir

• On manipule les clips depuis leur parent.

• Ne pas oublier de cocher la case “exporter pour ActionScript” dans les propriétés d'un symbole de bibliothèque si on veut l'instancier dynamiquement.

addChild et addChildAt déplacent les objets dès lors qu'ils sont déjà affichés.

• Utiliser removeChild ne supprime pas l'objet, il le retire seulement de l'affichage. Quand vous supprimez un objet d'affichage via removeChild, arrêtez systématiquement la lecture (stop) et supprimez les écouteurs qui y sont associés (removeEventListener).

• Pour rendre un objet éligible au ramasse-miettes on valorise à null la variable qui le référence

Conclusion

Et voilà ! C'est fini \o/
Vous savez tout (ou presque ;)) en ce qui concerne la manipulation des objets d'affichage. En toute théorie vous avez d'ores et déjà tout ce qu'il vous faut pour développer des animations graphiques dynamiques et interactives.

Néanmoins les méthodes getChild… (…At, …ByName) sont lourdes, peu pratiques et guère performantes.
Dès que vous vous serez familiarisés avec ces techniques de base il vous faudra apprendre à utiliser des tableaux (Array) pour y stocker les objets d'affichage et les manipuler simplement.
Je sais ! C'est un mot (tableau) qui peut faire peur. Je ne me l'explique pas bien, mais cet objet de première utilité jouit d'une sale réputation auprès des débutants. Ne vous laissez pas influencer, si vous êtes arrivés jusqu'ici sans dommage, le chapitre suivant ne sera que pure formalité et ensuite vous pourrez faire tout un tas de petits exercices (que je prépare derechef… d'ailleurs hop ! c'est le blog Annexe qui va les héberger et voici le premier : un memori)

1) on peut le stocker avec des copains dans un tableau par exemple et ne l'utiliser - afficher, ajouter - que plus tard
2) sans oublier de cocher la case exporter pour Action script ;)
3) comprendre on y a “accès”
4) genre Timer ou EnterFrame
5) genre MouseDown, MouseMove, MouseUp…
6) et on parle bien du conteneur direct, donc du parent
7) garbage collector
8) vous y trouverez aussi le code
9) et comme on est réputés ne pas connaitre les méthodes startDrag/stopDarg j'ai fait avec ce qu'on sait faire
10) l'objet, pas le nom sus forme de chaine de caractères ;)
11) Ceux qui viennent d'AS2 apprécieront
12) propriété rotation, ici appliquée à l'aide de l'outil de transformation puisque les instances sont disposées “à la main”
13) ça aurait été la même chose pour currentFrame, alpha et autre filtre…