Vous êtes sur la page 1sur 628

Sauf mention contraire, le contenu de cet ouvrage est publi sous la licence :

Creative Commons BY-NC-SA 2.0


La copie de cet ouvrage est autorise sous rserve du respect des conditions de la licence.
Texte complet de la licence disponible sur : http : //creativecommons.org/licenses/by-nc-sa/2.0/fr/
Mentions lgales
Conception couverture : amalgam impression
Illustrations chapitres : Fan Jiyong et Alexandra Persil
OpenClassrooms 2014 - ISBN : 979-10-90085-64-0

Avant-propos
i vous lisez ces lignes, cest que vous avez trs certainement envie dapprendre
programmer en Actionscript 3. Il sagit du langage de programmation de prdilection pour concevoir des applications Adobe Flash, applications notamment
trs rpandues sur Internet, sous forme de jeux interactifs, de lecteurs de vidos, de
bannires publicitaires. . .

Contrairement aux ides prconues, lActionscript ne se cantonne pas uniquement


la ralisation de vulgaires animations. Il est possible de concevoir des applications
en ligne visuellement trs avances ou de vrais logiciels de bureau laide de Flash.
Larrive de Adobe Air et Flex a galement normment contribu au dploiement de la
technologie Flash vers de nouvelles plateformes, telles que les terminaux mobiles iOS,
Android ou BlackBerry. Initialement, Flash a t conu pour raliser des animations
vectorielles, au travers du logiciel Flash Professional dit par la socit Adobe. Depuis
la version 3, lActionscript est devenu un langage de programmation part entire,
et il est maintenant possible de concevoir des applications Flash sans avoir recours
ce logiciel. Cet ouvrage sintresse justement lapprentissage de ce langage, en utilisant essentiellement des outils gratuits et accessibles tous. Certains dentre vous se
demandent peut-tre si lActionscript est un bon choix pour commencer la programmation ? Grce sa documentation fournie et ses concepts haut niveau, ce langage
de programmation est tout fait accessible aux dbutants. De plus, les possibilits
quoffre ce langage sont vastes, et le rendu des applications intresseront coup sr les
dveloppeurs plus expriments. Nhsitez donc pas vous lancer ds maintenant la
dcouverte de ce merveilleux langage quest lActionscript 3 !

Quallez-vous apprendre en lisant ce livre ?


Le plan de ce livre a t pens en partant du principe que le lecteur est un parfait
novice en programmation : ce cours se veut progressif et accessible tous. Voici les
diffrentes parties qui vous attendent dans cet ouvrage.
1. Les bases de lActionscript : cette premire partie est une introduction la
programmation et au langage Actionscript 3. Nous verrons ce quest rellement
lActionscript 3 et quels sont les outils indispensables pour suivre ce cours. Une
fois ces derniers en place, nous commencerons tudier les fondamentaux de la
i

CHAPITRE 0. AVANT-PROPOS
programmation : les variables, les conditions, les boucles, les fonctions...
2. La programmation oriente objet : au cours de cette partie, nous aborderons
un concept incontournable en Actionscript 3, la programmation oriente objet.
Il sagit dune manire de concevoir et de structurer le code au sein dun projet.
En organisant les programmes sous forme dobjets, le dveloppement de logiciels
devient plus efficace et intuitif. Nous aborderons les notions de classes, dhritage, de polymorphisme, dinterfaces... Un chapitre sur des notions avances la
programmation oriente objet en fin de partie vous permettra dapprofondir vos
connaissances.
3. Laffichage : tout au long de cette partie, nous dcouvrirons comment raliser
du contenu visuel, qui a fait toute la rputation des applications Flash. Nous
verrons notamment comment utiliser du texte et des images, mais surtout, nous
apprendrons dessiner des graphismes vectoriels directement partir du langage
de programmation. Un TP vous attend en fin de partie, et vous permettra de
vous exercer.
4. Interaction et animation : animer le contenu et le rendre interactif nest pas
chose aise. Nanmoins avec de prcieux conseils et quelques astuces, vous parviendrez crer les applications dynamiques et attrayantes. Pour vous le prouver,
nous raliserons travers un TP un vritable jeu de billard amricain. Vous prendrez alors conscience que vous avez dj atteint un excellent niveau !
5. Annexes : avant de vous laissez explorer de nouveaux horizons par vous-mmes,
nous reviendrons dans cette partie sur quelques rgles et astuces de bonnes pratiques adopter.

Comment lire ce livre ?


Suivez lordre des chapitres
Lisez ce livre comme on lit un roman. Il a t conu pour cela.
Contrairement beaucoup de livres techniques o il est courant de lire en diagonale et
de sauter certains chapitres, il est ici trs fortement recommand de suivre lordre du
cours, moins que vous ne soyez dj un peu expriments.

Pratiquez en mme temps


Pratiquez rgulirement lActionscript 3. Nattendez pas davoir fini la lecture de ce
livre pour allumer votre ordinateur et faire vos propres essais ; nhsitez pas modifier les codes donns en exemples, afin de bien cerner le comportement de chaque
instruction. Plus vous vous exercerez, et plus lapprentissage sera rapide et efficace.
ii

REMERCIEMENTS

Utilisez les codes web !


Afin de tirer parti dOpenClassrooms, dont ce livre est issu, celui-ci vous propose ce
quon appelle des codes web . Ce sont des codes six chiffres saisir sur une page
dOpenClassrooms pour tre automatiquement redirig vers un site web sans avoir
en recopier ladresse.
Pour utiliser les codes web, rendez-vous sur la page suivante :
http://www.openclassrooms.com/codeweb
Un formulaire vous invite rentrer votre code web. Faites un premier essai avec le code
ci-dessous :


Tester le code web
B
Code web : 123456


Ces codes web ont deux intrts :
ils vous redirigent vers les sites web prsents tout au long du cours, vous permettant
ainsi dobtenir les logiciels dans leur toute dernire version ;
ils vous permettent dafficher les codes sources inclus dans ce livre, ce qui vous vitera
davoir recopier certains programmes un peu longs.
Ce systme de redirection nous permet de tenir jour le livre que vous avez entre les
mains sans que vous ayez besoin dacheter systmatiquement chaque nouvelle dition.
Si un site web change dadresse, nous modifierons la redirection mais le code web
utiliser restera le mme. Si un site web disparat, nous vous redirigerons vers une page
dOpenClassrooms expliquant ce qui sest pass et vous proposant une alternative.
En clair, cest un moyen de nous assurer de la prennit de cet ouvrage sans que vous
ayez faire quoi que ce soit !

Remerciements
Nous tenons remercier toutes les personnes qui nous ont aides et soutenues dans la
ralisation de ce livre.

Guillaume Chau
Je souhaite remercier :
Ma famille et mes proches pour leur soutien et leurs encouragements inestimables,
Guillaume Lapayre pour mavoir soutenu dans le projet, aid rdiger le cours et
motiv aller de lavant,
Jonathan Baudoin pour son suivi et sa relecture minutieuse, ainsi que son engagement
auprs de nous dans le projet,
Mathieu Nebra, Pierre Dubuc et toute lquipe de Simple IT pour avoir cr la
plate-forme OpenClassrooms nous ayant permis dcrire cet ouvrage,
Mais surtout, tous les lecteurs pour leurs questions et leurs encouragements !
iii

CHAPITRE 0. AVANT-PROPOS

Guillaume Lapayre
Je souhaite remercier :
Mes parents, ma famille et mes proches pour leur soutien et leur encouragement,
quel que soit le projet dans lequel je mengage,
Guillaume Chau pour mavoir fait confiance et mavoir permis de travailler ses
cts et contribuer la rdaction de cet ouvrage,
Jonathan Baudoin pour avoir cru en ce projet, pour le temps pass la relecture ce
cours, et pour avoir support nos nombreux coups de flemme,
Mathieu Nebra et Pierre Dubuc, et toute lquipe de Simple IT, sans lesquels cet
ouvrage naurait jamais vu le jour,
Enfin, tous les lecteurs pour leurs encouragements et lintrt quils portent ce
cours.

iv

Table des matires

Avant-propos

Quallez-vous apprendre en lisant ce livre ? . . . . . . . . . . . . . . . . . . . .

Comment lire ce livre ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

ii

Suivez lordre des chapitres . . . . . . . . . . . . . . . . . . . . . . . . .

ii

Pratiquez en mme temps . . . . . . . . . . . . . . . . . . . . . . . . . .

ii

Utilisez les codes web ! . . . . . . . . . . . . . . . . . . . . . . . . . . . .

iii

Remerciements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

iii

Guillaume Chau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

iii

Guillaume Lapayre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

iv

Les bases de lActionscript

1 Vous avez dit Actionscript ?

Adobe Flash

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Prsentation de Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Un peu dhistoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Les drivs de Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Quelques exemples dutilisation . . . . . . . . . . . . . . . . . . . . . . . . . .

Le dynamisme apport au web par lActionscript . . . . . . . . . . . . .

Cration de sites web orients vers le visuel . . . . . . . . . . . . . . . .

Introduction dAdobe Air . . . . . . . . . . . . . . . . . . . . . . . . . .

LActionscript 3

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
v

TABLE DES MATIRES


Orient objet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

De haut niveau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10

vnementiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10

2 Votre premier programme avec Flex SDK


Prambule . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12

Le compilateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12

Le lecteur Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13

Installation des outils . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14

Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14

Flex SDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14

Version de dbogage du lecteur Flash . . . . . . . . . . . . . . . . . . . .

19

Crer les sources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

21

Compiler le programme de test . . . . . . . . . . . . . . . . . . . . . . .

21

Dis bonjour au monsieur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

23

Structure de notre programme . . . . . . . . . . . . . . . . . . . . . . .

23

Commentez votre code ! . . . . . . . . . . . . . . . . . . . . . . . . . . .

30

Afficher un message dans la console . . . . . . . . . . . . . . . . . . . . .

30

Place au test ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

32

FlashDevelop la rescousse ! . . . . . . . . . . . . . . . . . . . . . . . . . . .

36

Tlchargement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

36

Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

36

Un peu de paramtrage . . . . . . . . . . . . . . . . . . . . . . . . . . .

40

Crons un projet Actionscript . . . . . . . . . . . . . . . . . . . . . . . .

43

Bien utiliser Flashdevelop . . . . . . . . . . . . . . . . . . . . . . . . . .

43

Compiler et tester notre projet . . . . . . . . . . . . . . . . . . . . . . .

47

3 Les variables

vi

11

51

Dclarer et utiliser des variables . . . . . . . . . . . . . . . . . . . . . . . . . .

52

Dclaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

52

Utiliser les variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

53

Les nombres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

54

Les diffrents types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

54

Oprations sur les nombres . . . . . . . . . . . . . . . . . . . . . . . . .

56

La classe Math . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

58

TABLE DES MATIRES


Les chanes de caractres

. . . . . . . . . . . . . . . . . . . . . . . . . . . . .

60

chappement des caractres spciaux . . . . . . . . . . . . . . . . . . . .

60

Utiliser les variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

61

Concatnation de chanes . . . . . . . . . . . . . . . . . . . . . . . . . .

62

Quelques variables et fonctions utiles . . . . . . . . . . . . . . . . . . . .

62

4 Les conditions

67

criture dune condition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

68

Quest-ce quune condition ? . . . . . . . . . . . . . . . . . . . . . . . . .

68

Les oprateurs relationnels . . . . . . . . . . . . . . . . . . . . . . . . . .

68

Les oprateurs logiques

. . . . . . . . . . . . . . . . . . . . . . . . . . .

70

La priorit des oprateurs . . . . . . . . . . . . . . . . . . . . . . . . . .

71

Linstruction if. . .else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

72

La structure de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

72

Le type boolen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

74

La structure avec else if . . . . . . . . . . . . . . . . . . . . . . . . . .

75

Linstruction switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

76

Lutilisation conventionnelle . . . . . . . . . . . . . . . . . . . . . . . . .

76

Une utilisation spcifique lActionscript . . . . . . . . . . . . . . . . .

77

5 Les boucles

79

La boucle while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

80

Le principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

80

criture en Actionscript . . . . . . . . . . . . . . . . . . . . . . . . . . .

80

La boucle do. . .while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

82

La boucle for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

84

Prsentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

84

6 Les fonctions

87

Concept de fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Le principe de fonctionnement

88

. . . . . . . . . . . . . . . . . . . . . . .

88

Prsentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

89

Cration et appel de fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . .

90

Instructions de fonction . . . . . . . . . . . . . . . . . . . . . . . . . . .

90

Expressions de fonction . . . . . . . . . . . . . . . . . . . . . . . . . . .

92
vii

TABLE DES MATIRES


Quelques exemples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

92

Message de bienvenue . . . . . . . . . . . . . . . . . . . . . . . . . . . .

93

Calcul de PGCD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

93

Calcul dun maximum . . . . . . . . . . . . . . . . . . . . . . . . . . . .

93

7 Les tableaux

97

Le type Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

98

Cration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

98

Les lments du tableau . . . . . . . . . . . . . . . . . . . . . . . . . . .

98

Proprits du type Array . . . . . . . . . . . . . . . . . . . . . . . . . .

99

Le type Vector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100


Dclaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
Gestion des lments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
Les tableaux multidimensionnels . . . . . . . . . . . . . . . . . . . . . . . . . 102
Le concept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
Un peu de pratique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
Parcourir un tableau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
La boucle for classique . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
La boucle for...in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
La boucle for each . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

II

La Programmation Oriente Objet

8 La POO dans tous ses tats

109
111

Les notions-cls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112


Il tait une fois. . . un objet . . . . . . . . . . . . . . . . . . . . . . . . . 112
LObjet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
La Classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
Un autre exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
Lencapsulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
Lhritage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
Manipuler des objets : les chanes de caractres . . . . . . . . . . . . . . . . . 118
Lhorrible secret du type String . . . . . . . . . . . . . . . . . . . . . . 118
Crer un objet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
viii

TABLE DES MATIRES


Accder aux proprits dun objet . . . . . . . . . . . . . . . . . . . . . 121
Des pointeurs sous le capot . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
Plantons le dcor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
Explications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
9 Les classes (1re partie)
Crer une classe

125

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126

La Classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
Construire la classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
Des paramtres facultatifs pour nos mthodes . . . . . . . . . . . . . . . . . . 130
La surcharge de mthodes . . . . . . . . . . . . . . . . . . . . . . . . . . 130
Les paramtres facultatifs . . . . . . . . . . . . . . . . . . . . . . . . . . 131
Encapsulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
Les diffrents droits daccs . . . . . . . . . . . . . . . . . . . . . . . . . 132
Les accesseurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
Exercice : Crons notre premire classe . . . . . . . . . . . . . . . . . . . . . . 139
Prsentation de la classe . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
criture du code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
La classe complte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
10 Les classes (2nde partie)

145

Les lments statiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146


Les variables statiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
Les mthodes statiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
Une nouvelle sorte de variable : la constante ! . . . . . . . . . . . . . . . . 148
Prsentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
Intrt des constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
Un objet dans un objet (dans un objet. . .) . . . . . . . . . . . . . . . . . . . . 150
Le problme du ptrole

. . . . . . . . . . . . . . . . . . . . . . . . . . . 150

Une nouvelle classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153


Exercice : Jeu de rle

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157

Prsentation de lexercice . . . . . . . . . . . . . . . . . . . . . . . . . . 157


Solution initiale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
Une nouvelle classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
La bonne solution

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
ix

TABLE DES MATIRES


11 Lhritage

175

La notion dhritage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176


Construction dun hritage . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
La porte protected . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
Construction des sous-classes . . . . . . . . . . . . . . . . . . . . . . . . 178
La substitution dune sous-classe une superclasse . . . . . . . . . . . . 182
Le polymorphisme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
Les attributs de classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
Les diffrents droits daccs . . . . . . . . . . . . . . . . . . . . . . . . . 185
Exemple dutilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
12 Notions avances de la POO

189

Les classes dynamiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190


Dfinition de la classe de base . . . . . . . . . . . . . . . . . . . . . . . . 190
Dfinition de proprits hors de la classe . . . . . . . . . . . . . . . . . . 191
Les interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
Problme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
Utilisation des interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
Plus loin avec les interfaces . . . . . . . . . . . . . . . . . . . . . . . . . 198
Les classes abstraites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
Le concept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
Application lActionScript 3 . . . . . . . . . . . . . . . . . . . . . . . . 201
Les types inconnus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
Dterminer si un objet est une occurrence dune certaine classe . . . . . 203
Des paramtres de type inconnu

. . . . . . . . . . . . . . . . . . . . . . 204

Accder dynamiquement aux proprits . . . . . . . . . . . . . . . . . . . . . 206


Les objets anonymes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
Crer un objet anonyme . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
Les fonctions anonymes . . . . . . . . . . . . . . . . . . . . . . . . . . . 214

III

Laffichage

215

13 Les objets daffichage

217

Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
x

TABLE DES MATIRES


Les couleurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
Laffichage sur un cran . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
Larbre des objets daffichage . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
Larbre daffichage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
Les classes daffichage . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
Manipuler les conteneurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
Buvez du Sprite ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229
Ajouter des enfants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229
Afficher un objet sur la scne principale . . . . . . . . . . . . . . . . . . 230
Lindex daffichage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
Ajouter un enfant un index prcis

. . . . . . . . . . . . . . . . . . . . 234

Oprations sur les enfants . . . . . . . . . . . . . . . . . . . . . . . . . . 235


Retirer des enfants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
Proprits utiles des objets daffichage . . . . . . . . . . . . . . . . . . . . . . 238
Position . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
Un mot sur lorigine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
Taille . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242
Rotation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
Transparence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244
Supprimer un objet daffichage de la mmoire . . . . . . . . . . . . . . . . . . 245
14 Afficher du texte

249

Une histoire de TextField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250


La classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250
Utilisation de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
Slection du texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256
Centrer le champ de texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
Un mot sur la scne principale . . . . . . . . . . . . . . . . . . . . . . . 258
Adapter la taille du champ de texte au texte . . . . . . . . . . . . . . . 262
Modifier la position du champ de texte . . . . . . . . . . . . . . . . . . . 264
La mise en forme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268
Formatons notre champ de texte . . . . . . . . . . . . . . . . . . . . . . 268
Gestion du multi-ligne . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274
En HTML dans le texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278
xi

TABLE DES MATIRES


Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278
Balises principales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280
Balises de mise en forme . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
Les polices de caractres embarques . . . . . . . . . . . . . . . . . . . . . . . 287
Embarquer des polices . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
Rotation sur soi-mme . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
15 Dessiner avec lActionscript

303

Lobjet Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304


Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304
Des contours et des remplissages . . . . . . . . . . . . . . . . . . . . . . 306
Dessinez, cest gagn ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308
Les lignes et les courbes . . . . . . . . . . . . . . . . . . . . . . . . . . . 308
Les formes prdfinies . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310
Techniques avances . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311
Exercice : Dessine-moi un mouton . . . . . . . . . . . . . . . . . . . . . . . . 314
Conception du dessin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314
Code final . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
16 Utilisation des matrices

327

Les matrices ou la classe Matrix . . . . . . . . . . . . . . . . . . . . . . . . . 328


Introduction aux matrices . . . . . . . . . . . . . . . . . . . . . . . . . . 328
Lobjet Matrix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
Cration de dgrads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
Prsentation des dgrads . . . . . . . . . . . . . . . . . . . . . . . . . . 331
Ajouter une matrice de description . . . . . . . . . . . . . . . . . . . . . 332
Exemple : cration dun bouton . . . . . . . . . . . . . . . . . . . . . . . 334
Les transformations matricielles . . . . . . . . . . . . . . . . . . . . . . . . . . 335
Un objet transformer . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335
Cration dune matrice de transformation . . . . . . . . . . . . . . . . . 336
Pour finir avec les matrices . . . . . . . . . . . . . . . . . . . . . . . . . 338
17 Manipuler des images

341

Embarquer des images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342


Prparation de limage . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
xii

TABLE DES MATIRES


Librairie dimages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
Afficher des images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344
La classe Bitmap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344
Redimensionnement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
Oprations sur les images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
La classe BitmapData . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
Crer notre premire image . . . . . . . . . . . . . . . . . . . . . . . . . 351
Dessiner sur des images . . . . . . . . . . . . . . . . . . . . . . . . . . . 351
18 Filtres et modes de fusion

361

Les filtres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362


Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362
Cration dun exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362
Ajout de filtres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363
Application des filtres . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
Glossaire des filtres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
Les filtres de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
Correction de couleurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368
Convolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372
Mappage de dplacement . . . . . . . . . . . . . . . . . . . . . . . . . . 375
Les modes de fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376
Dfinition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376
Mise en place . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378
Glossaire de modes de fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . 378
Le mode de fusion par dfaut . . . . . . . . . . . . . . . . . . . . . . . . 378
Les fusions de calques . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378
Les fusions de transparence . . . . . . . . . . . . . . . . . . . . . . . . . 384
19 Les masques

387

Un masque. . . qui ne masque pas . . . . . . . . . . . . . . . . . . . . . . . . . 388


Le principe des masques . . . . . . . . . . . . . . . . . . . . . . . . . . . 388
Les masques en Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388
Niveaux de transparence multiples . . . . . . . . . . . . . . . . . . . . . . . . 390
Prsentation du concept . . . . . . . . . . . . . . . . . . . . . . . . . . . 390
Place au code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
xiii

TABLE DES MATIRES


Exercice : une lampe torche . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393
Prparation des images . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393
Mise en place du masque . . . . . . . . . . . . . . . . . . . . . . . . . . . 396
Projet final . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398
20 TP : Mauvais temps

403

Le cahier des charges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404


Lobjectif du chapitre . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404
Le travail raliser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405
Les images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406
La correction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
La structure du programme . . . . . . . . . . . . . . . . . . . . . . . . . 407
La classe Flocon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408
La classe Neige . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
La classe principale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412
Le code source complet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414
La classe Flocon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414
La classe Neige . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415
La classe principale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417

IV

Interaction et animation

21 Les vnements

419
421

Quest ce quun vnement ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422


Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422
Un jour au bureau. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422
Les couteurs en POO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424
Linterface IEventDispatcher . . . . . . . . . . . . . . . . . . . . . . . 424
La classe EventDispatcher . . . . . . . . . . . . . . . . . . . . . . . . . 425
Mise en place dun couteur . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426
Introduction aux fonctions de rappel . . . . . . . . . . . . . . . . . . . . 426
Crer une fonction dcouteur . . . . . . . . . . . . . . . . . . . . . . . . 428
Grer les couteurs dun objet . . . . . . . . . . . . . . . . . . . . . . . . 429
Le flux dvnements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
xiv

TABLE DES MATIRES


Prsentation du concept de flux dvnements . . . . . . . . . . . . . . . 430
Bien comprendre le fonctionnement . . . . . . . . . . . . . . . . . . . . . 433
Lobjet Event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 435
Prsentation de la classe Event . . . . . . . . . . . . . . . . . . . . . . . 435
Les proprits lis au flux dvnements . . . . . . . . . . . . . . . . . . 436
22 Interagir avec lutilisateur
La souris

439

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440

Lobjet MouseEvent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440


La technique du glisser-dposer . . . . . . . . . . . . . . . . . . . . . 446
Exercice : Crer et animer un viseur . . . . . . . . . . . . . . . . . . . . 447
Curseurs personnaliss . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449
Le clavier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455
Lobjet KeyboardEvent . . . . . . . . . . . . . . . . . . . . . . . . . . . 455
Exercice : grer laffichage de lanimation . . . . . . . . . . . . . . . . . 457
Champs de saisie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459
Retour sur lobjet TextField . . . . . . . . . . . . . . . . . . . . . . . . 459
vnements et TextField . . . . . . . . . . . . . . . . . . . . . . . . . . 463
Exercice : un mini formulaire . . . . . . . . . . . . . . . . . . . . . . . . 467
23 Animer des objets

473

Lanimation par images-cls . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474


Lvnement Event.ENTER_FRAME . . . . . . . . . . . . . . . . . . . . . . 474
Crer une animation basique . . . . . . . . . . . . . . . . . . . . . . . . 474
Lutilisation de Timer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477
La classe Timer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477
Exercice : une horloge . . . . . . . . . . . . . . . . . . . . . . . . . . . . 478
Les interpolations avec TweenMax . . . . . . . . . . . . . . . . . . . . . . . . 482
La librairie TweenMax . . . . . . . . . . . . . . . . . . . . . . . . . . . . 482
Les bases de lanimation avec TweenMax . . . . . . . . . . . . . . . . . . 484
Utilisation avance de TweenMax . . . . . . . . . . . . . . . . . . . . . . 488
24 Les collisions

495

Prambule . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 496
Dfinition dune collision . . . . . . . . . . . . . . . . . . . . . . . . . . . 496
xv

TABLE DES MATIRES


Dtecter des collisions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 496
La thorie des collisions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498
Collisions rectangulaires . . . . . . . . . . . . . . . . . . . . . . . . . . . 498
Collisions circulaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502
Collisions ponctuelles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 505
Les collisions de pixels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508
Utiliser lopacit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508
Application en code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510
25 TP : Jeu de billard
Objectifs

513

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 514

Les rgles de notre billard . . . . . . . . . . . . . . . . . . . . . . . . . . 514


Le droulement dune partie . . . . . . . . . . . . . . . . . . . . . . . . . 515
Consigne supplmentaire . . . . . . . . . . . . . . . . . . . . . . . . . . . 517
Prparation et conseils . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517
Prparation du projet . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517
Les diffrents lments du jeu . . . . . . . . . . . . . . . . . . . . . . . . 520
Un peu de Maths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 527
Organiser son projet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535
Organisation de lapplication . . . . . . . . . . . . . . . . . . . . . . . . . . . 535
La structure de lapplication . . . . . . . . . . . . . . . . . . . . . . . . . 535
Description des diffrents classes . . . . . . . . . . . . . . . . . . . . . . 537
Cration des classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537
Visuel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537
Bille . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539
Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 547
Trous . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 550
Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 554
Billard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 560
Main . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 573
Conclusion et amliorations possibles . . . . . . . . . . . . . . . . . . . . . . . 577
Sources du Billard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 577
Ides damlioration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 577
26 La gestion des erreurs
xvi

579

TABLE DES MATIRES


Les principes de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 580
Introduction la gestion des erreurs . . . . . . . . . . . . . . . . . . . . 580
Les diffrents types derreurs dexcution . . . . . . . . . . . . . . . . . . 580
Les erreurs synchrones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581
Lintruction throw . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581
Linstruction try...catch . . . . . . . . . . . . . . . . . . . . . . . . . . 583
Les erreurs asynchrones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585
Distribuer un objet ErrorEvent . . . . . . . . . . . . . . . . . . . . . . . 585
Grer des vnements derreurs . . . . . . . . . . . . . . . . . . . . . . . 585
Bien comprendre les deux approches . . . . . . . . . . . . . . . . . . . . . . . 586
Une classe utilisant les deux approches . . . . . . . . . . . . . . . . . . . 586
Intrts des erreurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 589

Annexes

591

27 Bonnes pratiques

593

La mmoire dans Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 594


Flash et la mmoire vive . . . . . . . . . . . . . . . . . . . . . . . . . . . 594
Le ramasse-miettes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 594
Prparer un objet pour la suppression . . . . . . . . . . . . . . . . . . . 594
Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 595
Les commentaires de documentation . . . . . . . . . . . . . . . . . . . . . . . 597
Ecrire un commentaire de documentation . . . . . . . . . . . . . . . . . 597
Gnrer la documentation de vos classes . . . . . . . . . . . . . . . . . . 598

xvii

TABLE DES MATIRES

xviii

Premire partie

Les bases de lActionscript

Chapitre

Vous avez dit Actionscript ?


Difficult :
Pour commencer ce cours en douceur, voici une petite introduction pour vous prsenter la
technologie Flash, ainsi que son langage de programmation principal, lActionscript 3 !
Pour ceux qui ne connatraient pas cette technologie, nous verrons ce quil est possible de
faire en Flash ainsi que les diffrentes utilisations de celui-ci. Nous essaierons galement
de prsenter les technologies Flex et Air qui peuvent servir enrichir Flash. Quelques
exemples de projets Flash vous seront donns afin que vous puissiez vous faire une ide des
possibilits de lActionscript.
Ce chapitre dintroduction ne prsente aucune difficult, mme si vous tes un parfait
dbutant en programmation. Je vous rappelle que ce cours est rdig avec une difficult
progressive aussi, contentez-vous de lire celui-ci votre rythme et tout ira bien !

CHAPITRE 1. VOUS AVEZ DIT ACTIONSCRIPT ?

Adobe Flash
Prsentation de Flash
Flash est une technologie actuellement dveloppe et soutenue par Adobe Systems
(prononcez adobi ).
Elle est principalement utilise pour afficher des animations dynamiques et interactives
dans des pages web travers le navigateur Internet. Elle permet, par exemple, dajouter
une vido ou un jeu sur son site web, animer une galerie dimages, proposer une interface
dynamique pour un service ou un logiciel en ligne.
Un document Flash est un fichier sous le format swf (Shockwave Flash), et vous en
avez srement ouvert plusieurs chaque visite sur le web : en effet, ces animations
Flash, couramment utilises sur Internet, sont un assemblage dimages, de textes, de
dessins et de sons pouvant sanimer et mme interagir avec vous.
Parmi ses concurrents, on peut citer Silverlight, de Microsoft ou encore Java, de Sun/Oracle. LHTML5, coupl avec le CSS3 est une nouvelle alternative standardise ces
animations, ne ncessitant pas de plug-in dans le navigateur. Les spcifications de
lHTML5 ne sont malheureusement pas encore finalises lheure actuelle. Je vous
encourage lire le tutoriel de Mathieu Nebra sur lHTML5 et le CSS3 sur OpenClassrooms, si vous vous sentez lme dun webdesigner !

Un peu dhistoire
Flash nest pas aussi rcent que lon pourrait le croire, car son anctre direct a vu
le jour en 1995 et est sorti un an plus tard : il sagit de FutureSplash Animator
(voir figure 1.1), un concurrent de Macromedia Shockwave cette poque (un autre
format multimdia orient vers le web). FutureSplash a t dvelopp par FutureWave
Software, une compagnie lorigine de SmartSketch, un logiciel de dessin vectoriel dont
il manquait la composante animation contrairement Shockwave.

Figure 1.1 FutureSplash Animator


Son succs amena Macromedia racheter FutureSplash Animator en dcembre 1996,
pour le renommer en Macromedia Flash (voir figure 1.2), contraction de Future et
Splash. En 2005, Adobe Systems acquiert Macromedia ; le dveloppement de Flash se
poursuit et aboutit une volution majeure de la technologie avec la sortie en 2007 de
CS3 (Creative Suite 3 ) : cest la naissance de lActionscript 3 et de Flash 9.
Depuis, Adobe travaille lamlioration du lecteur Flash avec notamment la sortie
en 2008 de la dixime version de Flash apportant quelques nouveauts et un dbut de
support de lacclration matrielle pour obtenir de meilleures performances. En 2011,
4

ADOBE FLASH

Figure 1.2 Macromedia Flash


une onzime version majeure apporte une nouveaut trs attendue : le support intgral de lacclration matrielle par la carte graphique, ouvrant la voie de nouveaux
contenus en 3D complexe. Le fameux moteur de jeux vido dEpic Games, lUnreal
Engine 3, a dailleurs t port sur la plate-forme Flash !
Adobe cherche maintenant faciliter lutilisation de sa technologie sur les autres appareils multimdia, et on peut dsormais dvelopper en Flash sur un tlphone portable
fonctionnant sous Android de Google, iOs dApple ou BlackBerry 10 de RIM, sur des
tablettes tactiles et mme sur des tlvisions !

Les drivs de Flash


La plupart des professionnels se servent du logiciel Flash Professionnal dAdobe,
mais il existe dautres faons dutiliser cette technologie. Voici les deux principales :
la premire utilise un autre langage tandis que la deuxime est en quelque sorte une
extension de lActionscript 3.
Flex
Flex est un logiciel jumeau de Flash Professionnal, il est orient dveloppement et
design dapplications (voir figure 1.3). Il permet principalement de combler les lacunes,
si on peut dire, de Flash en termes de cration dinterfaces utilisateur. Cest pourquoi,
celui-ci propose une grande collection de composants prconus faciles manipuler tels
que des boutons, des champs de texte, etc. Les dveloppeurs peuvent ainsi concevoir
trs rapidement une interface utilisateur pour des programmes qui ne ncessitent pas
toute la puissance de dessin de Flash.

Figure 1.3 Adobe Flex


Flex utilise principalement un autre langage invent par Macromdia : le MXML
(Macromedia Extensible Markup Language), une variante du langage trs connu quest
le XML. Le MXML est utilis pour dcrire la structure visuelle dune application de
la mme faon que pour crire une page web avec lHTML (lui aussi bas sur le
5

CHAPITRE 1. VOUS AVEZ DIT ACTIONSCRIPT ?


XML) ; on place alors des balises reprsentant les composants du programme tout
en les mettant en forme. Ensuite, lActionscript sajoute au XML dans une balise <mx:Script> et permet de manipuler et danimer les balises MXML ainsi que
dinteragir avec lutilisateur par exemple.
Pour obtenir plus dinformations, vous pouvez jeter un coup dil au tutoriel Flex de
Migs sur OpenClassrooms.
Air
Adobe Air est une variante de Flash permettant nimporte quelle animation cre
avec Flash ou Flex de sinstaller et de fonctionner comme une vritable application
(figure 1.4). Grce aux nombreuses nouvelles fonctionnalits et outils qui sont votre
disposition lorsque vous programmez une application Air, vous pouvez grer le systme de fichiers de lordinateur ou les disques amovibles, crer des bases de donnes,
monter un serveur, etc. Ainsi, peut-on programmer un traitement de texte ou encore
un logiciel de messagerie instantane, voire un navigateur Internet avec Flash.

Figure 1.4 Adobe Air


Une autre particularit de cette plate-forme ressemblant Flash est que, en plus du
MXML et de lActionscript 3, on peut utiliser uniquement du simple HTML, CSS
et Javascript pour crer de telles applications. Air utilise alors le moteur Webkit
(utilis par Chrome et Safari entre autres) pour afficher ces lments de pages web dans
les applications. Ceci reprsente un avantage non ngligeable pour les dveloppeurs
web voulant programmer des applications de bureau sans toutefois avoir apprendre
et matriser un autre langage de programmation !
Enfin, cest Air qui permet aux dveloppeurs Flash de crer des applications destination de mobiles comme liPhone, sur les tablettes tactiles ou encore sur les tlviseurs,
et cela depuis 2010 avec la sortie dAir 2.5 (voir figure 1.5).

Quelques exemples dutilisation


Pour bien cerner les possibilits de Flash et diffrencier les multiples variantes de cette
technologie, voici, rien que pour vous, quelques exemples illustrs.

Le dynamisme apport au web par lActionscript


Il est probable que la premire fois que vous ayez entendu parler de Flash soit en jouant
divers jeux sur le web. En effet, il existe de nombreux sites web proposant des jeux
6

QUELQUES EXEMPLES DUTILISATION

Figure 1.5 Prsentation dAdobe AIR 2.5, un driv de Flash.


Flash. Bien entendu, ceux-ci sont raliss en Flash laide du langage Actionscript.
Pour vous donner un exemple concret, je vous ai slectionn un jeu nomm Kingdom
Rush, dont un aperu est donn la figure 1.6.

Figure 1.6 Un jeu ralis en Flash : Kingdom Rush.

Cration de sites web orients vers le visuel


La technologie Flash est aussi grandement utilise dans la conception des sites web
eux-mmes. En gnral, les animations Flash sont plutt rserves aux sites web
statiques ou sites-vitrines. Ceux-ci sont trs apprcis pour leurs interactions et leurs
animations qui dynamisent normment la navigation : il est important, notamment
7

CHAPITRE 1. VOUS AVEZ DIT ACTIONSCRIPT ?


pour les sites commerciaux destination du grand public, dattirer le regard. Toutefois,
il est tout fait possible de crer des sites web dynamiques et interagir avec un serveur
grce au langage PHP par exemple. Pour que vous puissiez mieux vous faire une ide
de la chose, je vous propose daller visiter le site de la nouvelle srie de Canal+ (voir
figure 1.7) :


Carlos
.
B
Code web : 751006

Figure 1.7 Le site de la srie Carlos est ralis en Flash.

Introduction dAdobe Air


Comme nous le verrons dans le prochain chapitre, lutilisation de la technologie Flash
ncessite un lecteur spcifique nomm Flash Player. Celui-ci est trs rpandu lintrieur des navigateurs Internet, et lutilisation de Flash sest ainsi longtemps limite au
web. Heureusement, ceci nest plus le cas avec larrive dAdobe Air. En effet, cette
technologie vient ajouter de nouvelles fonctionnalits Flash et permettre lutilisation
de Flash hors-ligne en tant que programme. Pour vous donner un exemple, lapplication Flash du site de poker Winamax (voir figure 1.8), disponible initialement sur
navigateur Internet, a pu tre convertie en vritable logiciel grce Adobe Air.
Ainsi lutilisation dAdobe Air permet de porter les applications directement sur un
systme dexploitation. Cette technologie est notamment utilise aujourdhui par de
nombreux systmes dexploitation mobiles tels que liOS, Android ou BlackBerry 10.
8

LACTIONSCRIPT 3

Figure 1.8 Le logiciel Winamax utilise la technologie Air.

LActionscript 3
LActionscript est le langage de programmation servant faire fonctionner les animations Flash. Cest le plus utilis parmi les langages de Flash. Il est bas sur lECMAscript, linstar du Javascript utilis sur Internet, directement dans les pages
web. Sans lui, aucune animation ou interaction dans un fichier Flash ne serait possible
et celui-ci serait alors rduit une simple image fixe.
LActionscript est un langage orient objet, de haut niveau et vnementiel.

Orient objet
En effet, sa structure est base sur le concept dobjet, cest--dire que tous les lments
de lanimation (y compris ceux qui ne relvent pas de laffichage, comme par exemple les
nombres) sont des objets, avec des attributs et des mthodes qui leur sont attachs.
Chaque objet est dcrit par une classe : un ensemble dattributs et de mthodes
qui reprsentent son comportement.
Prenons comme exemple une voiture de sport : cest un objet qui a pour classe Voiture,
cest--dire quelle a par exemple un attribut vitesse qui nous permet de connatre sa
vitesse de dplacement, ou encore une mthode tourner gauche, qui la fait tourner.
Tous ces attributs et ces mthodes sont dcrits et expliqus dans la classe Voiture.
Sil nous prenait lenvie de programmer un jeu de course de voitures basique, il faudrait
dabord crire une classe Voiture, puis, sur le fichier principal, crer un nouvel objet
de la classe Voiture pour crer une voiture (et ensuite la dplacer par exemple).
Une partie toute entire sera consacre la programmation oriente objet, ne vous
en faites pas si vous narrivez pas tout bien saisir maintenant.
9

CHAPITRE 1. VOUS AVEZ DIT ACTIONSCRIPT ?

De haut niveau
LActionscript est un langage dit de haut niveau, cest--dire que son fonctionnement est trs loign du fonctionnement de lordinateur au niveau matriel, au contraire
des langages dit de bas niveau, proches de la machine (comme le langage C).
Gnralement, cela signifie quil est plus facile de raliser certaines choses ou quil faut
moins dinstructions, mais cela se traduit souvent par des performances plus faibles.
Le Java, le Python ou le Ruby sont dautres exemples de langages de haut niveau.

vnementiel
Enfin, cest un langage vnementiel, cest--dire que linteractivit de vos programmes
sera base sur des vnements que nous allons couter. Par exemple, pour utiliser
un bouton, nous allons couter (donc attendre) sur lui lvnement cliqu qui sera
dclench lorsque lutilisateur appuiera sur ce bouton. Bien sr, pendant ce temps,
nous pouvons faire autre chose : cest tout lintrt de ce systme.

En rsum
LActionscript est un langage interprt, il a donc besoin dun interprteur
(le lecteur Flash) pour tre excut.
La technologie Flash regroupe les programmes Flash classiques, les applications
Flex que lon peut trouver sur des pages web, ainsi que les applications AIR
destination du bureau ou dautres appareils comme les mobiles.
Le principal langage utilis dans ces programmes est lActionscript 3, mais on peut
aussi utiliser le MXML (pour Flex et AIR), voire lHTML et le Javascript (pour
les applications AIR uniquement).
LActionscript 3 est un langage de haut-niveau : son fonctionnement est loign de
la machine et il est en gnral plus facile dimplmenter des fonctionnalits complexes.
Cest aussi un langage orient objet : son fonctionnement est bas sur des concepts
dobjets et de classes.
Enfin, cest un langage vnementiel : on coute des objets, et si des vnements
surviennent, on peut excuter du code.

10

Chapitre

Votre premier programme avec Flex


SDK
Difficult :
Maintenant que vous en savez un peu plus sur Flash, il est grand temps de passer la
pratique et lessentiel de ce cours : lActionscript 3 ! Vous aurez besoin doutils pour
suivre ce cours et appliquer ce que vous apprendrez (cest trs important), mais ne vous
inquitez pas, tous sont gratuits.
Le compilateur, qui servira transformer votre code en animation, est effectivement gratuit
pour tout le monde et mme open-source ! Il sagit de Flex SDK, qui faisait partie du projet
Adobe Open Source et qui est rcemment pass sous laile de la Fondation Apache. Nous
utiliserons galement un logiciel facultatif pour nous aider coder et compiler nos projets,
disponible hlas uniquement sous Windows.

11

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK


Cette partie est un peu difficile, surtout si vous navez jamais programm :
accrochez-vous, relisez les parties que vous navez pas comprises ! La suite
en sera plus facile apprhender. La partie sur la compilation en ligne de
commande est facultative si vous travaillez sur Windows et que vous tes
allergiques la console. . .

Prambule
Le compilateur
Un compilateur est un programme trs utile dans la plupart des langages de programmation. Vous vous doutez bien que lordinateur ne sait pas interprter directement le
code que nous lui crivons : en effet, les langages de programmation ont t conus
pour tre facilement utilisables par les tres humains comme vous et moi. Or, les ordinateurs ne comprennent que les instructions en binaire de bas niveau (voir chapitre
prcdent). Il faut donc traduire nos programmes grce au compilateur ! (voir figure
2.1)

Figure 2.1 Le principe de la compilation


Certains langages de programmation sont interprts par un logiciel faisant
lintermdiaire entre le code et lordinateur : on peut en gnral se passer de
la compilation. Cest le cas de la plupart des langages utiliss sur Internet,
comme le Javascript ou le PHP. Mais cest aussi le cas de lActionscript !

Mais alors, pourquoi doit-on compiler nos programmes crits en Actionscript ?


En Actionscript 3, la compilation vous donne des informations sur vos erreurs
de syntaxe pour que vous les corrigiez plus facilement, mais elle permet surtout de
rassembler tout votre code et le contenu ncessaire au bon droulement de votre programme (comme les librairies) dans un seul fichier. Ainsi, il est plus facile dintgrer
une animation Flash dans un site web et il devient possible dimporter directement
dans lanimation des images, des sons, des polices de caractres ou dautres mdias
12

PRAMBULE
qui seront chargs en mme temps que votre programme. En outre, le compilateur
compresse votre animation afin quelle prenne moins de temps se charger.
Ainsi, en Flash, le compilateur ne traduit pas votre code en binaire (voir figure 2.2).
vrai dire, ce nest quun demi-compilateur : il ne soccupe seulement de lier plusieurs
fichiers en un seul (opration appele dition de liens), alors que les compilateurs
classiques traduisent galement le code.

Figure 2.2 Le compilateur Flash


Le fichier qui est produit est en gnral au format swf (ShockWave Flash) ; cest lui
qui sera charg par un navigateur Internet par exemple.

Le lecteur Flash
Donc il nous faut un logiciel pour que lordinateur comprenne notre code ?

Oui ! Cest l que le lecteur Flash (ou Flash Player en anglais) entre en scne (voir
figure 2.3). Ce logiciel contient un ensemble doutils permettant dexcuter votre programme : Flash Player est un interprteur, et lActionscript est un langage interprt.

Figure 2.3 Le lecteur Flash


Tout ce processus se droule lintrieur dune machine virtuelle. Concrtement, Flash
Player cache le systme sur lequel votre programme tourne et gre lui-mme la mmoire et les autres changes ncessaires au bon droulement de votre programme.
Ainsi, ce dernier peut fonctionner correctement sur plusieurs systmes dexploitation
(Windows, Mac, Linux, Android, etc.) totalement diffrents. Entre autres, il dispose
13

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK


dun compilateur la vole, ou JIT (Just In Time) qui traduit en temps rel certains
passages de votre code en binaire afin damliorer les performances.

Installation des outils


Ainsi, pour programmer en Actionscript, il nous faut plusieurs outils, dont un
compilateur et un lecteur Flash. Nous allons ds prsent nous occuper de tout
cela !

Java
Java est une technologie similaire Flash, dveloppe initialement par Sun Microsystems (rachet par Oracle), qui regroupe un ensemble doutils permettant de crer des
applications (voir figure 2.4). Or, le compilateur de Flash est crit en Java : il faut
donc que Java soit install sur votre ordinateur. Si vous tes certains que cest dj le
cas, vous pouvez passer ltape suivante. Sinon, tlchargez et installez Java :


Tlchargez Java
.
B
Code web : 741426

Figure 2.4 Le logo Java

Flex SDK
Le Flex SDK (Software Development Kit) est un ensemble doutils de dveloppement
qui permettent, entre autres, de compiler des programmes crits en Actionscript 1, 2
ou 3, et des applications Flex ou Air.
Depuis 2011, Adobe a plac Flex sous licence Apache, par le biais de la Fondation
Apache. Le Flex SDK est ainsi distribu maintenant sous lappellation Apache Flex,
et est donc un projet open source (figure 2.5).
Nous verrons, dans la dernire partie de ce chapitre, comment utiliser un
logiciel nous permettant de dvelopper en Actionscript sans utiliser la console
de lignes de commande : il sagit de Flashdevelop (Windows uniquement).
Si vous ne voulez pas essayer de compiler avec la console et que vous tes
sous Windows, vous pourrez alors vous passer de la console pour compiler
vos applications.
14

INSTALLATION DES OUTILS

Figure 2.5 Le logo Apache Flex

Tout dabord, il vous faut disposer dAdobe Air pour installer le SDK, et suivez
ensuite les instructions dinstallation.


Adobe Air
.
B
Code web : 815403


Ensuite, il faut que vous rcupriez le SDK sur le site dApache :


Apache Flex SDK
B
.
Code web : 944481


Cliquez sur le bouton Download, lancez le tlchargement (voir figure 2.6) et allez
prendre un caf.

Figure 2.6 Page de tlchargement dApache Flex


Une fois le tlchargement termin, installez et lancez lapplication Apache Flex SDK
Installer. Un cran de slection de la version des diffrents composants du SDK saffiche une fois lapplication ouverte (voir figure 2.7).
15

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Figure 2.7 Application dinstallation

Laissez les valeurs telles quelles sont : les dernires versions sont en effet slectionnes
par dfaut.
Sur lcran suivant, choisissez lemplacement dinstallation du SDK, de prfrence un
rpertoire facilement accessible (votre dossier personnel par exemple) et nommez-le
Flex SDK 4.
Ensuite, vous devez accepter les licences dutilisation des diffrents composants du SDK
en cochant les cases de la liste des composants (voir figure 2.8).

Figure 2.8 Liste des composants du SDK


Le tlchargement et linstallation des composants dbute alors. Une fois linstallation
termine, vous pouvez fermer lapplication.
16

INSTALLATION DES OUTILS


Pour les utilisateurs de linux, il faut installer Adobe AIR 2.6.0 pour pouvoir
utiliser lapplication dinstallation de Flex SDK 4. Skype peut galement
entrer en conflit avec Adobe AIR, il faut alors le dsinstaller.
Vous voil arms dun compilateur Flash ! Mais comment sen sert-on ? Avec les lignes
de commande pardi ! Pour les utilisateurs de Windows, il est grand temps de renouer
une relation avec le terminal ! Pour Mac et Linux en revanche, cela ne devrait pas trop
vous poser de problmes. . .
Voici la marche suivre pour lancer un terminal :
Windows : dans le menu dmarrer, allez dans
Tous les
 programmes, Accessoires,

Invite de commandes, ou appuyez sur Windows +R  et entrez cmd puis validez
(voir figure 2.9).
Linux : comment a, vous ne savez pas ouvrir un terminal ? :- Le gnome-terminal
(Gnome) ou la Konsole (KDE) conviendront parfaitement (voir figure 2.10).
Mac : dans le Finder, slectionnez Applications, puis Utilitaires et enfin Terminal
(voir figure 2.11).
Sur Windows, il existe une alternative au terminal classique, bien plus complte et confortable, car elle se rapproche de ceux des systmes dexploitation
Linux ou Mac. Il sagit de Powershell ; pour le lancer, appuyez sur Windows+R, entrez powershell et validez. Dsormais, vous pouvez par exemple
appuyer sur TAB pour complter automatiquement une commande ou un
chemin, comme sur Linux !
Maintenant, il va falloir se placer dans le dossier bin du SDK : utilisez la commande
cd (Change Directory) pour vous dplacer dans larborescence de fichiers.

Figure 2.9 Windows

17

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Figure 2.10 Linux

Figure 2.11 Mac

18

INSTALLATION DES OUTILS

Version de dbogage du lecteur Flash


Un deuxime outil va nous tre indispensable : il sagit dune version lgrement diffrente du lecteur Flash habituel que lon trouve dans les navigateurs Internet par
exemple. En effet, ceFlash Player de dbogage peut sexcuter tout seul comme
une quelconque application et dispose surtout de fonctions de dbogage trs utiles.
Par exemple, si un problme survient pendant que lon teste notre programme, une
fentre nous affichera les dtails de lerreur, la ligne incrimine et les diffrents appels
de fonctions ayant conduit cette erreur.
Vous pouvez ds prsent rcuprer le lecteur sur le site web dAdobe :


Flash Player de dbogage
B
Code web : 927850


Un large choix de versions soffre vous : il faut prendre le lecteur appel Projector
content debugger , correspondant votre systme dexploitation :
si vous tes sur Windows, il faut cliquer sur le lien Download the Windows Flash
Player xx.x Projector content debugger,
si vous tes sur Max, il sagit du lien Download the Macintosh Flash Player xx.x
Projector content debugger
enfin, si vous tes sur Linux, le bon lien est Download the Linux Flash Player xx.x
Projector content debugger.
Sur Windows
Lancez le fichier excutable tlcharg une fois afin que les fichiers .swf soient automatiquement associs au Lecteur Flash (voir figure 2.12)
Sur Linux
Commencez par extraire larchive tlcharge. Pour que son utilisation soit plus facile,
et surtout parce que lon en aura besoin un peu plus loin, vous pouvez dplacer lexcutable flashplayerdebugger vers le dossier /usr/bin et le renommer en flashplayer
grce la commande suivante (noubliez pas de vous placer dans le dossier de larchive
extraite) :
sudo mv f l as h playerdebugger / usr / bin / flashplayer

Une fois le dplacement effectu, relancez votre console et replacez-vous dans le dossier
Flex SDK 4/bin.
Sur Mac
Installez le lecteur Flash en double-cliquant sur linstallateur Install Adobe Flash
Player Debugger 11.dmg (voir figure 2.13)
19

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Figure 2.12 Lecteur Flash de dbogage Windows

Figure 2.13 Installation de Flash Player Debugger

20

INSTALLATION DES OUTILS

Crer les sources


Vu que nous navons pas encore attaqu lcriture de programmes en Actionscript
3, je vous ai concoct un petit code de test, qui va nous permettre de vrifier que votre
installation fonctionne bien.
Pour les utilisateurs de Windows, il est ncessaire de pouvoir enregistrer vos
fichier dans nimporte quelle extension : sinon, il y a de grandes chances
pour que Windows vous trahisse en sauvegardant votre fichier Test.as en
Test.as.txt par exemple, sans que vous ne en rendiez compte ! Pour viter
cela, il faut dsactiver une fonctionnalit de Windows qui masque la plupart
des extensions : dans une fentre de lexplorateur de fichiers, allez dans le
menu Options des dossiers, puis dans longlet Affichage et dcochez
Masquer les extensions des fichiers dont le type est connu.
Commencez par crer un rpertoire Sources dans le dossier bin o lon mettra les
sources de nos futurs programmes. Dans le rpertoire Sources, crez un nouveau fichier nomm Test.as et copiez-y le code en utilisant un diteur de texte quelconque,
tel que le Bloc-notes si vous tes sous Windows. Utilisez le code web ci-dessous pour
afficher le code et le copier/coller.

Code pour test.as
B
Code web : 171910

Compiler le programme de test


Pour compiler Test.as, revenez dans le terminal pour lancer le programme mxmlc
contenu dans le dossier bin.

Windows
.\ mxmlc . exe " Sources / Test . as "

Linux et Max
./ mxmlc Sources / Test . as

Il est possible que vous ayez besoin des droits administrateurs sur Linux pour
pouvoir compiler. Pour contourner le problme, essayez dajouter bash ou
sudo avant la commande ./mxmlc.
21

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK



Ensuite, appuyez sur Entre  pour lancer la compilation (voir figures 2.14, 2.15 et
2.16 pour les diffrents cas).

Figure 2.14 Windows

Figure 2.15 Linux


Aprs quelques instants, et si tout sest bien pass, un fichier Test.swf a t cr dans
le dossier Sources ; il vous suffit de louvrir avec le lecteur de dbogage que nous avons
tlcharg prcdemment !
22

DIS BONJOUR AU MONSIEUR

Figure 2.16 Mac


Sur Windows ou Mac
Double-cliquez sur le fichier Test.swf. Si jamais le lecteur Flash ne souvre pas,
choisissez-le avec la commande Ouvrir avec... ou dans la liste Slectionner un
programme install (voir figures 2.17 et 2.18).
Sur Linux
Entrez dans votre terminal (voir figure 2.19) :
flashplayer Sources / Test . swf

Si votre curseur laisse une trane blanche et brumeuse, cela signifie que la compilation
a russi et que vous tes prts pour passer la suite !

Dis bonjour au monsieur


Nous allons maintenant crire de A Z notre premier programme Flash ! Commencez
par crer un nouveau fichier Actionscript dans le rpertoire Source, et nommez-le
Hello.as.

Structure de notre programme


Un programme crit intgralement en Actionscript, ce qui sera le cas durant ce cours,
prsente toujours la mme structure : le code est obligatoirement mis dans des fonctions, elles-mmes places dans une classe, englobe par un paquet (on utilise alors
23

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Figure 2.17 Windows

Figure 2.18 Mac


24

DIS BONJOUR AU MONSIEUR

Figure 2.19 Linux


le mot anglais package). Pour linstant, il y a de grandes chances que les trois termes
que je viens dutiliser soient obscurs pour vous ; la seule chose importante retenir est
lorganisation de ces trois niveaux qui composent le code source de tout fichier Actionscript. Pas de panique : nous explorerons plus en dtails chacune de ces notions
plus tard dans le cours.
Vous trouverez un petit schma rcapitulatif la figure 2.20.

Figure 2.20 Structure dun programme

Le package
Commenons par le plus simple : le package. Il est compos dun nom facultatif et
dun bloc daccolades. Nous utilisons le mot-cl package comme ceci :
1

package nom {

2
3

25

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK


Un mot-cl (ou rserv) est une expression qui est utilise par le langage et
qui lui est donc rserve. Vous ne pourrez donc pas utiliser ce type de mots
autrement que tels quils ont t dfinis en Actionscript.
Le nom du package dcrit la position de la classe dans larborescence des fichiers de
votre projet. Effectivement, vous ne pouvez choisir vous-mmes le nom du package :
vous devez mettre le chemin relatif du fichier par rapport au fichier principal (celui que
lon compile avec la commande mxmlc vue plus haut), en sparant les dossiers par des
points ( la place des slashes ou antislashes).
Par exemple, si votre fichier principal Hello.as se trouve dans le dossier source et
que vous crez un nouveau dossier ET dans lequel vous rajoutez un dossier telephoner,
en y mettant un fichier Actionscript Maison.as qui est utilis par votre programme
principal, vous devrez crire son package ainsi :
1

package ET . telephoner {

2
3

Larborescence des fichiers est alors Sources/ET/telephoner/Maison.as.


Comment cela, on peut utiliser un autre fichier Actionscript depuis notre
programme principal ?
Bien sr ! Cest mme trs utile : il vaut mieux faire plusieurs fichiers bien tris (un
dossier pour les utilitaires, un dossier pour le chargement de son. . .), que mettre lensemble des donnes dans un seul et unique fichier. Imaginez que votre programme fasse
plusieurs centaines de milliers de lignes de code : il vous sera impossible de vous y
retrouver ! Nous allons voir cette notion appele importation de fichiers dans trs
peu de temps.

Quen est-il de notre fichier Hello.as ?

Trs bonne question : pour le programme principal contenu dans le fichier que vous
allez compiler avec la commande mxmlc, il ny a pas de nom de package ! Et oui, il est
dj dans le dossier principal de votre projet, inutile donc de mettre un chemin.
Dans ce cas, le package scrit ainsi :
1

package {

2
3

Vous pouvez crire ce code dans votre fichier vide si vous ne lavez pas dj fait !
26

DIS BONJOUR AU MONSIEUR


Importer des fichiers Actionscript
Comme nous lavons vu, importer des fichiers peut savrer trs utile, voire vital dans
la plupart des cas. Limportation est une instruction (ou une ligne de code si vous
prfrez) qui permet de rendre tout le code du fichier import utilisable dans notre
code. Il y a deux types de fichiers que vous pouvez importer : les fichiers contenus dans
les packages de Flash (commenant par flash.) et vos propres fichiers. Dans les
deux cas, on utilise le mot-cl import suivi du package du fichier importer, son nom
et un point-virgule :
1

import ET . telephone . Maison ;

La plupart des instructions et lignes de code devraient tre termines par un


point-virgule en fin de ligne. Je dis devraient car il est tolr domettre
le point-virgule, mais cest trs fortement dconseill : il est le symbole qui
indique clairement la fin de votre ligne de code. Il est possible, dans de rares
cas, que vous obteniez des erreurs cause de cela. Votre ordinateur ne sautodtruira pas si vous ne mettez pas les points-virgules, mais ce serait une
trs, trs, trs mauvaise habitude : si jamais vous voulez apprendre et utiliser
un autre langage, vous oublierez constamment les points-virgules et maudirez
le jour o vous avez dcid de ne pas suivre mon conseil. . . :- Vous remarquerez quil ne faut pas mettre de point-virgule quand il sagit de blocs de
code dlimits par des accolades ({ et }), comme pour le package que lon
vient de voir.
Les importations scrivent juste aprs avoir ouvert la premire accolade du package :
1

package {

import ET . telephone . Maison ;

3
4
5

Pour notre programme, il va falloir importer un fichier standard de Flash : Sprite. Il


est ncessaire pour toute application : nous dtaillerons son utilit bien plus tard dans
le cours car il nous manque trop de notions actuellement. Je peux tout de mme vous
dire que cela nous permet dafficher le programme et donc de le lancer : effectivement,
tout programme Flash a besoin dun affichage pour sexcuter.
Je vous donne le code du fichier import que vous devez avoir dans votre Hello.as :
1

package {

import flash . display . Sprite ;

3
4
5

27

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK


Vous laurez srement compris, le package du fichier est flash.display
(gestion de laffichage).

La classe
Ensuite, vient la. . . Comment a vous ne savez pas ? Retournez vite regarder le schma !
Effectivement, dans le package, on trouve une classe. Cette notion est un concept trs
important de la programmation oriente objet que jai mentionne dans lintroduction. Il est trop tt pour dvelopper cette notion, mais rassurez-vous : une partie
entire de ce cours sera consacre lorient objet.
Lessentiel est de retenir que la classe est obligatoire et que sa syntaxe est la suivante :
les mots-cls public class suivis du nom de la classe et dun bloc daccolades, comme
pour le package.
1

public class NomDeMaClasse {

2
3

Attention ! Le nom dune classe ne doit contenir que des lettres, et doit tre
identique au nom du fichier dans lequel elle se trouve (sans lextension). De
plus, il doit imprativement commencer par une majuscule : cela explique
pourquoi tous nos fichiers Actionscript ont une majuscule depuis le dbut
du cours !
tant donn que le nom du fichier est le mme que celui de la classe de ce fichier, nous
parlerons dsormais de classe dans les deux cas.
Il existe une notation appele Camel (chameau) ou CamelCase (notation
chameau), trs utilise dans le monde de linformatique. Je lai utilise pour
crire NomDeMaClasse : chaque mot dbute par une majuscule, comme des
bosses de chameau ! Son utilit est purement esthtique car cette notation
amliore la lisibilit du code lorsque lon ne peut pas utiliser despaces ou
dautres caractres spciaux. Cest le cas ici avec le nom des classes. Je pense
que cest une bonne habitude prendre, alors autant commencer tout de
suite : avouez que si javais crit Nomdemaclasse, ce serait beaucoup moins
lisible !
La classe se dispose juste aprs les importations de fichiers, comme ceci pour notre
fichier Hello.as :
1

package {

2
3

import flash . display . Sprite ;

4
5

28

public class Hello extends Sprite {

DIS BONJOUR AU MONSIEUR


6
7
8

Les plus observateurs dentre vous auront remarqu que jai ajout deux mots derrire
le nom de notre classe. Le mot-cl extends (tendre en anglais) permet dutiliser la
classe Sprite dune manire un peu spciale, comme nous le verrons dans la partie
consacre lorient objet.
Les fonctions
Maintenant que notre classe est prte, il faut crire une ou plusieurs fonctions pour
pouvoir mettre du code dedans ! Une de ces fonctions est obligatoire et elle porte un
nom : il sagit du constructeur de la classe. Devinez quoi ? Cest encore li lorient
objet ! Pour faire simple, ce constructeur est automatiquement excut dans certains
cas, lorsque lon utilise une classe. Ici, le code lintrieur sera parcouru au lancement
de notre programme. Pour crire un constructeur, on utilisera les mots-cls public
function suivis du nom de la classe, de parenthses et dun nouveau bloc daccolades.
Pour notre classe Hello contenue dans notre fichier Hello.as, le constructeur ressemblera ceci :
1

public function Hello () {

2
3

Et voil ! Notre fichier est fin prt pour que nous commencions (enfin) coder !
Voici le code complet de notre fichier Hello.as pour que vous puissiez vrifier :
1
2

// Premier niveau : le paquet


package {

// Les classes import es


import flash . display . Sprite ;

4
5
6

// Deuxi me niveau : la classe du fichier


public class Hello extends Sprite {

7
8
9

// Troisi me niveau : la ou les fonctions

10
11

// Constructeur de la classe
public function Hello () {

12
13
14

// Nous allons coder ici !

15
16

17
18
19
20

29

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Commentez votre code !


Avez-vous remarqu que jai insr du texte en franais dans le code prcdent qui na
a priori rien faire l ? On appelle cela des commentaires. Vous pouvez y crire absolument nimporte quoi et pour cause, ils seront tout simplement ignors lorsque vous
lancerez votre programme. Vous vous demandez alors quoi servent-ils ? La rponse
est plutt simple : commenter un code permet de sy retrouver mme si nous avons
nous-mmes crit le code en question. Imaginez que vous reveniez dessus quelques mois
plus tard : sil ny a aucun commentaire, vous serez aussi perdu que si vous naviez
pas t le programmeur ! Cela peut mme arriver dans un intervalle de quelques jours
seulement. Et ce serait encore pire si vous souhaitiez que votre code soit lu ou utilis
par dautres personnes. . . Mais attention, il ne sagit pas non plus dinonder votre code
de commentaires : vous ne russiriez qu le rendre encore plus illisible et incomprhensible ! Il faut trouver un juste milieu : commentez quand cela est ncessaire pour
dcrire brivement ce que fait un morceau de votre programme afin de vous en rappeler
facilement plus tard.
Il existe deux types de commentaires : les commentaires en ligne et les commentaires multi-lignes.
Les commentaires en ligne
Ce sont des commentaires qui ne comportent quune seule ligne. On les dbute par
deux slashs, comme ceci :
1

// Voici un commentaire en ligne

Tout le texte suivant les deux slashs sera considr comme du commentaire.
Vous pouvez mettre un commentaire en fin de ligne, sans gner personne :
1

import display . Sprite ; // Pour l ' affichage

Les commentaires multi-lignes


Cette fois-ci, il est possible dtaler notre commentaire sur plusieurs lignes. Pour
cela, il faut dbuter notre commentaire par un slash et une astrisque et terminer
explicitement le commentaire par une astrisque et un slash :
1
2
3
4

/* Ceci
est un commentaire
sur quatre
lignes . */

Afficher un message dans la console


Avant toute chose, il est important de souligner que la technologie Flash na jamais
t conue pour tre utilise en lignes de commande : en effet, son objectif est de propo30

DIS BONJOUR AU MONSIEUR


ser des applications et des animations entirement graphiques. Cela implique que lon
ne puisse quafficher du texte la console (avec quelques efforts) et quil est impossible
dentrer des donnes au clavier via la console, comme en langage C par exemple.
Cest une fonction qui nous permettra dafficher des messages dans la console : elle
rpond au doux nom de trace() et est quasiment exclusivement utilise pour le dbogage des programmes Flash.
Cette fonction est accessible partout dans tout code Actioncript, il suffit de lappeler.
Lappeler ? Comme mon chien pour partir en balade ?

Oui, on utilise le terme appeler lorsque lon utilise une fonction : nous nallons pas
crire du code entre les accolades de la fonction trace(), nous allons nous contenter
de lutiliser. En effet, son code est dj prt et fait partie du lecteur Flash lui-mme !
Pour lutiliser, nous allons prendre presque la mme syntaxe que celle du constructeur
Hello (qui est lui aussi une fonction), sans le bloc daccolades et sans oublier le pointvirgule (car il sagit dune instruction) :
1

trace ( " texte afficher " ) ;

Entre les deux parenthses, vous devez spcifier la fonction trace() ce quelle doit
afficher. Ce peut tre du texte (dlimit par des guillemets) ou un nombre. Par exemple,
pour afficher 42 dans la console, nous cririons :
1

trace ( 42 ) ;

vous de jouer ! Faites en sorte sans le tester que votre programme Hello soit capable dafficher le grand classique Hello world ! . Souvenez-vous o il faut mettre les
instructions dans le programme Hello que nous avons crit jusqu prsent !
1
2

// Premier niveau : le paquet


package {

3
4
5

// Les classes import es


import flash . display . Sprite ;

6
7
8

// Deuxi me niveau : la classe du fichier


public class Hello extends Sprite {

9
10

// Troisi me niveau : la ou les fonctions

11
12
13

// Constructeur de la classe
public function Hello () {

14

trace ( " Hello world ! " ) ;

15
16
17

18

31

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK


19

20

Place au test !
Compiler notre programme
Commenons tout dabord par compiler Hello.as. Il y a une petite diffrence par
rapport tout lheure : cette fois-ci, il va falloir activer le mode dbogage lors de la
compilation, pour que lon puisse afficher le message Hello world ! dans la console.
Pour ce faire, ajoutons un paramtre lors de la compilation : -debug=true.
Sur Windows :
.\ mxmlc . exe - debug = true " Sources / Hello . as "

Sur Linux :
./ mxmlc - debug = true " Sources / Hello . as "

Et enfin, sur Mac :


./ mxmlc - debug = true Sources / Hello . as

Encore une fois, il est possible que vous ayez besoin des droits administrateurs sur Linux pour pouvoir compiler. Pour contourner le problme, essayez
dajouter bash ou sudo avant la commande ./mxmlc.
Si tout cest bien pass, votre console devrait afficher quelque chose comme ce que vous
voyez la figure 2.21.
Lancer le dbogueur Flash
Pour pouvoir afficher les messages de la fonction trace(), il nous faut utiliser un autre
outil notre disposition : le dbogueur Flash. En effet, Flash Player, mme en
version de dbogage, ne peut pas afficher des messages en continu dans une console. Il
se contente de les envoyer : le dbogueur va alors se charger de rcuprer les messages
et de nous les prsenter dans la console. Il sagit du programme fdb qui devrait tre
dans le rpertoire Flex SDK 4/bin (voir figure 2.22).
Lancez le programme dans votre console :
Sur Windows :
.\ fdb . exe

Sur linux :
32

DIS BONJOUR AU MONSIEUR

Figure 2.21 Rsultat de la compilation

Figure 2.22 Contenu du rpertoire Flex SDK 4/bin

33

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

./ fdb

Sur Mac :
./ fdb

Un nouvel invit de commande, gr par fdb, devrait apparatre, comme la figure


2.23.

Figure 2.23 Le nouvel invit de commande gr par fdb

Lancer notre programme


Tout dabord il faut lancer une session de dbogage pendant laquelle le dbogueur
essayera de rcuprer les messages de dbogage du lecteur Flash :
run

Le dbogueur est ainsi en attente du lecteur Flash : lancez votre programme en


double-cliquant dessus, ou avec la commande que lon a vu plus haut dans le cas de
Linux. Le lecteur Flash nest cependant pas encore dmarr, il ne devrait donc pas se
passer grand-chose lcran.
Une fois que la session est correctement dmarre, entrez cette commande dans fdb
pour rellement lancer le programme :
34

DIS BONJOUR AU MONSIEUR

continue

Miracle ! Notre trace("Hello world !"); a fonctionn et le message est apparu dans
la console ! (voir figure 2.24)

Figure 2.24 Rsultat de la fonction trace()


Une fentre blanche sest ouverte : il sagit de notre animation ! Pour linstant, elle ne
fait presque rien, nous remdierons cela dans la suite du cours.
Vous pouvez maintenant fermer votre programme. Si plus tard vous voulez quitter fdb,
entrez cette commande :
quit

Vous pouvez galement lister lintgralit des commandes du dbogueur avec cette
commande :
help

Lorsque vous programmez en lignes de commande, je vous conseille douvrir


deux consoles : une pour la compilation laide de mxmlc, et une autre pour
le dbogueur fdb. Cela vous vitera de quitter et relancer ce dernier chaque
compilation ; il vous suffira dutiliser la commande run chaque fois que vous
voulez tester votre programme.
35

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK


Il en faut faire des efforts pour dboguer en lignes de commande, mais une fois
que vous avez pris le coup de main, cest plus facile. Pour se faciliter la vie, mieux vaut
squiper avec les meilleurs outils ! En effet, il existe des diteurs de code trs facile
dutilisation qui intgrent galement des outils prts lemploi pour compiler et tester
nos programmes !

FlashDevelop la rescousse !
Pour Windows, il existe un trs puissant diteur pour programmer en Flash, de
plus, il est gratuit et libre : jai nomm Flashdevelop ! Flashdevelop est ce que
lon appelle un IDE (Integrated Development Environment, environnement de
dveloppement intgr en anglais) : cest un logiciel contenant tout le ncessaire pour
programmer dans un ou plusieurs langages (ici lActionscript, mais pas seulement).
Vous allez voir : compiler sera dsormais aussi simple que dappuyer sur un bouton !

Tlchargement
Flashdevelop est donc disponible au tlchargement gratuitement, malheureusement,
la version officielle est rserve aux utilisateurs de Windows (voir figure 2.25). Commencez par tlcharger Flashdevelop.


Flashdevelop
B
Code web : 868865


Il est possible, pour les utilisateurs dun autre systme dexploitation, dutiliser une
machine virtuelle, tant que les dveloppeurs nauront pas eu le temps dadapter Flashdevelop dautres supports. Il existe galement une version alternative, sous forme
dun plugin pour le logiciel Eclipse. Rassurez-vous, le reste du cours ne porte pas sur
Flashdevelop, vous pourrez tout faire sans !


Plugin
B
Code web : 649014




Eclipse
B
.
Code web : 752289

Installation
Une fois linstallateur de Flashdevelop tlcharg, lancez-le et appuyez sur Next (voir
figure 2.26).
Cet cran nous permet de choisir dinstaller ou non des composants supplmentaires,
comme le Flex SDK. Pour viter tout problme, nous allons laisser les options par
dfaut, mais vous pouvez dcocher Install Flex SDK si vous lavez dj tlcharg et
que vous tes sr de vous. Je vous conseille toutefois de laisser le programme installer
le compilateur lui-mme pour viter tout problme. Cliquez sur Next (voir figure 2.27).
36

FLASHDEVELOP LA RESCOUSSE !

Figure 2.25 Tlchargement de FlashDevelop

Figure 2.26 Installation de FlashDevelop : tape 1

37

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Figure 2.27 Installation de FlashDevelop : tape 2


Choisissez le dossier dinstallation de Flashdevelop, puis cliquez une nouvelle fois sur
Next (voir figure 2.28).

Figure 2.28 Installation de FlashDevelop : tape 3


Allez prendre un caf pendant linstallation ! (voir figure 2.29)
Cliquez sur Finish pour terminer linstallation (voir figure 2.30).
Si Flashdevelop ne se lance pas tout seul, lancez-le. Vous arrivez sur lcran daccueil
(voir figure 2.31).
38

FLASHDEVELOP LA RESCOUSSE !

Figure 2.29 Installation de FlashDevelop : tape 4

Figure 2.30 Installation de FlashDevelop : tape 5

39

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Figure 2.31 Page de dmarrage de FlashDevelop


Vous pouvez fermer la page daccueil en cliquant sur la croix correspondante (voir figure
2.32).

Figure 2.32 Fermeture de la page daccueil

Un peu de paramtrage
Si vous avez dcoch Install Flex SDK lors de linstallation du logiciel, il faut lui
dire o se trouve le Flex SDK que nous avions tlcharg au dbut avant de pouvoir
lutiliser : autrement, il ne pourra pas compiler notre projet, ce qui serait bien dommage.
Ces manipulations vous seront galement utiles si vous mettez jour le Flex SDK
plus tard.
Commenons par nous rendre dans les paramtres du logiciel, laide du menu Tools
(voir figure 2.33).
40

FLASHDEVELOP LA RESCOUSSE !

Figure 2.33 Accs aux paramtres de FlashDevelop


La fentre des paramtres de Flashdevelop souvre ; slectionnez AS3Context dans la
liste de gauche, puis Installed Flex SDKs dans le panneau de droite. Ensuite, cliquez
sur le petit bouton avec trois points, comme la figure 2.34.

Figure 2.34 Paramtres de FlashDevelop


Le gestionnaire des SDK souvre et est normalement vide. Nous allons ajouter notre
SDK dans la liste : cliquez sur le bouton Ajouter en bas gauche (voir figure 2.35).
Un nouveau SDK est apparu dans la liste ! Il faut maintenant spcifier le chemin (Path)
41

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Figure 2.35 diteur de collections InstalledSDK

du SDK en le slectionnant et en cliquant sur le petit bouton de droite trois points


(voir figure 2.36).

Figure 2.36 Mise en place du SDK

Choisissez le dossier o vous avez plac le SDK au dbut du chapitre, par exemple
D:\Flex SDK 4. Pour finir, validez en cliquant sur le bouton OK et fermez la fentre
des paramtres laide du bouton Close situ en bas droite.
42

FLASHDEVELOP LA RESCOUSSE !

Crons un projet Actionscript


Pour pouvoir programmer sereinement au mme endroit durant le cours, il nous faut
crer un projet Actionscript 3. Pour cela, allez dans le menu Project de la barre de
menus en haut, et cliquez sur New Project (voir figure 2.37).

Figure 2.37 Cration dun nouveau projet


Une nouvelle fentre apparat, proposant plusieurs types de projets. Slectionnez AS3
Project et donnez un nom votre projet dans le champ Name. Vous pouvez demander
Flashdevelop de vous crer automatiquement un dossier pour votre projet, en cochant
la case Create directory for project (voir figure 2.38).
Validez et notre projet est prt ! Flashdevelop a cr pour nous les dossiers et fichiers de
base quil faut pour commencer travailler sur notre programme Flash. Slectionnez
le panneau Project en bas droite : il nous affiche larborescence de notre projet (voir
figure 2.39).
Le dossier bin doit contenir tous les mdias qui seront chargs lexcution de notre
programme (pour linstant, nous allons le laisser tel quil est). Cest aussi le dossier
o notre fichier SWF sera cr la compilation. Le dossier lib sert regrouper tous
les mdias et librairies que vous pourriez importer dans votre programme, comme je
lai expliqu au tout dbut du chapitre. Laissons-le vide galement. Enfin, le dossier
src contient tous les fichiers de code qui composent notre programme. tendez-le,
et vous verrez que Flashdevelop a cr pour nous un fichier Actionscript principal
(reconnaissable la petite flche verte), quil a nomm Main.as. Double-cliquez dessus
pour louvrir dans lditeur.

Bien utiliser Flashdevelop


Avoir de bons outils ne suffit pas : il est primordial de bien savoir les utiliser ! Ainsi,
avant de tester notre projet, il est prfrable de faire un petit tour du propritaire.
43

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Figure 2.38 Paramtrage du nouveau projet

Figure 2.39 Arborescence du projet

44

FLASHDEVELOP LA RESCOUSSE !
Linterface
Linterface de Flashdevelop, bien qucrite en anglais, est plutt claire et surtout trs
pratique (voir figure 2.40). Dtaillons-la ensemble.

Figure 2.40 Linterface de FlashDevelop


1. La barre de menu
Toutes les fonctionnalits de Flashdevelop sont accessibles dans ces menus.
File (Fichier) : vous trouverez ici toutes les commandes en rapport avec les fichiers,
comme la cration de nouveaux documents, la sauvegarde, limpression. . .
Edit (dition) : ce deuxime menu concerne le texte que vous tapez dans lditeur. Vous pouvez ainsi facilement annuler des modifications, copier-coller du texte,
commenter du code slectionn. . .
View (Affichage) : ici, vous pouvez modifier la prsentation de Flashdevelop, et rouvrir les panneaux que vous auriez malencontreusement ferm.
Search (Recherche) : si vous voulez effectuer des recherches de texte dans votre
document ou dans le contenu des fichiers de votre projet, passez par ce menu !
Debug (Dbogage) : ce menu est un peu plus technique et concerne les sessions
de dbogage que vous effectuerez dans Flashdevelop (comme avec fdb). Nous en
reparlerons plus tard.
Project (Project) : tout ce qui touche la gestion de vos projets, comme la cration,
louverture, mais aussi pour tester votre projet actuel.
Insert (Insertion) : ici vous pouvez insrer du texte spcial dans votre document,
comme lheure actuelle (timestamp) ou une couleur entre autres.
Refactor (Refactorisation) : derrire ce terme barbare se cachent les oprations automatiques de maintenance et de mise en forme de votre code afin de le retravailler
pour quil soit plus clair (Code formatter). Dans Flashdevelop se trouvent gale45

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK


ment des outils de gnration de code pour travailler plus vite (Code generator).
Tools (Outils) : ici vous trouverez des outils pour le dveloppement en Flash, et
plusieurs fentres de paramtrage du logiciel.
Macros : il sagit de scripts lancer dans le logiciel pour automatiser certaines tches ;
toutefois, nous naborderons pas les macros de Flashdevelop dans ce cours.
Syntax (Syntaxe) : dans ce menu, vous pouvez spcifier Flashdevelop dans quel
langage vous tes en train de coder, afin quil puisse colorier le code de manire
adquate. En gnral, on nutilise pas ce menu, car Flashdevelop dtecte le type de
chaque fichier laide de son extension.
Help (Aide) : ce menu regroupe toutes les aides disponibles pour Flashdevelop, et
permet galement de vrifier les mises jour du logiciel.
2. La barre de raccourcis
Les commandes les plus utilises sont rassembles ici pour pouvoir les utiliser directement sans avoir passer par les menus.
3. Les raccourcis de dbogage
Cette zone de la barre des raccourcis est rserve aux boutons utiles pour compiler notre
projet (Build Project), le tester (Test Project) et changer le mode de dbogage
(choisir Debug revient ajouter le paramtre -debug=true au compilateur du Flex
SDK comme nous lavons vu plus haut).
4. Lditeur de texte
Cest ici que vous crirez vos programmes. gauche sont affichs les numros des lignes,
et en haut se trouvent les diffrents documents ouverts sous forme donglets.
5. Les panneaux de dveloppement
Ce sont des outils qui vous faciliteront la vie lorsque vous programmerez.
6. La console de sortie
Dans ce panneau seront affichs tous les messages de Flashdevelop (comme ltat de
la compilation par exemple) et les messages du lecteur Flash (par exemple, avec la
fonction trace()).

Lauto-compltion
Cette fonctionnalit est trs utile et vous lutiliserez en permanence pendant que vous
programmerez : en effet, elle peut terminer ce que vous tes en train de taper votre
place (toujours dans une optique de gain de temps) et peut galement vous aider
choisir quoi taper grce aux informations quelle propose.
Commenons par complter notre classe Main : placez-vous dans la fonction _init
aprs le commentaire // entry point (point dentre) et commencez taper trace.
Surprise ! Un menu souvre au bout du quatrime caractre, vous proposant dajouter
la fonction trace(), avec en bonus sa description ! (voir figure 2.41)

Pour valider votre choix, appuyez sur Entre et le mot trace est automatiquement
termin ! Bien entendu, cela na pas une grande utilit dans notre cas car le nom de la
46

FLASHDEVELOP LA RESCOUSSE !

Figure 2.41 Auto-compltion de la fonction trace()


fonction est trs court. Mais imaginez si vous aviez retenir toutes les fonctions et si
en plus leur nom fasait vingt caractres !
Il est galement possible dactiver lauto-compltion tout moment, mme
si lon na rien encore tap : il suffit dappuyer simultanment sur les touches
Ctrl et Espace.

Compiler et tester notre projet


Terminez votre ligne de code pour que votre programme affiche Hello world ! dans
la console. Comment a, vous ne vous souvenez plus comment faire ? ! Bon daccord, je
vous donne la ligne ajouter, mais cest bien parce que cest vous :
1

trace ( " Hello world ! " ) ;

Voici quoi doit ressembler le fichier aprs modifications :


1
2
3

package {
import flash . display . Sprite ;
import flash . events . Event ;

4
5
6
7
8
9

/* *
* ...
* @author Guillaume
*/
public class Main extends Sprite {

10
11
12
13
14
15
16

public function Main () : void {


if ( stage )
init () ;
else
addEventListener ( Event . ADDED_TO_STAGE , init ) ;
}

17

47

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK


private function init ( e : Event = null ) : void {
removeEventListener ( Event . ADDED_TO_STAGE , init ) ;
// entry point

18
19
20
21
22

23

trace ( " Hello world ! " ) ;

24

25
26
27

Mais pourquoi le code est diffrent par rapport tout lheure ?

Trs bonne question ! Flashdevelop, en crant notre projet, a automatiquement rempli cette classe avec le code de base de telle sorte quil ny ait aucun problme pour
nous. Les fonctions quil a rajout sont utiles dans certains cas pour viter des erreurs
daffichage. Retenez quil faut commencer programmer juste aprs le commentaire
// entry point seulement dans notre classe Main. Dans les autres classes que vous
crerez, ce code supplmentaire ne sera pas ncessaire.
Une fois que votre classe Main est prte, lancez la compilation en cliquant sur le
bouton en forme de flche bleue (Test Project)

dans la barre des raccourcis ou en
appuyant simultanment sur les touches Ctrl et Entre . Vous remarquerez quil y
a un bouton Build Project immdiatement gauche qui ne sert qu compiler notre
projet sans le lancer.
Si tout ce passe bien, une fentre du lecteur Flash souvre avec votre programme et la
console affiche notre message Hello world ! , comme la figure 2.42.

Figure 2.42 Lancement du programme


48

FLASHDEVELOP LA RESCOUSSE !
Cest aussi simple que cela !

En rsum
Lopration de vrification des erreurs, dassemblage des diffrents fichiers et de compression dun projet sappelle la compilation.
Le Flex SDK est un ensemble doutils de dveloppement, et notamment un compilateur permettant daboutir au fichier swf.
FlashDevelop est un IDE, cest--dire un outil qui permet dcrire, de compiler et
de tester du code Actionscript plus facilement.
En Actionscript, le code scrit lintrieur de fonctions, elles-mmes contenues
dans une classe, le tout plac dans un package.
Il est possible dinsrer des commentaires au milieu du code grce aux caractres
// , /* et */ .
Il existe une fonction trace() qui permet dcrire du texte dans la console, et est
principalement utilise pour les tapes de dbogage.

49

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

50

Chapitre

Les variables
Difficult :
Les variables sont un des lments les plus importants dans tous les langages de programmation : elles permettent de mmoriser des informations de toutes sortes. Sans elles, les
programmes seraient tous trs basiques et moins puissants, le monde informatique serait
alors dun ennui mortel.
Un petit exemple concret : vous voulez que votre programme vous dise bonjour, aprs lui
avoir donn votre nom. Une variable (appele monNom par exemple) se chargera alors de
mmoriser le mot que vous lui entrerez pour plus tard permettre au programme de vous
appeler par votre nom : il lui suffira de regarder ce quil se trouve dans la variable monNom.

51

CHAPITRE 3. LES VARIABLES

Dclarer et utiliser des variables


Dclaration
Le mot-cl var
La premire chose faire avant dutiliser des variables, cest de les crer :
1

var maVariable ;

Pour cela, nous avons notre disposition un mot-cl (ou mot rserv) obligatoire : var.
Cette instruction permet de dclarer une variable ; elle sutilise de la faon suivante :
var suivit dun espace et du nom de la variable.
Petit rappel : un mot-cl (ou rserv) est une expression qui est utilise par
le langage et qui lui est donc rserve, cest--dire que vous ne pouvez pas
appeler une variable var ou utiliser ce mot rserv pour autre chose que son
utilit premire.
Dsormais, vous savez crer une variable, mais le code prcdent nest pas trs utile.
En effet, chaque variable possde un type, indispensable, qui dcrit son comportement
et son utilit (par exemple : nombre, entier, chane de caractres, etc.). Sans ce type,
le langage ne saurait pas qui il a affaire en lisant une variable et surtout comment
lutiliser.
Noubliez pas de mettre le point-virgule en fin de ligne !

Comme pour les noms de classes, il est prfrable dutiliser la notation


Camel pour le nom de nos variables : leNomDeMaVariable au lieu de
lenomdemavariable. Vous pouvez galement utiliser lunderscore (_) pour
simuler les espaces qui eux sont interdits.

Le typage
Il faut donc assigner un type chaque nouvelle variable pour que le programme puisse
la reconnatre. Pour cela, on utilise les deux points ainsi :
1

var maVariable : sonType ;

Ce type suivra la variable tout au long de lexcution du programme.


Avant, en Actionscript 2, il tait possible de dclarer des variables sans les typer, le
lecteur Flash se chargeait de deviner le type de ces variables. Bien entendu, cette
technique est proscrire pour des raisons de performances et de rigueur (imaginez
52

DCLARER ET UTILISER DES VARIABLES


plusieurs centaines de variables qui vous avez affaire, mais dont vous ne connaissez
pas le type). Dsormais, les variables doivent tre types la cration : on appelle cela
le typage strict. Cest une des principales raisons de lamlioration des performances
des animations depuis le passage lActionscript 3.
Les diffrents types que vous pourrez utiliser seront dtaills un peu plus loin.
Initialiser la nouvelle variable
Aprs avoir cr une variable, il vous prendra peut-tre lenvie dy mettre quelque
chose pour la rutiliser plus tard :
1

var maVariable : sonType = ceQueJeMetsDedans ;

Vous remarquerez quon peut remplir une variable directement sa cration (ce qui est
drlement pratique), en mettant un signe gal aprs le type ; on appelle cette opration linitialisation. Ainsi, ds quelle sera cre, la variable maVariablesera du type
sonTypeet contiendra ceQueJeMetsDedans.
Vous ntes videmment pas obligs dinitialiser les variables, vous pourrez leur donner
une valeur (ou un contenu si vous prfrez) plus tard laide de laffectation.
Les valeurs par dfaut
Lorsque vous crez une variable et que vous ne linitialisez pas, elle nest pas tout fait
vide ; en effet, elle contient automatiquement une valeur par dfaut qui sera souvent
null, sauf quelques cas particuliers selon le type de la variable. Ainsi, si vous crivez
ceci :
1

var maVariable : sonType ;

maVariable contiendra sa valeur par dfaut, donne par son type.


Le mot-cl null est rserv lActionscript, vous ne pouvez donc pas appeler une variable null. Cette valeur remplace lancien mot-cl quivalent
undefined valable en Actionscript 2. Nanmoins, une variable que vous ninitialisez pas contient undefined si elle na pas de type, et vous pourrez rencontrer ce mot-cl avec les tableaux dans un des chapitres suivants.

Utiliser les variables


Affectation
Tout au long de lexcution du programme, vous aurez srement besoin de modifier le
contenu dune variable en fonction des besoins du moment. La mthode est presque
identique linitialisation, car on utilise nouveau le signe gal :
53

CHAPITRE 3. LES VARIABLES


1

maVariable = nouveauContenu ;

Ainsi, la valeur nouveauContenu sera stocke dans la variable maVariable.


Il est absolument interdit daffecter une valeur une variable si cette dernire
nexiste pas. Cela naurait aucun sens et le compilateur vous le fera savoir en
refusant de compiler votre programme. Noubliez donc pas de dclarer vos
variables avant de les utiliser.

Lecture
Il est tout aussi intressant de pouvoir lire une variable pour utiliser son contenu : par
exemple, le programme aura besoin de regarder ce que contient la variable monNom pour
pouvoir afficher Bonjour Georges ! si jai mis Georges dans la variable avant.
Par exemple, pour copier le contenu de la variable a dans la variable b, il faut donc
crire :
1

b = a ; // Je prends ce qu ' il y a dans la variable a , et je le


mets dans b

Vous pouvez voir ainsi que la faon de procder est trs simple : il suffit de renseigner
le nom de la variable.
Petite piqre de rappel : // Je prends ce quil y a dans la
variable a, et je le mets dans b est un commentaire ; il permet dcrire des informations sur le programme destination dventuels
lecteurs ou pour vous-mmes afin de vous rappeler quoi sert ce que vous
avez tap l par exemple. Les commentaires ninfluent en aucune faon sur
le fonctionnement du programme, ils sont tout simplement ignors.
Avec les dclarations des variables, cela donnerait :
1
2
3
4

var a : typeDeA = contenuA ;


var b : typeDeB = contenuB ;
b = a ; // Je prends ce qu ' il y a dans la variable a , et je le
mets dans b
// La variable b contient maintenant " contenuA "

Les nombres
Les diffrents types
Comme vous pouvez vous en douter, les nombres sont trs utiliss dans le monde de
linformatique, tant donn que le numrique est bas sur des suites de 0 et de 1. Il
existe diffrents types de nombres en ActionScript 3, chacun ayant sa spcificit.
54

LES NOMBRES
Le type int
Le type int sert manipuler des entiers relatifs. Voici un exemple de dclaration et
dinitialisation de ce type de variables :
1

var monEntier : int = - 100 ;

Ce type permet de manipuler des nombres cods sur 32 bits (cest--dire 32 0 ou


1 ), donc compris entre -2 147 483 648 et 2 147 483 647. Si vous sortez de cet
encadrement, vous obtiendrez une erreur. La valeur par dfaut de ce type est 0.
Pour accder rapidement ces deux valeurs, utilisez respectivement
int.MIN_VALUE et int.MAX_VALUE. Ce sont des variables un peu spciales
car elles sont utilisables partout dans votre code et on ne peut que les lire.
On les appelle des constantes, notion que nous aborderons dans le chapitre
sur lorient objet.

Le type uint
Le type uint sert manipuler des entiers naturels ou non-signs (cest--dire positifs),
voici un exemple de dclaration et dinitialisation :
1

var monEntier : uint = 42 ;

Le type uint permet dutiliser des entiers naturels cods sur 32 bits galement, donc
compris entre 0 et 4 294 967 295. Comme le type int, la valeur par dfaut est 0, et
vous obtiendrez aussi une erreur si vous sortez de cet encadrement. Dans certaines
situations, lutilisation de ce type ralentit lgrement lexcution de votre programme.
Ainsi, je vous conseille dutiliser le type int si les nombres que vous voulez manipuler
sont infrieurs 2 147 483 647.
Pour accder rapidement ces deux valeurs, utilisez respectivement
uint.MIN_VALUE et uint.MAX_VALUE. Elles sont galement utilisables en
lecture seule partout dans votre code.

Le type Number
Le type Number sert manipuler tous les nombres (entiers comme flottants), dans un
intervalle extrmement grand. On peut presque considrer quon peut y mettre tous
les nombres. Voici comment les utiliser :
1

var monNombre : Number = 3 . 1415 ;

55

CHAPITRE 3. LES VARIABLES


Comme dans la plupart des langages de programmation, et de faon gnrale
en informatique, on utilise la notation anglaise des nombres flottants (ou
virgule). Cest--dire qu la place de la virgule, on met un point : 3,14 crit
en franais donne 3.14 en Actionscript.
La valeur par dfaut de ce type est NaN.
Le mot-cl NaN signifie Not a Number (pas un nombre) : votre nombre prend
cette valeur si vous ne linitialisez pas une certaine valeur ou si vous tentez
dy stocker autre chose quun nombre.
Ainsi, le code suivant ne ferait pas derreur, mais la variable nbr aurait pour valeur
NaN :
1
2

var nbr : Number = Number ( " Je veux un nombre ! " ) ; // On force la


variable contenir du texte ...
trace ( nbr ) ; // Affiche : NaN

Pour accder rapidement la valeur minimum ou la valeur maximum autorise, utilisez respectivement Number.MIN_VALUE et Number.MAX_VALUE.
Une nouvelle fois, elles sont utilisables en lecture seule partout dans votre
code.
Vous tes curieux de savoir quels sont le minimum et le maximum autoriss ? Voici le
code pour les afficher :
1
2
3
4

trace ( Number . MIN_VALUE + " " + Number . MAX_VALUE ) ;


// Affiche : 4 . 9406564584124654e - 324 1 . 79769313486231e + 308
// Le " e " signifie " fois dix puissance " ; par exemple , 1e + 10
quivaut 1x10 ^ 10 = 10 000 000 000
// 1 . 79769313486231e + 308 est donc un nombre 309 chiffres

Si par mgarde vous essayez daffecter un nombre flottant (cest--dire


virgule, comme 3.14) une variable de type int ou uint, il sera automatiquement arrondi lentier infrieur avant dtre stock dans la variable. Par
exemple, 3.14 deviendra 3, et 45.9 deviendra 45.

Oprations sur les nombres


Les oprateurs de base
Pour effectuer une opration entre deux nombres, on procde comme sur les cahiers
de Maths lcole ! Lopration est effectue lors de lexcution du programme et le
rsultat peut tre stock dans une variable monNombre par exemple. Voici un tableau
qui regroupe les oprations de base :
56

LES NOMBRES
Nom de lopration
Addition
Soustraction
Multiplication
Division
Modulo

Symbole
+
*
/
%

Exemple
monNombre
monNombre
monNombre
monNombre
monNombre

=
=
=
=
=

1
8
2
8
8

+
*
/
%

4;
3;
3;
4;
5;

//
//
//
//
//

monNombre
monNombre
monNombre
monNombre
monNombre

=
=
=
=
=

5
5
6
2
3

Pour ceux qui ne le connatraient pas, le modulo est un oprateur moins


courant qui permet de renvoyer le reste de la division euclidienne entre deux
nombres.
Ces oprations peuvent tre effectues sur des variables des trois types de nombres que
nous avons vu prcdemment, mme en les mlangeant. Voici quelques exemples de
calculs :
1
2
3
4
5

var unEntier : uint = 3 + 42 ;


var unAutreEntier : int = - 25 ;
var monResultat : Number = unEntier * unAutreEntier ;
monResultat = monResultat / 100 ;
trace ( monResultat ) ; // Affiche : - 11 . 25

Contrairement beaucoup dautres langages, diviser par zro ne fera


pas planter votre programme. . . Le rsultat de lopration sera en fait
Number.POSITIVE_INFINITY, autrement dit, le nombre infini ! Faites trs
attention vrifier quune telle chose narrive pas, sinon vous pourriez avoir
des surprises lors de lexcution de votre programme. . .
Notez galement quil faut tre prudent sur le type de variables utilis pour les calculs.
Je rappelle quun nombre virgule sera automatiquement arrondi lentier infrieur
si vous tentez de laffecter une variable de type int ou uint. Reprez donc ce qui se
droule au fil de ces instructions :
1
2
3
4

var unEntier : uint =


var unNombre : Number
var monResultat : int
trace ( monResultat ) ;

2;
= 3 . 14 ;
= unEntier + unNombre ;
// Affiche : 5

Simplifier les calculs


Comme dans beaucoup de langages, il est possible en Actionscript de simplifier des
calculs de ce genre :
1

monResultat = monResultat / 100 ;

Ainsi lcriture de cette instruction peut tre simplifie et rduite sous la forme :
1

monResultat /= 100 ;

57

CHAPITRE 3. LES VARIABLES


Ce code est donc plus rapide crire, et provoque le mme rsultat que prcdemment.
Bien videmment, cette manipulation nest pas rserve la division, mais peut tre
effectue avec nimporte quel autre oprateur arithmtique : +=, -=, *=, /= et %=.
Nous avons prsent fait le tour des oprateurs disponibles en Actionscript.
Mais quen est-il des autres oprations mathmatiques plus complexes,
comme la racine carre ?
En effet, il nexiste pas doprateurs arithmtiques en Actionscript 3 pour effectuer
de telles oprations. Heureusement, une classe un peu spciale appele Math est fournie
par Flash.

La classe Math
Cette classe na pas besoin dtre importe, elle est accessible en permanence. Elle
contient une flope doutils mathmatiques trs utiles comme les puissances, les fonctions trigonomtriques, les nombres alatoires. . .

Les puissances
Ces fonctions de la classe Math vous permettent de manipuler les puissances sur des
nombres :
1
2
3
4
5

var monNombre : Number = 42 ;


// Elever la puissance
trace ( Math . pow ( monNombre , 5 ) ) ;
// Racine carr e
trace ( Math . sqrt ( monNombre ) ) ;

Les arrondis
Il existe trois types darrondis : larrondi classique, larrondi lentier infrieur le plus
proche et larrondi lentier suprieur le plus proche :
1
2
3
4
5
6
7

58

var monNombre : Number = 3 . 1415 ;


// Arrondi
trace ( Math . round ( monNombre ) ) ; // 3
// Entier inf rieur
trace ( Math . floor ( monNombre ) ) ; // 3
// Entier sup rieur
trace ( Math . ceil ( monNombre ) ) ; // 4

LES NOMBRES
Trigonomtrie
Cosinus, sinus, tangente, arc-cosinus, arc-sinus et arc-tangente sont des fonctions trigonomtriques que nous propose la classe Math :
La valeur de \pi est accessible laide de Math.PI.

1
2

var angle1 : Number = Math . PI / 2 ;


var angle2 : Number = Math . PI / 6 ;

3
4
5
6

// Cosinus
trace ( Math . cos ( angle1 ) ) ;
// 6 . 123233995736766e - 17

7
8
9
10

// Sinus
trace ( Math . sin ( angle1 ) ) ;
// 1

11
12
13
14

// Tangente
trace ( Math . tan ( angle1 ) ) ;
// 163312 39353195370

15
16
17
18

// ArcCosinus
trace ( Math . acos ( angle2 / angle1 ) ) ;
// 1 . 2309594173407747

19
20
21
22

// ArcSinus
trace ( Math . asin ( angle2 / angle1 ) ) ;
// 0 . 3398369094541219

23
24
25
26

// ArcTangente
trace ( Math . atan ( angle1 ) ) ;
// 1 . 0038848218538872

Les angles sont toujours exprims en radians.

Il existe une variante de la fonction arc-tangente en Actionscript 3 :


Math.atan2(). Elle sert principalement calculer sans erreur langle entre
deux positions. Nous en aurons besoin plus loin dans le cours.

59

CHAPITRE 3. LES VARIABLES


Nombre alatoire
Il serait trs intressant de fabriquer des nombres alatoires, pour des jeux par exemple.
Cela est possible avec la fonction Math.random() :
1

trace ( Math . random () ) ; // Affiche un nombre flottant al atoire


compris entre 0 et 1

Pour gnrer un nombre alatoire entre deux valeurs a et b (voir figure 3.1), il faut
utiliser la formule suivante :
1

trace ( a + Math . random () * ( b - a ) ) ;

Figure 3.1 Cration dun nombre alatoire

Les chanes de caractres


Les chanes de caractres sont galement trs utilises. Il sagit dune suite de caractres qui forme du texte. Par exemple, Hello world ! est une chane de caractres ;
son premier caractre est le H , et son dernier caractre est le ! .
Une chane de caractres est toujours entoure de guillemets, comme nous lavons
vu dans le chapitre prcdent :
1

trace ( " Hello world ! " ) ;

Mais vous pouvez aussi mettre des apostrophes la place des guillemets :
1

trace ( ' Hello world ! ') ;

Attention toutefois ne pas mlanger les deux, cela ne marcherait pas. Ainsi,
le code trace("Hello world !); est incorrect.

chappement des caractres spciaux


Mais si je veux mettre des guillemets ou des apostrophes dans ma chane de
caractres ?
60

LES CHANES DE CARACTRES


Je vous voyais venir ! Effectivement, mettre des guillemets dans une chane de caractres guillemets ou des apostrophes dans une chane de caractres apostrophes serait problmatique : en effet, le compilateur pensera que vous avez termin
votre chane au deuxime guillemet ou apostrophe rencontr, et se demandera pourquoi
diable dautres caractres se baladent derrire !
Dans cet exemple, vous pouvez voir que la coloration syntaxique nous montre le problme :
1

trace ( " Hello . swf a dit : " Hello world ! " " ) ;

En effet, le Hello world ! nest dans ce cas plus considr comme faisant partie de
la chane de caractres. . .
Pour remdier cela, il faut chapper le ou les caractres qui posent problme. Cela
consiste mettre un autre caractre spcial, lantislash (\), qui permettra de dire que
le caractre suivant doit tre pris pour un caractre tout fait banal dans notre chane.
Ainsi, le code correct serait :
1

trace ( " Hello . swf a dit : \" Hello world !\" " ) ;

Vous pouvez galement remplacer les guillemets par des apostrophes dans les cas o
a vous arrange de faire ainsi :
1

trace ( ' Hello . swf a dit : " Hello world !" ') ;

Plus besoin dchapper, car ce nest plus le caractre guillemet qui prcise o dbute
et o se termine la chane, mais lapostrophe. Par contre, si vous voulez mettre une
apostrophe en plus, le problme va revenir :
1

trace ( ' Hello . swf m 'a dit : " Hello world ! " ') ;

Encore une fois, le compilateur ne va vraiment rien comprendre ce que vous lui
crivez. Solution : chapper le caractre apostrophe qui pose problme !
1

trace ( ' Hello . swf m \ ' a dit : " Hello world !" ') ;

Vous pouvez systmatiquement chapper les guillemets et apostrophes dans


les chanes de caractres si cela vous met laise.

trace ( ' Hello . swf m \ ' a dit : \" Hello world !\" ') ;

Utiliser les variables


Maintenant, si nous voulons mmoriser des chanes de caractres, il va falloir les
ranger dans des variables de type String. Par exemple, pour mmoriser notre phrase
Hello world ! dans la variable coucou, il faut procder ainsi :
61

CHAPITRE 3. LES VARIABLES


1
2

var coucou : String = " Hello world ! " ;


trace ( coucou ) ; // Affiche : Hello world !

La valeur par dfaut dune variable de type String est null.

Concatnation de chanes
Concatner deux chanes de caractres consiste les assembler pour ne former quune seule chane. Par exemple, concatner la chane Hello avec la chane
world ! donnerait une nouvelle chane plus grande : Hello world ! . Pour cela, il
faut utiliser loprateur + (qui sert aussi additionner deux nombres), de cette faon :
1

" Hello " + " world ! "

Ainsi, si lon voulait afficher notre texte en deux parties, nous cririons ceci :
1

trace ( " Hello " + " world ! " ) ;

Il est alors possible de concatner des chanes avec des variables de tout type (y compris
avec des nombres) et de diffrentes manires :
1
2
3
4
5
6

var coucouDebut : String = " Hello " ;


var coucouFin : String = " ! " ;
var monNom : String = " J r me " ;
var monAge : int = 42 ;
trace ( coucouDebut + monNom + coucouFin + " Tu as " + monAge + "
ans , n 'est - ce pas ? " ) ;
// Affiche : Hello J r me ! Tu as 42 ans , n 'est - ce pas ?

7
8
9

trace ( Number . MIN_VALUE + " " + Number . MAX_VALUE ) ;


// Affiche : 4 . 9406564584124654e - 324 1 . 79769313486231e + 308

Quelques variables et fonctions utiles


Ces variables ou fonctions sont obligatoirement attaches une variable de type String
laide dun point. Vous ne pouvez pas les utiliser sur une chane de caractres simple
comme "Hello world !".
Longueur dune chane
Pour connatre la longueur dune chane de caractres, cest--dire, le nombre de
caractres quelle contient, il faut utiliser la variable length disponible sur notre chane
de cette manire :
62

LES CHANES DE CARACTRES


1
2
3

var coucou : String = " Hello world ! " ;


trace ( " Cette cha ne contient " + coucou . length + " caract res . "
);
// Affiche : Cette cha ne contient 13 caract res .

Le point est important : il signifie que cest la longueur de cette chane particulire que
lon veut.

Changer la casse dune chane


La casse est ltat dune lettre, cest--dire si elle est en minuscule ou en majuscule.
Il est possible de modifier la casse de lensemble dune chane de caractres
en utilisant les fonctions toLowerCase() (en casse minuscule) et toUpperCase() (en
casse majuscule) :
1
2
3
4
5

var coucou : String = " Hello world ! " ;


// En minuscules
trace ( coucou . toLowerCase () ) ; // hello world !
// En majuscules
trace ( coucou . toUpperCase () ) ; // HELLO WORLD !

Rechercher dans une chane


Il peut tre utile de rechercher un ou plusieurs caractres dans une chane. Pour cela,
on utilise la fonction indexOf() (position de) :
1

maVariable . indexOf ( " Cha ne recherch e " ) ;

La fonction renvoie la position du premier caractre de la chane recherch dans la


variable, ou -1 si elle ne la pas trouv.
Vous pouvez aussi spcifier une variable de type String entre les parenthses,
au lieu dune chane de caractres simple.
Cherchons la position de la premire lettre a dans notre variable :
1
2

var coucou : String = " Hello world ! " ;


trace ( coucou . indexOf ( " a " ) ) ; // -1 , on n 'a rien trouv

Effectivement, il ny a pas de a dans notre chane. . . Retentons notre chance avec


le mot world :
1

trace ( coucou . indexOf ( " world " ) ) ; // 6 ! Victoire !

Bravo, nous avons trouv le mot world la septime lettre !


63

CHAPITRE 3. LES VARIABLES


Il se situe la septime position, car le numro des caractres commence
zro : le premier caractre a le numro 0, le deuxime a le numro 1 et
ainsi de suite. Du coup, pour avoir le numro du dernier caractre dans la
chane, il faut prendre sa longueur moins un : coucou.length - 1.

Remplacer dans une chane


Cette fonction replace() est similaire la fonction de recherche, mais il faut en plus
indiquer le texte qui va remplacer lancien.
1

maVariable . replace ( " Cha ne recherch e " , " Cha ne ins rer la
place " ) ;

Modifions dynamiquement notre chane pour remplacer world par Jrme :


1

trace ( coucou . replace ( " world " , " J r me " ) ) ; // Hello J r me !

La variable de dpart nest pas modifie : la fonction se contente de renvoyer la nouvelle


chane que lon peut afficher ou mettre dans une variable :
1
2
3
4

var coucou : String = " Hello world ! " ;


var salut : String = coucou . replace ( " world " , " J r me " ) ;
trace ( salut ) ; // Hello J r me !
trace ( coucou ) ; // Hello world !

Le texte nest remplac quune seule fois : ds que le texte recherch est
rencontr, il est remplac et la fonction sarrte.

1
2

var coucou : String = " Hello world world world ! " ;


trace ( coucou . replace ( " world " , " J r me " ) ) ; // Hello J r me world
world !

Pour pouvoir remplacer tous les world en Jrme , il faut faire autant de
replace()que ncessaire :
1
2
3
4
5
6
7

64

var coucou : String = " Hello world world world ! " ;


coucou = coucou . replace ( " world " , " J r me " ) ;
trace ( coucou ) ; // Hello J r me world world !
coucou = coucou . replace ( " world " , " J r me " ) ;
trace ( coucou ) ; // Hello J r me J r me world !
coucou = coucou . replace ( " world " , " J r me " ) ;
trace ( coucou ) ; // Hello J r me J r me J r me !

LES CHANES DE CARACTRES


Il existe une autre mthode bien plus efficace et puissante qui consiste utiliser les expressions rgulires (ou RegExp) : ce sont des codes suivant
des rgles prcises, capables de rechercher et de remplacer du texte plusieurs fois dans une mme chane, ceci parmi une foule dautres choses fort
utiles. Malheureusement, cette notion est plutt complexe apprhender, je
ne laborderais pas dans le cours.

En rsum
Une variable permet de mmoriser une valeur.
Le mot-cl var sert dclarer une variable qui peut tre affecte dune valeur par
un signe = .
On utilise les trois types int, uint et Number pour des valeurs numriques.
Pour effectuer des calculs, il existe principalement les oprateurs de base : +, -,
*, / et %.
Grce la classe Math, il est possible de raliser des oprations mathmatiques
complexes.
Le type String est rserv lutilisation des chanes de caractres.
Diffrentes fonctions permettent de manipuler les chanes de caractres et il est
possible de les concatner grce loprateur +.

65

CHAPITRE 3. LES VARIABLES

66

Chapitre

Les conditions
Difficult :
Nous avons vu dans le prcdent chapitre comment manipuler les nombres laide doprateurs
et de variables. Nous allons voir prsent comment tester le contenu de ces variables ;
ainsi vous pourrez excuter des instructions ou non pour les diffrentes valeurs que pourront
prendre vos variables. Comme vous pourrez le voir, les conditions sont trs utiles dans le
monde de linformatique, et sont la base de linteractivit des machines, sans quoi elles
feraient toujours la mme chose !

67

CHAPITRE 4. LES CONDITIONS

criture dune condition


Quest-ce quune condition ?
Les conditions permettent de tester le contenu dune ou plusieurs variables. Ainsi,
vous pourrez excuter des instructions diffrentes suivant le rsultat du test. Grce ces
structures conditionnelles, le programme sera alors en mesure de prendre des dcisions.
Nos programmes seront donc moins monotones et pourront ragir diffremment suivant
les circonstances : imaginez si tous les programmes faisaient exactement la mme chose
quel que soit le contexte, cela serait bien ennuyeux ! Voici le genre dinstructions que
nous serons capables de raliser laide des conditions :
1
2

SI ma condition est vraie


ALORS effectuer mes instructions

Dans une condition, nous pourrons ainsi tester diffrentes choses. Par exemple, nous
pourrions tester un nombre entier pour savoir sil est positif ou non. Nous cherchons
donc une relation entre deux valeurs pour pouvoir les comparer. Pour cela, nous utiliserons donc divers oprateurs prsents dans la suite de ce cours. Si la condition est
vraie, alors les instructions qui la suivent sont excutes. Dans le cas contraire, elles
sont tout simplement ignores.
Ne vous inquitez pas si vous avez du mal saisir le concept, vous comprendrez mieux
au fil du chapitre.
En Actionscript, comme dans beaucoup dautres langages, les conditions renvoient automatiquement une valeur de type Boolean comme nous le verrons
plus loin dans le chapitre : true pour vraie et false pour fausse.

Les oprateurs relationnels


Les oprateurs relationnels permettent de comparer une variable une valeur ou
deux variables entre elles. Dans le tableau ci-dessous sont rpertoris les diffrents
symboles correspondants. Ces symboles seront utiliss en permanence, cest pourquoi
il serait judicieux de les retenir.
De manire gnrale, les oprateurs sont utiliss ainsi : une variable ou une valeur,
loprateur et une autre variable ou valeur. Voici quelques exemples de conditions :
1
2
3
4

// Cette condition est vraie si monEntier contient un nombre


sup rieur 2
monEntier > 2
// Cette deuxi me condition est vraie si maVariable et
monAutreVariable contiennent la m me valeur
monVariable == monAutreVariable

Vous pouvez galement comparer des chanes de caractres :


68

CRITURE DUNE CONDITION


Oprateur

1
2
3
4
5
6

<

Signification pour des valeurs numriques


est infrieur

>

est suprieur

<=

est infrieur ou gal

>=

est suprieur ou gal

==
!=
===
!==

est
est
est
est

gal
diffrent de
strictement gal
strictement diffrent de

Signification pour des caractres


est avant dans lordre alphabtique
est aprs dans lordre alphabtique
est avant dans lordre alphabtique ou identique
est aprs dans lordre alphabtique ou identique
est identique
est diffrent de
est strictement identique
est strictement diffrent de

var t1 : String = " Salut " ;


var t2 : String = " Salut " ;
var t3 : String = " Bonjour " ;
trace ( t1 == t2 ) ; // Affiche : true
trace ( t1 == t3 ) ; // Affiche : false
trace ( t1 > t3 ) ; // Affiche : true , car Salut est apr s Bonjour
dans l ' ordre alphab tique

Vous remarquerez que le test dgalit seffectue laide de deux signes = .


Les dbutants omettent souvent le deuxime symbole = , ce qui est source
derreurs dans votre code. En effet, le symbole = seul est un signe daffectation pour les variables comme nous lavons vu dans le prcdent chapitre.

Comparer deux variables : une question de types


Un oprateur relationnel permet de comparer uniquement deux expressions du mme
type. Il nest pas possible de comparer deux variables dont lune, par exemple, serait de
type int et lautre de type String. Si cela se produisait, le compilateur vous afficherait
un message derreur de ce type : Error : Comparison between. . . . Toutefois, il existe
une exception : les nombres qui peuvent tre compars entre eux mme si leur type
varie entre int, uint et Number. Par exemple, le code suivant fonctionnera sans erreur :
1
2
3

var nombre : Number = 0 . 4 ;


var entier : int = 1 ;
trace ( nombre < entier ) ; // Affiche : true

Mais alors, comment puis-je facilement comparer un nombre et une chane


de caractres ?
69

CHAPITRE 4. LES CONDITIONS


Et bien, il suffit de transformer lune de nos deux variables pour que les deux aient
exactement le mme type ! Par exemple, transformons le nombre en chane de caractres :
1
2
3

var nombre : Number = 3 . 14 ;


var texte : String = " 3 . 14 " ;
trace ( nombre . toString () == texte ) ; // Affiche : true

En effet, taper .toString() derrire notre variable de type Number transforme sa valeur
en chane de caractres afin que la comparaison fonctionne correctement !
La variable nombre nest pas rellement transforme, elle reste de type Number
par la suite.

Prcisions sur les oprateurs stricts


Les oprateurs stricts (=== et !==) servent comparer deux objets quelconques (par
exemple, deux variables) en regardant non seulement leur valeur, mais aussi leur type.
Ces oprateurs sont peu utiliss : en gnral, on connat lavance le type des variables
que lon manipule. Par exemple, je dclare et initialise trois variables de type Object,
cest--dire quelles nont pas de type bien dfini et que lon peut y mettre ce que
lon souhaite ; attention toutefois ne pas abuser de ce type un peu spcial, il ralentit
lexcution de votre programme. Ensuite, je teste la valeur de ces variables avec ==,
pour finalement tester leur valeur et leur type en mme temps avec ===. De toute
vidence, le caractre 3 nest pas du mme type que lentier 3.
1
2
3
4
5
6

var nom : Object = " 42 " ;


var prenom : Object = " 42 " ;
var age : Object = 42
trace ( nom === prenom ) ; // Affiche : true
trace ( nom == age ) ; // Affiche : true
trace ( nom === age ) ; // Affiche : false

Dans ce cas trs prcis, votre programme Flash convertira automatiquement le


format des variables lorsquil est ncessaire, sauf si vous utilisez les oprateurs
=== ou !==. Ainsi, la comparaison entre la chane de caractres et lentier se
droule sans accroc.

Les oprateurs logiques


Contrairement aux oprateurs prcdents qui permettaient de comparer des valeurs, les
oprateurs logiques servent combiner plusieurs conditions. Ceux-ci peuvent avoir
leur utilit lorsque nous voulons tester par exemple, si un nombre est compris dans un
intervalle. Les oprateurs relationnels ne permettent pas ce genre de comparaison.
70

CRITURE DUNE CONDITION


Nous pouvons donc contourner le problme en combinant plusieurs conditions. Prenons
un exemple : nous voulons savoir si une variable monNombre est comprise entre 0 et 10.
Pour cela nous pourrions dcomposer ce test en deux conditions :
monNombre est suprieur 0.
monNombre est infrieur 10.
Les oprateurs logiques nous permettent alors dassocier ces deux conditions en une
seule : monNombre > 0 ET monNombre < 10.
Le tableau ci-dessous prsente donc ces diffrents oprateurs, ainsi que les symboles
qui leur sont associs :
Oprateur
!
&&
||

Signification
NON logique
ET logique
OU logique

Ainsi, nous allons comparer notre nombre par rapport un intervalle laide de loprateur && :
1
2

// Test pour savoir si monNombre est compris entre 0 et 10


monNombre > 0 && monNombre < 10

La priorit des oprateurs


Pour dcider dans quel ordre les diffrentes oprations seront effectues, les oprateurs
respectent les rgles de priorit suivantes :
Les oprateurs arithmtiques (+, -, *, /, %) sont prioritaires par rapport aux
oprateurs relationnels (==, !=, <, >, etc. . .).
Les oprateurs relationnels sont prioritaires par rapport aux oprateurs logiques
(!, && et ||).
Les oprations entoures de parenthses sont toujours prioritaires.
Ainsi la condition 3 + 4 > 5 est vraie du fait que laddition est effectue avant la
comparaison.
Quelques exemples doprations imbriques :
1
2
3
4
5

trace ( 1
trace ( 1
trace ( 1
trace ( 1
trace ( 1

== 2 ) ; // Affiche : false
+ 1 == 2 ) ; // Affiche : true
== 2 || 2 == 2 ) ; // Affiche : true
!= 2 && 1 + 1 == 2 ) ; // Affiche : true
!= 2 && 1 + 2 == 2 ) ; // Affiche : false

Pour mieux comprendre lutilisation de ces conditions, nous allons tudier diffrentes
structures qui les utilisent. Commenons tout de suite avec linstruction if...else.
71

CHAPITRE 4. LES CONDITIONS

Linstruction if. . .else


La structure de base
La syntaxe
Linstruction if...else est la structure de base des conditions. Grce elle, nous
pouvons excuter des instructions diffrentes suivant si la condition est vraie ou fausse.
Sans plus attendre, voyons la structure if...else crite en Actionscript :
1
2
3
4
5
6
7
8

if ( /* Condition */ )
{
// Instructions si la condition est vraie
}
else
{
// Instructions si la condition est fausse
}

Vous remarquerez donc, dans cette structure, les deux blocs dinstructions dfinis par les
paires daccolades. Si la condition est vrifie, alors le premier bloc dinstructions sera
excut, sinon (traduction du mot else ) ce sera le second. Bien entendu, lcriture
du bloc else nest pas obligatoire. En revanche, il nest pas possible dcrire un bloc
else seul. Vous pourriez donc vous contenter du code suivant :
1
2
3
4

if ( /* Condition */ )
{
// Instructions si la condition est vraie
}

Parce que rien ne vaut un bon exemple, nous allons tout de suite tester une premire
condition dans notre IDE. Pour cela, nous prendrons une variable nomme maVie
reprsentant, par exemple, la vie restante dans un jeu quelconque. Nous pourrions
alors tester si vous tes encore en vie ou si vous tes mort. Voici donc le code insrer
juste aprs le commentaire // entry point de votre classe Main :
1

var maVie : uint = 1 ;

2
3
4
5
6
7
8
9
10

if ( maVie == 0 )
{
trace ( " Vous tes mort . " ) ;
}
else
{
trace ( " Vous tes toujours en vie . " ) ;
}

11
12

// Affiche : Vous tes toujours en vie .

Ici la variable maVie est gale 1, et donc la condition maVie == 0 est fausse. Ainsi, lors
de lexcution, seule linstruction lintrieur des accolades du else sera excute. Vous
72

LINSTRUCTION IF. . .ELSE


verrez donc apparaitre le message : Vous tes toujours en vie. Nhsitez pas tester
ce code avec diffrentes valeurs pour maVie afin de bien comprendre le fonctionnement.
Pour crire une condition if seule ou if...else, il faut respecter un certain
nombre de rgles et de conventions que nous allons dtailler.

Les rgles et conventions dcriture


Nous allons maintenant dfinir quelles sont les diffrentes rgles dcriture ainsi que
des conventions fortement recommandes. Tout dabord, vous aurez srement remarqu labsence de point-virgule ; aprs les accolades. En effet, les conditions ne
se terminent jamais par un point-virgule. Dautre part, les parenthses qui entourent
votre condition sont obligatoires. En revanche, les accolades peuvent tre facultatives
mais uniquement dans un cas ; il sagit du cas o il ny a quune seule instruction
lintrieur du bloc dinstructions. Il est alors possible dcrire votre condition suivant
lune des trois formes ci-dessous :
1
2
3
4

if ( maVie == 0 )
trace ( " Vous tes mort . " ) ;
else
trace ( " Vous tes toujours en vie . " ) ;

ou bien :
1
2
3
4
5
6

if ( maVie == 0 )
trace ( " Vous tes mort . " ) ;
else
{
trace ( " Vous tes toujours en vie . " ) ;
}

ou encore :
1
2
3
4
5
6

if ( maVie == 0 )
{
trace ( " Vous tes mort . " ) ;
}
else
trace ( " Vous tes toujours en vie . " ) ;

Pour finir ce paragraphe, nous parlerons dune chose trs importante en termes de
prsentation. Vous aurez certainement remarqu la mise en forme utilise depuis le
dbut pour crire les conditions :
Laccolade ouvrante sur une ligne.
Vos instructions dcales vers la droite laide dune tabulation.
Laccolade fermante sur une ligne.
73

CHAPITRE 4. LES CONDITIONS


Cette mise en forme est appele lindentation et nest pas obligatoire cependant, il
est trs fortement dconseill de tout crire sur une seule ligne ou de ne pas dcaler
les instructions lintrieur des accolades. En effet, respecter ces rgles vous permettra
de rendre vos codes beaucoup plus clairs et lisibles par vous mais aussi par dautres
personnes qui ne connatront pas la faon dont vous avez ralis votre programme.
Les ternaires
Dans certains cas, il est possible de condenser des conditions : on appelle cela les
expressions ternaires. Cette technique nest pas applicable tout le temps et il ne
faut pas en abuser. Pour introduire cette notion, nous allons partir du code suivant :
1
2
3
4
5
6

var monMessage : String ;


if ( maVie == 0 )
monMessage = " Vous tes mort . " ;
else
monMessage = " Vous tes toujours en vie . " ;
trace ( monMessage ) ;

Vous remarquerez quici la condition sert uniquement affecter une variable dune
valeur qui dpend dune condition. Les expressions ternaires ne peuvent tre utilises
que dans ce cas-l ! Il est alors possible de rcrire le code prcdent sous une forme
condense :
1
2

var monMessage : String = ( maVie == 0 ) ? " Vous tes mort . " : "
Vous tes toujours en vie . " ;
trace ( monMessage ) ;

Le principe est alors dcrire lensemble de la condition en une seule ligne et daffecter
directement la variable. Cest une forme dcriture qui peut tre pratique, mais sachez
quen ralit elle est trs peu utilise car elle est difficile lire. Utilisez donc les expressions ternaires pour diminuer le volume de votre code, mais tchez de garder un code
qui soit le plus facilement lisible !
Lcriture des expressions ternaires est assez spciale et souvent trompeuse.
Notez donc la prsence du symbole ? qui permet de tester la condition
place juste avant, ainsi que le signe : permettant de remplacer le motcl else et de sparer les instructions.

Le type boolen
En Actionscript, il existe un type de variable de type boolen : Boolean. Ces variables ne peuvent prendre que deux valeurs : true ou false. Les boolens sont trs
utiliss avec les conditions car ils permettent facilement dexprimer si une condition
est vraie ou fausse. Dailleurs, une condition est elle-mme exprime sous la forme
dun boolen. Pour sen assurer, vous allez tester le code suivant :
74

LINSTRUCTION IF. . .ELSE


1
2
3
4

if ( true )
trace ( " Ma condition est vraie . " ) ;
else
trace ( " Ma condition est fausse . " ) ;

5
6

// Affiche : Ma condition est vraie .

Nous pouvons remarquer quen effet la condition true est vraie, cest pourquoi lutilisation de variables de type boolen peut tre prfrable. Il nest alors plus ncessaire
dcrire le test == true pour une variable de type boolen. Ainsi, si vous utilisez
des noms judicieux pour vos variables, le code paratra plus clair :
1

var estEnVie : Boolean = true ;

2
3
4
5
6
7
8
9
10

if ( estEnVie )
{
trace ( " Vous tes toujours en vie . " ) ;
}
else
{
trace ( " Vous tes mort . " ) ;
}

11
12

// Affiche : Vous tes toujours en vie .

tant donn que le rsultat dune condition est un boolen, il est tout fait possible
de le stocker dans une variable :
1
2
3

var maVie : uint = 1 ;


var estEnVie : Boolean = ( maVie > 0 ) ;
trace ( estEnVie ) ; // Affiche : true

Lutilisation des boolens sert principalement allger votre code et le


rendre plus lisible. Encore une fois, choisissez des noms explicites pour vos
variables, cela permettra de faire plus facilement ressortir la logique de votre
programme.

La structure avec else if


Avant de clore cette partie sur la structure if...else, nous allons voir comment raliser
des tests supplmentaires avec else if. Ici, rien de bien compliqu, cest pourquoi vous
comprendrez aisment le code ci-dessous :
1

var monNombre : int = 1 ;

2
3
4
5

if ( monNombre < 0 )
{
trace ( " Ce nombre est n gatif . " ) ;

75

CHAPITRE 4. LES CONDITIONS


6
7
8
9
10
11
12
13
14

}
else if ( monNombre == 0 )
{
trace ( " Ce nombre est nul . " ) ;
}
else
{
trace ( " Ce nombre est positif . " ) ;
}

15
16

// Affiche : Ce nombre est positif .

Bien quil soit possible deffectuer plusieurs tests la suite laide de cette mthode,
cela peut savrer assez rptitif. Cest pourquoi, il existe une structure qui permet
dallger lcriture de telles conditions : il sagit de linstruction switch que nous allons
dtailler dans la suite.

Linstruction switch
Lutilisation conventionnelle
Face la structure if...else, la condition switch permet de simplifier et dallger
le code lorsque vous voulez tester diffrentes valeurs pour une mme variable. Cette
structure noffre pas plus de possibilits que celle en if...else, il sagit simplement
dune manire diffrente dcrire des conditions. Voici comment se prsente linstruction
switch :
1
2
3
4
5
6
7
8
9
10
11
12
13
14

switch ( /* Variable */ )
{
case /* Argument */ :
// Instructions
break ;
case /* Argument */ :
// Instructions
break ;
case /* Argument */ :
// Instructions
break ;
default :
// Instructions
}

Pour utiliser cette structure, il suffit de renseigner la variable tester puis dtudier
les diffrents arguments. Notez la prsence de linstruction break; qui permet de
sortir du switch. Cette instruction est obligatoire, en cas dabsence, les instructions
situes en dessous seraient excutes. Enfin, le default correspond au cas par dfaut,
nous pouvons le comparer au else dune instruction if...else. Voici un exemple de
code que vous pouvez tester :
76

LINSTRUCTION SWITCH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

var monNombre : int


switch ( monNombre )
{
case 0 :
trace ( " Ce
break ;
case 1 :
trace ( " Ce
break ;
case 2 :
trace ( " Ce
break ;
default :
trace ( " Ce
}

= 1;

nombre vaut 0 . " ) ;


nombre vaut 1 . " ) ;
nombre vaut 2 . " ) ;
nombre ne vaut ni 0 , ni 1 , ni 2 . " ) ;

Notez quaprs chaque argument vous devez crire un double point et non
un point-virgule.

Une utilisation spcifique lActionscript


Contrairement dautres langages tels que le C ou encore le Java, linstruction switch
en Actionscript ne permet pas uniquement de faire des galits. En plaant la valeur
true la place de la variable, il est alors possible de la comparer avec un autre boolen, en particulier une condition. Voici la structure switch pouvant tester diverses
conditions :
1
2
3
4
5
6
7
8
9
10
11
12

switch ( true )
{
case ( /* Condition */ ) :
// Instructions
break ;
case ( /* Condition */ ) :
// Instructions
break ;
case ( /* Condition */ ) :
// Instructions
break ;
}

Voici un exemple concret qui permet de tester si une variable monNombre est un nombre
ngatif, nul ou positif :
1
2
3
4

var monNombre : int = 1 ;


switch ( true )
{
case ( monNombre < 0 ) :

77

CHAPITRE 4. LES CONDITIONS


5
6
7
8
9
10
11
12
13

trace ( " Ce nombre est n gatif . " ) ;


break ;
case ( monNombre == 0 ) :
trace ( " Ce nombre est nul . " ) ;
break ;
case ( monNombre > 0 ) :
trace ( " Ce nombre est positif . " ) ;
break ;

En rsum
Grce aux conditions, nous pouvons effectuer des choses diffrentes suivant ltat
dune ou plusieurs variables.
Les conditions sont ralises laide doprateurs relationnels et logiques, dont
le rsultat est un boolen.
Linstruction if...else est la plus utilise.
Les expressions ternaires permettent de condenser lcriture dune instruction
if...else.
Lorsque vous avez une multitude de valeurs tester, linstruction switch est plus
approprie.

78

Chapitre

Les boucles
Difficult :
Dans le chapitre prcdent, nous avons vu comment raliser des conditions et permettre
ainsi aux machines de faire des choix. Cest dj un grand pas dans le monde informatique,
mais ce nest pas suffisant : prsent, nous allons introduire les boucles !
Les boucles sont lies la notion de rptitivit : il sagit en fait de ritrer une srie
dinstructions plusieurs fois. Les boucles sont indispensables dans tout un tas de situations, par exemple lorsque nous demandons lutilisateur de jouer tant que la partie nest
pas termine. Pour cela, nous disposons de trois boucles en Actionscript 3 que nous
dtaillerons au fil du chapitre. tant donn que nous avons dj vu comment crire une
condition, ce chapitre devrait tre relativement simple apprhender.

79

CHAPITRE 5. LES BOUCLES

La boucle while
Le principe
Comme nous lavons dit prcdemment, les boucles permettent de rpter des instructions un certain nombre de fois. La difficult est alors de savoir quand ces instructions
doivent cesser dtre rptes. Pour cela, nous aurons besoin des conditions. Sans plus
attendre, voici le genre dinstructions ralisables laide des boucles :
1
2

TANT QUE ma condition est vraie


ALORS effectuer mes instructions

Dans une boucle while, la condition sutilise exactement de la mme manire que pour
une instruction if...else. Il faudra donc dclarer une variable avant la boucle puis
la tester lintrieur de la condition. En revanche, dans ce cas, la variable devra tre
mise jour lintrieur de la boucle pour pouvoir en sortir. En effet, pour stopper
la rptition des instructions, la condition doit obligatoirement devenir fausse un
certain moment. Oublier de mettre jour cette variable conduirait une boucle infinie,
les instructions se rpteraient alors linfini.
Dans le cas dune boucle while, la condition est teste avant dentrer dans la
boucle. Ainsi, si la condition est dj fausse avant la boucle, les instructions
lintrieur de celle-ci ne seront jamais excutes.
Vous comprendrez mieux le fonctionnement des boucles au fur et mesure de la
lecture de ce chapitre.

criture en Actionscript
En Actionscript, la boucle while permet de grer toutes les situations : celles que
nous verrons plus tard sont lgrement diffrentes, mais noffrent aucune fonctionnalit
supplmentaire. La structure dune boucle est trs similaire celle des structures
conditionnelles vues prcdemment. Voici donc comment crire une boucle while en
Actionscript :
1
2
3
4

while ( /* Condition */ )
{
// Instructions si vraie
}

Comme pour linstruction if...else, les accolades deviennent facultatives sil ny a


quune seule condition :
1
2

80

while ( /* Condition */ )
// Instruction si vraie

LA BOUCLE WHILE
Cette seconde syntaxe est correcte : en crivant cela vous naurez pas de
message derreur. Cependant, dans une boucle digne de ce nom, vous naurez
en ralit que trs rarement une seule instruction. En effet, votre boucle
contiendra toujours au moins une instruction ainsi quune mise jour de
votre variable.
Afin de mieux comprendre le fonctionnement et la syntaxe dune boucle while, nous
allons voir diffrents exemples dans la suite de ce cours.
Exemples dutilisation
Pour commencer, nous allons tester une boucle qui affiche la valeur de notre variable
teste dans la condition. Voici le code source de notre boucle tester :
var i : uint = 0 ;
while ( i < 5 )
{
trace ( i ) ;
i = i + 1;
}

1
2
3
4
5
6

Si vous lancez le projet, vous devriez obtenir ceci dans la console de sortie :
0
1
2
3
4

Vous constaterez alors que la valeur 5 nest pas affiche. Effectivement,


lorsque notre variable i prend cette valeur, la condition i < 5 nest plus
vrifie ; linstruction trace(i) nest donc plus excute. Il faudra ainsi tre
vigilant sur lcriture de votre condition pour que votre boucle sexcute bien
comme vous le dsirez.
Lintrt dutiliser une boucle while est que nous navons pas besoin de connatre
lavance ou de nous soucier du nombre de rptitions. Pour illustrer cela, nous allons
prendre un exemple : imaginons que nous cherchions la puissance de 2 correspondant
1024. Nous devons alors calculer les puissances successives de 2 jusqu atteindre 1024.
Cependant, dans notre cas, nous ne savons pas combien de fois nous allons devoir
rpter lopration. Nous utiliserons donc une boucle while de la manire suivante :
1
2
3
4
5
6

var monNombre : uint = 2 ;


var i : uint = 1 ;
while ( monNombre != 1024 )
{
i = i + 1;
monNombre *= 2 ;

81

CHAPITRE 5. LES BOUCLES


}
trace ( i ) ; // Affiche : 10

7
8

En effet, pour ceux qui connaissaient dj la rponse : 210 = 1024. Notre boucle sest
donc excute 9 fois ce qui correspond i = 10. Nous voyons bien ici que nous navions
pas besoin de connatre lavance le nombre de rptitions de la boucle.
Quelques astuces
Vous savez dj tout ce quil faut savoir sur la boucle while cependant, je vais vous
donner maintenant quelques astuces pour amliorer la lisibilit de votre code. Ces
conseils ne sont en aucun cas une obligation, il sagit principalement de pratiques trs
courantes chez les programmeurs. Elles permettront dallger votre code source mais
galement de le rendre plus lisible pour un autre programmeur. Voici donc ces astuces
fortement recommandes :
Traditionnellement, en Actionscript et dans beaucoup dautres langages, on utilise
les noms de variables i, j et k pour compter lintrieur dune boucle. En utilisant ces
noms, vous facilitez la lecture de votre code, surtout si celui-ci est assez consquent.
Lorsque vous utiliserez des boucles, vous serez trs souvent amen incrmenter ou
dcrmenter vos variables : i = i + 1 ou i = i- 1. Pour simplifier lcriture, nous
pouvons utiliser pour lincrmentation i++ et pour la dcrmentation i.
Enfin, nous allons revenir sur la notion de boucle infinie. Comme nous lavons dit, il
sagit dune boucle dont la condition est toujours vrifie. Les instructions lintrieur
sont alors rptes linfini. En voici un exemple :
var maCondition : Boolean = true ;
while ( maCondition )
{
trace ( " Ceci est une boucle infinie " ) ;
}

1
2
3
4
5

Vous vous en doutez certainement, cette boucle va afficher le message : Ceci est une
boucle infinie un nombre indfini de fois, comme ceci :
Ceci est une boucle infinie
Ceci est une boucle infinie
Ceci est une boucle infinie
...

En gnral, il faut tout prix viter dcrire ce genre de choses. Cependant, ce type de
boucles peut savrer utile dans certains cas.

La boucle do. . .while


Nous allons prsent parler de la boucle do...while qui est une voisine trs proche
de la boucle while. Toutefois, nous pouvons noter une diffrence dans la syntaxe par
82

LA BOUCLE DO. . .WHILE


lapparition du mot do ainsi que du transfert de la condition en fin de boucle. Ceci
apporte une lgre diffrence dans linterprtation du code, mais nous y reviendrons
aprs. Voici la syntaxe de cette nouvelle boucle :
1
2
3
4

do
{

// Instructions si vraie
} while ( /* Condition */ ) ;

Notez cependant lapparition dun point-virgule ; aprs la condition. Loubli de ce point-virgule est une erreur trs courante chez les dbutants. Veillez
donc ne pas commettre cette erreur, cela vous vitera des problmes de
compilation.

Quelle est la diffrence avec la boucle prcdente ?

Dans une boucle while classique, la condition est en dbut de boucle. Cest pourquoi la
boucle peut ne jamais tre excute si la condition est fausse ds le dpart. En revanche,
dans une boucle do...while, la condition est place la fin de la boucle. De ce fait,
la boucle sexcutera toujours au moins une fois. Il est donc possible dutiliser cette
boucle pour sassurer que le programme rentrera au moins une fois dans la boucle. Voici
un exemple de calcul de PGCD :
1
2
3
4
5
6
7
8
9

var nombre1 : uint = 556 ;


var nombre2 : uint = 148 ;
do
{
var reste : uint = nombre1 % nombre2 ;
nombre1 = nombre2 ;
nombre2 = reste ;
} while ( nombre2 != 0 ) ;
trace ( " PGCD = " + nombre1 ) ; // Affiche : PGCD = 4

Petit rappel : PGCD pour Plus Grand Commun Diviseur. Si vous ne vous
souvenez plus de lalgorithme, il faut diviser le plus grand nombre par le plus
petit. Ensuite, on prend le reste de la division euclidienne pour diviser le
nombre le plus petit. Puis on reprend le dernier reste pour diviser le reste de
la division prcdente. Et ainsi de suite jusqu ce quun reste soit nul. Vous
avez ainsi votre PGCD qui correspond au dernier reste non nul !
Une fois encore, vous pouvez remarquer quil nest pas ncessaire de connatre le nombre
dexcutions de la boucle contrairement une boucle for dont nous allons parler maintenant.
83

CHAPITRE 5. LES BOUCLES

La boucle for
Prsentation
La syntaxe
Comme nous lavons dj dit dans ce cours, la boucle while permet de raliser toute
sorte de boucle. Cependant, son criture est quelque peu fastidieuse cest pourquoi, il
existe une criture condense utile dans certains cas : la boucle for. Celle-ci est utilise
lorsque nous connaissons lavance le nombre dexcutions de la boucle directement
ou travers une variable. Cette boucle permet de concentrer le traitement de la variable utilise, rappelez-vous avec une boucle while, nous devions passer par les tapes
suivantes :
Dclaration et initialisation de la variable avant la boucle.
Condition sur la variable en entre de boucle.
Incrmentation de la variable lintrieur de la boucle.
Grce la boucle for, nous pouvons maintenant condenser ces trois tapes au mme
endroit :
1
2
3
4

for ( /* Initialisation */ ; /* Condition */ ; /* Incr mentation */


)
{
// Instructions
}

Attention, l encore, la prsence des points-virgules ; pour sparer


chaque champ. Cest galement une source de problmes pour la compilation.

Quelques exemples
La boucle for est trs utilise en programmation, elle permet dviter davoir crire
des instructions rptitives et galement de faire des recherches dans les tableaux,
notion que nous aborderons trs bientt. En attendant, voici quelques exemples dutilisation de la boucle for :
1
2
3
4

for ( var i : int = 0 ; i < 10 ; i ++)


{
trace ( " La valeur de i est " + i ) ;
}

Ici galement, les accolades deviennent facultatives sil ny a quune seule instruction.
Aussi, il est possible dutiliser la boucle for en dcrmentation ou en encore par pas
de 10 si vous le dsirez :
1
2

84

for ( var i : int = 10 ; i > 0 ; i - -)


trace ( " La valeur de i est " + i ) ;

LA BOUCLE FOR
La boucle for na rien de difficile, il sagit simplement dune boucle while condense.
En revanche, la syntaxe est assez spciale, cest pourquoi il est ncessaire de la retenir
car cette boucle vous servira plus que vous ne limaginez !

En rsum
Les boucles permettent de rpter une srie dinstructions tant quune condition est
vrifie.
La boucle while permet de tout faire mais il est possible que les instructions
lintrieur ne soient jamais excutes.
La boucle do...while est identique la prcdente, nanmoins la boucle est excute
au moins une fois.
La boucle for est une forme condense du while dans le cas o on connat le nombre
de rptitions de la boucle.
Lincrmentation est utilise en permanence dans les boucles et son criture peut
tre simplifie par les expressions i++ et i .

85

CHAPITRE 5. LES BOUCLES

86

Chapitre

Les fonctions
Difficult :
Maintenant, nous allons introduire les fonctions ! Sachez que cest un concept qui existe
dans tous les langages de programmation et que ces fonctions servent structurer notre
programme en petits bouts.
Nous verrons en quoi consistent rellement ces fonctions. Nous apprendrons comment
utiliser des fonctions toutes prtes, mais aussi comment en crer nous-mmes. Afin que
vous compreniez mieux toutes ces notions, je vous prsenterais quelques exemples qui
feront appel aux connaissances acquises jusquici.

87

CHAPITRE 6. LES FONCTIONS

Concept de fonction
Le principe de fonctionnement
Depuis le dbut de ce cours, tout ce que nous faisons se trouve lintrieur dune fonction nomme Main (ou peut-tre dune fonction init si vous utilisez FlashDevelop).
En effet, nous navons pas encore crit lextrieur des accolades de celle-ci. En gnral,
pour crire un programme, il faut compter entre une centaine de lignes de code jusqu
plusieurs milliers pour les plus consquents. Il nest donc pas envisageable dinsrer la
totalit du code lintrieur de la fonction Main. En effet, il faut organiser le code, ce
qui permet de le rendre plus lisible mais galement de faciliter le dbogage. Pour cela,
nous allons dcouper notre programme en morceaux. Nous regrouperons donc certaines
instructions ensemble pour crer des bouts de programme, puis nous les assemblerons
pour obtenir le programme complet. Chaque morceau est alors appel : fonction !
Comment se prsente une fonction ?

Une fonction est une srie dinstructions qui ont t regroupes pour une tche commune. Nous crons alors une fonction que nous appellerons chaque fois que nous en
avons besoin. Celle-ci se compose de la manire suivante :
Une ou des entres : il sagit dinformations qui seront utiles au cours de lexcution
de la fonction.
Le traitement et les calculs : cest le cur de la fonction, les instructions internes
sont excutes.
Une unique sortie : une fois les instructions de la fonction termines, celle-ci renvoie
un rsultat.
Pour rsumer tout ceci, vous trouverez la figure 6.1 un schma reprenant le principe
de fonctionnement.

Figure 6.1 Principe dune fonction


Notez quune fonction ne possde pas obligatoirement une entre et une sortie. Celle-ci peut trs bien se satisfaire uniquement dune entre ou dune sortie, et plus exceptionnellement aucune des deux. Nous reviendrons l-dessus
trs rapidement dans ce cours.
88

CONCEPT DE FONCTION
En rgle gnrale, on associe une fonction une tche bien prcise. Par exemple,
nous pourrions imaginer une fonction qui calcule et renvoie le carr dun nombre plac
en entre. Vous trouverez la figure 6.2 un schma de ce que cela donnerait.

Figure 6.2 Exemple dune fonction


Bien videmment, dans un programme, les fonctions sont gnralement plus complexes.
LActionscript possde dj des centaines de fonctions qui permettent par exemple
dafficher une image lcran ou encore de la transformer. Nous apprendrons les
utiliser ainsi qu crer nos propres fonctions.

Prsentation
Vous ne vous en doutez peut-tre pas, mais vous avez dj utilis des fonctions depuis
le dbut de ce cours ! Effectivement, nous avons dj utilis plusieurs fois la fonction
trace() et galement introduit la fonction toString(). Nanmoins, ces deux fonctions
sont lgrement diffrentes dans leur utilisation. Nous prsenterons donc brivement ici
ces diffrences entre les fonctions dites de base telle que la fonction trace() et les
mthodes comme la fonction toString(). Allons-y pour les fonctions de base !
Les fonctions de base
Lappel dune fonction telle que la fonction trace() se fait de manire la plus
basique qui soit. Rappelez-vous la faon dont nous crivions linstruction faisant appel
cette fonction :
1

trace ( " Texte afficher " ) ;

Vous remarquerez quil suffit simplement dcrire le nom de la fonction, ainsi que le
texte afficher entre parenthses. En revanche, ceci est diffrent pour les mthodes !
Les mthodes
Les mthodes sont lies la notion de POO ou Programmation Oriente Objet, je vous rappelle que nous y reviendrons dans une partie entirement consacre
ce concept. Contrairement aux fonctions de base, les mthodes sont associes
un objet. Pour vous montrer ceci, reprenons lexemple dutilisation de la fonction
toString() :
89

CHAPITRE 6. LES FONCTIONS


1
2

var nombre : Number = 3 . 14 ;


trace ( nombre . toString () == " 3 . 14 " ) ;

Ce quil faut noter par rapport la fonction trace(), cest que la mthode toString()
est lie lobjet nombre qui est de type Number. Notez le point . sparant lobjet
nombre de la mthode toString() ; il signifie que la mthode est lie lobjet et quelle
ne peut pas tre utilise indpendamment de lobjet auquel elle est associe. Quoi quil
en soit, vous aurez tout le temps de vous familiariser avec ceci au cours de la partie sur
la Programmation Oriente Objet.

Cration et appel de fonctions


Nous allons maintenant apprendre crer et appeler des fonctions. Nous verrons
quil existe deux faons de dclarer une fonction : les instructions de fonction et
les expressions de fonction. Commenons sans plus tarder par les instructions de
fonction.
Tout ce que nous allons voir ici concerne les fonctions de base. Nanmoins,
les mthodes ne sont pas trs diffrentes et reprendront tous les principes vus
tout au long du chapitre. Aussi, soyez attentifs tout ce qui sera dit ici ! Par
ailleurs, pour linstant, nous nous contenterons de tout crire lintrieur de
la fonction Main tel que nous le faisons depuis le dbut de ce cours.

Instructions de fonction
Dclaration
Linstruction de fonction est la premire technique permettant de dfinir une fonction. Il sagit sans aucun doute de la manire que vous serez le plus amens utiliser
lintrieur de vos programmes. Celle-ci dbute par le mot-cl function suivi du nom
donn cette fonction, dailleurs voici sa structure :
1
2
3
4

function nomDeLaFonction ( sesParametres ) : sonType


{
// Instructions ex cuter lors de l ' appel de la fonction
}

Pour faciliter la comprhension de tous ces champs, nous allons reprendre le modle
utilis plus haut pour dcrire une fonction :
Une ou des entres : il sagit des paramtres placs en entres, par ex :(monParam1:int,
monParam2:String). Vous pouvez galement ne renseigner aucun paramtre, vous
laisserez alors les parenthses vides, comme ceci ().
Le traitement et les calculs : cela correspond aux instructions places entre les
accolades de la fonction, qui seront excutes lappel de la fonction.
90

CRATION ET APPEL DE FONCTIONS


Une unique sortie : il est possible que la fonction ne renvoie aucune valeur, auquel cas
utilisez le mot-cl void comme type de renvoi. Dans le cas contraire, celle-ci ne peut
renvoyer quune unique variable. Le type de cette variable doit tre renseign aprs
les paramtres et prcd de deux-points : . Le renvoi de cette valeur seffectue
en utilisant le mot-cl return suivi de la valeur ou variable renvoyer.
Rien ne remplace un bon exemple, voici notre fonction qui lve un nombre au carr :
1
2
3
4
5
6

function carre ( nombre : int ) : int


{
var resultat : int = 0 ;
resultat = nombre * nombre ;
return resultat ;
}

Une variable dclare lintrieur dune fonction nest dfinie que pour cette
fonction. la fin de celle-ci, la variable est supprime de la mmoire et nest
donc plus accessible ! Ne tentez donc pas de rcuprer sa valeur en dehors
des accolades de la fonction !
Sachez quil est possible deffectuer des oprations aprs le mot-cl return, il est alors
prfrable de placer des parenthses autour du calcul. Veillez cependant ne pas en
faire trop, le code doit toujours rester ar et lisible. La fonction prcdente aurait donc
pu tre crite plus succinctement de la faon suivante :
1
2
3
4

function carre ( nombre : int ) : int


{
return ( nombre * nombre ) ;
}

Voil notre fonction est dfinie, il ne reste plus qu lappeler !

Appel
Lappel de la fonction nest pas bien compliqu sachant que vous avez dj ralis
cette opration ! omme pour la fonction trace(), nous allons maintenant appeler notre
fonction carre() en renseignant en paramtre le nombre que nous dsirons lever au
carr. La fonction nous renvoie une variable de type int, nous allons ainsi la stocker
dans une variable resultat dclare et de type int galement. Voici donc comment
procder :
1
2

var resultat : int = carre ( 4 ) ;


trace ( " le carr de 4 est " + resultat ) ; // Affiche : le carr
de 4 est 16

91

CHAPITRE 6. LES FONCTIONS


Lorsque votre fonction ne renvoie rien, le mot-cl void peut tre facultatif.
Cependant, je vous conseille fortement de lcrire quand mme. Dailleurs
le compilateur vous recommandera galement de prciser son type de renvoie : Warning: return value for function nomDeLaFonction has
no type declaration.
Ce nest pas trs flagrant dans ce cas, mais lutilisation des fonctions permet dorganiser
le code et de le rentre plus lisible. Ceci sera effectivement le cas lorsque vous aurez des
fonctions complexes, et que vous naurez plus qu les utiliser en les appelant en une
seule instruction ! Nous verrons diverses fonctions pour mieux comprendre juste aprs
les expressions de fonction.

Expressions de fonction
Les expressions de fonction sont beaucoup moins utilises que les instructions de
fonction et sont lgrement plus complexes. Les expressions de fonction utilisent
une instruction daffectation pour crire une fonction. Pour cela, il nous faut dfinir une fonction anonyme qui sera stocke dans une variable de type Function.
Pour viter de vous noyer dans des explications, voici la structure dune dclaration
dexpression de fonction :
1
2
3
4

var nomDeLaFonction : Function = function ( sesParametres )


{
// Instructions ex cuter lors de l ' appel de la fonction
};

Nous ne nous attarderons pas trop sur ces expressions de fonction, voici tout de
mme un exemple dutilisation :
1
2
3
4
5

var afficher : Function = function ( texte : String ) : void


{
trace ( texte ) ;
}
afficher ( " Ceci est la fonction afficher . " ) ;

Pour linstant, vous pouvez vous contenter uniquement des instructions de


fonction, ne vous compliquez pas la vie avec les expressions de fonction
qui sont moins utilises. En revanche, retenez bien comment utiliser ces instructions de fonction que nous utiliserons dsormais tout le temps.

Quelques exemples
Pour clore ce chapitre sur les fonctions, nous verrons quelques exemples de fonctions
qui pourront vous tre utile lavenir.
92

QUELQUES EXEMPLES

Message de bienvenue
Voici une fonction qui se contente dafficher un message de bienvenue la personne
indique en paramtre. Cette fonction ne renvoie aucune valeur.
1
2
3
4
5

function bienvenue ( nom : String ) : void


{
trace ( " Bonjour " + nom + " et bienvenue sur le Site du Z ro
!");
}
bienvenue ( " Marcel Dupont " ) ; // Affiche : Bonjour Marcel Dupont
et bienvenue sur le Site du Z ro !

Pour que votre code soit encore plus lisible, nhsitez pas donner des noms
explicites vos fonctions !

Calcul de PGCD
Dans cet exemple, nous allons calculer le PGCD entre deux nombres comme nous avons
appris le calculer dans le chapitre prcdent :
1
2
3
4
5
6
7
8
9
10
11

function calculPGCD ( nombre1 : int ,


{
do
{
var reste : uint = nombre1
nombre1 = nombre2 ;
nombre2 = reste ;
} while ( nombre2 != 0 ) ;
return nombre1 ;
}
trace ( " Le PGCD de 56 et 42 est :
Affiche : Le PGCD de 56 et 42

nombre2 : int ) : int

% nombre2 ;

" + calculPGCD ( 56 , 42 ) ) ; //
est : 14

Pour ceux qui voudraient rellement utiliser cette fonction, sachez quici le
nombre1 est suppos plus grand que le nombre2. Si vous le dsirez, nhsitez
pas rajouter une condition pour tester si cest effectivement le cas !

Calcul dun maximum


Voici une fonction qui pourrait vous tre utile, celle-ci vous renvoie le plus grand nombre
entre ces deux paramtres. Il ny a rien de trs compliqu, voici comment procder :
1
2

function max ( nombre1 : int , nombre2 : int ) : int


{

93

CHAPITRE 6. LES FONCTIONS


3
4
5
6
7
8
9
10
11
12
13
14
15
16

var resultat : int = 0 ;


if ( nombre1 > nombre2 )
{
resultat = nombre1 ;
}
else
{
resultat = nombre2 ;
}
return resultat ;

}
var nombre1 : int = 2 ;
var nombre2 : int = 3 ;
trace ( " Le maximum entre " + nombre1 + " et " + nombre2 + " est
" + max ( nombre1 , nombre2 ) ) ; // Affiche : Le maximum entre 2
et 3 est 3

Lorsque vous raliserez des programmes assez consquents, vous devrez conomiser
au maximum les instructions dans vos programmes pour gagner en performance ou
simplement pour le rendre plus lisible. Il peut alors devenir intressant de regarder si
vos fonctions ne peuvent pas scrire diffremment, mais surtout en moins de lignes.
Ceci peut tre le cas pour cette fonction o nous pouvons aisment nous dispenser du
bloc dinstructions else. Effectivement, testez le code suivant, vous verrez quil fait
exactement la mme chose :
1
2
3
4
5
6
7
8
9
10
11
12

function max ( nombre1 : int , nombre2 : int ) : int


{
var resultat : int = nombre1 ;
if ( nombre2 > nombre1 )
{
resultat = nombre2 ;
}
return resultat ;
}
var nombre1 : int = 2 ;
var nombre2 : int = 3 ;
trace ( " Le maximum entre " + nombre1 + " et " + nombre2 + " est
" + max ( nombre1 , nombre2 ) ) ; // Affiche : Le maximum entre 2
et 3 est 3

Vous verrez que la recherche dun optimum (maximum ou minimum) est une pratique
assez courante avec les tableaux, mais nous verrons ceci dans le prochain chapitre !

En rsum
Les fonctions permettent dorganiser le code, de le rendre plus lisible mais galement
de se sparer de tches rptitives.
Pour dclarer une fonction, on utilise le mot-cl function.
94

QUELQUES EXEMPLES
Une fonction peut recevoir plusieurs paramtres en entre, mais ne peut retourner
quune valeur au plus.
On utilise le mot-cl return pour renvoyer une valeur.
On prfre gnralement les instructions de fonction auxquelles on peut attribuer
un nom.

95

CHAPITRE 6. LES FONCTIONS

96

Chapitre

Les tableaux
Difficult :
Pour clore cette premire partie du cours, nous verrons les tableaux qui sont trs utiliss
en programmation !
Les variables de base, prsentes dans un chapitre prcdent, sont trs utiles, mais possdent leurs limites lorsquil sagit de grer beaucoup de valeurs. Effectivement, laide de
variables nous pouvons associer une valeur un nom. Ceci peut tre handicapant lors du
traitement dune quantit de valeurs importante. Cest ici quentrent en jeu les tableaux !
Le principe des tableaux est de pouvoir stocker plusieurs valeurs sous un mme nom. Ceci
facilitera alors le traitement de ces donnes puisque celles-ci seront enregistres sous le
mme nom et seront simplement diffrencies par un indice lintrieur du tableau.
En Actionscript, nous avons plusieurs manires de crer et dutiliser des tableaux. Dans
ce chapitre, nous verrons les deux types de tableaux : Array et Vector.

97

CHAPITRE 7. LES TABLEAUX

Le type Array
Le premier type de tableau utilis en Actionscript est Array. En Actionscript, les
tableaux ne sont pas fixs en taille ce qui permet une programmation plus souple.
De plus, en ce qui concerne le type Array, les tableaux ne sont pas typs, cest--dire
quils ne sont pas rservs un seul type de variable. Il est alors possible dinsrer dans
un tableau des variables de type int, uint, Number, String ou encore tout ce qui vous
passe par la tte.

Cration
La cration dun tableau de type Array peut tre ralise de multiples faons. Cependant, les tableaux sont soumis aux mmes rgles que les variables. Cest pourquoi,
nous retrouverons donc la structure de base commune toute variable :
1

var nomDuTableau : Array = ceQueJeMetsDedans ;

En revanche, lorsquil sagit dinitialiser un tableau, nous avons le choix entre diverses mthodes. Voici quatre manires diffrentes dinitialiser une variable de type
Array :
1
2
3
4

var monTableau : Array = new Array ( 3 ) ; // Cr ation d ' un tableau


de 3 valeurs non renseign es
var monTableau : Array = new Array () ; // Cr ation d ' un tableau
vide
var monTableau : Array = new Array ( " Site " , " du " , " Z ro " ) ; // Cr
ation d ' un tableau contenant les 3 valeurs indiqu es
var monTableau : Array = [ " Site " , " du " , " Z ro " ]; // Cr ation du m
me tableau contenant les 3 valeurs indiqu es

Dans beaucoup de langages, la longueur dun tableau doit tre dfinie lors de
sa dclaration. Ce nest pas le cas en Actionscript, il est tout fait possible
de changer la longueur dun tableau en cours de programme.
La fonction trace() permet galement dafficher le contenu dun tableau. Vous pouvez
ainsi tout moment connatre ltat de votre tableau :
1
2

var monTableau : Array = [ " Site " , " du " , " Z ro " ];
trace ( monTableau ) ; // Affiche : Site , du , Z ro

Les lments du tableau


Mme si un tableau regroupe plusieurs valeurs, celles-ci doivent pouvoir tre utilises
sparment. Cest ici quentre en jeu la notion dindice lintrieur dun tableau. Ces
indices sont utiliss entre crochets [] pour prciser la position de llment dsir dans
le tableau. Les valeurs peuvent alors tre traites comme nimporte quelle variable :
98

LE TYPE ARRAY
1
2
3
4
5

var monTableau : Array = new Array ( 3 ) ;


monTableau [ 0 ] = 4 ;
monTableau [ 1 ] = 5 ;
monTableau [ 2 ] = monTableau [ 0 ] + monTableau [ 1 ];
trace ( monTableau [ 2 ]) ; // Affiche : 9

Attention, en programmation les indices des tableaux commencent toujours


0. Ainsi, le troisime lment du tableau se trouve lindice2. Ce nest pas
trs compliqu comprendre, mais on a souvent tendance loublier les
premires fois.
Comme nous venons de le voir, les valeurs lintrieur dun tableau se manipulent de
la mme manire que les variables. Toutefois, une valeur non initialise dans le tableau
aura une valeur par dfaut, undefined :
1
2

var monTableau : Array = new Array () ;


trace ( monTableau [ 0 ]) ; // Affiche : undefined

Proprits du type Array


Enfin, pour en finir avec le type Array, nous allons voir quelques mthodes et proprits qui pourront vous tre utiles. Tout dabord, lorsque vous utiliserez des tableaux, vous naurez pas besoin de connatre en permanence la taille de votre tableau.
En revanche, vous pouvez tout moment avoir besoin de connatre cette longueur de
tableau. Pour cela, vous pouvez utiliser la proprit length associe aux tableaux de
type Array. Voici comment lutiliser :
1
2
3

var monTableau : Array = new Array ( 5 ) ;


var taille : int = monTableau . length ;
trace ( taille ) ; // Affiche : 5

Nous allons prsent voir diffrentes mthodes permettant dinsrer ou de supprimer


des lments dans un tableau. Dabord, la mthode push() permet dajouter un ou
plusieurs lments la fin du tableau. loppos, la mthode unshift() insre un ou
plusieurs lments au dbut du tableau, cest--dire lindice 0. Pour finir, la mthode
splice() est un compromis car elle permet dinsrer des lments un indice spcifi.
Voici un exemple dutilisation de ces mthodes :
1
2
3
4
5

var monTableau : Array = [ " Site " , " du " , " Z ro " ];
monTableau . unshift ( " Bienvenue " ) ;
monTableau . splice (1 , 0 , " sur " ," le " ) ;
monTableau . push ( " ! " ) ;
trace ( monTableau ) ; // Affiche : Bienvenue , sur , le , Site , du , Z ro ,!

99

CHAPITRE 7. LES TABLEAUX


La mthode splice() peut avoir des finalits diffrentes suivant les paramtres renseigns. Voici donc la signification de chacun de ses paramtres :
Indice de dpart o on se place pour effectuer les oprations. Nombre dlments devant tre supprims partir de lindice de dpart. Srie dlments
qui doivent tre insrs la suite de lindice de dpart. Ainsi, la mthode
splice() permet la fois dinsrer des lments mais galement de supprimer ou remplacer des lments. Dans le cas prsent, la mise zro du
deuxime paramtre permet uniquement dinsrer des lments sans en supprimer.
Enfin, pour supprimer des lments nous avons galement trois mthodes : pop(),
shift(), et splice(). Symtriquement push() et unshift(), les mthodes pop()
et shift() permettent de supprimer des lments respectivement la fin ou au dbut
dun tableau. Pour supprimer des lments au milieu du tableau, il faut utiliser la
mthode splice() prsente juste avant. Encore une fois, voici un exemple pour bien
comprendre :
1
2
3
4
5

var monTableau : Array = [ " Bienvenue " , " sur " , " le " , " Site " , " du " ,
" Z ro " , " ! " ];
monTableau . pop () ;
monTableau . splice (1 , 2 ) ;
monTableau . shift () ;
trace ( monTableau ) ; // Affiche : Site , du , Z ro

Le type Vector
Le second type de tableaux utilis en Actionscript est Vector. Vous verrez que ces
tableaux sont trs proches de ceux de type Array, ils sont notamment galement non
fixs en taille. La principale diffrence vient du fait que les tableaux de type Vector
sont typs. Cest--dire quune fois dclar pour un certain type de variables, il nest
pas possible dy mettre autre chose. Voyons tout ceci plus en dtails !

Dclaration
Ici encore, la dclaration ressemble celle dune variable, mais une nuance prs.
tant donn que les tableaux de type Vector sont typs, il est ncessaire de prciser le
type de variables qui sera utilis laide des chevrons <> . Voici donc comment
dclarer un tel tableau :
1

var nomDuTableau : Vector . < Type > = ceQueJeMetsDedans ;

Pour initialiser un tableau de type Vector, voici les mthodes proposes :


1
2
3

var monTableau : Vector . < String > = new Vector . < String >() ;
var monTableau : Vector . < int > = new Vector . < int >( 3 ) ;
var monTableau : Vector . < String > = Vector . < String >([ " Site " , " du " ,
" Z ro " ]) ;

100

LE TYPE VECTOR
tant donn que ces tableaux sont typs, vous ne pouvez pas insrer une
valeur dont le type ne correspondrait pas celui dclar. En effet, ceci entrainerait des erreurs dexcution ou de compilation.
Notez que la taille du tableau peut toutefois tre fixe en utilisant un paramtre supplmentaire de type Boolean et valant true. Voici le code correspondant :
1

var monTableau : Vector . < int > = new Vector . < int >( 3 , true ) ;

Gestion des lments


Tout comme les tableaux Array, les valeurs internes peuvent tre manipules laide
dindices mis entre crochets [] . Voici encore quelques exemples de manipulations
de valeurs lintrieur dun tableau :
1
2
3
4
5
6
7
8

var monTableau : Vector . < int > = new Vector . < int >( 10 ) ;
monTableau [ 0 ] = 0 ;
monTableau [ 1 ] = 1 ;
for ( var i : int = 2 ; i < monTableau . length ; i ++)
{
monTableau [ i ] = monTableau [i - 1 ] + monTableau [i - 2 ];
}
trace ( monTableau ) ; // Affiche : 0 ,1 ,1 ,2 ,3 ,5 ,8 , 13 , 21 , 34

Pour les plus perspicaces dentre vous, vous aurez vu apparatre les premiers
termes de la Suite de Fibonacci qui sont en effet : 0,1,1,2,3,5,8,13,21,34.
En augmentant la taille du tableau, vous pourrez ainsi avoir tous les termes
de la suite que vous dsirez !
Grce cet exemple nous commenons cerner lintrt de lutilisation des tableaux.
Effectivement, lorsque nous utilisons des boucles par exemple, il devient relativement
simple de lier notre variable i de boucle avec les indices du tableau. Ceci avait dj
t dit prcdemment, mais nous allons le rappeler, les boucles sont extrmement utiles
et performantes pour parcourir des tableaux.
Pour allier tableaux et fonctions, nous allons transformer le code prcdent pour
crer une fonction renvoyant le nime terme de la suite de Fibonacci. Dcouvrons
cette fonction :
1
2
3
4
5
6
7
8
9

function suiteFibonacci ( terme : int ) : uint


{
var monTableau : Vector . < uint > = new Vector . < uint >( terme ) ;
monTableau [ 0 ] = 0 ;
monTableau [ 1 ] = 1 ;
for ( var i : int = 2 ; i < monTableau . length ; i ++)
{
monTableau [ i ] = monTableau [i - 1 ] + monTableau [i - 2 ];
}

101

CHAPITRE 7. LES TABLEAUX


10
11
12
13
14

return ( monTableau [ terme - 1 ]) ;


}
trace ( suiteFibonacci ( 10 ) ) ; // Affiche : 34
trace ( suiteFibonacci ( 20 ) ) ; // Affiche : 4181
trace ( suiteFibonacci ( 30 ) ) ; // Affiche : 514229

Enfin, vous noterez que les mthodes push(), pop(), shift, unshift() et splice()
fonctionnent galement avec les tableaux de type Vector.

Les tableaux multidimensionnels


Le concept
Nous allons maintenant dcouvrir les tableaux multidimensionnels : un nom barbare pourtant, cette notion nest pas si complique que a ! Les tableaux multidimensionnels ne sont en ralit que des tableaux imbriqus dans dautres tableaux.
Certes, cest une notion qui fait peur aux premiers abords cependant, il ny a rien de
nouveau en matire de code. Pour mieux comprendre de quoi il sagit, nous allons illustrer cette notion par un exemple. Nous pourrions crer une liste regroupant lensemble
des livres de la collection Le Livre du Zro , il serait alors possible de raliser cela
avec un tableau classique ou monodimensionnel. Imaginons maintenant quen plus de
stocker le nom des livres, nous souhaitions y ajouter le nom de lauteur et lanne de
sortie. Dans ce cas, nous avons besoin dutiliser un tableau bidimensionnel de la
manire suivante :
1
2
3
4
5

var livres : Array = new Array () ;


livres [ 0 ] = [ " R alisez votre site web avec HTML5 et CSS3 " , "
Mathieu Nebra " , 2011 ];
livres [ 1 ] = [ " Apprenez programmer en Java " , " Cyrille Herby " ,
2011 ];
livres [ 2 ] = [ " D butez dans la 3D avec Blender " , " Antoine Veyrat
" , 2012 ];
livres [ 3 ] = [ " R digez des documents de qualit avec LaTeX " , " No
l - Arnaud Maguis " , 2010 ];

Sachant que les lments du tableau principal sont des tableaux, vous obtiendrez donc
un tableau en utilisant la notation avec indice vue prcdemment :
1

trace ( livres [ 0 ]) ; // Affiche : R alisez votre site web avec


HTML5 et CSS3 , Mathieu Nebra , 2011

Il est bien videmment possible daccder une valeur lintrieur du second tableau.
Pour cela, nous devrons utiliser une notation double indice, cest ce qui rend ce
tableau multidimensionnel ! Regardez plutt ce code :
1

102

trace ( livres [ 0 ][ 0 ]) ; // Affiche : R alisez votre site web avec


HTML5 et CSS3

LES TABLEAUX MULTIDIMENSIONNELS


Pour bien comprendre, nous pouvons effectuer une analogie avec un tableau
Excel par exemple o le premier indice correspondrait au numro de la ligne
et le second au numro de la colonne. Si vous en avez besoin, sachez que
vous pouvez raliser des tableaux de la dimension que vous souhaitez.

Un peu de pratique
Dans cette section, nous allons raliser plusieurs fonctions pour apprendre bien manipuler les tableaux. Pour les tests, nous reprendrons le tableau prcdent :
1
2
3
4
5

var livres : Array = new Array () ;


livres [ 0 ] = [ " R alisez votre site web avec HTML5 et CSS3 " , "
Mathieu Nebra " , 2011 ];
livres [ 1 ] = [ " Apprenez programmer en Java " , " Cyrille Herby " ,
2011 ];
livres [ 2 ] = [ " D butez dans la 3D avec Blender " , " Antoine Veyrat
" , 2012 ];
livres [ 3 ] = [ " R digez des documents de qualit avec LaTeX " , " No
l - Arnaud Maguis " , 2010 ];

Pour viter de surcharger le code de ce cours, nous ne rcririons pas ces lignes avant
chaque fonction. vous de les copier si vous souhaitez raliser des essais.
Qui est-ce ?
La fonction prsente ci-dessous permet de retrouver lauteur dun livre. Pour cela,
nous raliserons donc une boucle lintrieur de laquelle nous rechercherons le livre
spcifi en paramtre. Une fois le livre trouv, il ne reste plus qu retenir lindice
correspondant dans le tableau et de renvoyer le nom de lauteur. Voici la fonction en
question :
1
2
3
4
5
6
7
8
9
10
11
12
13
14

function auteur ( monTableau : Array , monLivre : String ) : String


{
var i : int = 0 ;
var continuer : Boolean = true ;
do
{
if ( monTableau [ i ][ 0 ] == monLivre )
continuer = false ;
i ++;
} while ( continuer ) ;
return monTableau [i - 1 ][ 1 ]
}
trace ( auteur ( livres , " Apprenez programmer en Java " ) ) ; //
Affiche : Cyrille Herby
trace ( auteur ( livres , " R alisez votre site web avec HTML5 et
CSS3 " ) ) ; // Affiche : Mathieu Nebra

103

CHAPITRE 7. LES TABLEAUX


Vous remarquerez que dans cet exemple, nous combinons la fois : condition, boucle,
fonction et tableau. Si vous avez bien compris cet exemple cest que vous tes au point
sur la premire partie et donc fin prt pour entamer la deuxime !

Trions par chronologie


Comme cela est annonc dans le titre, cette fonction va nous permettre de trier le
tableau en fonction de lanne de sortie des livres. Pour faire cela, nous allons devoir
crer un nouveau tableau que nous allons remplir au fur et mesure. Nous prendrons
donc chaque livre du premier tableau, puis nous chercherons o linsrer dans le second.
Pour raliser ceci, nous devrons utiliser deux boucles, une pour chaque tableau. Cette
fonction est plus complexe que la prcdente :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

function tri ( monTableau : Array ) : Array


{
var nouveauTableau : Array = new Array () ;
nouveauTableau [ 0 ] = monTableau [ 0 ];
for ( var i : int = 1 ; i < monTableau . length ; i ++)
{
var j : int = 0 ;
var continuer : Boolean = true ;
while ( continuer )
{
if ( j >= nouveauTableau . length || monTableau [ i ][ 2 ]
<= nouveauTableau [ j ][ 2 ])
continuer = false ;
j ++;
}
nouveauTableau . splice (j -1 , 0 , monTableau [ i ]) ;
}
return nouveauTableau
}
livres = tri ( livres ) ;
trace ( livres [ 0 ]) ; // Affiche : R digez des documents de qualit
avec LaTeX , No l - Arnaud Maguis , 2010
trace ( livres [ 1 ]) ; // Affiche : Apprenez programmer en Java ,
Cyrille Herby , 2011
trace ( livres [ 2 ]) ; // Affiche : R alisez votre site web avec
HTML5 et CSS3 , Mathieu Nebra , 2011
trace ( livres [ 3 ]) ; // Affiche : D butez dans la 3D avec Blender ,
Antoine Veyrat , 2012

Prenez le temps de bien assimiler ces deux exemples qui reprennent la quasi-totalit
des concepts de la premire partie.
104

PARCOURIR UN TABLEAU

Parcourir un tableau
Il existe plusieurs manires de parcourir un tableau, que ce soit un Array ou un
Vector. Il faut savoir que certaines sont plus rapides que dautres, il faut savoir choisir
laquelle utiliser en fonction des possibilits. Nous utiliserons chaque fois la boucle
for que nous avons dj vue prcdemment, nanmoins lActionscript en propose
quelques variantes encore plus efficaces.

La boucle for classique


Comme nous lavons vu, la boucle for est particulirement bien adapte au parcours
dun tableau. Pour rappel, voici un exemple de manipulation de ce type de boucle :
1
2
3
4
5

var monTableau : Array = [ " l ment n 1 " , " l ment n 2 " , " l ment
n 3 " , " l ment n 4 " ];
for ( var i : int = 0 ; i < monTableau . length ; i ++)
{
trace ( monTableau [ i ]) ;
}

Ce qui affichera :
l ment
l ment
l ment
l ment

n1
n2
n3
n4

Dans une boucle for classique, nous nous basons donc sur lindice, ou la position,
des diffrents lments lintrieur du tableau. Pour cela, nous avons alors besoin de
connatre la longueur de celui-ci, que nous pouvons dailleurs stocker dans une variable :
1
2
3
4
5
6

var monTableau : Array = [ " l ment n 1 " , " l ment n 2 " , " l ment
n 3 " , " l ment n 4 " ];
var longueur : int = monTableau . length ;
for ( var i : int = 0 ; i < longueur ; i ++)
{
trace ( monTableau [ i ]) ;
}

Cependant, il est galement possible dutiliser dautres boucles o la connaissance de


la longueur dun tableau devient superflue ; jai nomm les boucles for...in et for
each !

La boucle for...in
La boucle for...in est trs proche de la boucle for classique, et sutilise quasiment de
la mme manire. Toutefois, il nest pas ncessaire de connatre le nombre dlments
105

CHAPITRE 7. LES TABLEAUX


contenus dans un tableau pour parcourir lintgralit de ce dernier. Voici un exemple
dutilisation de cette boucle :
1
2
3
4
5

var monTableau : Array = [ " l ment n 1 " , " l ment n 2 " , " l ment
n 3 " , " l ment n 4 " ];
for ( var i : String in monTableau )
{
trace ( monTableau [ i ]) ;
}

Ce qui nous affichera comme prcdemment :


l ment
l ment
l ment
l ment

n1
n2
n3
n4

Ainsi, vous pouvez considrer que dans une boucle for...in la variable se comporte
comme un indice qui sincrmente automatiquement et qui parcourt lintgralit du
tableau.
Il est fort probable que certains dentre vous se demandent alors, pourquoi
diable la variable i est-elle de type String et non de type int ?
Pour comprendre cela, nous allons devoir brivement sortir du cadre de ce chapitre.
En ralit, la boucle for...in nest pas propre aux tableaux, mais peut tre utilise
pour parcourir dautres types dlments ou objets. Pour mieux cerner le problme,
nous allons imaginer lobjet ou la variable suivante :
1

var monObjet : Object = { a : " l ment A " , b : " l ment B " , c : " l ment
C " };

Nous avons donc ici une sorte de tableau contenant trois lments. Nanmoins, ces
lments ne sont pas rangs laide dun indice, mais plutt grce une tiquette ou
proprit et ne sont donc pas disposs suivant un ordre particulier. La seule manire
de faire rfrence un lment lintrieur de cette variable est donc dutiliser les
tiquettes associes chacun de ces lments.
Lutilisation de la boucle for...in prend alors tout son sens :
1
2
3
4

for ( var i : String in monObjet )


{
trace ( i + " : " + monObjet [ i ]) ;
}

Voici le rsultat :
a : l ment A
b : l ment B
c : l ment C

106

PARCOURIR UN TABLEAU
Pour utiliser correctement la boucle for...in, vous devez vous rappeler qu
lintrieur de celle-ci nous travaillons non pas laide dun indice numrique
mais bien avec une tiquette sous forme de chane de caractres. Dans
le cas dun tableau de type Array ou Vector, la variable utilise reprsente
nanmoins lindice, mais toujours sous la forme dune chane de caractres de
type String !

La boucle for each


La dernire boucle permettant de parcourir un tableau est la boucle for each. Contrairement ses congnres, la variable utilise lintrieur de celle-ci ne fait pas rfrence
lindice, ou ltiquette, associ aux lments dun tableau, mais aux lments euxmmes.
La manipulation des lments devient alors beaucoup plus simple :
1
2
3
4
5

var monTableau : Array = [ 12 , 42 , 10 , 3 ];


for each ( var nombre : int in monTableau )
{
trace ( nombre ) ;
}

Comme vous limaginez, dans ce cas, le type de la variable devra sadapter suivant la
nature des lments contenus lintrieur du tableau :
1
2
3
4
5

var monTableau : Array = [ 2 .3 , 24567673 , 42 , 3 . 14 , 276 . 54 ];


for each ( var nombre : Number in monTableau )
{
trace ( nombre ) ;
}

Ou encore :
1
2
3
4
5

var monTableau : Array = [ ' Hello ' , ' world ' , '! ' ];
for each ( var chaine : String in monTableau )
{
trace ( chaine ) ;
}

Notez toutefois quen utilisant cette boucle vous perdez la notion de reprage
lintrieur du tableau et vous ntes alors plus en mesure de relier llment
au tableau.
Bien videmment, ce qui est faisable avec un tableau de type Array, lest aussi avec un
autre tableau de type Vector :
1
2

var monVecteur : Vector . < String > = Vector . < String >([ ' Hello ' , '
world ' , '! ' ]) ;
for each ( var chaine : String in monVecteur )

107

CHAPITRE 7. LES TABLEAUX


3

4
5

trace ( chaine ) ;

En rsum
Grce aux tableaux, nous pouvons stocker plusieurs valeurs sous un mme nom de
variable.
Les lments dun tableau sont accessibles via un indice qui dmarre 0.
Les tableaux de type Array ne sont ni fixs, ni typs.
Les tableaux de type Vector ne sont pas fixs, mais en revanche ils sont typs.
Diffrentes mthodes permettent de manipuler des tableaux la fois de Array et de
type Vector.
On utilise gnralement les boucles for, for...in ou for each pour parcourir un
tableau.
Il est possible de crer des tableaux multidimensionnels en utilisant une notation
double indice.

108

Deuxime partie

La Programmation Oriente
Objet

109

Chapitre

La POO dans tous ses tats


Difficult :
Nous allons maintenant attaquer la deuxime partie du cours, traitant dune notion trs importante en Actionscript 3 : la Programmation Oriente Objet (ou POO). Apprhender
cette notion sera peut-tre difficile au dbut, mais vous finirez par tomber sous le charme
de cette faon de programmer, je vous le promets !
Cette partie sera galement loccasion de faire (enfin !) un peu de pratique loccasion de
quelques exercices que nous raliserons ensemble.
Attachez vos ceintures, cest parti ! La POO naura bientt plus aucun secret pour vous !

111

CHAPITRE 8. LA POO DANS TOUS SES TATS

Les notions-cls
Il tait une fois. . . un objet
Vous avez srement une ide de ce quest un objet : dans la vie de tous les jours, nous
en voyons, nous en touchons des centaines. Ils ont chacun une forme et remplissent
une ou plusieurs tches. On distingue rapidement plusieurs catgories dobjets qui
se ressemblent : quand vous mettez la table, vous manipulez des objets (fourchettes,
couteaux, cuillres, . . .) appartenant la catgorie couvert . Bien sr, vous pouvez
avoir plusieurs objets de cette catgorie, voire plusieurs fourchettes identiques. Les
objets de la catgorie fourchette font galement partie de la catgorie couvert
car les fourchettes ne sont en fait que des couverts particuliers.
La programmation oriente objet part de ces diffrentes observations pour introduire de nouveaux concepts en programmation afin de rendre le dveloppement de
logiciels plus efficace et intuitif.
Lautre faon de programmer est appele le procdural o il ny a grossomodo que des variables, des fonctions et des instructions effectues les
unes la suite des autres. La POO est diffrente par bien des aspects.

LObjet
Prenons une de vos fourchettes, comme la figure 8.1.

Figure 8.1 Une fourchette (image de ArnoldReinhold, tire du site Wikimedia Commons)
Il sagit dun objet ayant une forme particulire et une certaine utilit, caractristiques
que lon peut retrouver dans les autres fourchettes. Un objet en programmation
112

LES NOTIONS-CLS
est galement une entit possdant des proprits que lon peut retrouver sur dautres
objets de la mme catgorie. Il ne sagit ni dune variable, ni dune fonction, mais
dun mlange des deux : cest un nouveau concept part entire. Un objet peut donc
contenir plusieurs variables (appeles attributs) et plusieurs fonctions (appeles mthodes). Ces variables et fonctions (appeles proprits) sont profondment lies
lobjet qui les contient : les attributs stockent des informations sur cet objet. Par
exemple, si mon objet fourchette possde un attribut poids , cet attribut reprsente la masse de cette fourchette et non la masse dune autre fourchette pose
ct.

La Classe
Seulement, vous avez sur votre table non pas une mais dix fourchettes, quoique pas
exactement identiques. En effet, cette fourchette ci et plus lgre que cette fourchette l,
donc son attribut poids est plus faible. Mais ces deux objets restent des fourchettes,
malgr leur diffrence de poids. Fourchette est donc la catgorie de ces objets, appele
classe.
On dit que les objets dune classe sont des instances (ou occurrences) de
cette classe.
Une classe dcrit la nature de ses objets : cest un schma permettant de fabriquer et
de manipuler plusieurs objets possdant les mmes attributs et mthodes. Par exemple,
la classe Fourchette pourrait dcrire les attributs poids , taille , nombre de
dents , etc. (voir figure 8.2)
Nous pourrions aussi crer une classe Couteau pour les couteaux, et une classe Cuillre
pour les cuillres.
En Actionscript 3, les classes sont considres comme des types, au mme
titre que les int, Number ou String.

Un autre exemple
Une fois la table mise, vous tournez la tte et admirez travers la fentre votre magnifique voiture toute neuve (figure 8.3) : ne serait-ce pas un objet de la classe Voiture ?
Avec un objet aussi complexe, cette classe contient certainement plus dattributs et
de mthodes que la classe Fourchette. . .
Voici quelques exemples dattributs : taille (un grand classique), marque , couleur , nombre de pneus , nombre de siges ; et quelques exemples de mthodes :
verrouiller les portires , dmarrer le moteur , acclrer , freiner , tourner
gauche , tourner droite . . . (voir figure 8.4)
113

CHAPITRE 8. LA POO DANS TOUS SES TATS

Figure 8.2 La classe Fourchette et quelques instances

Figure 8.3 Votre magnifique voiture

114

LES NOTIONS-CLS

Figure 8.4 La classe Voiture et une instance


Vous apercevez un peu plus loin la voiture de votre voisin gare en face (figure 8.5).
Cest galement un objet de la classe Voiture, avec une marque, une couleur, un
nombre de pneus et de siges, la possibilit dacclrer, de freiner, de tourner gauche
ou droite. . . Seulement, elle na ni la mme marque, ni la mme couleur que la vtre.
Ces deux objets sont des instances de la classe Voiture.

Figure 8.5 La voiture de mon voisin est une autre instance

Lencapsulation
Vous vous souvenez avoir ouvert le capot de votre voiture aprs lavoir gar : vous avez
intensment regard ce quil y a lintrieur (figure 8.6). Malgr votre immense effort
de concentration, le fonctionnement du moteur, de tous ces cbles, circuits lectriques
et autres tuyaux vous chappe encore. . .
Fort heureusement, lorsque vous refermez le capot et montez dans votre voiture, vous
115

CHAPITRE 8. LA POO DANS TOUS SES TATS

Figure 8.6 Sous le capot. . .


oubliez toute cette mcanique trop complique, et vous conduisez laide dun volant,
de pdales et dun levier de bote de vitesse (figure 8.7). Grce eux, vous pouvez
utiliser votre voiture sans tre ingnieur en gnie mcanique ou lectronique !

Figure 8.7 Votre volant vous facilite bien la tche. . .


Imaginez maintenant que vous criviez une classe trs complexe, qui permet de faire
plein de choses incroyables (figure 8.8) ! Malheureusement, personne ne voudra de votre
magnifique classe : qui serait assez fou pour se plonger dans votre code et tentez de le
dchiffrer ?
En effet, votre code est un peu comme le bazar qui se trouve sous le capot de votre voiture. Mais vous tes malins et vous fournissez aux autres dveloppeurs des mthodes
116

LES NOTIONS-CLS

Figure 8.8 Ce quoi votre code pourrait ressembler. . .


trs simples et faciles comprendre, tout en cachant littralement sous le capot ce
quelles font, linstar du volant, des pdales et du frein main. Ainsi, les programmeurs qui utiliseront votre classe (y compris vous-mmes) auront un volant disposition
au lieu dun moteur et vingt-et-un tuyaux. On appelle ce principe lencapsulation.

Lhritage
Puis, votre regard se porte sur lautoroute au loin (figure 8.9) : vous distinguez dautres
voitures. Mais des formes diffrentes se dplacent parmi elles : ce ne sont de toute
vidence pas des voitures, mais plutt des camions et des motos. Vous remarquez que
ces objets comportent eux aussi des roues ; ils ont eux aussi une couleur et une marque ;
ils peuvent eux aussi acclrer, freiner, tourner gauche, tourner droite. . . Ce seraient
presque des objets de la classe Voiture.

Figure 8.9 Une autoroute belge (image de Purka, tire du site Wikimedia Commons)
117

CHAPITRE 8. LA POO DANS TOUS SES TATS


Mince alors ! Il va falloir refaire de nouvelles classes quasiment identiques. . . Pourquoi
ne pas faire une classe Vhicule plus gnraliste, qui dcrirait les attributs et mthodes
communs aux classes Voiture, Camion et Moto ? Cest une excellente ide !
Notre nouvelle classe Vhicule dcrit donc les attributs et les mthodes communs
tous les vhicules routiers, comme le nombre de roues et de siges, la marque, la couleur,
les mthodes acclrer , freiner , tourner gauche , tourner droite . . . On
lappelle la classe mre (ou superclasse), par opposition aux classes Voiture, Camion
et Moto qui sont ses classes filles (ou sous-classes). On dit galement que les classes
Voiture, Camion et Moto hritent de la classe Vhicule.
Dsormais, inutile de rcrire les attributs et mthodes de la classe Vhicule dans la
classe Voiture, car cette dernire hrite des attributs et des mthodes de la classe
Vhicule (voir figure 8.10) ! Ainsi tous nos objets de la classe Voiture sont galement
des objets de la classe Vhicule, mais leur description dans la classe Voiture est plus
prcise (par exemple, les voitures ont un coffre, alors que les camions ont une remorque).
Lun des intrts de lhritage est donc de pouvoir crer plusieurs classes diffrentes
drivant dune classe-mre sans avoir recopier les attributs et les mthodes communes dans chaque classe. Cest aussi une faon de penser et concevoir le programme
de manire logique et cohrente.
Si nous revenions sur le premier exemple, la classe Fourchette, ainsi que les classes
Couteau et Cuillre, sont des sous-classes de la classe Couvert !

Manipuler des objets : les chanes de caractres


Lhorrible secret du type String
Vous souvenez-vous des chanes de caractres que nous avons vues dans la premire
partie ?
1

var coucou : String = " Hello world ! " ;

Regardez bien le type de la variable : String. . . Il cache un terrible secret : il sagit en


ralit dune classe ! Et oui ! En crivant la ligne au-dessus, nous avons sans le savoir,
cr une instance de la classe String. Et nous avons galement utilis des proprits
de cette classe !

Crer un objet
Tout dabord, il nous faut apprendre crer des objets. Il y a une syntaxe particulire
respecter :
1

new String () ; // Je cr un objet de la classe String ( je l ' ai


d ' ailleurs cr dans le vide , cette instruction ne servira
rien : D )

118

MANIPULER DES OBJETS : LES CHANES DE CARACTRES

Figure 8.10 Les trois classes sont des sous-classes de la classe Vhicule

119

CHAPITRE 8. LA POO DANS TOUS SES TATS


Comme vous pouvez le voir, nous utilisons le mot-cl new, suivi du nom de la classe
de lobjet que nous voulons crer, et dventuels paramtres entre parenthses (comme
pour les fonctions). Par exemple, si nous voulions crer un objet de la classe String
contenant la chane "Hello world!", nous procderions ainsi :
1

var coucou : String = new String ( " Hello world ! " ) ; // Je cr un


objet String contenant la cha ne " Hello world !"

Mais, avant nous navions pas besoin de new pour faire a !

Effectivement, la classe String possde une particularit : cest un type de donnes.


Cela signifie que les objets de cette classe sont un peu spciaux : ils peuvent agir en
tant que simple donne (nombre, chane de caractres, etc.). Ainsi, nous pouvons nous
passer de la syntaxe de cration dun objet :
1

var coucou : String = " Hello world ! " ;

revient crire :
1

var coucou : String = new String ( " Hello world ! " ) ;

Quen est-il de int, uint et Number ?

Et bien, figurez-vous que ce sont galement des classes, qui fonctionnent de la mme
manire que la classe String !
Il est impossible dutiliser le mot-cl new pour crer des objets des classes int
et uint ! Cest la raison pour laquelle elles commencent par une minuscule,
cela permet de bien marquer la diffrence avec les autres classes.
En effet, ces deux classes sont encore plus spciales et nutilisent quune seule syntaxe :
celle que vous avez apprise dans la premire partie du cours. Par contre, la classe
Number fonctionne tout fait normalement, comme la classe String :
1
2

var entier : int = new int ( - 47 ) ; // INTERDIT ! ! !


var entier2 : int = - 42 ; // Autoris

3
4
5

var entierNonSigne : uint = new uint ( 47 ) ; // NOOON ! Tout sauf a


!
var entierNonSigne2 : uint = 47 ; // Ouf !

6
7
8

var nombre : Number = new Number ( 3 . 1415 ) ; // Pas de probl me


var nombre2 : Number = 3 . 1415 ; // Pour les flemmards

120

DES POINTEURS SOUS LE CAPOT


10
11

var monNom : String = new String ( " Bryan " ) ; // Je sens que je
connais cette phrase ...
var ouSuisJe : String = " In the kitchen ! " ; // Argh !

Accder aux proprits dun objet


Reprenons un peu plus de code que nous avons crit dans la premire partie :
1
2
3

var coucou : String = new String ( " Hello world ! " ) ;


trace ( " Cette cha ne contient " + coucou . length + " caract res . "
);
// Affiche : Cette cha ne contient 13 caract res .

et observons plus particulirement cette expression : coucou.length.

Nous avons utilis la proprit length de la classe <minicode type="actionscript"String</minicode>


qui renvoie la longueur de la chane ! Dcortiquons cette instruction :
Tout dabord, nous renseignons le nom de la variable contenant notre objet. Ici, il
sagit de coucou, variable que nous avons dclar plus haut avec cette ligne : var
coucou:String = "Hello world !"..
Ensuite, nous utilisons le caractre point . pour signaler que nous allons utiliser
un attribut ou une mthode de cet objet-l.
Enfin, nous spcifions quelle proprit nous voulons utiliser : ici, nous tapons donc
length, la proprit de la classe String qui nous intresse.
Nous obtenons ainsi la longueur de lobjet chane de caractres contenu dans la
variable coucou ! En franais, cela donnerait quelque chose comme : Lis la proprit
longueur de lobjet contenu dans ma variable coucou.

Des pointeurs sous le capot


Plantons le dcor
Prenons notre classe Voiture, et supposons quelle ait une proprit marque de type
String qui contient le nom de la marque des voitures.
Crons un objet de la classe Voiture et spcifions sa marque :
1
2

var lienVoiture : Voiture = new Voiture () ; // Je cr ma voiture


...
lienVoiture . marque = " Peugeot " ; // ... de marque Peugeot .

Dclarons une deuxime variable :


1

var lienVoiture2 : Voiture ; // Je d clare une autre variable

121

CHAPITRE 8. LA POO DANS TOUS SES TATS

La variable nest pas initialise, elle contient donc null.

Ensuite, procdons une affectation :


lienVoiture2 = lienVoiture ; // C ' est bien une affectation ...
Mais que fait - elle r ellement ?

Nous allons regarder de quelle marque sont les voitures (vous avez srement devin) :
trace ( lienVoiture . marque ; // Affiche : Peugeot
trace ( lienVoiture2 . marque ) ; // Affiche : Peugeot

1
2

Bien ! Maintenant, modifions la marque de lienVoiture2 :


1
2
3

lienVoiture2 . marque = " Renault " ;


// Nous pourrions galement faire :
lienVoiture2 . marque = new String ( " Renault " ) ;

Enfin, regardons nouveau la marque des voitures :


1
2

trace ( lienVoiture . marque ) ; // Affiche : Renault


trace ( lienVoiture2 . marque ) ; // Affiche : Renault

Horreur ! Les deux ont la mme marque ! La rponse est simple : il sagit du mme
objet ! Et oui, il ny en a quun seul et unique !

Explications
Lorsque nous crons lobjet de classe Voiture, il est stock dans la mmoire vive de
votre systme. Ensuite, quand nous laffectons une variable, un lien vers cet objet est
cr, puis stock dans la variable. On dit alors que les variables sont des pointeurs :
elles pointent du doigt lobjet qui leur est associ, afin que nous, programmeurs, puissions accder cet objet. Dailleurs, vous aurez peut-tre remarqu le nom prcis que
jai donn mes variables : lienVoiture et lienVoiture2 ; nest-ce pas vocateur ?
(voir figure 8.11 )
Bien videmment, jai nomm les variables ainsi dans un but pdagogique :
vitez dappeler vos variables de cette faon, cela ne servirait rien (et tous
vos collgues vous dvisageraient dun air bizarre).
Donc, lorsque nous crivons notre affectation, nous nous contentons en ralit de recopier le pointeur vers lobjet initialement cr :
1

lienVoiture2 = lienVoiture ; // Recopions le pointeur de


lienVoiture dans lienVoiture2

Ainsi, en utilisant les proprits de lobjet de lienVoiture2, nous utilisons galement


celles de lobjet de lienVoiture. Logique : il sagit du mme objet !
122

DES POINTEURS SOUS LE CAPOT

Figure 8.11 Les variables-pointeurs sont toutes les deux lies lobjet.

Et si nous crions un autre objet de classe Voiture ?

Trs bonne ide ! Crons un nouvel objet et affectons-le la variable lienVoiture2 :


1

lienVoiture2 = new Voiture () ; // Un deuxi me objet Voiture


entre en sc ne !

Modifions sa marque :
1

lienVoiture2 . marque = " Citro n " ;

Et regardons la marque des deux voitures :


1
2

trace ( lienVoiture . marque ) ; // Affiche : Renault


trace ( lienVoiture2 . marque ) ; // Affiche : Citro n

Ouf ! Quel soulagement ! Nous avons bien deux objets distincts de la classe Voiture !

En rsum
Les objets contiennent des proprits : les variables sont appeles attributs et les
fonctions mthodes.
Chaque objet est dcrit par une classe : il sagit dune sorte de plan de construction
des objets. On dit que les objets sont des instances (ou occurrences) de leur classe.
Lencapsulation est un principe important en POO qui consiste cacher le fonctionnement interne des classes, et montrer seulement une interface simplifie.
Lhritage est un autre principe, tout aussi important, consistant faire hriter des
classes (dites classes filles) dune classe mre.
En Actionscript 3, tout est objet : tout ce que vous manipulerez, ce sera des objets.
Le mot-cl new permet de crer des objets.
La plupart des variables sont en ralit des pointeurs (ou liens) vers des objets
stocks en mmoire.

123

CHAPITRE 8. LA POO DANS TOUS SES TATS

124

Chapitre

Les classes (1re partie)


Difficult :
Dans le chapitre prcdent, nous avons introduit la notion de classe et nous avons mme
appris utiliser la classe String. Cest dj un bon dbut dans la dcouverte de la Programmation Oriente Objet, mais ce nest pas suffisant. partir de maintenant, nous
allons apprendre crer nos propres classes. En utilisant le concept dobjets ou de classes,
la Programmation Oriente Objet permet dorganiser le code vraiment diffremment de
la programmation procdurale.
tant donn quil y a beaucoup de choses dire sur le sujet, la thorie sur les classes
stalera sur deux chapitres. Ce chapitre portera sur les principes fondamentaux, nous le
complterons avec quelques notions supplmentaires dans le prochain chapitre.

125

CHAPITRE 9. LES CLASSES (1RE PARTIE)

Crer une classe


La Classe
Rappels
Comme nous lavons dj mentionn, une classe est lensemble du code permettant de
reprsenter un objet dans un programme. Celle-ci est constitue de variables appeles
attributs et de fonctions appeles mthodes. On parle galement de proprits
pour dfinir lensemble des attributs et des mthodes dune classe. Ainsi, grce
ces proprits, nous allons pouvoir structurer notre objet et dfinir lintgralit de ses
caractristiques.
Une fois que la classe est dfinie, nous pouvons alors crer des instances ou occurrences de cette classe. Pour vous faire une ide, on peut considrer une instance
comme un objet physique , en opposition la classe qui dfinit plutt une description gnrale de lobjet. Ainsi, nous pouvons crer plusieurs instances dun mme objet,
mais dont les caractristiques pourront varier lgrement.
Il est important de bien faire la diffrence entre la classe, qui est unique et
qui dcrit un certain objet, et ses instances qui peuvent tre multiples et
qui sont les objets rels . Ceux-ci peuvent tre dcrits partir des mmes
proprits dont les valeurs peuvent varier.
Pour rassurer tout le monde, nous allons prendre un petit exemple concret :
Une classe Voiture permet de dfinir lensemble du parc automobile europen. Cette
classe Voiture dfinit lensemble des caractristiques que peut possder une automobile. Il serait par exemple possible dy retrouver la marque de celle-ci, mais galement
sa couleur ou encore son immatriculation que nous pourrions dfinir comme attributs.
Maintenant nous savons ce quest une Voiture, nous aurions peut-tre lenvie den
crer quelques-unes. Cest une trs bonne ide, et nous allons commencer par crer
une Renault de couleur grise et immatricule dans le Rhne . Voil maintenant que nous en avons besoin dune seconde ; trs bien, voici une Peugeot de
couleur noire et immatricule dans le Cantal .
Dans cet exemple, nous avons donc utilis une classe Voiture pour en crer deux
instances qui sont la Renault et la Peugeot.
Structure
Si vous avez bien suivi le deuxime chapitre de la premire partie, vous devriez vous
rappeler dun schma reprsentant la structure de la classe principale. Je vous propose de gnraliser ce schma et de le complter un peu plus avec ce que nous venons de
dcouvrir. Nous pouvons y ajouter notamment les attributs et les mthodes. Vous
verrez la figure 9.1 comment sont structures les classes.
126

CRER UNE CLASSE

Figure 9.1 Schma gnral de la structure dune classe.


Vous ne devriez donc pas tre surpris de la manire dont nous dfinissons une classe
lintrieur du code :
1
2

package
{

public class NomDeLaClasse


{
// Attributs

4
5
6
7

// M thodes

8
9

10
11
12

Nous allons prsent apprendre dfinir chacune des proprits de la classe !

Construire la classe
Package
Avant toute chose, nous allons brivement reparler de la notion de package. Nous
lavions dfini comme dcrivant la position de la classe dans larborescence des fichiers
de votre projet. Rassurez-vous, cest toujours le cas ! Cependant, je voudrais prsenter
ici la manire adopter pour positionner ses propres classes dans diffrents dossiers.
Pour linstant, il est vrai que nous ne disposons pas dun projet consquent
et que le nombre de classes est assez faible. Cependant, lorsque nos projets
grandiront et que les classes vont se multiplier, nous devrons faire le tri et
ranger nos classes dans diffrents dossiers afin dy voir plus clair.
Voici donc un conseil quil serait prudent de suivre : organisez vos classes en fonction
de leur nature et de leur utilit !
Par exemple, nous pourrions imaginer un package nomm vehicules qui contiendrait les classes Voiture, Camion et Moto. Puis nous crons deux nouvelles classes
127

CHAPITRE 9. LES CLASSES (1RE PARTIE)


Fourchette et Couteau, qui nont apparemment strictement rien faire dans le package
vehicules. Il nous faut alors en insrer un nouveau que nous pourrions nommer
couverts.
Attributs
Nous allons maintenant prsenter le premier type de proprits dune classe : il sagit
des attributs ! Les attributs ont en ralit des variables, nous pouvons donc les
dclarer comme nimporte quelle variable :
1

var _unAttribut : String ;

Lorsquon programme en POO, on a lhabitude de ne pas initialiser les variables lors


de la dclaration, mais plutt lintrieur dun constructeur que nous dtaillerons
un peu aprs dans ce cours.
Nous introduisons galement le mot-cl private devant la dclaration de lattribut,
dont nous reparlerons aussi plus tard :
private var _unAttribut : String ;

a y est, nous avons notre premier attribut !


Par convention, en Actionscript 3, nous ajouterons un caractre underscore
_ devant le nom de tous nos attributs. Cela nous sera pratique lorsque
nous crirons des accesseurs et mutateurs.

Mthodes
Comme nous lavons prcis plus haut, les mthodes sont des fonctions. Il peut donc
sagir aussi bien dinstructions de fonction que dexpressions de fonction (pour
ceux qui auraient tout oubli, allez faire discrtement un tour dans le chapitre sur les
fonctions !). Nanmoins, je vous avais dit que les instructions de fonction taient
prfrables, nous utiliserons donc ce type de fonctions :
1
2
3
4

function uneM thode () : void


{
// Instructions
}

Bien entendu, lintrieur de ces mthodes nous avons accs aux diffrents attributs
afin de pouvoir modifier leur valeur ou simplement lire leur contenu. Au final, seuls les
attributs peuvent mmoriser des choses et ainsi se souvenir de ltat de lobjet en
question. Cest la raison pour laquelle, en gnral, vos mthodes serviront lire ou
modifier le contenu dun ou plusieurs attributs.
Voil comment notre mthode pourrait modifier un attribut :
1

128

function uneM thode ( nouvelleValeur : String ) : void

CRER UNE CLASSE


2

3
4

unAttribut = nouvelleValeur ;

Bien sr, nous pouvons faire toutes sortes de manipulations lintrieur dune mthode
et pas simplement affecter ou lire le contenu dun attribut.
Contrairement dautres langages, lActionscript ne prend pas en compte la
surcharge de mthodes. Pour ceux qui dcouvrent ce terme, ne vous inquitez
pas, nous en reparlerons avant la fin de ce chapitre.
Enfin, les mthodes prennent galement un mot-cl devant leur dclaration, qui est
cette fois-ci public :
1
2
3
4

public function uneM thode () : void


{
// Instructions
}

Les mots-cls private et public sont lis la notion dencapsulation que


nous dcouvrirons plus en profondeur au cours du chapitre. En attendant,
sachez que ces mots-cls existent et considrez quils font partie de la dclaration des proprits dune classe.

Constructeur
prsent, il est temps dintroduire une mthode un peu particulire : le constructeur !
Le constructeur est la mthode appele par dfaut lors de linitialisation dun objet,
vous savez lorsque vous utilisez le mot-cl new. Vous noterez que cette mthode possde
obligatoirement le mme nom que celui de la classe. Par exemple, pour notre classe
nomme Voiture, notre constructeur pourrait ressembler ceci :
1
2
3
4

public function Voiture ()


{
// Instructions
}

Le constructeur dune classe sert principalement initialiser lensemble des attributs dclars dans celle-ci.
Vous remarquerez que le constructeur ne peut pas renvoyer de valeur, aussi
vitez dinsrer le mot-cl return lintrieur de celui-ci. Une instruction de
renvoi serait ignore lexcution, et pourrait entraner des messages derreur
lors de la compilation.
Ne vous inquitez pas si certains points sont encore flous dans votre esprit, nous allons
crer ensemble une classe pas pas la fin du chapitre !
129

CHAPITRE 9. LES CLASSES (1RE PARTIE)

Des paramtres facultatifs pour nos mthodes


La surcharge de mthodes
Dans beaucoup de langages utilisant la Programmation Oriente Objet, on retrouve le concept de surcharge de mthodes, mais ce nest pas le cas en ActionScript 3. Contrairement son nom abominable, ce concept est relativement simple et
consiste a dfinir plusieurs mthodes portant le mme nom. Il est alors possible de
dfinir des paramtres de types diffrents ou encore dutiliser un nombre de paramtres
diffrent. Ceci est trs utile et permet, par exemple, de dfinir plusieurs constructeurs
nayant pas le mme nombre de paramtres :
1
2

package
{

public class MaClasse


{
// Attribut
private var _unAttribut : int ;

4
5
6
7
8

// Constructeurs
public function MaClasse ()
{
_unAttribut = 0 ;
}

9
10
11
12
13
14

public function MaClasse ( entier : int )


{
_unAttribut = entier ;
}

15
16
17
18
19

20
21
22

Dans lexemple prcdent, il serait possible dinstancier une classe sans renseigner de
paramtres avec le premier constructeur, ou en prcisant la valeur de lentier avec le
second. Cette technique servirait donc rendre lutilisation dune classe plus simple
et plus souple, en permettant lappel dune mme fonction avec des paramtres
diffrents.
Malheureusement donc, la surcharge de mthodes est strictement interdite en Actionscript, vous ne trouverez donc jamais deux mthodes ayant le mme nom au sein
dune classe, et ceci est aussi valable pour les constructeurs. En revanche, il est possible
de contourner le problme, voire mme de le simplifier : cest le rle des paramtres
facultatifs !
130

DES PARAMTRES FACULTATIFS POUR NOS MTHODES

Les paramtres facultatifs


Dfinition
En Actionscript, il existe un concept qui permet dobtenir une utilisation similaire
une surcharge de mthodes. Il sagit des paramtres facultatifs ! Cette nouvelle
notion est associe en ralit la dfinition de fonctions et nest donc pas limite aux
seules mthodes. Ainsi, pour insrer un paramtre facultatif, il suffit de lui prciser
une valeur par dfaut dans lors de la dfinition de la fonction, comme ceci :
1
2
3
4

function maFonction ( entier : int , texte : String = " Valeur par d


faut " , nombre : Number = 0 ) : void
{
trace ( nombre , texte ) ;
}

En utilisant ici des valeurs par dfaut pour les deux derniers paramtres, il alors possible
de les omettre lors de lappel de la fonction. Ainsi, contrairement la surcharge
de mthode, nous navons pas besoin, en Actionscript, de rcrire lintgralit du
contenu de la fonction pour chaque dfinition de nouveaux paramtres.
Attention cependant lordre de dfinition des paramtres. Les paramtres
facultatifs doivent obligatoirement tre placs la fin de la liste des paramtres. Ils doivent galement tre crits dans un ordre dutilisation prcis que
nous allons prciser en parlant des appels de ces fonctions.

Appels
Comme leur nom lindique, les paramtres facultatifs peuvent tre omis lors de
lappel de la fonction. Ainsi, la fonction dfinie prcdemment, peut tre appele en
renseignant uniquement le premier paramtre :
1

maFonction ( 10 ) ;

Il est galement possible de renseigner les deux premiers paramtres, sans le troisime :
1

maFonction ( 10 , " Nouveau texte " ) ;

Attention toutefois lordre de dfinition des paramtres facultatifs. En


effet, sil est possible de renseigner le premier paramtre facultatif et domettre
le second, linverse est impossible. Ainsi, lappel suivant nest pas correct :
maFonction(10, 5). Cest pourquoi, vous devez tre vigilant dans lordre
de dfinition des paramtres facultatifs de vos fonctions !
Enfin, voici dernier appel possible de votre fonction, qui comprend lintgralit des
paramtres :
1

maFonction ( 10 , " Nouveau texte " , 5 ) ;

131

CHAPITRE 9. LES CLASSES (1RE PARTIE)


Ainsi, grce la dfinition de paramtres facultatifs, nous avons trois manires
diffrentes dappeler la mme fonction !

Encapsulation
Lencapsulation que nous allons redcouvrir maintenant est lun des concepts les
plus importants de la Programmation Oriente Objet ! Vous rappelez-vous du
mot-cl private que nous avons introduit avant chacun de nos attributs ? Il permet
de masquer la proprit laquelle il est associ, celle-ci nest donc pas visible depuis
lextrieur de la classe en question. Ainsi, partir de maintenant, nous masquerons
obligatoirement lensemble de nos attributs ! Pour y accder, nous serons donc dans
lobligation de faire appel une mthode intermdiaire qui nous permettra de vrifier
les donnes et daffecter les attributs en consquence, hors du champ de vision de
lutilisateur.
Lintrt de lencapsulation est de simplifier lutilisation des objets en masquant lensemble des attributs et des mthodes qui sont utiles simplement au fonctionnement
de lobjet. Ainsi, vu de lextrieur, nous pourrons manipuler ces objets facilement, sans
nous soucier de leur fonctionnement interne.
Ce concept introduit donc la notion de droits daccs que nous allons voir tout de
suite !

Les diffrents droits daccs


Il nest pas possible de parler dencapsulation sans toucher un mot des droits daccs
ou portes. Ces droits daccs dfinissent la visibilit dune proprit au sein de votre
code. En Actionscript, il existe trois portes qui sont public, private et internal.
Ces mots-cls se placent juste avant la dclaration des proprits auxquelles ils
sont associs.
En ralit, il existe une quatrime porte nomme protected. Cependant,
celle-ci est profondment lie la notion dhritage dont nous reparlons dans
le chapitre qui lui est consacr.

Privs
Les droits daccs dits privs sutilisent avec le mot-cl private. Ils permettent
de restreindre lutilisation de la proprit la classe o elle est dfinie. Ainsi, cette
proprit ne sera pas visible depuis lextrieur de cette classe. Voici un attribut dont
la porte est de type private :
1

132

private var _monAttribut : String ;

ENCAPSULATION
Je rappelle que tous nos attributs doivent tre invisibles depuis lextrieur de
la classe o ils sont dfinis, utilisez donc la porte private.

Publiques
Les droits daccs publics sont associs au mot-cl public, que nous avons dj
crois plusieurs fois. Celui-ci permet de rendre visible partout dans le code la proprit
laquelle il est associ. Ce sera donc le cas pour la majorit de vos mthodes. Dailleurs,
il est impossible daffecter une autre porte que public un constructeur :
1
2
3
4

public function MonConstructeur () : void


{
...
}

Internes
Les droits daccs internes sont un peu spciaux. Ils sont associs au motcl internal. Les proprits dfinies avec ce type de portes sont visibles depuis
lensemble du package, dont la classe o elle est dclare appartient.
1

internal var _monAttribut : int ;

Cette porte nest pas trs utilise en gnral, mais sachez quil sagit de la
porte par dfaut lorsquaucune autre nest spcifie.

Les accesseurs
Syntaxe
Il existe un type de mthodes un peu spcial, directement li la notion dencapsulation :
les accesseurs ! On dsigne par accesseurs lensemble des accesseurs et mutateurs,
galement appeles getters et setters. Ceux-ci permettent laccs direct un attribut
de porte private en lecture par laccesseur et en criture par le mutateur. Ainsi,
dans beaucoup de langages de programmation, on retrouve un ensemble daccesseurs
dont le nom dbute par get (de langlais to get qui signifie obtenir ) et un ensemble
de mutateurs dont le nom dbute par set (de langlais to set qui signifie dfinir ).
Pour grer lensemble des accesseurs, lActionscript a introduit deux mots-cls get
et set qui permettent notamment de donner un nom identique aux deux accesseurs.
Illustrons cela par dun exemple. Voici un attribut quelconque dont la porte est de
type private :
133

CHAPITRE 9. LES CLASSES (1RE PARTIE)


private var _texte : String ;

tant donn que cet attribut est de type private, il nest pas accessible depuis lextrieur de la classe o il a t dfini. Cependant, il est probable que nous ayons besoin de
modifier cet attribut depuis la classe principale. Si nous voulons respecter le concept
dencapsulation, nous devons donc conserver la porte de cet attribut et dfinir des
accesseurs pour y avoir accs :
1
2
3
4
5

// Accesseur
public function get texte () : String
{
return _texte ;
}

6
7
8
9
10
11

// Mutateur
public function set texte ( nouveauTexte : String ) : void
{
_texte = nouveauTexte ;
}

Comme vous le voyez, mes deux accesseurs utilisent le mme nom de fonction, ce
qui est drlement pratique. Mais lutilisation des accesseurs va plus loin que a, car
leur utilisation est un peu particulire. Ainsi, laccesseur get dune instance nomme
MonObjet sutilise sans les parenthses :
1

var maVariable : String = MonObjet . texte ;

Quant lui, le mutateur sutilise galement sans parenthses, mais avec le symbole
gal = qui est considr comme un signe daffectation :
MonObjet . texte = " Nouvelle cha ne de caract res " ;

Une telle utilisation des accesseurs est spcifique lActionscript. Cette technique permet de manipuler les accesseurs comme sil sagissait de lattribut
lui-mme. Cependant, en utilisant les getters et setters, vous respectez le
concept dencapsulation. Ainsi, les proprits cres partir daccesseurs
sont considres comme tant des attributs, et non des mthodes.

Une raison supplmentaire dutiliser les accesseurs


Lorsque vous utilisez des accesseurs, vous ntes pas obligs de vous contenter de lire
un attribut dans un getter ou de lui affecter une nouvelle valeur dans un setter :
en effet, il est tout fait possible dajouter du code supplmentaire, voire de ne pas
manipuler dattribut en particulier !
Prenons la classe suivante :
1
2

package
{

134

ENCAPSULATION
/* *
* Une classe d ' exemple
*/
public class Voiture
{
private var _largeur : int ;

3
4
5
6
7
8
9

public function Voiture ()


{

10
11
12

13
14

public function get largeur () : int


{
return _largeur ;
}

15
16
17
18
19

public function set largeur ( value : int ) : void


{
_largeur = value ;
}

20
21
22
23
24
25
26
27
28

29

public function mettreAJour () : void


{
// Mettre jour l ' affichage
}

30
31

Dans un premier temps, imaginons que dans notre classe, nous disposions dune mthode mettreAJour() qui met jour laffichage de notre objet en fonction de la valeur
de lattribut _largeur. Pour spcifier la largeur de la voiture, nous procderions ainsi :
1
2
3
4
5

var voiture : Voiture = new Voiture () ;


voiture . largeur = 100 ; // Largeur de la voiture
voiture . mettreAJour () ; // Mettons jour l ' affichage de la
voiture pour une largeur de 100
voiture . largeur = 150 ; // Changeons la largeur de la voiture
voiture . mettreAJour () ; // Mettons jour l ' affichage de la
voiture pour une largeur de 150

Grce aux accesseurs, il est possible de lappeler automatiquement ds que lon modifie
la largeur de lobjet :
1
2
3
4
5

public function set largeur ( value : int ) : void


{
_largeur = value ;
mettreAJour () ;
}

135

CHAPITRE 9. LES CLASSES (1RE PARTIE)


Ainsi, au lieu davoir appeler manuellement la mthode mettreAJour(), il suffit de
modifier la largeur :
1
2
3
4
5

var voiture : Voiture = new Voiture () ;


voiture . largeur = 100 ; // Largeur de la voiture
// L ' affichage de la voiture est automatiquement mis jour
dans l ' accesseur set largeur !
voiture . largeur = 150 ; // Changeons la largeur de la voiture
// Encore une fois , l ' affichage de la voiture est
automatiquement mis jour , il n 'y a rien d ' autre faire !

Maintenant, nous aimerions limiter les valeurs possibles de lattribut largeur ; disons
quil doit tre suprieur 100 et infrieur 200.
1
2
3
4
5
6
7
8
9
10
11
12

var voiture : Voiture = new Voiture () ;


voiture . largeur = 100 ; // Largeur de la voiture
// On v rifie que la largeur est dans les limites
if ( voiture . largeur < 100 )
{
voiture . largeur = 100 ;
}
else if ( voiture . largeur > 200 )
{
voiture . largeur = 200 ;
}
trace ( voiture . largeur ) ; // Affiche : 100

13
14
15
16
17
18
19
20
21
22
23
24

voiture . largeur = 250 ; // Changeons la largeur de la voiture


// On v rifie une fois de plus que la largeur est dans les
limites
if ( voiture . largeur < 100 )
{
voiture . largeur = 100 ;
}
else if ( voiture . largeur > 200 )
{
voiture . largeur = 200 ;
}
trace ( voiture . largeur ) ; // Affiche : 200

Vous remarquerez que cest plutt fastidieux. Bien sr, nous pourrions utiliser une
fonction, mais il vaut mieux mettre dans la classe Voiture ce qui appartient la classe
Voiture ! Encore une fois, les accesseurs nous facilitent grandement la tche, voyez
plutt :
1
2
3

public function set largeur ( value : int ) : void


{
_largeur = value ;

4
5
6

136

// _largeur doit tre comprise entre 100 et 200


if ( _largeur < 100 )

ENCAPSULATION
{

_largeur = 100 ;
}
else if ( _largeur > 200 )
{
_largeur = 200 ;
}

8
9
10
11
12
13
14
15
16

mettreAJour () ;

Le code principal serait alors crit ainsi :


1
2
3
4

var voiture : Voiture = new Voiture () ;


voiture . largeur = 100 ; // Largeur de la voiture
// Plus besoin de v rifier que la largeur est dans les limites ,
l ' accesseur le fait pour nous !
trace ( voiture . largeur ) ; // Affiche : 100

5
6
7

voiture . largeur = 250 ; // Changeons la largeur de la voiture


trace ( voiture . largeur ) ; // Affiche : 200

Avouez que cest extrmement pratique ! Je vous conseille dappliquer cette faon de
faire le plus souvent possible, cela vous rendra service.

Gnrateur de code dans Flashdevelop


Il existe un outil trs pratique disponible dans la plupart des IDE, dont Flashdevelop,
pour gnrer automatiquement des portions de codes. Nous pouvons lutiliser, entre
autres, pour gnrer les accesseurs de nos attributs ! Pour cela, il faut suivre trois
tapes : voir les figures 9.2, 9.3 et 9.4.
Il est galement possible de se passer de la deuxime tape en utilisant directement le raccourci Ctrl + Maj + 1.
Le code ainsi gnr, ressemblera ceci :
1
2
3
4

public function get texte () : String


{
return _texte ;
}

5
6
7
8
9

public function set texte ( value : String ) : void


{
_texte = value ;
}

137

CHAPITRE 9. LES CLASSES (1RE PARTIE)

Figure 9.2 1. Placer le curseur sur la ligne de lattribut dont il faut gnrer les
accesseurs

Figure 9.3 2. Slectionner loption Code Generator

138

EXERCICE : CRONS NOTRE PREMIRE CLASSE

Figure 9.4 3. Slectionner une des trois options

Exercice : Crons notre premire classe


Prsentation de la classe
Description
Afin de mieux apprivoiser toutes ces nouvelles notions, nous allons maintenant crire
notre premire classe pas pas ! Nous allons donc crer une classe Voiture, que je vous
propose de dcouvrir maintenant. Nous y intgrerons les attributs suivants, ainsi que
les accesseurs correspondants :
SaMarque : cet argument de type String permet de dfinir la marque de la voiture.
Celui-ci sera dfini dans le constructeur et il sagit du seul attribut qui ne possdera pas de mutateur. En effet, une voiture peut tre repeinte, modifie par divers
accessoires qui influeront sur sa longueur ou encore elle peut changer de plaque
dimmatriculation. En revanche, elle ne peut pas changer sa marque de fabrique.
SaCouleur : cet argument de type String reprsente la couleur de peinture de la
voiture. Celle-ci sera manipule par les deux accesseurs nomms couleur.
SaLongueur : la longueur du vhicule sera dfinie par une variable de type int. Deux
accesseurs longueur permettront de manipuler cet lment. Lors dune affectation,
nous devrons vrifier si la valeur renseigne est positive. Dans le cas contraire, nous
utiliserons la valeur -1 pour prciser que la longueur est non renseigne .
SonImmatriculation : enfin limmatriculation du vhicule sera stocke dans un attribut de type String, qui possdera deux accesseurs immatriculation.
Lanons-nous donc dans la conception de cette classe. Lisez avec attention afin de noter
les diffrentes tapes de cration dune classe.
139

CHAPITRE 9. LES CLASSES (1RE PARTIE)


UML : Unified Modeling Language
Lorsque lon programme, il est possible de reprsenter les diffrentes classes sur un
schma pour rsumer leurs proprits. Il existe diffrentes modlisations standards
dont lUnified Modeling Language ou UML. Cette reprsentation est trs souvent
associe aux langages orients objets comme lActionscript. Sans donner plus de dtails, je vous propose de dcouvrir la figure 9.5 la reprsentation correspondant
notre classe Voiture.

Figure 9.5 Reprsentation UML de la classe Voiture


Comme vous le voyez, notre classe est divise en deux parties : les attributs et les
mthodes ! Ceux-ci sont donc lists en spcifiant de quels types ils sont, ainsi que
les paramtres renseigner en ce qui concerne les mthodes. Cela permet de dresser
une sorte de plan de construction de la classe coder, mais galement son mode
demploi pour dventuels autres programmeurs. Cela permet galement de mettre en
vidence les relations liant les classes les unes aux autres, comme nous le verrons au
cours des chapitres venir. Vous aurez trs certainement remarqu les signes - et
+ qui prcdent lensemble de nos proprits. Ceux-ci permettent de reprsenter
les diffrents droits daccs lis chacune de nos proprits de la manire suivante :
- pour privs, + pour publiques, ~ pour internes et # pour protgs.
Lobjectif du cours nest pas de vous apprendre utiliser lUML, cependant,
nous utiliserons quelques schmas qui sont souvent bien plus parlants que des
mots. Vous apprendrez lire et utiliser les bases de cette modlisation au fil
des chapitres de cette partie.

criture du code
Prparation du nouveau fichier
Tout dabord, pour crer une nouvelle classe, nous aurons besoin dun nouveau fichier
Actionscript ! Nous allons donc insrer une classe nomme Voiture avec File > New
> AS3 Document si vous tes sous FlashDevelop ou crer un nouveau fichier nomm
140

EXERCICE : CRONS NOTRE PREMIRE CLASSE


Voiture.as si vous nutilisez pas ce logiciel.
Puis, nous insrerons lintrieur le code de dfinition de la classe, comme ceci :
1
2
3
4

package
{
public class Voiture
{

6
7
8

Dclaration des attributs


Prcdemment, nous avons dfini les quatre attributs qui sont saMarque, saCouleur,
saLongueur et sonImmatriculation. Tous ces attributs ont videmment des droits
daccs de type private, pour respecter le concept dencapsulation.
Voici donc les diffrentes dclarations dattributs :
1
2
3
4

private
private
private
private

var
var
var
var

_marque : String ;
_couleur : String ;
_longueur : int ;
_immatriculation : String ;

Le constructeur
Comme nous lavons rapidement introduit, le constructeur de cette classe devra recevoir en paramtre la marque de fabrication du vhicule. Sachant que les autres attributs
possdent des setters, nous ne les introduirons pas dans la liste des paramtres spcifier au constructeur. Nanmoins, ceux-ci devront tout de mme tre initialiss.
Il est recommand dutiliser, ds que cela est possible, les accesseurs et les
mutateurs au sein mme de la classe, exception faite du constructeur, o
cela nest gnralement pas ncessaire.
Dcouvrons tout de suite ce constructeur :
1
2
3
4
5
6
7

public function Voiture ( marque : String )


{
_marque = marque ;
_couleur = " Sans couleur " ;
_longueur = -1 ;
_immatriculation = " Non immatricul e " ;
}

141

CHAPITRE 9. LES CLASSES (1RE PARTIE)


Vous pouvez utiliser des noms de paramtres identiques aux noms de vos
proprits (ici marque) : ils sont en effet prioritaires. Pour pouvoir utiliser
explicitement une proprit de lobjet, il faut ajouter le mot-cl this devant : si nous avions un mutateur pour lattribut marque, nous devrions
crire this.marque = marque; pour lutiliser.

Les accesseurs
Chaque attribut possde un ou deux accesseurs, nous ne les dtaillerons donc pas
tous. Je vous propose plutt de dcouvrir un getter et un setter. Nous allons prendre
lexemple des accesseurs longueur, dont voici le getter :
1
2
3
4

public function get longueur () : int


{
return _longueur ;
}

Cet accesseur na rien de trs compliqu, nous ne nous y attarderons donc pas davantage. En revanche, pour le mutateur, nous devons vrifier si la valeur spcifie est
positive, je vous rappelle. Nous devrons donc utiliser une condition en if...else pour
faire la vrification.
Voici donc le mutateur en question, que vous tes normalement en mesure de comprendre par vous-mmes maintenant :
1
2
3
4
5
6
7

public function set longueur ( nouvelleLongueur : int ) : void


{
if ( nouvelleLongueur > 0 )
_longueur = nouvelleLongueur ;
else
_longueur = -1 ;
}

Flicitations, nous avons termin lcriture de votre premire classe !

La classe complte
Parce quil est probable que certains ne soient pas pleinement satisfaits avant davoir vu
lintgralit de celle-ci, je vous propose ici un rcapitulatif intgral de la classe Voiture :
1
2
3
4
5
6
7
8
9

package
{
public class Voiture
{
/* ************** Attributs ************** */
private var _marque : String ;
private var _couleur : String ;
private var _longueur : int ;
private var _immatriculation : String ;

142

EXERCICE : CRONS NOTRE PREMIRE CLASSE


10
11
12
13
14
15
16
17
18

/* ************ Constructeur ************ */


public function Voiture ( marque : String )
{
_marque = marque ;
_couleur = " Sans couleur " ;
_longueur = -1 ;
_immatriculation = " Non immatricul e " ;
}

19
20
21
22
23
24

/* ************** Accesseurs ************** */


public function get marque () : String
{
return _marque ;
}

25
26
27
28
29

public function get couleur () : String


{
return _couleur ;
}

30
31
32
33
34

public function get longueur () : int


{
return _longueur ;
}

35
36
37
38
39

public function get immatriculation () : String


{
return _immatriculation ;
}

40
41
42
43
44
45

/* ************** Mutateurs ************** */


public function set couleur ( nouvelleCouleur : String ) :
void
{
_couleur = nouvelleCouleur ;
}

46
47
48
49
50

public function set longueur ( nouvelleLongueur : int ) : void


{
_longueur = ( nouvelleLongueur > 0 ) ?
nouvelleLongueur : -1 ;
}

51
52
53
54
55

public function set immatriculation (


n ou ve ll e Im ma tr i cu la ti o n : String ) : void
{
_immatriculation = no uv e ll eI mm a tr ic u la ti on ;
}

56

143

CHAPITRE 9. LES CLASSES (1RE PARTIE)


}

57
58
59

Vous
pouvez lafficher pour la copier
 en utilisant le code web ci-dessous.
Classe Voiture
B
Code web : 255948

En rsum
Le mot-cl this fait rfrence lobjet lui-mme.
Les classes sont tries dans diffrents package en fonction du type dobjets quelles
reprsentent.
Le constructeur est une mthode particulire appele la cration dune instance,
o on initialise gnralement les attributs.
Il est possible de dfinir des paramtres facultatifs lintrieur de nos fonctions
et mthodes pour palier limpossibilit de surcharger celles-ci.
Lencapsulation est le concept permettant de masquer le fonctionnement interne
dune classe.
Pour grer les droits daccs, nous disposons des diffrents mots-cls public,
private, internal et protected (que nous aborderons plus loin).
Des accesseurs peuvent tre dclars laide des mots-cls get et set, et simplifient
laccs aux attributs dune classe.

144

Chapitre

10

Les classes (2nde partie)


Difficult :
Dans le chapitre prcdent, nous avons prsent les bases de la thorie des classes. Nous
allons maintenant introduire des notions complmentaires qui vous permettront de structurer votre code encore plus facilement et proprement. Contrairement la plupart des notions
de cette partie sur la POO, celles que nous allons dcouvrir dans ce chapitre nont pas t
prsentes dans le premier chapitre et sont donc compltement nouvelles. Redoublez donc
dattention !

145

CHAPITRE 10. LES CLASSES (2NDE PARTIE)

Les lments statiques


Peut-tre que certains se rappellent de la classe Math que nous avons dj utilis. Ils
se demandent alors pourquoi nous lavions utilis en employant directement le nom de
la classe et sans passer par une instance de celle-ci :
1

var monNombre : Number = Math . sqrt ( 2 ) ;

Comment cela est-ce possible ?

Maintenant que vous avez dj quelques connaissances en POO, il est tout fait
justifi de se poser ce genre de question. En fait, la classe Math utilise des lments
qui sont un peu particuliers : les lments statiques ! Comme nous le verrons, ces
lments statiques ne sont pas dfinis pour les instances dune classe, mais pour la
classe elle-mme. Il existe deux types dlments statiques qui sont :
Les variables statiques.
Les mthodes statiques.
Nous verrons donc comment crer ces lments et leur intrt.

Les variables statiques


Les variables statiques sont dclares laide du mot-cl static, et sont associes,
donc dfinies, pour la classe. Prenons lexemple de notre classe Voiture du chapitre
prcdent et ajoutons-y une variable statique reprsentant le nombre de fois o celle-ci
a t instancie :
public static var occurences : int = 0 ;

Cette variable est donc partage par la classe, elle nappartient pas aux instances de
celle-ci. Toutefois, cette variable est accessible depuis nimporte quel point de la classe.
Nous pourrions notamment incrmenter cette variable lintrieur du constructeur de
la classe Voiture afin de comptabiliser le nombre doccurrences de celle-ci :
occurrences ++;

Grce cette variable statique, nous pourrions obtenir le nombre dinstances de la


classe Voiture, nimporte o dans le code. Pour cela, nul besoin de crer une nouvelle
instance de la classe, il suffit dutiliser le nom de la classe lui-mme :
1
2
3
4

var uneRenault : Voiture = new Voiture ( " Renault " ) ;


var unePeugeot : Voiture = new Voiture ( " Peugeot " ) ;
var uneCitroen : Voiture = new Voiture ( " Citro n " ) ;
trace ( Voiture . occurrences ) ; // Affiche : 3

146

LES LMENTS STATIQUES


Un lment statique ne peut tre utilis quavec la classe o celui-ci est
dclar. Il est impossible de faire rfrence un lment statique laide
dune instance de cette classe : des erreurs seraient alors engendres.

Les mthodes statiques


Il existe un second type dlments statiques : il sagit des mthodes statiques.
Dans le chapitre prcdent, je vous avais dit que les mthodes servaient principalement la lecture ou la modification dun attribut. Nous pouvons donc introduire les
mthodes statiques comme lensemble des mthodes qui offrent des fonctionnalits
naffectant pas au moins lun des attributs dune classe.
Ces lments statiques sont galement dclars laide du mot-cl static :
1
2
3
4

public static function uneMethode () : void


{
// Instructions
}

laide de ces mthodes statiques, il nous est possible de recrer la classe Math,
que nous pourrions renommer MaClasseMath. Voici par exemple la redfinition de la
mthode pow() en puissance() :
1
2
3
4
5
6
7
8
9

public static function puissance ( nombre : int , exposant : int ) : int


{
var resultat : int = nombre
for ( var i : int = 1 ; i < exposant ; i ++)
{
resultat *= nombre ;
}
return resultat ;
}

Le code complet de la classe serait :


1
2
3
4
5
6
7
8
9
10
11
12
13
14

package
{
public class MaClasseMath
{
public static function puissance ( nombre : int , exposant :
int ) : int
{
var resultat : int = nombre
for ( var i : int = 1 ; i < exposant ; i ++)
{
resultat *= nombre ;
}
return resultat ;
}
}

147

CHAPITRE 10. LES CLASSES (2NDE PARTIE)


15

Vous remarquerez que cette classe ne possde pas de constructeur : en effet,


il est permis de ne pas mettre de constructeur si vous ne vous en servirez
pas. Ici, nous navons pas mis de constructeur car nous nallons jamais crer
dinstance de cette classe.
Nous pouvons ainsi lutiliser sans crer doccurrences de cette nouvelle classe :
1
2

var monNombre : int = MaClasseMath . puissance (2 , 10 ) ;


trace ( monNombre ) ; // Affiche : 1024

Des classes telles que Math ont t conues pour tre utilises uniquement grce des
lments statiques. En utilisant ce principe, vous pouvez ainsi regrouper un ensemble
de fonctionnalits lintrieur dune mme classe. Vous naurez donc pas besoin de crer
doccurrences de celle-ci et vous ferez ainsi lconomie des instructions de dclarations
et dinitialisations des instances.
Il est impossible dutiliser le mot-cl this dans les mthodes statiques, car
elles ne sont lies aucun objet en particulier.

Une nouvelle sorte de variable : la constante !


Lorsque nous avons introduit les variables dans la premire partie, nous navons pas
parl des constantes ! Comme son nom lindique, la valeur dune constante est
fige contrairement celle dune variable qui est voue voluer au cours du programme. Ces constantes sont principalement utilises en POO et reprsentent des
caractristiques constantes dun objet.
Je vous invite dcouvrir ce nouveau type dlment sans plus attendre !

Prsentation
Dclaration
De la mme faon que nous avions linstruction ou mot-cl var pour dclarer une variable, nous disposons du mot-cl const en ce qui concerne les constantes. Comme
les variables, ces dernires possdent galement un type. Voici par exemple la dclaration dune constante de type String :
1

148

const MA_CONSTANTE : String ;

UNE NOUVELLE SORTE DE VARIABLE : LA CONSTANTE !


Vous remarquerez quici nous nutilisons pas la notion Camel. Effectivement,
il est de coutume dcrire les noms de constantes en lettres majuscules. Cela
permet de les diffrencier des variables, et de prciser quil sagit bien dune
constante. Utilisez lunderscore _ pour sparer les diffrents mots lintrieur du nom de votre constante.
Le code prcdent na malheureusement aucun intrt et ne sert rien sans linitialisation
de la constante !
Initialisation
Tout comme une variable, il est important dinitialiser une constante. Vous pouvez procder exactement de la mme manire que pour une variable. La technique
dinitialisation dpend bien entendu du type de la constante.
Voici donc comment initialiser notre constante prcdente de type String :
1

const MA_CONSTANTE : String = " Valeur " ;

Contrairement aux variables, Il est strictement impossible dinitialiser la valeur


dune constante ailleurs que lors de sa dclaration. tant donn que la valeur
dune constante est non modifiable, nessayez pas non plus de procder une
affectation.

Intrt des constantes


Il y a certainement plus de la moiti, voire mme les trois quarts dentre vous qui se
sont pos la question suivante :

quoi ces constantes peuvent-elles bien servir ?

Contrairement ce que vous pensez, les constantes ont plusieurs utilits.


Tout dabord, elles permettent de mettre des noms sur des valeurs. Votre programme
ne marchera pas mieux avec cela, cest uniquement une question de clarification
du code. Avouez quil est quand mme plus ais de comprendre la signification
dune expression si celle-ci utilise des noms plutt que des valeurs : prixRoue *
NOMBRE_DE_ROUES plutt que prixRoue * 4. Dans le second cas, nous pourrions
nous demander sil sagit dune augmentation du prix dune roue, une conversion du
prix des euros aux dollars, ou bien une multiplication par le nombre de roues. Dans
la premire expression, lopration est tout fait claire ; ce qui simplifie grandement
le travail de relecture dun code.
Une autre utilit des constantes est de sassurer de la prennisation du code. Imaginez que le nombre de roues de votre voiture puisse servir plusieurs calculs comme
149

CHAPITRE 10. LES CLASSES (2NDE PARTIE)


le prix de lensemble, son poids, etc. Vous devrez donc utiliser cette valeur plusieurs
fois dans votre code et des endroits diffrents. Ainsi, en utilisant une constante la
place de la valeur relle, vous facilitez une ventuelle mise jour de votre programme
dans lhypothse de linvention de la voiture 6 roues ! Essayez dimaginer le travail
quil aurait fallu fournir pour remplacer chacune des valeurs prsentes dans des coins
opposs de votre code.
Nutilisez pas non plus des constantes tour de bras dans vos programmes.
Leur but est de simplifier la lecture du code ; nallez donc pas le compliquer
davantage !

Un objet dans un objet (dans un objet. . .)


Jusqu prsent, nous navions utilis quune seule classe la fois. Mais l o la POO
devient vraiment intressante, cest lorsque nous combinons les classes entre elles !

Le problme du ptrole
Reprenons la classe Voiture :
1
2
3
4
5
6
7
8
9

package
{
public class Voiture
{
/* ************** Attributs ************** */
private var _marque : String ;
private var _couleur : String ;
private var _longueur : int ;
private var _immatriculation : String ;

10
11
12
13
14
15
16
17
18

/* ************ Constructeur ************ */


public function Voiture ( marque : String )
{
_marque = marque ;
_couleur = " Sans couleur " ;
_longueur = -1 ;
_immatriculation = " Non immatricul e " ;
}

19
20
21
22
23
24

/* ************** Accesseurs ************** */


public function get marque () : String
{
return _marque ;
}

25
26

150

public function get couleur () : String

UN OBJET DANS UN OBJET (DANS UN OBJET. . .)


{

27
28

29

return _couleur ;

30

public function get longueur () : int


{
return _longueur ;
}

31
32
33
34
35

public function get immatriculation () : String


{
return _immatriculation ;
}

36
37
38
39
40

/* ************** Mutateurs ************** */


public function set couleur ( nouvelleCouleur : String ) :
void
{
_couleur = nouvelleCouleur ;
}

41
42
43
44
45
46

public function set longueur ( nouvelleLongueur : int ) : void


{
_longueur = ( nouvelleLongueur > 0 ) ?
nouvelleLongueur : -1 ;
}

47
48
49
50
51

public function set immatriculation (


n ou ve ll e Im ma tr i cu la ti o n : String ) : void
{
_immatriculation = no uv e ll eI mm a tr ic u la ti on ;
}

52
53
54
55
56

57
58
59

Nous voulons prsent que nos objets contiennent de lessence. Pour cela, nous serions
tent de procder ainsi :
1
2
3
4
5
6
7
8
9

package
{
public class Voiture
{
/* ************** Attributs ************** */
private var _marque : String ;
private var _couleur : String ;
private var _longueur : int ;
private var _immatriculation : String ;

10
11

private var _typeEssence : String ;

151

CHAPITRE 10. LES CLASSES (2NDE PARTIE)


12
13

private var _prixEssence : Number ;


private var _quantiteEssence : Number ;

14
15
16
17
18
19
20
21
22
23
24
25

/* ************ Constructeur ************ */


public function Voiture ( marque : String )
{
_marque = marque ;
_couleur = " Sans couleur " ;
_longueur = -1 ;
_immatriculation = " Non immatricul e " ;
_typeEssence = " Sans Plomb " ;
_prixEssence = 1 . 4 ; // Euros par litre
_quantiteEssence = 10 ; // Litres
}

26
27
28
29
30
31

/* ************** Accesseurs ************** */


public function get marque () : String
{
return _marque ;
}

32
33
34
35
36

public function get couleur () : String


{
return _couleur ;
}

37
38
39
40
41

public function get longueur () : int


{
return _longueur ;
}

42
43
44
45
46

public function get immatriculation () : String


{
return _immatriculation ;
}

47
48
49
50
51

public function get typeEssence () : String


{
return _typeEssence ;
}

52
53
54
55
56

public function get prixEssence () : Number


{
return _prixEssence ;
}

57
58
59
60
61

152

public function get quantiteEssence () : Number


{
return _quantiteEssence ;
}

UN OBJET DANS UN OBJET (DANS UN OBJET. . .)


62

/* ************** Mutateurs ************** */


public function set couleur ( nouvelleCouleur : String ) :
void
{
_couleur = nouvelleCouleur ;
}

63
64
65
66
67
68

public function set longueur ( nouvelleLongueur : int ) : void


{
_longueur = ( nouvelleLongueur > 0 ) ?
nouvelleLongueur : -1 ;
}

69
70
71
72
73

public function set immatriculation (


n ou ve ll e Im ma tr i cu la ti o n : String ) : void
{
_immatriculation = no uv e ll eI mm a tr ic u la ti on ;
}

74
75
76
77
78

public function set typeEssence ( nouveauType : String ) :


void
{
_typeEssence = nouveauType ;
}

79
80
81
82
83

public function set prixEssence ( nouveauPrix : Number ) :


void
{
_prixEssence = nouveauPrix ;
}

84
85
86
87
88

public function set quantiteEssence ( nouvelleQuantite :


Number ) : void
{
_quantiteEssence = nouvelleQuantite ;
}

89
90
91
92
93

94
95
96

Notre classe commence devenir complique, il vaudrait mieux crer une nouvelle
classe pour partager les proprits.

Une nouvelle classe


Crons une classe Essence mettre dans le fichier Essence.as :
1

package

153

CHAPITRE 10. LES CLASSES (2NDE PARTIE)


2

3
4
5
6
7
8

public class Essence


{
/* ************** Attributs ************** */
private var _type : String ;
private var _prix : Number ;
private var _quantite : Number ;

/* ************ Constructeur ************ */


public function Essence ()
{
_type = " Sans Plomb " ;
_prix = 1 . 4 ; // Euros par litre
_quantite = 10 ; // Litres
}

10
11
12
13
14
15
16
17

/* ************** Accesseurs ************** */


public function get type () : String
{
return _type ;
}

18
19
20
21
22
23

public function get prix () : Number


{
return _prix ;
}

24
25
26
27
28

public function get quantite () : Number


{
return _quantite ;
}

29
30
31
32
33

/* ************** Mutateurs ************** */


public function set type ( nouveauType : String ) : void
{
_type = nouveauType ;
}

34
35
36
37
38
39

public function set prix ( nouveauPrix : Number ) : void


{
_prix = nouveauPrix ;
}

40
41
42
43
44

public function set quantite ( nouvelleQuantite : Number ) :


void
{
_quantite = nouvelleQuantite ;
}

45
46
47
48
49
50

154

UN OBJET DANS UN OBJET (DANS UN OBJET. . .)


51
52

Vous
pouvez lafficher pour la copier
 en utilisant le code web ci-dessous.
Classe Essence
B
Code web : 750046


Nous transfrons donc toutes les proprits relatives lessence de la voiture dans la
nouvelle classe. Il va falloir maintenant adapter la classe Voiture :
1
2
3
4
5
6
7
8
9

package
{
public class Voiture
{
/* ************** Attributs ************** */
private var _marque : String ;
private var _couleur : String ;
private var _longueur : int ;
private var _immatriculation : String ;

10
11

private var _carburant : Essence ; // Nouvel attribut


pointant sur un objet de classe Essence !

12
13
14
15
16
17
18
19
20
21

/* ************ Constructeur ************ */


public function Voiture ( marque : String )
{
_marque = marque ;
_couleur = " Sans couleur " ;
_longueur = -1 ;
_immatriculation = " Non immatricul e " ;
_carburant = new Essence () ; // Nous cr ons un objet
Essence par d faut dans le constructeur
}

22
23
24
25
26
27

/* ************** Accesseurs ************** */


public function get marque () : String
{
return _marque ;
}

28
29
30
31
32

public function get couleur () : String


{
return _couleur ;
}

33
34
35
36
37

public function get longueur () : int


{
return _longueur ;
}

38
39

public function get immatriculation () : String

155

CHAPITRE 10. LES CLASSES (2NDE PARTIE)


{

40
41

42

return _immatriculation ;

43

public function get carburant () : Essence // Nouvel


accesseur , renvoyant un objet de classe Essence
{
return _carburant ;
}

44
45
46
47
48

/* ************** Mutateurs ************** */


public function set couleur ( nouvelleCouleur : String ) :
void
{
_couleur = nouvelleCouleur ;
}

49
50
51
52
53
54

public function set longueur ( nouvelleLongueur : int ) : void


{
_longueur = ( nouvelleLongueur > 0 ) ?
nouvelleLongueur : -1 ;
}

55
56
57
58
59

public function set immatriculation (


n ou ve ll e Im ma t ri cu la t io n : String ) : void
{
_immatriculation = no uv e ll eI mm a tr ic ul a ti on ;
}

60
61
62
63
64
65

66
67
68

69

public function set carburant ( nouveauCarburant : Essence )


: void // Nouveau mutateur , affectant un objet de
classe Essence
{
_carburant = nouveauCarburant ;
}

70
71

Comme vous pouvez le constater, nous pouvons crire des attributs pointant sur des
objets. Nous pourrions mme mettre un attribut de type Voiture !
private var ancienneVoiture : Voiture ; // L ' ancienne voiture du
propri taire

Pour modifier le carburant de notre voiture, il faut procder ainsi :


1
2
3

var maVoiture = new Voiture ( " Peugeot " ) ;


maVoiture . carburant . type = " Diesel " ;
trace ( " Type de carburant : " + maVoiture . carburant . type ) ; //
Affiche : Type de carburant : Diesel

156

EXERCICE : JEU DE RLE


Vous remarquerez que nous procdons de la mme faon que pour toutes les proprits,
en utilisant le caractre point . , comme nous lavons vu dans le premier chapitre
cette partie. Il suffit donc de mettre un point chaque fois que nous voulons accder
la proprit dun objet :
Une premire fois lorsque nous voulons accder la proprit carburant de notre
objet maVoiture.
Une seconde fois lorsque nous voulons modifier le type du carburant de la voiture.
Pour rsumer la situation, je vous propose un petit schma UML des classes Voiture
et Essence que nous venons de crer (voir figure 10.1).

Figure 10.1 Les classes Voiture et Essence


En ralit, nous combinons depuis le dbut la classe Voiture et la classe
String : beaucoup de nos attributs sont du type String. Rappelez-vous :
les chanes de caractres sont aussi des objets !

Exercice : Jeu de rle


Prsentation de lexercice
Le combat final contre le grand Mchant approche ! Votre personnage, son pe lgendaire au poing, se dresse devant cet immense monstre arm jusquaux dents !
Le moment est venu de passer la pratique ! Je propose la ralisation dun petit programme ressemblant un jeu de rle afin de bien revoir les notions essentielles du
chapitre.
Lobjectif de cet exercice est de crer la (ou les) classe(s) ncessaires au bon fonctionnement du programme principal (que nous adapterons si besoin). Voici le droulement
de ce programme :
Nous crons un objet reprsentant votre personnage, puis nous larmons.
157

CHAPITRE 10. LES CLASSES (2NDE PARTIE)


Nous crons de faon similaire lobjet reprsentant le Mchant.
Le Mchant attaque une fois votre personnage.
Votre personnage riposte et attaque une fois le Mchant.
Pour apporter un peu de piment ce programme, les personnages peuvent succomber
aux attaques, et leur arme peut infliger un coup critique (elle a des chances dinfliger
le double de dgts ladversaire).
Nous allons passer par trois tapes successives, que jai nommes solutions, pour voir
comment programmer correctement en Orient Objet pas pas : chaque tape, nous
amliorerons notre code.
Il ne sagit pas dun TP : nous allons programmer ensemble et progressivement.

Solution initiale
Cration de la classe
Commenons par crer notre premire classe : jai choisi de lappeler Personnage.
En effet, ce sera la classe des objets reprsentant nos deux personnages (vous et le
Mchant). Dans un nouveau fichier, appel Personnage.as, crivons la structure de
base de notre classe : le package, la classe et le constructeur :
1
2

package
{

public class Personnage


{

4
5
6

// Constructeur
public function Personnage ()
{

7
8
9
10
11
12
13

Les attributs
Ensuite, ajoutons les attributs de la classe. Pour cela, rflchissons aux donnes utiles
pour notre combat. Comme dans tous les jeux avec des combats (ou presque), donnons
un niveau de sant nos personnages, que nous initialiserons 100. Et pour les armer,
indiquons la puissance de lattaque quils vont porter leur adversaire ainsi que les
chances de coup critique :
1

// Sant du personnage

158

EXERCICE : JEU DE RLE


2

private var _sante : int ;

3
4
5

// D g ts de base
private var _degats : int ;

6
7
8

// Chances de faire une critique ( sur 100 )


private var _chanceCritique : int ;

Les accesseurs
Noublions pas daccompagner les attributs de leurs accesseurs :
1
2
3
4

public function get sante () : int


{
return _sante ;
}

5
6
7
8
9

public function set sante ( value : int ) : void


{
_sante = value ;
}

10
11
12
13
14

public function get degats () : int


{
return _degats ;
}

15
16
17
18
19

public function set degats ( value : int ) : void


{
_degats = value ;
}

20
21
22
23
24

public function get chanceCritique () : int


{
return _chanceCritique ;
}

25
26
27
28
29

public function set chanceCritique ( value : int ) : void


{
_chanceCritique = value ;
}

Le contructeur
Ensuite, initialisons nos attributs au sein du constructeur :
1
2
3

// Constructeur
public function Personnage ()
{

159

CHAPITRE 10. LES CLASSES (2NDE PARTIE)


4
5
6
7

sante = 100 ;
degats = 0 ;
chanceCritique = 0 ;

La mthode
Enfin, ajoutons une mthode, afin que nos personnages puissent attaquer un autre
personnage :
1
2
3

public function attaquer ( cible : Personnage ) : void


{
var degatsAppliques : int = degats ;

// On jette un d 100 faces : si le r sultat est inf


rieur ou gal la chance de coup critique , l '
attaque fait un coup critique !
if ( Math . random () * 100 <= chanceCritique )
{
trace ( " Critique ! " ) ;
// On double les d g ts !
degatsAppliques *= 2 ;
}

6
7
8
9
10
11
12

// On applique les d g ts
cible . sante -= degatsAppliques ;

13
14
15
16
17
18
19
20
21
22
23
24

if ( cible . sante <= 0 )


{
trace ( " La cible est d c d e . " ) ;
}
else
{
trace ( " Il reste " + cible . sante + " PV la
cible . " ) ;
}

Comme vous pouvez le constater, nous passons en paramtre un objet de la classe


Personnage, afin de rendre le code logique et surtout trs lisible. Ainsi, pour quun
personnage attaque un second, il faudra procder ainsi :
1

personnageA . attaquer ( personnageB ) ; // Le personnageA attaque le


personnageB ! S ' en est fini de lui !

La classe complte
Si tout se passe bien, vous devriez normalement avoir une classe Personnage qui correspond la description de la figure 10.2.
160

EXERCICE : JEU DE RLE

Figure 10.2 La classe Personnage


Voici le code complet de notre classe Personnage, pour vrifier le vtre :
1
2

package
{

3
4
5

public class Personnage


{

6
7
8

// Sant du personnage
private var _sante : int ;

9
10
11

// D g ts de base
private var _degats : int ;

12
13
14

// Chances de faire une critique ( sur 100 )


private var _chanceCritique : int ;

15
16
17
18
19
20
21

public function Personnage ()


{
sante = 100 ;
degats = 0 ;
chanceCritique = 0 ;
}

22
23
24
25
26

public function get sante () : int


{
return _sante ;
}

27
28
29
30
31

public function set sante ( value : int ) : void


{
_sante = value ;
}

32
33
34
35

public function get degats () : int


{
return _degats ;

161

CHAPITRE 10. LES CLASSES (2NDE PARTIE)


}

36
37

public function set degats ( value : int ) : void


{
_degats = value ;
}

38
39
40
41
42

public function get chanceCritique () : int


{
return _chanceCritique ;
}

43
44
45
46
47

public function set chanceCritique ( value : int ) : void


{
_chanceCritique = value ;
}

48
49
50
51
52

public function attaquer ( cible : Personnage ) : void


{
var degatsAppliques : int = degats ;

53
54
55
56

// On jette un d 100 faces : si le r sultat est


inf rieur ou gal la chance de coup critique ,
l ' attaque fait un coup critique !
if ( Math . random () * 100 <= chanceCritique )
{
trace ( " Critique ! " ) ;
// On double les d g ts !
degatsAppliques *= 2 ;
}

57

58
59
60
61
62
63
64

// On applique les d g ts
cible . sante -= degatsAppliques ;

65
66
67
68
69
70
71
72
73
74
75
76
77
78

162

if ( cible . sante <= 0 )


{
trace ( " La cible est d c d e . " ) ;
}
else
{
trace ( " Il reste " + cible . sante + " PV la
cible . " ) ;
}

EXERCICE : JEU DE RLE


Le programme principal
Votre classe Main vide (contenue dans le fichier Main.as) devrait ressembler cela :
1
2
3

package {
import flash . display . Sprite ;
import flash . events . Event ;

public class Main extends Sprite {

5
6

public function Main () : void {


if ( stage )
init () ;
else
addEventListener ( Event .
ADDED_TO_STAGE , init ) ;
}

7
8
9
10
11
12
13

private function init ( e : Event = null ) : void {


removeEventListener ( Event .
ADDED_TO_STAGE , init ) ;
// entry point

14
15
16
17
18
19
20

Rappel : il faut commencer programmer aprs le commentaire // entry


point (point dentre ) la ligne 17.
Commenons par dclarer la variable qui pointera vers le premier objet de classe
Personnage (celui qui vous reprsente) :
1

var moi : Personnage = new Personnage () ;

Ensuite, donnons-lui son pe lgendaire (elle fait 80 dgts de base et a 80 chances


sur 100 de faire un coup critique) :
1
2

moi . degats = 80 ;
moi . chanceCritique = 80 ;

Le code pour crer le Mchant est trs similaire :


1
2
3

var mechant : Personnage = new Personnage () ;


mechant . degats = 40 ;
mechant . chanceCritique = 10 ;

Enfin, simulons le combat pique qui a lieu entre nos deux personnages ! Si vous vous
souvenez de ma remarque sur la mthode attaquer() un peu plus haut, vous savez
comment procder :
163

CHAPITRE 10. LES CLASSES (2NDE PARTIE)


trace ( " Le m chant m ' attaque ! " ) ;
mechant . attaquer ( moi ) ;

1
2
3
4
5

trace ( " Il va conna tre ma fureur ! A l ' attaque ! " ) ;


moi . attaquer ( mechant ) ;

Voici le code complet de notre classe Main :


1
2

package
{

3
4

import flash . display . Sprite ;


import flash . events . Event ;

5
6
7

public class Main extends Sprite


{

public function Main () : void


{
if ( stage )
init () ;
else
addEventListener ( Event .
ADDED_TO_STAGE , init ) ;
}

9
10
11
12
13
14
15
16

private function init ( e : Event = null ) : void


{
removeEventListener ( Event .
ADDED_TO_STAGE , init ) ;
// entry point

17
18
19
20
21

// Cr ation du personnage vous repr


sentant
var moi : Personnage = new Personnage () ;
moi . degats = 80 ;
moi . chanceCritique = 80 ;

22
23
24
25
26

// Cr ation du personnage M chant


var mechant : Personnage = new Personnage
() ;
mechant . degats = 40 ;
mechant . chanceCritique = 10 ;

27
28
29
30
31
32
33
34
35
36
37
38

164

// Simulation du combat
trace ( " Le m chant m ' attaque ! " ) ;
mechant . attaquer ( moi ) ;
trace ( " Il va conna tre ma fureur ! A l '
attaque ! " ) ;
moi . attaquer ( mechant ) ;

EXERCICE : JEU DE RLE


39

Rsultat
Nous pouvons maintenant compiler et tester le projet. Voici ce que donne la console :
Le m chant m attaque !
Critique !
Il reste 20 PV la cible .
Il va conna tre ma fureur ! A l attaque !
Critique !
La cible est d c d e .

Gagn !
Attendez malheureux ! Ne criez pas victoire trop vite ! En effet, notre classe pourrait
tre amliore. . . Vous ne voyez pas en quoi ? Et bien, pensez au chapitre prcdent :
Un objet dans un objet (dans un objet. . .) . Maintenant, rflchissez cette problmatique : comment pourrait-on mieux sparer les donnes et les proprits de ma
classe Personnage ? En crant de nouvelles classes, pardi !

Une nouvelle classe


En effet, il serait judicieux de reprsenter les armes que portent nos personnages par
des objets part entire : cela semble logique, et cela respecte les principes de la POO.
En outre, cela nous faciliterait normment la tche si nous devions grer un inventaire
par exemple : nous pourrions mettre autant dobjets que lon veut, et quiper nos
personnages avec, tout ceci de faon trs souple et naturelle !
La classe Arme
Lide est donc de transfrer toutes les proprits relatives aux armes dans une nouvelle
classe Arme, comme la figure 10.3.

Figure 10.3 Transfert des proprits dans la classe Arme


Il nous faudra donc crer une nouvelle classe (ici dans le fichier Arme.as) :
165

CHAPITRE 10. LES CLASSES (2NDE PARTIE)


1
2

package
{

public class Arme


{

4
5
6

// D g ts de l ' arme
private var _degats : int ;

7
8
9

// Chances de faire un coup critique ( sur 100 )


private var _chanceCritique : int ;

10
11
12

public function Arme ()


{
degats = 0 ;
chanceCritique = 0 ;
}

13
14
15
16
17
18

public function get chanceCritique () : int


{
return _chanceCritique ;
}

19
20
21
22
23

public function set chanceCritique ( value : int ) : void


{
_chanceCritique = value ;
}

24
25
26
27
28

public function get degats () : int


{
return _degats ;
}

29
30
31
32
33
34
35
36
37
38
39

public function set degats ( value : int ) : void


{
_degats = value ;
}

La classe Personnage
Noublions pas dadapter la classe Personnage, comme nous lavons fait dans le chapitre
prcdent :
1
2

package
{

3
4

166

public class Personnage

EXERCICE : JEU DE RLE


5

6
7
8

// Sant du personnage
private var _sante : int ;

9
10
11

// Arme quip e
private var _armeEquipee : Arme ; // Nouvel attribut
pointant sur l ' arme quip e

12
13
14
15
16

public function Personnage ()


{
sante = 100 ;
}

17
18
19
20
21

public function get sante () : int


{
return _sante ;
}

22
23
24
25
26

public function set sante ( value : int ) : void


{
_sante = value ;
}

27
28
29
30
31

public function get armeEquipee () : Arme // Nouvel


accesseur
{
return _armeEquipee ;
}

32
33
34
35
36

public function set armeEquipee ( value : Arme ) : void //


Nouveau mutateur
{
_armeEquipee = value ;
}

37
38
39
40
41
42
43
44
45
46
47

public function attaquer ( cible : Personnage ) : void


{
// Au cas o aucun arme n ' est quip e ( l ' objet
armeEquipee est null )
if ( armeEquipee == null )
{
trace ( " Aucune arme quip e : l ' attaque choue . "
);
}
else
{
var degatsAppliques : int = armeEquipee . degats ;
// D sormais , on utilise les propri t s de l
' objet armeEquipee

167

CHAPITRE 10. LES CLASSES (2NDE PARTIE)


48

if ( Math . random () * 100 <= armeEquipee .


chanceCritique ) // Ici aussi , on utilise les
propri t s de l ' objet armeEquipee
{
trace ( " Critique ! " ) ;
// On double les d g ts !
degatsAppliques *= 2 ;
}

49

50
51
52
53
54
55

// On applique les d g ts
cible . sante -= degatsAppliques ;

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

if ( cible . sante <= 0 )


{
trace ( " La cible est d c d e . " ) ;
}
else
{
trace ( " Il reste " + cible . sante + " PV la
cible . " ) ;
}

Le programme principal
L aussi, il va falloir adapter un peu : au lieu daffecter directement les dgts et les
chances de coup critique aux personnages, nous crons dans un premier temps les armes
via des objets de classe Arme, pour ensuite les quiper aux personnages :
1
2
3

var epeeLegendaire : Arme = new Arme () ;


epeeLegendaire . degats = 80 ;
epeeLegendaire . chanceCritique = 50 ;

4
5
6
7

var hacheDeGuerre : Arme = new Arme () ;


hacheDeGuerre . degats = 40 ;
hacheDeGuerre . chanceCritique = 10 ;

8
9
10

var moi : Personnage = new Personnage () ;


moi . armeEquipee = epeeLegendaire ;

11
12
13

var mechant : Personnage = new Personnage () ;


mechant . armeEquipee = hacheDeGuerre ;

14
15
16

168

trace ( " Le m chant m ' attaque ! " ) ;


mechant . attaquer ( moi ) ;

EXERCICE : JEU DE RLE


17
18

trace ( " Il va conna tre ma fureur ! A l ' attaque ! " ) ;


moi . attaquer ( mechant ) ;

Vous avouerez que ce code est quand mme plus clair que le prcdent !
Rsultat
Et voici le rsultat la console lorsque lon teste le projet :
Le m chant m attaque !
Il reste 60 PV la cible .
Il va conna tre ma fureur ! A l attaque !
Critique !
La cible est d c d e .

Rien na vraiment chang ( part ma chance qui sest envole !) : ce nest


toutefois pas pour rien que nous avons modifi notre code. En effet, il est
primordial de programmer correctement pour que vos projets soient lisibles,
facilement modifiables et maintenables.
Malheureusement, notre code pose encore problme : il ne respecte pas bien le principe
dencapsulation. Si vous regardez bien la mthode attaquer(), nous utilisons des
proprits de la classe Arme et reproduisons son comportement ( savoir : les coups
critiques) dans la classe Personnage : en toute logique, si une arme devrait faire un
coup critique, nous devrions le dterminer dans la bonne classe, autrement dit la classe
Arme !

La bonne solution
La bonne faon de procder consiste donc appliquer les dgts qui vont tre fait dans
la classe Arme. Pour cela, crons dans cette classe une nouvelle mthode frapper() :
1
2
3

public function frapper ( cible : Personnage ) : void


{
var degatsAppliques : int = degats ;

4
5

6
7
8
9
10
11

// On jette un d 100 faces : si le r sultat est inf


rieur ou gal la chance de coup critique , l '
attaque fait un coup critique !
if ( Math . random () * 100 <= chanceCritique )
{
trace ( " Critique ! " ) ;
// On double les d g ts !
degatsAppliques *= 2 ;
}

12
13

// On applique les d g ts

169

CHAPITRE 10. LES CLASSES (2NDE PARTIE)


cible . sante -= degatsAppliques ;

14
15

Il va donc falloir appeler cette nouvelle mthode dans la mthode attaquer() de la


classe Personnage :
1
2
3
4
5
6
7
8
9

public function attaquer ( cible : Personnage ) : void


{
if ( armeEquipee == null )
{
trace ( " Aucune arme quip e : l ' attaque choue . "
);
}
else
{
armeEquipee . frapper ( cible ) ; // Nous appelons la
nouvelle m thode ici

10
11
12
13
14
15
16
17
18

19
20

if ( cible . sante <= 0 )


{
trace ( " La cible est d c d e . " ) ;
}
else
{
trace ( " Il reste " + cible . sante + " PV
la cible . " ) ;
}

Les classes
Lun des intrts de lutilisation de la reprsentation UML est justement de faciliter cette tape de conception et dorganisation des diffrentes classes dun mme
programme. Cela permet de visualiser la structure dun projet en ne faisant ressortir
que les informations utiles et ainsi, programmer plus rapidement et de manire plus
propre.
Finalement, vos classes devraient ressembler la figure 10.4.
Voici le code complet de nos classes :
1
2

package
{

3
4
5

public class Personnage


{

6
7
8
9

170

// Sant du personnage
private var _sante : int ;

EXERCICE : JEU DE RLE

Figure 10.4 Les classes Personnage et Arme

10
11

// Amre quip e
private var _armeEquipee : Arme ;

12
13
14
15
16

public function Personnage ()


{
sante = 100 ;
}

17
18
19
20
21

public function get sante () : int


{
return _sante ;
}

22
23
24
25
26

public function set sante ( value : int ) : void


{
_sante = value ;
}

27
28
29
30
31

public function get armeEquipee () : Arme


{
return _armeEquipee ;
}

32
33
34
35
36

public function set armeEquipee ( value : Arme ) : void


{
_armeEquipee = value ;
}

37
38
39
40
41
42
43
44

public function attaquer ( cible : Personnage ) : void


{
if ( armeEquipee == null )
{
trace ( " Aucune arme quip e : l ' attaque choue . "
);
}
else

171

CHAPITRE 10. LES CLASSES (2NDE PARTIE)


{

45
46

armeEquipee . frapper ( cible ) ;

47
48
49
50
51
52
53
54
55
56
57
58
59

1
2

if ( cible . sante <= 0 )


{
trace ( " La cible est d c d e . " ) ;
}
else
{
trace ( " Il reste " + cible . sante + " PV la
cible . " ) ;
}

package
{

3
4
5

public class Arme


{

6
7
8

// D g ts de l ' arme
private var _degats : int ;

9
10
11

// Chances de faire un coup critique ( sur 100 )


private var _chanceCritique : int ;

12
13
14
15
16
17

public function Arme ()


{
degats = 0 ;
chanceCritique = 0 ;
}

18
19
20
21
22

public function get chanceCritique () : int


{
return _chanceCritique ;
}

23
24
25
26
27

public function set chanceCritique ( value : int ) : void


{
_chanceCritique = value ;
}

28
29
30
31
32
33

172

public function get degats () : int


{
return _degats ;
}

EXERCICE : JEU DE RLE


public function set degats ( value : int ) : void
{
_degats = value ;
}

34
35
36
37
38

public function frapper ( cible : Personnage ) : void


{
var degatsAppliques : int = degats ;

39
40
41
42

// On jette un d 100 faces : si le r sultat est


inf rieur ou gal la chance de coup critique ,
l ' attaque fait un coup critique !
if ( Math . random () * 100 <= chanceCritique )
{
trace ( " Critique ! " ) ;
// On double les d g ts !
degatsAppliques *= 2 ;
}

43

44
45
46
47
48
49
50
51
52
53
54
55

// On applique les d g ts
cible . sante -= degatsAppliques ;

Le programme
Le programme principal ne change pas par rapport la solution prcdente :
1
2
3

var epeeLegendaire : Arme = new Arme () ;


epeeLegendaire . degats = 80 ;
epeeLegendaire . chanceCritique = 50 ;

4
5
6
7

var hacheDeGuerre : Arme = new Arme () ;


hacheDeGuerre . degats = 40 ;
hacheDeGuerre . chanceCritique = 10 ;

8
9
10

var moi : Personnage = new Personnage () ;


moi . armeEquipee = epeeLegendaire ;

11
12
13

var mechant : Personnage = new Personnage () ;


mechant . armeEquipee = hacheDeGuerre ;

14
15
16
17
18

trace ( " Le m chant m ' attaque ! " ) ;


mechant . attaquer ( moi ) ;
trace ( " Il va conna tre ma fureur ! A l ' attaque ! " ) ;
moi . attaquer ( mechant ) ;

173

CHAPITRE 10. LES CLASSES (2NDE PARTIE)


Rsultat
Enfin, voici le rsultat de lexcution de notre programme :
Le
Il
Il
Il

m chant m attaque !
reste 60 PV la cible .
va conna tre ma fureur ! A l attaque !
reste 20 PV la cible .

En rsum
Il est possible dutiliser des lments dits statiques qui sont directement lis la
classe et non ses instances.
Ces lments statiques sont dclars laide du mot-cl static et facilitent
lajout de fonctionnalits au programme.
Il est impossible dutiliser le mot-cl this dans les mthodes statiques.
Nous pouvons crer des constantes qui sont similaires aux variables, mais qui ne
peuvent pas tre modifies.
Pour dclarer une constante, nous devons utiliser le mot-cl const.
Il est possible de combiner les classes entre elles : les objets peuvent alors contenir
dautres objets.

174

Chapitre

11

Lhritage
Difficult :
Dans ce chapitre, nous allons parler dhritage ! Sachez quil sagit de lune des notions les
plus importantes de la Programmation Oriente Objet et qui en font tout son intrt !
Nous dtaillerons ce concept tout au long du chapitre, mais pour vous situer rapidement
ce dont il sagit, cela permet de crer une ou des nouvelles classes en se basant sur une
autre. Ainsi, nous pouvons crire des classes qui sont similaires en utilisant une autre classe
qui regroupe lensemble des proprits communes. Dans ce chapitre, la seule difficult que
vous aurez affronter sera la notion dhritage en elle-mme. Au niveau du code, il ny
aura pas normment de nouveauts, ce qui vous simplifiera la vie !

175

CHAPITRE 11. LHRITAGE

La notion dhritage
Nous avons dj brivement prsent le concept dans les parties prcdentes, cependant,
vu son importance, il nest pas superflu dy revenir ! Lhritage permet de crer une ou
des nouvelles classes en rutilisant le code dune classe dj existante. On parle alors
de classe de base ou superclasse ou encore classe-mre pour cette dernire, et
de sous-classes ou classes-filles pour les classes hrites de celle-ci. Lide est donc
ici dtendre une classe de base, notamment en lui ajoutant de nouvelles proprits.
Dailleurs, le mot-cl qui permet dtendre une classe est extends :
public class Hello extends Sprite {

1
2
3

Nous reviendrons sur la syntaxe Actionscript plus tard. Pour linstant, nous allons
principalement nous focaliser sur la notion dhritage.
Quand est-ce utile dutiliser lhritage ?

Cest en effet une question laquelle les dbutants ont souvent du mal rpondre. En
ralit, nous pouvons introduire une relation dhritage lorsque la condition suivante
est respecte : la sous-classe est un sous-ensemble de la superclasse.
Ce terme mathmatique barbare signifie que la sous-classe appartient lensemble
de la superclasse. Si ce nest pas encore bien clair, voici quelques exemples qui vous
aideront bien comprendre :

LActionscript appartient lensemble des langages de programmation.


Les fourmis appartiennent lensemble des insectes.
Les avions appartiennent lensemble des vhicules.
Les voitures appartiennent galement lensemble des vhicules.
Les 4L appartiennent lensemble des voitures.

Comme vous pouvez le constater, les relations prcdentes ne peuvent seffectuer que
dans un seul sens. Vous remarquerez galement, daprs les deux derniers exemples,
quil est possible davoir plusieurs niveaux dhritage.
En quoi est-ce diffrent dune instance de classe ?

Il est vrai quil serait possible, par exemple, de crer des instances Avion et Voiture
dune classe Vehicule. Nous pourrions de cette manire dfinir des valeurs distinctes
pour chacun des attributs afin de les diffrencier. En utilisant le concept dhritage,
nous pourrions crire deux sous-classes Avion et Voiture qui hriteraient de lensemble
des attributs et mthodes de la superclasse, et ce sans rcrire le code lintrieur de
celles-ci. Mais tout lintrt vient du fait que lutilisation de lhritage nous permet de
176

CONSTRUCTION DUN HRITAGE


dfinir de nouveaux attributs et de nouvelles mthodes pour nos sous-classes. Sachez
quil est galement possible de redfinir des mthodes de la superclasse, mais
nous en reparlerons quand nous introduirons le polymorphisme plus loin dans ce
chapitre !

Construction dun hritage


Dans la suite de ce chapitre, nous allons principalement nous intresser aux manipulations du ct des classes-filles. Cependant, nous aurons besoin dune superclasse
partir de laquelle nous pourrons travailler. Ainsi, je vous propose une classe Vehicule,
dont le code est donn ci-dessous :
1
2
3
4
5
6

package
{
public class Vehicule
{
protected var _marque : String ;
protected var _vitesse : int ;

public function Vehicule ( marque : String , vitesse : int )


{
_marque = marque ;
_vitesse = vitesse ;
}

8
9
10
11
12
13

public function get marque () : String


{
return _marque ;
}

14
15
16
17
18

public function get vitesse () : int


{
return _vitesse ;
}

19
20
21
22
23

public function set vitesse ( vitesse : int ) : void


{
_vitesse = vitesse ;
}

24
25
26
27
28

29
30
31

177

CHAPITRE 11. LHRITAGE

La porte protected
Nous avions rapidement mentionn cette porte sans en expliquer vraiment le fonctionnement. Maintenant vous savez comment fonctionne lhritage, nous allons pouvoir
utiliser cette nouvelle porte quest protected ! Cette porte a t introduite afin de
rendre les proprits visibles non seulement depuis la classe o elles sont dfinies comme
private, mais galement depuis lensemble de ses sous-classes. Voyez les attributs de
la classe Vehicule dfinie juste avant :
protected var _marque : String ;
protected var _vitesse : int ;

1
2

Ces attributs seront donc visibles depuis les ventuelles sous-classes que nous pourrons
dfinir.
Lorsque nous avions introduit le concept dencapsulation, nous avions dit
quil fallait spcifier une porte de type private tous vos attributs. Or,
comme nous lavons dit, les attributs de ce type ne sont accessibles que depuis
la classe o ils ont t dclars. Cest pourquoi, il est maintenant prfrable
dopter pour la porte protected chaque fois que lune de vos classes est
susceptible devenir une superclasse. En pratique, on utilise quasiment tout
le temps cette porte dans lhypothse dun hritage futur.
prsent, vous connaissez lensemble des portes que propose lActionscript, dont
voici un petit rcapitulatif :
public : proprit visible nimporte o.
private : proprit visible uniquement lintrieur de la classe qui la dfinie.
protected : proprit visible depuis la classe o elle est dfinie ainsi que depuis
lensemble de ses sous-classes.
internal : proprit visible depuis lensemble du package o elle est dfinie.

Construction des sous-classes


Lhritage
Comme nous lavons dit en dbut de chapitre, lhritage se fait en tendant une
classe laide du mot-cl extends comme ceci :
1
2
3
4

package
{
public class Voiture extends Vehicule
{

5
6
7

178

CONSTRUCTION DUN HRITAGE


Attention lordre dans lequel sont placs les diffrents lments. Nous
sommes ici en train de dclarer une nouvelle classe nomme Voiture qui
hrite de la classe Vehicule.
Par cette simple extension, la classe Voiture hrite donc de lensemble des proprits de
la classe Vehicule. Il est toutefois ncessaire de lui rajouter au moins un constructeur,
et, ventuellement, quelques proprits supplmentaires pour lui donner de lintrt.
Par exemple, nous pourrions introduire un attribut _traction pour dfinir si la voiture
est une traction ou non, ou encore un attribut _immatriculation pour identifier celleci :
1
2
3
4
5
6
7
8

package
{
public class Voiture extends Vehicule
{
protected var _traction : Boolean ;
protected var _immatriculation : String ;
}
}

Le constructeur
Comme toute classe, notre sous-classe Voiture doit possder un constructeur. Cependant, celle-ci hrite dune classe-mre qui possde son propre constructeur qui
est ncessaire linitialisation des attributs. Depuis une classe-fille, il est possible
dappeler le constructeur de sa superclasse par la fonction super() :
1
2
3
4
5

public function Voiture ()


{
super () ;
// Instructions suppl mentaires
}

Lappel du constructeur super() de la superclasse doit obligatoirement tre


la premire instruction du constructeur de votre sous-classe. Les nouvelles
instructions seront places la suite pour permettre linitialisation de vos
nouvelles variables.
Voici donc un exemple de constructeur pour notre classe Voiture :
1
2
3
4
5
6

public function Voiture ( marque : String , vitesse : int ,


immatriculation : String )
{
super ( marque , vitesse ) ;
_immatriculation = immatriculation ;
_traction = true ;
}

179

CHAPITRE 11. LHRITAGE


Vous remarquerez que la fonction super() est le constructeur de la superclasse. Il est donc normal de retrouver les diffrents paramtres du constructeur dfini plus haut.

Les mthodes
En plus de pouvoir dfinir de nouveaux attributs, il est possible de rajouter autant de
mthodes que nous souhaitons lintrieur dune sous-classe. tant donn nous utilisons encore le concept dencapsulation, nous commencerons par crer des accesseurs
ce nouvel attribut. Je vous propose de dcouvrir quelques-uns dentre eux :
1
2
3
4

public function set immatriculation ( no uv el l eI mm at r ic ul a ti on :


String ) : void
{
_immatriculation = no uv e ll eI mm a tr ic ul a ti on ;
}

5
6
7
8
9

public function get immatriculation () : String


{
return _immatriculation ;
}

Comme vous pouvez le voir, ces mthodes fonctionnent exactement de la mme manire que pour une classe quelconque. En revanche, ce qui peut tre intressant, cest
dutiliser les mthodes dfinies lintrieur de la classe mre. Ainsi, si les mthodes de
votre classe mre ont une porte public ou protected, celles-ci sont accessibles depuis
les classes filles. Nous avons ainsi un mot-cl super qui nous permet de faire rfrence
la superclasse et dutiliser ses proprits. Voici, par exemple, une mthode nomme
accelerer() qui permet daugmenter la vitesse du vhicule :
1
2
3
4
5

public function accelerer () : void


{
var nouvelleVitesse : int = super . vitesse + 15 ;
super . vitesse = nouvelleVitesse ;
}

Vous noterez que nous aurions pu utiliser directement lattribut _vitesse de


la classe Vehicule pour dfinir la variable nouvelleVitesse. En revanche,
nous sommes obligs dutiliser laccesseur vitesse() pour modifier la valeur
de lattribut. En effet, seules les proprits dfinies par le mot-cl function,
donc les mthodes, peuvent tre redfinies. Nous reviendrons l-dessus juste
aprs, lorsque nous parlerons du polymorphisme.

Le mot-cl super fait rfrence lobjet via la classe-mre, par opposition


au mot-cl this qui pointe sur lobjet en lui-mme.
180

CONSTRUCTION DUN HRITAGE


Nanmoins, le mot-cl super est facultatif dans la plupart des cas. Le code ci-dessous
est tout fait fonctionnel :
1
2
3
4
5

public function accelerer () : void


{
var nouvelleVitesse : int = vitesse + 15 ; // L ' accesseur de
la classe - m re sera automatiquement s lectionn
vitesse = nouvelleVitesse ;
}

Il peut mme tre simplifi (vu que vous avez compris le principe) :
1
2
3
4

public function accelerer () : void


{
vitesse += 15 ;
}

Rappel : les accesseurs simulent le fonctionnement des attributs. Il est donc


possible dutiliser ici tous les oprateurs mathmatiques : vitesse est considr comme un nombre.
Comme je nai pas tout rcrit, je vous propose tout de mme un schma UML
rsumant les proprits des deux classes Vehicule et Voiture ainsi que le lien qui les
unit la figure 11.1.

Figure 11.1 Hritage entre les classes Vehicule et Voiture

181

CHAPITRE 11. LHRITAGE

La substitution dune sous-classe une superclasse


Un autre avantage de lutilisation de lhritage est le fait de pouvoir substituer
une sous-classe une superclasse. Cest--dire quil est possible de manipuler une
classe-fille comme sil sagissait dune instance de la classe-mre.
Parce quun exemple vaut mille mots, prenons le code suivant :
1
2
3
4
5
6
7

8
9
10
11
12
13

var MesVehicules : Array = new Array () ;


MesVehicules . push ( new Vehicule ( " Airbus A380 " , 900 ) ) ;
MesVehicules . push ( new Vehicule ( " Bicyclette " , 25 ) ) ;
MesVehicules . push ( new Voiture ( " Renault 4L " , 100 , " 911 SDZ 15 " ) )
;
for ( var i : int = 0 ; i < MesVehicules . length ; i ++)
{
trace ( " Un v hicule de type " + MesVehicules [ i ]. marque + "
peut se d placer la vitesse de " + MesVehicules [ i ].
vitesse + " km / h . " ) ;
}
/* Affiche :
Un v hicule de type Airbus A380 peut se d placer la vitesse
de 900km / h .
Un v hicule de type Bicyclette peut se d placer la vitesse de
25km / h .
Un v hicule de type Renault 4L peut se d placer la vitesse de
100km / h .
*/

Il ny a rien de surprenant dans cet exemple, les accesseurs de la classe Vehicule sont
bien accessibles depuis la classe Voiture. En revanche, ce qui deviendrait intressant,
ce serait de crer une mthode presenter() qui permet de prsenter un objet de type
Vehicule, comme ci-dessous :
1
2
3
4
5
6
7

8
9
10
11
12
13
14

var MesVehicules : Array = new Array () ;


MesVehicules . push ( new Vehicule ( " Airbus A380 " , 900 ) ) ;
MesVehicules . push ( new Vehicule ( " Bicyclette " , 25 ) ) ;
MesVehicules . push ( new Voiture ( " Renault 4L " , 100 , " 911 SDZ 15 " ) )
;
function presenter ( unVehicule : Vehicule ) : void
{
trace ( " Un v hicule de type " + unVehicule . marque + " peut
se d placer la vitesse de " + unVehicule . vitesse + " km
/h.");
}
for ( var i : int = 0 ; i < MesVehicules . length ; i ++)
{
presenter ( MesVehicules [ i ]) ;
}
/* Affiche :
Un v hicule de type Airbus A380 peut se d placer la vitesse
de 900km / h .

182

LE POLYMORPHISME
15
16
17

Un v hicule de type Bicyclette peut se d placer la vitesse de


25km / h .
Un v hicule de type Renault 4L peut se d placer la vitesse de
100km / h .
*/

Comment se fait-il quil ny ait pas derreur pour lobjet de type Voiture ?

Comme nous lavons dit plus haut dans ce cours, nous pouvons substituer une sousclasse une superclasse. En dautres termes, il est possible dutiliser une classe-fille
comme sil sagissait de la classe-mre. Dailleurs, si vous vous rappelez bien nous
avions dit quune sous-classe tait un sous-ensemble de la superclasse, ce qui veut
dire quune Voiture est un Vehicule. Il nest donc pas surprenant de pouvoir utiliser
un objet de type Voiture en tant que Vehicule.
Encore une fois, attention au sens de lhritage ! Dans notre exemple, il nest
pas possible de substituer un Vehicule une Voiture ; seul le sens oppos
est exact !

Le polymorphisme
Nous allons maintenant parler du polymorphisme ! Nous avons l-encore un nom
barbare associ un concept qui nest pas si compliqu en ralit.
Prcdemment, nous avons appris tendre une superclasse en ajoutant de nouvelles
mthodes lintrieur dune sous-classe. Cependant, il est galement possible de redfinir (rcrire) une mthode. Ainsi, nous avons la possibilit dutiliser un nom de
mthode commun pour une mthode qui se comportera diffremment suivant le type
de lobjet.
Pour vous montrer cela, nous allons insrer une nouvelle mthode quon nommera
sePresenter() lintrieur de la classe Vehicule :
1
2
3
4

public function sePresenter () : void


{
trace ( " Un v hicule de type " + marque + " peut se d placer
la vitesse de " + vitesse + " km / h . " ) ;
}

Rappel : il est conseill dutiliser les accesseurs dans la classe elle-mme (sauf
dans le constructeur).
Si nous ne faisons rien, la classe Voiture hritera de cette nouvelle mthode et nous
183

CHAPITRE 11. LHRITAGE


pourrons lutiliser sans problme. Cependant, nous aimerions personnaliser le message,
notamment en rajoutant son numro dimmatriculation qui permet galement de lidentifier. Nous devrons donc rcrire la mthode sePresenter() pour la classe Voiture.
Heureusement, nous disposons dun mot-cl override, qui permet justement de redfinir une mthode. Voici comment lutiliser :
1
2
3
4
5

override public function sePresenter () : void


{
trace ( " Une voiture " + marque + " peut se d placer la
vitesse de " + vitesse + " km / h . " ) ;
trace ( " Son immatriculation est : " + immatriculation ) ;
}

Ainsi, nous pouvons utiliser la mthode sePresenter() sans nous soucier du type
dobjets que nous sommes en train de manipuler.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

var MesVehicules : Array = new Array () ;


MesVehicules . push ( new Vehicule ( " Airbus A380 " , 900 ) ) ;
MesVehicules . push ( new Vehicule ( " Bicyclette " , 25 ) ) ;
MesVehicules . push ( new Voiture ( " Renault 4L " , 100 , " 911 SDZ 75 " ) )
;
for ( var i : int = 0 ; i < MesVehicules . length ; i ++)
{
MesVehicules [ i ]. sePresenter () ;
}
/* Affiche :
Un v hicule de type Airbus A380 peut se d placer la vitesse
de 900km / h .
Un v hicule de type Bicyclette peut se d placer la vitesse de
25km / h .
Une voiture Renault 4L peut se d placer la vitesse de 100km / h
.
Son immatriculation est : 911 SDZ 75
*/

Pour rsumer, le polymorphisme est une technique trs puissante, surtout


lorsquelle est associe la substitution dune sous-classe une superclasse.
Nous pouvons ainsi dfinir des mthodes par dfaut dans la classe-mre,
puis de les redfinir pour diffrentes classes-filles. Il est ensuite possible dutiliser ces diffrents objets de la mme faon comme sil sagissait de la mme
classe. Vous verrez dans la suite que cest un atout non ngligeable !

Les attributs de classe


Lorsque nous avions parl dencapsulation, nous avions introduit les droits daccs
pour les diffrentes proprits dune classe. Or, pour ceux qui lauraient galement
184

LES ATTRIBUTS DE CLASSE


remarqu, nous avons depuis le dpart toujours insr le mot-cl public devant la
dfinition de chacune de nos classes.
Il existe aussi des droits daccs pour les classes ?

En effet, tout comme les proprits, les classes possdent des droits daccs qui
permettent de dfinir comment nous pouvons accder la classe et mme la modifier.
En ralit, on parle dattributs de classes et dattributs de proprits de classes,
cependant, nous emploierons dans ce cours, le terme droits daccs pour viter la
confusion avec les variables internes aux classes appeles galement attributs.

Les diffrents droits daccs


En ce qui concerne la dfinition de classes, lActionscript propose quatre droits
daccs diffrents. Sans plus attendre, je vous propose de les dcouvrir :
public : les droits daccs publics permettent comme pour les proprits, de
rendre la classe visible et accessible partout dans le code. Il sagit des droits daccs
recommands dans la majorit des cas.
internal : identiquement aux proprits, les droits daccs internes restreignent laccessibilit de la classe au package o elle est dfinie uniquement. Ces
droits daccs ne sont pas trs utiliss, mais il sagit de la valeur par dfaut lors dune
dfinition de classe.
final : ces droits daccs sont directement lis la notion dhritage. Le terme
final fait ici rfrence au fait que la classe ne peut plus tre tendue par une
autre classe.
dynamic : ce mot-cl permet de dfinir une classe dynamique, cest--dire modifiable
depuis lextrieur de celle-ci, loppos des classes classiques dites scelles. Nous
reviendrons sur ce concept un peu particulier dans le prochain chapitre.
Pour rsumer tout ce qui concerne les droits daccs et lencapsulation, vous
devez vous rappeler quon doit principalement limiter laccs aux attributs en
utilisant prfrentiellement le mot-cl protected. Pour les mthodes et les
classes en gnral, vous privilgierez principalement un accs publique
laide du mot-cl public. Il existe nanmoins divers autres droits daccs
qui ne sont utiles que dans de rares occasions.

Exemple dutilisation
Vous laurez compris, ces droits daccs sutilisent galement devant la dclaration
de la classe en question. Voici par exemple la dfinition de la classe Vehicule que
nous avons ralise au dbut du chapitre :
185

CHAPITRE 11. LHRITAGE


1
2

public class Vehicule


{

3
4

Nous allons essayer ici de comprendre un peu mieux lutilit du mot-cl final, troitement li au concept dhritage ! Ce mot-cl permet de dfinir la classe laquelle il
est associ, comme tant la dernire classe qui finalise larborescence dhritage. Cela
signifie que cette classe peut trs bien hriter dune autre classe, mais en aucun cas
vous ne pourrez crer de classes-filles celle-ci. Je vous propose donc une petite manipulation afin de vrifier la vracit de ces propos. Redfinissez donc la classe Vehicule
de type final :
1
2
3
4
5
6

package
{
final class Vehicule
{
protected var _marque : String ;
protected var _vitesse : int ;

public function Vehicule ( marque : String , vitesse : int )


{
_marque = marque ;
_vitesse = vitesse ;
}

8
9
10
11
12
13

public function get marque () : String


{
return _marque ;
}

14
15
16
17
18

public function get vitesse () : int


{
return _vitesse ;
}

19
20
21
22
23

public function set vitesse ( vitesse : int ) : void


{
_vitesse = vitesse ;
}

24
25
26
27
28

29
30
31

Nous avons donc maintenant une classe Vehicule quil nous est interdit dtendre.
Voyons donc ce qui se passe lorsquon tente den crer une sous-classe :
1
2
3

package
{
public class Voiture extends Vehicule

186

LES ATTRIBUTS DE CLASSE


{

4
5
6
7

Si vous tentez donc de lancer votre programme, le compilateur refusera de compiler le


projet en vous prcisant lerreur suivante : Base class is final. , qui signifie que la
classe dont on essaie dhriter est de type final et que notre hritage est donc contraire
cette dfinition de classe.
Comme vous pouvez le constater, ce mot-cl final napporte aucune relle
fonctionnalit, mais il sagit plutt dune scurit. Nanmoins, lutilit de ce
type de droits daccs est assez restreinte et vous dfinirez majoritairement
des classes de type public.

En rsum
Lhritage permet de crer une ou des nouvelles classes en utilisant le code dune
classe dj existante.
Pour hriter dune classe, il faut utiliser le mot-cl extends.
La porte protected est spcifique lhritage.
Le constructeur de la superclasse peut tre appel par la fonction super().
Dans le cas dune relation par hritage, il est possible de substituer une sous-classe
une superclasse.
Le polymorphisme permet de redfinir une mthode de la superclasse par lintermdiaire du mot-cl override.
Les diffrents droits daccs lis la dfinition dune classe sont public, internal,
final et dynamic.

187

CHAPITRE 11. LHRITAGE

188

Chapitre

12

Notions avances de la POO


Difficult :
Nous allons maintenant dcouvrir des notions disons plus. . . avances de la POO.
Avant de dmarrer ce chapitre, laissez-moi vous prciser que les concepts abords ici sont
gnralement rservs aux projets complexes ou denvergure. Il est donc fort probable que
vous nutilisiez pas ces concepts dans vos premiers projets et mme que vous nen voyez
pas encore lutilit. Cest pourquoi, il nest pas essentiel pour la suite du cours dtre
totalement au clair avec ces notions. Lisez donc attentivement ce chapitre, mais nhsitez
pas y revenir plus tard pour effectuer une lecture plus approfondie.

189

CHAPITRE 12. NOTIONS AVANCES DE LA POO

Les classes dynamiques


Dfinition de la classe de base
Nous allons ici revenir sur la notion de classes dynamiques prsente dans le chapitre prcdent. Contrairement aux classes normales dites scelles , le principe des
classes dynamiques est de pouvoir rajouter de nouvelles proprits lors de lexcution du programme. Bien videmment, avant dajouter de nouvelles proprits, il
est dabord ncessaire de dfinir une classe de base, mais cette fois laide du type
dynamic.
Nous allons donc partir dune classe Personnage trs basique :
1
2

package
{

dynamic class Personnage


{

4
5
6

protected var _sante : int ;

7
8

public function Personnage ()


{
sante = 100 ;
}

9
10
11
12
13

public function get sante () : int


{
return _sante ;
}

14
15
16
17
18
19
20
21
22
23
24

public function set sante ( value : int ) : void


{
_sante = value ;
}

Nous en reparlerons un peu plus loin, mais notez toutefois quune classe
dynamique respecte le principe dencapsulation. Nous avons ainsi nos attributs qui sont restreints la classe ainsi qu dventuelles sous-classes.
Nous pouvons ainsi instancier autant de fois quon veut cette classe Personnage, comme
ci-dessous :
1
2

var guerrier : Personnage = new Personnage () ;


var magicien : Personnage = new Personnage () ;

Nous allons maintenant voir comment tendre les fonctionnalits de notre classe durant
190

LES CLASSES DYNAMIQUES


lexcution en ajoutant de nouvelles proprits celle-ci.

Dfinition de proprits hors de la classe


En pratique
Maintenant que notre classe Personnage est dfinie de type dynamic, nous allons pouvoir crer une instance de celle-ci, puis lui ajouter de nouvelles proprits. Comme
vous avez pu le deviner, la dfinition de nouvelles proprits se fait partir dune occurrence de la classe en question. Nous allons donc prendre lexemple dun magicien :
1

var magicien : Personnage = new Personnage () ;

Ce type de personnage pourrait donc tre dot de facults magiques. Nous allons donc
lui rajouter un nouvel attribut _mana qui dfinit la rserve de magie du personnage :
1

magicien . _mana = 50 ;

Nous avons ainsi cr ici un nouvel attribut nomm _mana. Cette nouvelle proprit sera
alors effective lexcution du code et sera lie uniquement loccurrence magicien
de la classe Personnage. Cest pourquoi, un nouvel objet guerrier de cette classe, ne
disposerait pas de cet attribut.
Lutilisation de classes dynamiques ne se limite pas simplement la dfinition de nouveaux attributs, mais stend galement la dfinition de nouvelles mthodes. Dfinissons par exemple une nouvelle mthode lancerSort() spcifique linstance magicien
de la classe Personnage :
1
2
3
4
5

magicien . lancerSort = function ( cible : Personnage ) : void


{
cible . sante -= 25 ;
_mana -= 20 ;
};

Nous pouvons ainsi appeler cette mthode comme nimporte quelle autre de la classe
de base :
1

magicien . lancerSort ( guerrier ) ;

Comme vous pouvez le constater, les expressions de fonction sont particulirement utiles pour la dfinition de mthodes de classes dynamiques.

Remarques importantes
Vous aurez certainement remarqu labsence de droits daccs lis aux nouvelles
proprits. En effet, il nest pas ncessaire de les spcifier, tant donn que ces proprits
191

CHAPITRE 12. NOTIONS AVANCES DE LA POO


sont lies linstance de la classe et non la classe elle-mme. Ainsi, celles-ci ne sont
accessibles qu partir de loccurrence o elles ont t dfinies.
Pour revenir sur la notion dencapsulation, les portes private et protected limitent laccs des proprits auxquelles elles sont associes la classe uniquement, ou
ventuellement aux classes filles. Ainsi dans le cas des classes dynamiques, la dfinition de nouvelles proprits se fait lextrieur de la classe de base. Cest pourquoi
nous navons pas accs aux proprits prives dans la dfinition de ces nouvelles
proprits lors de lexcution du code.
Pourquoi passer par des classes dynamiques alors que lhritage permet
dj de faire tout cela ?
Il est vrai que dans la quasi totalit des cas, vous naurez pas besoin de passer par
la dfinition de classes dynamiques. Dailleurs, ces dernires ne permettent pas de
sparer la dfinition dune classe de son utilisation par la cration dinstances. Cest
la raison pour laquelle, il est toujours prfrable de passer par la conception de classes
non dynamiques. Cependant, ces classes dynamiques peuvent trouver leur utilit
lorsque des proprits dpendent de certaines donnes dont on ne dispose pas la
compilation. Quoi quil en soit, si vous ne savez pas quelle solution utiliser, prfrez
lhritage aux classes dynamiques chaque fois que cela est possible !

Les interfaces
Problme
Introduction
Pour introduire les interfaces, nous allons nous servir dun exemple. Nous allons reprendre lide de crer des personnages pour un jeu quelconque. Pour cela, nous allons
garder notre classe de base nomme Personnage. Cependant, nous voulons dans notre
jeu, non pas avoir de simples instances de la classe Personnage, mais plutt des lutins, des elfes et des ogres qui hritent de cette classe de base. Ceux-ci possdent alors
des aptitudes diffrentes que lon pourrait classer dans deux catgories : Magicien et
Guerrier !
Voici donc une prsentation des diffrentes races :
Lutin : ces petits bonhommes aux pouvoirs sensationnels se servent exclusivement
de la magie et possdent donc uniquement les aptitudes de la catgorie Magicien.
Elfes : ces tres baigns dans la magie, ont galement un certain talent dans la
conception et lutilisation darmes ; ils sont donc la fois Magicien et Guerrier.
Ogres : ces brutes tout droit sorties des grottes nont aucun sens de la magie, et
possdent donc seulement les aptitudes de la catgorie Guerrier.
Nous allons donc voir ici les problmes auxquels nous allons nous heurter pour conce192

LES INTERFACES
voir le code de ces diffrentes classes, toutefois, nous verrons quil est possible de les
contourner.

Les limites de lhritage


Lobjectif ici est donc de concevoir trois classes pour notre jeu : Lutin, Elfe et Ogre.
Pour raliser cela, vous pourriez avoir lide dutiliser de concept dhritage. Nous
pourrions donc organiser nos diffrentes classes suivant un double hritage. Ainsi, nous
aurions donc une classe de base Personnage, dont hriteraient les deux classes suivantes : Magicien et Guerrier. Puis nos trois classes Lutin, Elfe et Ogre seraient des
classes filles ces deux dernires. Ceci ne poserait aucun problme en ce qui concerne
les classes Lutin et Ogre. Seulement voil, la classe Elfe devrait alors hriter en mme
temps des deux classes Magicien et Guerrier, or ceci est interdit.
En effet, si dans certains langages tels que le C++, les hritages multiples
sont autoriss, cette pratique est interdite en Actionscript. Ainsi, une classe
ne peut hriter que dune unique superclasse !
Cependant, il existe un concept en Actionscript qui permet de contourner ce problme : les interfaces !

Utilisation des interfaces


Le principe
Une interface nest pas vraiment une classe, il sagit plutt dune collection de dclarations de mthodes. Contrairement aux classes, vous ne trouverez ni attribut ni
constructeur au sein dune interface. De plus, le terme dclaration de la dfinition prcdente nous indique que nous nous contenterons de dcrire les mthodes.
Ainsi, nous dfinirons la manire dont doit tre construite chacune des mthodes sans
en prciser le fonctionnement interne. Voici comment procder pour une dclaration
dune mthode :
1

function uneMethode ( param : String ) : void ;

De la mme faon que pour une dclaration de variable, vous remarquerez quon
omet le contenu de la mthode normalement plac entre accolades. Toutefois, nous
retrouvons dans cette dclaration lensemble des informations utiles de la mthode,
savoir : le nom de la fonction, les diffrents paramtres, le type de valeur renvoy.
Une interface sera donc un ensemble de dclarations de mthodes, regroupes
autour dune utilit commune. Nous pourrons ainsi crer de nouvelles classes qui utilisent ces interfaces et nous redfinirons lensemble des mthodes. On appelle cela
limplmentation !
193

CHAPITRE 12. NOTIONS AVANCES DE LA POO

Quel est lintrt des interfaces si il faut redfinir lensemble des mthodes ?

tant donn que le contenu des mthodes nest pas dfini lintrieur des interfaces, il
va bien videmment falloir le faire dans les classes qui les implmentent. Cest pourquoi,
il est fort probable que vous vous demandiez quoi pourrait bien vous servir ce concept.
Je vais donc essayer de vous lexpliquer en quelques mots.
Lorsque nous avions vu la notion dencapsulation, je vous avais prcis le fait que nous
devions masquer le fonctionnement interne dune classe lutilisateur de celle-ci. Ainsi,
lutilisation de la classe devenait plus aise car nous navions plus qu manipuler des
mthodes explicites qui se chargeaient du travail laborieux. Une interface va donc nous
servir dcrire linterface dune pseudo-classe, cest--dire, prsenter celle-ci telle
quelle est vue de lextrieur. Nous obtiendrons donc une sorte de mode demploi
qui explique comment cette pseudo-classe doit tre manipule.
Nous conviendrons que le concept dinterfaces na dutilit que dans de gros
projets. Cela permet de dfinir les normes respecter, et ainsi, de garantir
la compatibilit des classes qui les implmenteront. Ces dernires pourront
alors tre utilises de la mme manire malgr les diffrences de contenu
lintrieur de chacune des mthodes. Cela vient donc complter la notion de
polymorphisme et lide de pouvoir utiliser des objets diffrents comme sil
sagissait du mme.
Ce morceau consquent de thorie va maintenant laisser place la pratique qui, je suis
daccord avec vous, permet en gnral de mieux cerner la chose.
Les bases de la conception
prsent, nous allons reprendre notre problme de personnages concernant des lutins,
des elfes et des ogres ! Parce quun schma est toujours plus explicite quun long discours, je vous laisse dcouvrir la figure 12.1 lensemble de ces classes et interfaces que
nous allons raliser.
En premier lieu, nous allons crer une classe Personnage en tant que superclasse pour
la suite. Celle-ci na rien dextraordinaire puisquelle est identique ce que nous avons
ralise prcdemment. Je vous laisse nanmoins le temps de la reprendre avant de
passer la suite :
1
2

package
{

3
4
5

public class Personnage


{

6
7
8

194

protected var _sante : int ;

LES INTERFACES

Figure 12.1 Les classes et les interfaces que nous allons raliser
public function Personnage ()
{
sante = 100 ;
}

9
10
11
12
13

public function get sante () : int


{
return _sante ;
}

14
15
16
17
18
19
20
21
22
23
24

public function set sante ( value : int ) : void


{
_sante = value ;
}

Les interfaces
Nous voil enfin au cur du problme, nous allons devoir crer les deux interfaces
Magicien et Guerrier ! tant donn quil sagit dun exemple, nous nallons pas raliser des dizaines de dclarations de mthodes. Je vous propose ainsi de lier deux mthodes lancerSort et guerison notre interface Magicien. Voici donc notre premire
interface :
1
2

package
{

195

CHAPITRE 12. NOTIONS AVANCES DE LA POO


3
4
5
6
7
8

public interface Magicien


{
function lancerSort ( cible : Personnage ) : void ;
function guerison () : void ;
}

Dclarons galement deux mthodes pour notre seconde interface, nommes assenerCoup
et seSoigner. En voici le rsultat :
1
2
3
4
5
6
7
8

package
{
public interface Guerrier
{
function assenerCoup ( cible : Personnage ) : void ;
function seSoigner () : void ;
}
}

prsent, nous disposons des bases ncessaires la cration de nos classes relles ,
cest--dire celles que nous utiliserons dans la pratique. Nous pourrons ainsi combiner
les notions dhritage et dimplmentation pour raliser celles-ci.
Notez que dans cet exemple nous utilisons simultanment les notions
dhritage et dimplmentation. Toutefois, en pratique, il nest pas dobligatoire de procder un hritage pour utiliser les interfaces. Il est donc
tout fait possible dutiliser uniquement la notion dimplmentation.

Limplmentation
Tout comme nous avions le mot-cl extends pour lhritage, nous utiliserons implements
pour implmenter une interface dans une classe. tant donn que le contenu de
chacune des mthodes nest pas dfini dans les interfaces, nous allons devoir le faire ici.
Je vous propose donc de dcouvrir les trois classes finales qui implmenteront donc
les interfaces dfinies juste avant. Commenons par la classe Lutin :
1
2

package
{

3
4
5

public class Lutin extends Personnage implements Magicien


{

6
7
8
9
10

public function Lutin ()


{
super () ;
}

11
12

196

public function lancerSort ( cible : Personnage ) : void

LES INTERFACES
{

13
14
15
16
17
18
19
20
21
22
23

cible . sante -= 10 ;
trace ( " Sort : Boule de feu " ) ;

}
public function guerison () : void
{
this . sante += 10 ;
trace ( " Sort : Gu rison " ) ;
}

La classe Elfe est sans doute la plus complexe, puisquelle implmente les deux interfaces la fois :
1
2

package
{

public class Elfe extends Personnage implements Magicien ,


Guerrier
{

4
5
6

public function Elfe ()


{
super () ;
}

7
8
9
10
11

public function lancerSort ( cible : Personnage ) : void


{
cible . sante -= 5 ;
trace ( " Sort : Tornade " ) ;
}

12
13
14
15
16
17

public function guerison () : void


{
this . sante += 5 ;
trace ( " Sort : Gu rison " ) ;
}

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

public function assenerCoup ( cible : Personnage ) : void


{
cible . sante -= 5 ;
trace ( " Coup : p e " ) ;
}
public function seSoigner () : void
{
this . sante += 5 ;
trace ( " Soin : Herbe m dicinale " ) ;
}

197

CHAPITRE 12. NOTIONS AVANCES DE LA POO


Lorsque lon ralise un hritage et une ou plusieurs implmentations en
mme temps, lhritage doit toujours tre effectu en premier. Cest pourquoi le mot-cl extends sera toujours plac avant implements dans la
dclaration de la classe. Vous remarquerez galement que les diffrentes
interfaces implmentes ici sont spares par une virgule.
Enfin, la classe Ogre ne devrait maintenant plus poser de problmes :
1
2

package
{

public class Ogre extends Personnage implements Guerrier


{

4
5
6

public function Ogre ()


{
super () ;
}

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

public function assenerCoup ( cible : Personnage ) : void


{
cible . sante -= 10 ;
trace ( " Coup : Hache de guerre " ) ;
}
public function seSoigner () : void
{
this . sante += 10 ;
trace ( " Soin : Bandage " ) ;
}

Sachant que les mthodes sont dclares uniquement lintrieur des interfaces, celles-ci doivent obligatoirement tre redfinies dans les classes qui les
implmentent. Veillez donc bien toutes les redfinir sous peine de messages
derreurs lors de la compilation de votre projet.

Plus loin avec les interfaces


Nous avons vu le principe des interfaces, mais je vais ici vous prsenter une utilisation
qui en fait tout leur intrt !
Imaginez maintenant que vous vouliez crer un jeu beaucoup plus complet, qui risque
dvoluer dans une version ultrieure. Vous voulez cette fois multiplier le nombre
des races des personnages avec, par exemple, les classes Humain, Nain, Lutin, Elfe,
Centaure, Minotaure, Ogre, Gnome et Troll. Cette fois, vous navez plus de simples
magiciens ou de purs guerriers, mais chacune des races dispose de lensemble des facul198

LES INTERFACES
ts. Ainsi, chaque espce est capable de lancer des sorts ou de se battre avec nimporte
quel type darmes. En revanche, chacun possde une liste limite de sorts au dpart,
mais peut la dvelopper au fil du jeu. Tous ces sorts sont utiliss de la manire, seuls
leurs effets et leurs dgts sont diffrents de lun lautre.
Une architecture judicieuse de vos classes serait alors de crer une interface Sort, qui
serait implmente par chacun de vos divers sorts. Lintrt serait alors de pouvoir crer
une liste de sort de type Vector.<Sort> comme attribut de votre classe Personnage.
Chaque sort serait alors utilis de la mme faon quel que soit celui-ci.
Voici un schma la figure 12.2 qui rsume la situation et qui devrait plus facilement
vous sduire.

Figure 12.2 Crez une interface Sort


Vous pouvez ainsi crer un nouvel Ogre nomm budoc. Hritant de la classe Personnage,
votre personnage va pouvoir apprendre de nouveaux sorts au fil du jeu. Voici, par
exemple, notre ami budoc qui apprend les sorts Guerison et Eclair :
1
2
3

var budoc : Ogre = new Ogre () ;


budoc . ajouterSort ( new Guerison () ) ;
budoc . ajouterSort ( new Eclair () ) ;

Je vous ai prsent le concept avec les interfaces, mais sachez que cette
pratique peut galement tre utilise avec la relation dhritage, mme si
cela est moins courant. Au risque de me rpter encore une fois, une des
grandes forces de la POO est justement de pouvoir se servir dobjets diffrents
de la mme manire grce ces techniques dhritage, de polymorphisme
et dimplmentation.
Nous sommes maintenant arrivs au bout de ces explications sur les interfaces. Jespre
vous avoir convaincus de leur utilit et jose croire que vous les utiliserez de la bonne
faon.
199

CHAPITRE 12. NOTIONS AVANCES DE LA POO

Les classes abstraites


Le concept
Une classe abstraite est une classe que lon ne peut pas instancier, cest--dire que lon
ne peut pas directement crer dobjet de cette classe avec le mot-cl new. Lorsque lon
choisit de rendre une classe abstraite, on restreint ainsi ses possibilits dutilisation.
Par contre, les sous-classes de cette classe abstraite ne sont pas forcment abstraites,
moins de lindiquer chaque fois !
Pour comprendre pourquoi cela pourrait amliorer la cohrence de votre code, reprenons lexemple des vhicules sur lautoroute (voir figure 12.3).

Figure 12.3 Diagramme UML des classes Vehicule et Voiture


Il tait alors possible de crer directement un vhicule :
1

var vehicule : Vehicule = new Vehicule ( ' Renault ' , 0 ) ;

Maintenant, si notre application ne soccupe que de voitures, il serait inutile dutiliser


directement la classe Vehicule alors que nous disposons de sa sous-classe Voiture. Si
nous laissions dautres programmeurs la possibilit de crer des vhicules au lieu de
voitures, ils auraient une chance sur deux de se tromper et doublier dutiliser la classe
Voiture. Pour cela, il faut rendre la classe Vehicule abstraite (voir figure 12.4) !
Par opposition une classe abstraite, une classe qui peut tre instancie est
une classe concrte.

200

LES CLASSES ABSTRAITES

Figure 12.4 Diagramme UML de la classe abstraite Vehicule et de sa sous-classe


Rappel : une sous-classe dune classe abstraite nest pas forcment abstraite ;
il faut le spcifier chaque fois. Dans notre exemple, on peut donc instancier
la classe Voiture, mais pas la classe Vehicule.
Ainsi, nous sommes dsormais obligs dutiliser la classe Voiture pour crer un objet
voiture : notre code est cohrent !
1

var vehicule : Vehicule = new Vehicule ( ' Renault ' , 0 ) ; // Interdit


!

2
3

var voiture : Voiture = new Voiture ( ' Renault ' , 0 , ' BX6F57 ') ; //
Autoris

Application lActionScript 3
Malheureusement, ce principe de classes abstraites ne dispose pas de mcanismes
officiels au sein du langage, il faut donc le programmer soi-mme. Cela ne signifie
pas quil ne faut pas lutiliser, et plusieurs classes fournies par Flash sont des classes
abstraites ! Mais rassurez-vous, cest en ralit trs simple.
Le principe est le suivant : nous allons faire une vrification dans le constructeur de la
classe-mre abstraite, laide dun paramtre et du mot-cl this. En effet, seule une
sous-classe de cette classe peut passer en paramtre du constructeur le mot-cl this !
Voici le code de la classe abstraite :
1
2

package
{

201

CHAPITRE 12. NOTIONS AVANCES DE LA POO


import flash . errors . Ill egalO perati onErr or ;
/* *
* Une classe abstraite
*/
public class MaClasseAbstraite
{

3
4
5
6
7
8
9

public function MaClasseAbstraite ( moi : MaClasseAbstraite


)
{
// Nous v rifions si le param tre de v rification
correspond l ' objet
if ( moi != this )
{
// Sinon , quelqu ' un tente d ' instancier cette
classe , nous envoyons donc une erreur
// car seule une sous - classe peut passer le mot
- cl ' this ' en param tre au constructeur
throw new Ill egalOp erati onErro r ( "
MaClasseAbstraite est une classe abstraite
et ne peut donc pas tre directement
instanci e . " ) ;
}
}

10
11
12
13
14
15
16
17

18
19
20

21
22
23

Le
mot-cl
throw
permet
denvoyer
une
erreur ;
ici
IllegalOperationError, qui indique quil sagit dune opration illgale. Pour linstant, il nest pas ncessaire que vous vous attardiez sur cette
instruction, nous reviendrons sur la gestion des erreurs dans un chapitre
ddi plus loin dans ce cours.
Nous demandons dans le constructeur un paramtre moi obligatoire, du mme type
que la classe elle-mme : ainsi, seuls les objets des sous-classes de MaClasseAbstraite
seront accepts. Ensuite, nous vrifions que ce paramtre pointe vers le mme objet,
cest--dire que cet objet qui vient dtre cr est bien une instance dune sous-classe.
Rappel : le mot-cl this est une rfrence qui pointe sur lunique objet qui
fait actuellement travailler le corps de la classe. Mme en remontant entre les
sous-classes, cette rfrence pointe toujours sur le mme objet (qui appartient
toutes ces classes en mme temps, comme nous lavons vu dans le chapitre
sur lhritage).
Voici le code de la sous-classe concrte :
202

LES TYPES INCONNUS


1
2
3
4
5
6
7

package
{
/* *
* Une sous - classe concr te .
*/
public class MaClasseConcrete extends MaClasseAbstraite
{

public function MaClasseConcrete ()


{
// On envoie la r f rence de l ' objet qui vient d '
tre cr la classe m re pour passer la v
rification
super ( this ) ;

9
10
11

12
13

14
15

16
17
18

Dans le constructeur de la classe-fille concrte, nous appelons le constructeur de la


classe-mre abstraite laide du mot-cl super pour passer la vrification.
Voici ce que cela donne lorsque nous voulons crer un objet de chaque classe :
1

var objet1 : MaClasseAbstraite = new MaClasseAbstraite () ; // Une


erreur va tre envoy e

2
3

var objet2 : MaClasseConcrete = new MaClasseConcrete () ; // Tout


va bien .

Les types inconnus


Dterminer si un objet est une occurrence dune certaine classe
Le mot-cl is permet de renvoyer un boolen pour savoir si un objet quelconque est
une occurrence dune certaine classe ou dune sous-classe.
1
2
3
4

var
var
var
var

entier : int = - 23 ;
entierPositif : uint = 42 ;
nombre : Number = 3 . 14 ;
chaine : String = ' Hello world ! ';

5
6
7
8
9
10

// entier est du type int


trace ( entier is int ) ; // Affiche : true
// entier n ' est pas du type uint
trace ( entier is uint ) ; // Affiche : false
// La classe int est une sous - classe de Number

203

CHAPITRE 12. NOTIONS AVANCES DE LA POO


trace ( entier is Number ) ; // Affiche : true

11
12
13
14
15

trace ( entierPositif is uint ) ; // Affiche : true


// La classe uint est aussi une sous - classe de Number
trace ( entierPositif is Number ) ; // Affiche : true

16

trace ( nombre is int ) ; // Affiche : false


trace ( nombre is Number ) ; // Affiche : true

17
18
19

trace ( chaine is String ) ; // Affiche : true


trace ( chaine is int ) ; // Affiche : false

20
21

Cela fonctionne galement avec les fonctions ! Car il faut toujours se rappeler quen
ActionScript 3, tout est objet : les variables, les fonctions, les objets de la classe
Voiture, leurs attributs, leurs mthodes. . . Les fonctions sont de classe Function,
comme on peut le confirmer dans cet exemple :
1
2
3
4

function maFonction () : void


{
trace ( ' Je suis dans une fonction ! ') ;
}

5
6
7
8
9

// Toute fonction est une instance de la classe Function !


trace ( maFonction is Function ) ; // Affiche : true
// Mais chaine n ' est pas une fonction
trace ( chaine is Function ) ; // Affiche : false

10
11
12
13
14

// Tout objet est une instance de la classe Object !


trace ( entier is Object ) ; // Affiche : true
trace ( chaine is Object ) ; // Affiche : true
trace ( maFonction is Object ) ; // Affiche : true

Des paramtres de type inconnu


Dans les fonctions, il est possible de demander des paramtres de type inconnu,
cest--dire dont nous ne pouvons pas connatre la classe lavance ! Pour cela, nous
pouvons utiliser la classe Object qui est la classe-mre de tous les objets en ActionScript 3.
1
2
3
4
5
6
7

function quiSuisJe ( quelqueChose : Object ) : void


{
if ( quelqueChose is Function )
{
trace ( ' Je suis une fonction ! ') ;
}
}

Il existe un raccourci pour spcifier que le type dun paramtre est inconnu : le caractre
* ! Reprenons lexemple prcdent en utilisant ce raccourci :
204

LES TYPES INCONNUS


1
2
3
4
5
6
7

function quiSuisJe ( quelqueChose :*) : void


{
if ( quelqueChose is Function )
{
trace ( ' Je suis une fonction ! ') ;
}
}

Essayons cette fonction avec une autre fonction :


1
2
3
4

function maFonction () : void


{
trace ( ' Je suis dans une fonction ! ') ;
}

5
6
7
8
9
10
11
12

function quiSuisJe ( quelqueChose :*) : void


{
if ( quelqueChose is Function )
{
trace ( ' Je suis une fonction ! ') ;
}
}

13
14
15

// Nous passons l ' objet maFonction de classe Function en param


tre !
quiSuisJe ( maFonction ) ; // Affiche : Je suis une fonction !

Lobjet maFonction est une occurrence de la classe Function (tant donn que cest
une fonction), donc le test est positif et le message Je suis une fonction ! est affich.
Nous pourrions ensuite appeler la fonction laide de la mthode call() de la classe
Function :
1
2
3
4

function maFonction () : void


{
trace ( ' Je suis dans une fonction ! ') ;
}

5
6
7
8
9
10
11
12
13
14

function quiSuisJe ( quelqueChose :*) : void


{
if ( quelqueChose is Function )
{
trace ( ' Je suis une fonction ! ') ;
// On appelle la fonction !
quelqueChose . call () ;
}
}

15
16
17

// Nous passons l ' objet maFonction de classe Function en param


tre
quiSuisJe ( maFonction ) ; // Affiche : Je suis une fonction ! Je
suis dans une fonction !

205

CHAPITRE 12. NOTIONS AVANCES DE LA POO

Accder dynamiquement aux proprits


En ActionScript 3, il est possible daccder une proprit dun objet en connaissant son nom uniquement lexcution. Par exemple, vous obtenez le nom dun attribut
dans une variable de type String, et vous voulez ensuite modifier sa valeur pour faire
une animation ou autre chose.
Prenons une classe Voiture disposant dun attribut vitesse et dune mthode accelerer :
1
2
3
4

package
{
public class Voiture
{

private var _vitesse : int ;

6
7

public function Voiture ()


{
vitesse = 10 ;
}

8
9
10
11
12

public function get vitesse () : int


{
return _vitesse ;
}

13
14
15
16
17

public function set vitesse ( value : int ) : void


{
_vitesse = value ;
}

18
19
20
21
22
23
24
25
26

27

public function accelerer ( combien : int = 1 ) : void


{
vitesse += combien ;
}

28
29

La syntaxe respecter pour accder lattribut de nom vitesse est la suivante :


1
2

var objet : Voiture = new Voiture () ;


var nomDeLaPropriete : String = ' vitesse ';

trace ( objet [ nomDeLaPropriete ]) ; // Affiche la vitesse de la


voiture : 10

Ou plus simplement :
1
2

var objet : Voiture = new Voiture () ;


trace ( objet [ ' vitesse ' ]) ; // Affiche : 10

206

ACCDER DYNAMIQUEMENT AUX PROPRITS

Rappel : une proprit constitue dun ou plusieurs accesseurs est considre comme un attribut.
En guise dexemple, supposons que nous voulons disposer dune fonction qui augmente
de 10 nimporte quel attribut numrique dun objet quelconque, sans avoir besoin de
plus de prcisions concernant sa classe.
1
2
3
4
5
6
7
8
9
10
11
12

function augmenter ( objet : Object , propriete : String ) : void


{
// On v rifie le type de la propri t : il faut que ce soit
un nombre
if ( objet [ propriete ] is int || objet [ propriete ] is uint ||
objet [ propriete ] is Number )
{
objet [ propriete ] += 10 ;
}
else
{
trace ( " Attention : La propri t " + propriete + " sur l
' objet " + objet + " n ' est pas un nombre . " ) ;
}
}

crivons un petit programme principal qui cre un objet Voiture et qui utilise cette
fonction pour augmenter sa vitesse :
1
2
3
4

package
{
import flash . display . Sprite ;
import flash . events . Event ;

5
6
7
8
9
10

/* *
* Programme principal
*/
public class Main extends Sprite
{

11
12
13
14
15
16
17
18

public function Main () : void


{
if ( stage )
init () ;
else
addEventListener ( Event . ADDED_TO_STAGE , init ) ;
}

19
20
21
22
23

private function init ( e : Event = null ) : void


{
removeEventListener ( Event . ADDED_TO_STAGE , init ) ;
// entry point

24

207

CHAPITRE 12. NOTIONS AVANCES DE LA POO


// On cr une voiture
var voiture : Voiture = new Voiture () ;
// On initialise sa vitesse 10
voiture . vitesse = 10 ;
// On augmente sa vitesse de 10
augmenter ( voiture , ' vitesse ') ;
trace ( voiture . vitesse ) ; // Affiche : 20

25
26
27
28
29
30
31
32

33
34

public function augmenter ( objet : Object , propriete :


String ) : void
{
// On v rifie le type de la propri t : il faut que
ce soit un nombre
if ( objet [ propriete ] is int || objet [ propriete ] is
uint || objet [ propriete ] is Number )
{
objet [ propriete ] += 10 ;
}
else
{
trace ( " Attention : La propri t " + propriete +
" sur l ' objet " + objet + " n ' est pas un
nombre . " ) ;
}
}

35
36
37
38
39
40
41
42
43
44

45
46
47

48
49
50

Est-ce que cela fonctionne pour les mthodes ?

La rponse est oui, nous pouvons aussi le faire pour les mthodes ! Il suffit dajouter
des paramtres comme pour nimporte quel appel de fonction. Par exemple :
1
2

var voiture : Voiture = new Voiture () ;


voiture . vitesse = 10 ;

3
4
5
6

// Appelons la m thode ' accelerer ' de notre objet voiture !


voiture [ ' accelerer ' ]( 5 ) ;
trace ( voiture . vitesse ) ; // Affiche : 15

7
8
9
10

// Ce qui revient crire :


voiture . accelerer ( 5 ) ;
trace ( voiture . vitesse ) ; // Affiche : 20

208

LES OBJETS ANONYMES


11
12
13
14
15

// Avec les accesseurs , la propri t vitesse est concid r e


comme un attribut
trace ( voiture [ ' vitesse '] is Function ) ; // Affiche : false
// Alors que accelerer est bien une m thode
trace ( voiture [ ' accelerer '] is Function ) ; // Affiche : true

Voici un exemple plus concret. Nous pourrions coder une fonction qui anime une proprit numrique dun objet dune valeur une autre pendant un certain temps mais,
malheureusement, nous ne sommes pas encore assez avanc dans le cours pour pouvoir faire cela. Toutefois, je vous montre quoi pourrait ressembler la signature de la
fonction et un exemple dutilisation :
1
2
3
4

function animer ( objet : Object , propriete : String , valeurDepart :* ,


valeurArrivee :* , duree : Number ) : void
{
// Animation l ' aide de objet [ propriete ]
}

Jutilise la notation avec ltoile pour le type de valeurDepart et


valeurArrivee pour que lon puisse passer des nombres de type int, uint
ou Number. Attention toutefois vrifier leurs types dans le corps de la fonction.
Dans notre classe Main, nous pourrions crire :
1

var voiture : Voiture = new Voiture () ;

2
3
4

// Acc l rons !
animer ( voiture , ' vitesse ' , 0 , 100 , 3 ) ; // Nous animons la
vitesse de l ' objet voiture de 0 100 pendant 3 secondes

Avec cette fonction, nous pourrions donc animer nimporte quel attribut de nimporte
quel objet !

Les objets anonymes


Crer un objet anonyme
Un objet anonyme est un objet dynamique qui na pas de classe (autre que la
classe Object). On peut modifier ses proprits de manire totalement libre : crer de
nouveaux attributs ou de nouvelles mthodes, les modifier aprs coup. . . En effet, ses
proprits ne sont pas dcrite dans une classe particulire, donc on peut faire ce que
lon veut (ce qui peut parfois poser problme, o lon devra effectuer de nombreux tests
sur lobjet anonyme car on ne sait pas lavance comment il sera structur).
Pour crer un objet anonyme, il y a deux faons de procder. La premire est de
crer une instance de la classe Object comme ceci :
209

CHAPITRE 12. NOTIONS AVANCES DE LA POO


1

var objetAnonyme : Object = new Object () ;

Puis on peut lui affecter des proprits librement :


1
2
3

// Ajoutons quelques attributs


objetAnonyme . nom = " Site du Z ro " ;
objetAnonyme . adresse = " www . siteduzero . com " ;

trace ( objet . nom + " : " + objet . adresse ) ;

Nous obtenons dans la console :


Site du Z ro : www . siteduzero . com

On peut galement crer un objet anonyme avec des accolades en spcifiant directement ses proprits spares par des virgules ainsi :
1

2
3
4
5
6

nomPropriete1 : valeur1 ,
nomPropriete2 : valeur2 ,
nomPropriete3 : valeur3 ,
...

Reprenons notre exemple en utilisant cette mthode :


1
2
3
4

var objet : Object = {


nom : " Site du Z ro " ,
adresse : " www . siteduzero . com "
};

trace ( objet . nom + " : " + objet . adresse ) ;

Ce qui nous donne nouveau :


Site du Z ro : www . siteduzero . com

Il peut parfois tre utile, comme dans le cas o une fonction attend beaucoup de
paramtres facultatifs. Par exemple, nous pourrions avoir une fonction attendant neuf
paramtres facultatifs (jai volontairement mis en forme les paramtres pour quils
soient plus lisibles) :
1
2
3
4
5
6
7
8
9

210

function creerEmailBrouillon (
objet : String = " " ,
message : String = " " ,
date : Date = null ,
e ma i l sDestinataires : Array = null ,
emailsCC : Array = null ,
emailsCCI : Array = null ,
emailExpediteur : String = " " ,
piecesJointes : Array = null ,

LES OBJETS ANONYMES


10
11
12
13
14

d e m a n d e r C o n f i r m a t i o n L e c t u r e : Boolean = false
) : void
{
// Code ici
}

Cette fonction cr un brouillon de-mail : aucun champ nest obligatoire car tous les
paramtres ont une valeur par dfaut. En effet, lorsque vous enregistrez un brouillon
de-mail, vous ntes pas oblig de remplir tous les champs. Nous pouvons donc appeler
cette fonction sans lui passer de paramtre :
1

cre e r Em a il B ro uillon () ; // Tous les param tres auront leur


valeur par d faut

Mais que devrions-nous faire si nous ne voulons enregistrer que le-mail de lexpditeur
seul ? Et bien, il faudrait spcifier quand-mme des valeurs pour les paramtres prcdent le paramtre emailExpediteur, ce qui serait fastidieux et peu commode ! Voyez
plutt :
1

cre e r Em a il B ro uillon ( " " , " " , null , null , null , null , "
z o z o r @ o p e nclassrooms . com " ) ;

Pour remdier ce problme, nous pouvons nutiliser quun seul paramtre : un objet
anonyme !
1
2
3
4

function c re e rEmailBrouillon ( options : Object = null ) : void


{
// Code ici
}

Nous pouvons maintenant nous contenter de passer uniquement les paramtres qui
nous intressent lors de lappel de la fonction :
1
2
3

cre e r Em a il B ro uillon ({
emailExpediteur : " zozor@openclassrooms . com "
}) ;

Il faut avouer que cest tout de mme plus lisible et moins fastidieux taper. Dans
la fonction creerEmailBrouillon, il va falloir faire plusieurs tests sur les paramtres,
afin de savoir sils ont t passs avant de les utiliser. On commence dabord par tester
lexistence de lobjet options, puis on regarde si chaque paramtre est dfini, cest-dire sil est diffrent de undefined (indfini en anglais) et si son type est correct.
1
2
3
4
5
6
7

function c re e rEmailBrouillon ( options : Object = null ) : void


{
if ( options ) // Equivaut : options != null
{
// On v rifie si le param tre objet est d fini et est
de type String
if ( options . objet != undefined && options . objet is
String )
{

211

CHAPITRE 12. NOTIONS AVANCES DE LA POO


8
9
10

// Traiter l ' objet


trace ( " Objet : " + options . objet ) ;

11
12
13
14
15
16

if ( options . message != undefined && options . message is


String )
{
// Traiter le message
trace ( " Message : " + options . message ) ;
}

17
18
19
20
21
22

if ( options . date != undefined && options . date is Date )


{
// Traiter la date de l ' email
trace ( " Date : " + options . date ) ;
}

23
24
25
26
27

28

if ( options . emailsDestinataires != undefined && options


. emailsDestinataires is Array )
{
// Traiter la liste des destinataires
trace ( " Emails destinataires : " + options .
emailsDestinataires . join ( " , " ) ) ; // On affiche
les emails s par s par des virgules gr ce au
join (" ,")
}

29
30
31
32
33
34

if ( options . emailsCC != undefined && options . emailsCC


is Array )
{
// Traiter la liste des destinataires en copie
trace ( " Emails destinataires en copie : " + options .
emailsCC . join ( " , " ) ) ;
}

35
36
37
38
39
40

if ( options . emailsCCI != undefined && options . emailsCCI


is Array )
{
// Traiter la liste des destinataires en copie cach
e
trace ( " Emails destinataires en copie cach e : " +
options . emailsCCI . join ( " , " ) ) ;
}

41
42
43
44
45

212

if ( options . emailExpediteur != undefined && options .


emailExpediteur is String )
{
// Traiter d ' adresse de l ' exp diteur
trace ( " Email de l ' exp diteur : " + options .
emailExpediteur ) ;

LES OBJETS ANONYMES


}

46
47

if ( options . piecesJointes != undefined && options .


piecesJointes is Array )
{
// Traiter la liste des pi ces jointes
trace ( " URL des pi ces jointes : " + options .
piecesJointes . join ( " , " ) ) ;
}

48
49
50
51
52
53
54
55
56
57
58

59

if ( options . d e m a n d e r C o n f i r m a t i o n L e c t u r e != undefined &&


options . d e m a n d e r C o n f i r m a t i o n L e c t u r e is Boolean )
{
// Traiter l ' option de demande de confirmation de
lecture
trace ( " Confirmation de lecture : " + options .
demanderConfirmationLecture );
}

60
61
62

// Suite ventuelle du code ici

Il est ncessaire de bien documenter cette fonction en dtaillant les diffrents


paramtres afin que lon puisse par la suite lutiliser facilement.
Avec ce squelette de code, nous obtenons dans la console :
Email de l exp diteur : zozor@openclassrooms . com

Seul le paramtre emailExpediteur a t dtect et son type a bien t valid.


Essayons de passer plusieurs paramtres :
1
2
3

4
5

cre e r Em a il B ro uillon ({
date : new Date () , // Date d ' aujourd ' hui
e ma i l sD e stinataires :[ " titi@openclassrooms . com " , "
t at a @openclassrooms . com " , " toto@openclassrooms . com " ] , //
Destinataires
emailExpediteur : " zozor@openclassrooms . com " // Exp diteur
}) ;

Ce qui nous donne dans la console :


Date : Wed Nov 6 16:11:31 GMT +0100 2013
Emails destinataires : titi@openclassrooms . com ,
t at a @ op e nc lassrooms . com , toto@openclassrooms . com
Email de l exp diteur : zozor@openclassrooms . com

213

CHAPITRE 12. NOTIONS AVANCES DE LA POO

Les fonctions anonymes


Une fonction anonyme est une fonction dont on ne prcise pas le nom. Par exemple,
cette fonction est anonyme :
1
2
3
4

function () : void
{
trace ( " Hello world ! " ) ;
}

Comme vous pouvez le constater, cette fonction na pas de nom dfinit entre le mot-cl
function et les parenthses des paramtres. On ne peut donc pas lappeler directement.
Par contre, on peut laffecter une variable de type Function comme ceci :
1
2
3
4

var hello : Function = function () : void


{
trace ( " Hello world ! " ) ;
}

Pour lappeler, on considre que la variable est directement la fonction :


hello () ; // Appelle la fonction contenue dans la variable hello

Nous pouvons ainsi crer des mthodes sur un objet anonyme en affectant une fonction
anonyme une proprit de cet objet :
1
2
3
4
5

var anonyme : Object = new Object () ;


anonyme . hello = function () : void
{
trace ( " Hello world ! " ) ;
};

6
7

anonyme . hello () ; // Affiche : Hello world !

En rsum
Il est possible de crer des classes dynamiques que lon peut modifier durant
lexcution, grce au type dynamic.
Les interfaces permettent dhriter en quelque sorte de plusieurs classes pour partager des proprits communes.
Nos classes peuvent tre abstraites : dans ce cas, on renvoie une erreur si quelquun
essaye den crer une instance.
Le type des variables que nous manipulons peut tre indfini ; on peut alors le tester
laide du mot-cl is.
Il est possible daccder dynamiquement des proprits dont on connat le nom.
Un objet anonyme est un objet sans classe que lon peut modifier librement, et
une fonction anonyme est une fonction sans nom.

214

Troisime partie

Laffichage

215

Chapitre

13

Les objets daffichage


Difficult :
Dans ce chapitre, nous allons aborder le systme qui va nous permettre (enfin !) dafficher
des lments (texte, dessins, images, etc.) lcran ! Mais en pratique, nous ne pourrons
rellement afficher quelque chose quau chapitre suivant car il nous faut aborder quelques
notions de base auparavant.
Nous allons voir notamment :
Comment dcrire une couleur en ActionScript.
Le fonctionnement de laffichage sur un cran.
Le systme daffichage de Flash.
Cest parti !

217

CHAPITRE 13. LES OBJETS DAFFICHAGE

Introduction
Les couleurs
Composer une couleur
En informatique, les couleurs sont dcomposes en couleurs principales : le rouge, le
vert et le bleu. partir de ces trois couleurs, il est possible de crer nimporte quelle
autre couleur en les dosant (voir figure 13.1).

Figure 13.1 Les couleurs principales de la lumire


Exemple : je souhaite crer une couleur orange. Lorange est constitu de jaune et de
rouge. Ainsi, il nous faut dabord faire du jaune (rouge + vert), puis rajouter du rouge
(voir figure 13.2). Au final, lorange se cre grosso-modo avec deux quantits de rouge
pour une quantit de vert.

Figure 13.2 Composition de la couleur orange

218

INTRODUCTION
Notation hexadcimale
Pour dcrire une couleur compose de rouge, de vert et de bleu, nous utiliserons la
notation hexadcimale. On commence par crire 0x pour signifier que lon utilise
la notation hexadcimale, puis on dcrit les quantits de chacune des trois couleurs
rouge, vert et bleu : deux chiffres, allant de 0 (le minimum) F (le maximum) pour
chacune, ce qui fait six chiffres.
Pourquoi jusqu F ? Depuis quand F est un chiffre ?

Excellente question ! En ralit, il existe diffrents systmes de notation pour les nombres.
Celle que vous et moi utilisons tous les jours sappelle la notation dcimale. Cela
signifie que nous utilisons les chiffres de 0 9 pour crire les nombres. On dit aussi que
nous crivons les nombres en base dix. Une autre notation trs connue est la notation
binaire : nous dcrivons les nombres avec seulement les chiffres 0 et 1. On parle alors
de base deux. Par exemple, 5 en base dix scrit 101 en base deux !
La notation hexadcimale utilise non pas dix, mais seize chiffres ! On parle de base
seize pour cette notation. Les chiffres vont de 0 15. Avouez cependant qucrire
un chiffre laide de deux chiffres serait plutt embtant. . . Comment faire alors la
diffrence entre 12 (le chiffre) et 12 (le nombre compos du chiffre 1 et du chiffre 2) ?
Impossible !
Ainsi, nous utilisons les 6 premires lettres de lalphabet pour remplacer les chiffres 10
15, ce qui est tout de mme bien plus pratique.
Chiffre (dcimal)
10
11
12
13
14
15

Notation hexadcimale
A
B
C
D
E
F

En dehors de lActionScript, on utilise plus gnralement le # pour commencer une notation hexadcimale.
Ainsi, pour crire notre chiffre 12, nous utilisons C ! Voici quelques exemples de nombre
en base dix convertis en base seize :
Afin de dcrire une couleur, nous utiliserons donc deux chiffres en hexadcimal pour le
rouge, le vert et le bleu, de 00 FF, ce qui fait de 0 255 en dcimal. Par exemple,
pour notre couleur orange, nous crirons : 0xFF8000, car il y a deux doses de rouge
pour une dose de vert (voir figure 13.3).
219

CHAPITRE 13. LES OBJETS DAFFICHAGE


Base dix
12
5
31
32
16
160
66

Base seize
C
5
1F
20
10
A0
42

Figure 13.3 Notation hexadcimale de la couleur orange


La plupart des logiciels de dessin et retouche dimage affichent la notation
hexadcimale des couleurs quil est alors facile de copier-coller. Il existe galement des outils ou des sites Internet spcialiss dans la cration de couleur
qui fournissent cette notation (comme par exemple ColRD). Attention toutefois, il ne faut pas oublier quen ActionScript, la notation hexadcimale
commence par 0x et non pas par # !

Stocker une couleur dans une variable


Le type quil faut utiliser pour stocker un nombre en notation hexadcimale est le
type uint :
1
2

var orange : uint = 0xFF8000 ;


var orange2 : uint = 0xff8000 ; // Les lettres peuvent aussi tre
not es en minuscule

La variable ainsi cre peut tre manipule comme nimporte quelle autre variable :
1
2
3
4

220

trace ( " La couleur orange vaut


16744448
trace ( " La couleur orange vaut
base dix . " ) ; // 16744448
trace ( " La couleur orange vaut
base seize . " ) ; // FF8000
trace ( " La couleur orange vaut
base deux . " ) ; // 1111 1111

" + orange + " en base dix . " ) ; //


" + orange . toString ( 10 ) + " en
" + orange . toString ( 16 ) + " en
" + orange . toString ( 2 ) + " en
1000 0000 0000 0000

INTRODUCTION
Vous remarquerez que la couleur est stocke sous la notation dcimale, cest,
en effet, la seule notation supporte par les types de nombres. Par contre, il
est facile de retrouver la notation hexadcimale ou binaire grce la mthode
toString() comme dans lexemple ci-dessus.

Laffichage sur un cran


Tous les crans daffichage sont composs dune grille de petits carrs de lumire que
lon nomme pixels (voir figure 13.4). Nous allons voir comment utiliser cette grille
pour positionner des objets.

Figure 13.4 Lcran est compos dune grille de pixels

Le repre
Les pixels forment donc une grille suivant deux axes : laxe des X et laxe des Y. On
se situe alors sur un espace en 2D. Pour mieux visualiser la grille, nous allons utiliser
la figure 13.5 un repre qui nous montre les axes et lorigine de la grille.
Une position (cest--dire un point prcis de ce repre) est dcrite par deux coordonnes : la position en X, et la position en Y. On crit toujours les coordonnes en 2D
dans cet ordre : dabord les X, puis les Y. Ainsi, il nest pas ncessaire de tout le temps
prciser qui est quoi. Dans lexemple la figure 13.6, le pixel que lon a colori en bleu
se trouve la position (5,6), cest--dire 5 pixels du bord gauche de lcran, et 6
pixels du bord suprieur de lcran.
Tout au long du cours, il faudra avoir ce repre en tte ds quil sagira
de positionner un objet lcran. Il faut savoir quil est possible que les
coordonnes soient ngatives, mais, dans ce cas, les pixels qui dpassent ne
seront pas affichs (faute de pixels sur votre cran).

221

CHAPITRE 13. LES OBJETS DAFFICHAGE

Figure 13.5 Repre de laffichage

Figure 13.6 Exemple de position sur lcran

222

LARBRE DES OBJETS DAFFICHAGE

Larbre des objets daffichage


Larbre daffichage
Pour bien comprendre de quoi il sagit, commenons par un exemple concret, et revenons sur notre chre voiture. Nous voulons maintenant lafficher et lanimer sur notre
cran ! Nous allons utiliser un modle simplifi, celui de la figure 13.7.

Figure 13.7 Votre magnifique voiture simplifie


Supposons que cette voiture soit compose dune carrosserie et de deux roues. Vue de
lextrieur, la voiture est un objet et un seul (voir figure 13.8).

Figure 13.8 La voiture vue de lextrieur


Mais en ralit, il y a trois objets lintrieur de cet objet (voir figure 13.9) : la
carrosserie en orange et les deux roues en bleu.

Figure 13.9 Lobjet Voiture est compos dautres objets


Lorsque nous voudrons afficher la voiture, nous crerons tout dabord un conteneur
(par exemple, avec la classe Sprite), puis nous ajouterons lintrieur trois autres
objets daffichage (voir figure 13.10) : un pour la carrosserie, et un pour chaque roue.
223

CHAPITRE 13. LES OBJETS DAFFICHAGE

Figure 13.10 Nous disposons les diffrents objets dans le conteneur Voiture

Ainsi, si nous bougeons le conteneur voiture , les roues se dplaceront en mme


temps que la carrosserie ; si nous tournons le conteneur, lensemble fera une rotation
comme sil sagissait dun unique objet, linstar de ce qui se passerait dans la vraie
vie ! La voiture pourrait elle-mme se trouver dans un autre conteneur rue , que lon
pourrait faire dfiler comme un tout. . .
Ainsi, larbre daffichage est une arborescence dobjets daffichage inclus les uns
dans les autres dans une certaine logique. Voici un schma la figure 13.11 reprsentant
larbre daffichage de notre application.

Figure 13.11 Larbre daffichage de la voiture


Vous remarquerez que la racine de larbre est compose dun objet que jai
appel scne principale. Cest un objet spcial de la classe Stage qui est
toujours prsent pour la gestion de laffichage.
Maintenant, si nous voulons quil y ait deux voitures dans la rue, il suffit den ajouter
une autre dans le conteneur rue (voir figure 13.12).
224

LARBRE DES OBJETS DAFFICHAGE

Figure 13.12 Plusieurs voitures dans larbre daffichage


Il est important de se rappeler que modifier lapparence ou la position dun
conteneur impactera tous les enfants comme sil sagissait dun seul et unique
objet. Il est nanmoins possible de modifier les enfants sparment.

Les classes daffichage


En ActionScript, il existe plusieurs classes diffrentes ddies laffichage, comme
on peut le constater la figure 13.13.

Figure 13.13 Extrait de larbre dhritage des classes daffichage


225

CHAPITRE 13. LES OBJETS DAFFICHAGE


Par exemple, la classe TextField sert afficher du texte ; nous en reparlerons dans le
prochain chapitre. Elle est une sous-classe de InteractiveObject (pour les objets interactifs), elle-mme sous-classe de DisplayObject. Ainsi, toutes les classes daffichage
sont des sous-classes de la classe DisplayObject.
Rappel : les classes abstraites ne peuvent pas tre instancies directement,
cest--dire que lon ne peut pas crer de nouveaux objets de ces classes avec
le mot-cl new. Il est toutefois possible de spcifier des paramtres de type
de classes abstraites dans les mthodes, ce nest pas gnant.

La classe DisplayObject (abstraite)


Il sagit de la classe daffichage de base. Cest partir delle que toutes les autres classes
daffichage sont drives ; elle contient les proprits utiles pour manipuler des objets
daffichage simples. Encore une fois, tant donn quil sagit dune classe abstraite,
inutile dessayer de crer un objet de la classe DisplayObject.

La classe Bitmap
Cette classe permet dafficher des images composes de pixels. Les objets de cette classe
sont purement visuels ; il est impossible de grer directement les clics de souris dessus
par exemple. Nous apprendrons manipuler des images dans les prochains chapitres.

La classe Shape
Cette classe permet de crer des objets lgers permettant de dessiner lcran : tracer
des lignes, des formes, remplir. . . linstar des objets de la classe Bitmap, les objets
de la classe Shape sont purement visuels.

La classe Video
Comme vous vous en doutez, cette classe permet laffichage de vidos (avec le son).
Cest aussi une classe crant des objets purement visuels.

La classe InteractiveObject (abstraite)


Cette classe permet dintroduire de linteractivit pour nos objets daffichage : il sera
ainsi possible de savoir si lutilisateur clique sur un objet dune sous-classe de la classe
InteractiveObject.
226

LARBRE DES OBJETS DAFFICHAGE


La classe SimpleButton
Cette classe permet de fabriquer des boutons basiques rapidement : on peut ainsi lui
spcifier quel objet sera affich dans diffrents tats (normal, souris au-dessus, cliqu,
. . .), et automatiquement changer le curseur de la souris au-dessus en doigt. Cette classe
est utilise par Flash Pro dAdobe pour crer les boutons.
La classe TextField
Avec cette classe, nous prsenterons du texte lcran pendant le prochain chapitre. Il
est possible de formater le texte laide dune forme trs allge dHTML (le langage
principal utilis pour crer des sites web).
La classe DisplayObjectContainer (abstraite)
Cette dernire classe abstraite introduit la notion de conteneur : il est dsormais
possible dajouter plusieurs objets daffichage enfants dans un seul conteneur, afin de les
manipuler ensemble comme sil sagissait dun seul objet (pensez la fonction Grouper
des logiciels de bureautique).
La classe Loader
Cette classe nous permettra de charger du contenu externe notre application,
condition quil soit visuel.
La classe Stage (abstraite)
Les objets de cette classe sont des objets spciaux qui reprsentent la scne daffichage
de lapplication. Il est bien videmment impossible de crer directement une instance
de la classe Stage. Attention, la plupart des proprits hrites des classes-mres ne
fonctionnent pas sur eux (comme par exemple la position, lopacit, etc.).
La classe Sprite
Non, il ne sagit pas de la boisson ! :- Les objets de cette classe sont les plus utiliss
en tant que conteneurs, et en tant que dessins interactifs. Vous en userez (et abuserez)
en programmant en ActionScript !
La classe MovieClip
Cette classe drive de la classe Sprite ajoute un composant complexe et plutt lourd :
une ligne de temps (ou timeline en anglais). Cela consiste en une srie dimages-cls
pouvant tre rparties sur diffrents niveaux, afin de crer des animations complexes
(voir figure 13.14). Cette classe a tout dabord t conue pour tre utilise dans le
227

CHAPITRE 13. LES OBJETS DAFFICHAGE


logiciel danimation Flash Pro dAdobe ; ainsi, tant dun intrt limit pour une utilisation en ActionScript, nous ne lutiliserons quasiment pas dans ce cours.

Figure 13.14 Un exemple de timeline dans Flash Pro


Il existe dautres classes daffichage que je nai pas mentionnes ici : nous ne
les aborderons pas, elles sont trop avances et donc inutiles dans le cadre de ce
cours. Mais si vous tes curieux, vous pouvez toujours explorer les possibilits
supplmentaires qui soffrent vous en visitant la documentation.
Si nous reprenions notre exemple de la voiture, les schmas des arbres daffichage
ressembleraient aux deux figures 13.15 et 13.16.

Figure 13.15 Larbre daffichage de la voiture

Manipuler les conteneurs


Toutes les nouvelles proprits (attributs et mthodes) que nous allons voir
sont issues de la classe DisplayObjectContainer. Je vous conseille daller lire en parallle la documentation officielle du langage ActionScript 3 en
franais. Nhsitez surtout pas lutiliser aussi souvent que vous en sentez le
besoin, elle est trs pratique !
228

MANIPULER LES CONTENEURS

Figure 13.16 Plusieurs voitures dans larbre daffichage



Documentation officielle
B
Code web : 403326


.

Buvez du Sprite !
Comme nous lavons vu prcdemment, la classe Sprite va nous permettre de crer des
conteneurs daffichage trs polyvalents tout en restant lgers. Commenons par crer
un conteneur que nous appellerons voiture.
1
2

// Cr ation du conteneur ' voiture '


var voiture : Sprite = new Sprite () ;

Comme vous pouvez le remarquer, le constructeur de la classe Sprite ne


prend pas de paramtre.

Ajouter des enfants


Pour ajouter des objets daffichage enfants dans notre conteneur voiture, il faut utiliser
la mthode addChild(enfant:DisplayObject):void fournie par la classe DisplayObject
Container. Elle prend en paramtre lenfant ajouter dans le conteneur.
1
2
3
4

// Cr ons une roue


var roue : Sprite = new Sprite () ;
// Ajoutons - la dans la voiture
voiture . addChild ( roue ) ;

5
6
7
8

// Cr ons la rue et ajoutons la voiture dans la rue


var rue : Sprite = new Sprite () ;
rue . addChild ( voiture ) ;

229

CHAPITRE 13. LES OBJETS DAFFICHAGE


Lobjet roue1 est dsormais affich lintrieur du conteneur voiture, lui-mme affich
dans le conteneur rue. Mais il manque quelque chose : il faut ajouter lobjet rue dans
la scne principale, sinon il ne sera pas affich !

Afficher un objet sur la scne principale


Dans notre projet, nous utilisons une classe principale que nous avons appele Main
(dans le fichier Main.as) :
package {
import flash . display . Sprite ;
import flash . events . Event ;

1
2
3
4

/* *
* ...
* @author Guillaume
*/
public class Main extends Sprite {

5
6
7
8
9
10

public function Main () : void {


if ( stage )
init () ;
else
addEventListener ( Event . ADDED_TO_STAGE , init ) ;
}

11
12
13
14
15
16
17

private function init ( e : Event = null ) : void {


removeEventListener ( Event . ADDED_TO_STAGE , init ) ;
// entry point

18
19
20
21
22

23

trace ( " Hello world ! " ) ;

24

25
26
27

Regardez droit dans les yeux la dclaration de la classe Main : cest une sous-classe
de Sprite ! Notre classe principale est donc un conteneur, qui est automatiquement
ajout la scne au dmarrage de notre application ; ainsi, il ne nous reste plus qu
ajouter nos objets dans le conteneur de classe Main qui nous est offert !
Pour ajouter notre rue sur la scne principale, nous procderons ainsi :
1

this . addChild ( rue ) ;

Le code peut tre raccourci en enlevant le mot-cl this :


1

230

addChild ( rue ) ;

MANIPULER LES CONTENEURS


Rappel : le mot-cl this permet daccder lobjet courant. Si nous lutilisons dans des mthodes non statiques de la classe Main, nous pointerons sur
lobjet qui reprsente notre application. Il est toutefois possible domettre le
mot-cl this si cela ne pose pas de problme de conflit de noms (typiquement, lorsque vous avez la fois un attribut dans votre classe et un paramtre
du mme nom dans la mthode, il faut utiliser this pour accder lattribut
de la classe). Du coup, le code ci-dessus ne fonctionnera pas dans une autre
classe ; il faudrait alors utiliser une variable pointant sur lobjet de la classe
Main.
Voici le code complet de la classe Main :
1
2
3

package {
import flash . display . Sprite ;
import flash . events . Event ;

4
5
6
7
8
9

/* *
* ...
* @author Guillaume
*/
public class Main extends Sprite {

10

public function Main () : void {


if ( stage )
init () ;
else
addEventListener ( Event . ADDED_TO_STAGE , init ) ;
}

11
12
13
14
15
16
17

private function init ( e : Event = null ) : void {


removeEventListener ( Event . ADDED_TO_STAGE , init ) ;
// entry point

18
19
20
21

// Cr ation du conteneur ' voiture '


var voiture : Sprite = new Sprite () ;

22
23
24

// Cr ons une roue


var roue : Sprite = new Sprite () ;
// Ajoutons - la dans la voiture
voiture . addChild ( roue ) ;

25
26
27
28
29

// Cr ons la rue et ajoutons la voiture dans la rue


var rue : Sprite = new Sprite () ;
rue . addChild ( voiture ) ;

30
31
32
33
34
35

36

// On ajoute la rue sur la sc ne principale


addChild ( rue ) ;

37
38

231

CHAPITRE 13. LES OBJETS DAFFICHAGE


39
40

Si vous testez le code ce stade, vous risquez dtre un peu dus : en effet,
les conteneurs sont vides par dfaut ! Vous devrez vous contenter dune triste
scne vide, mais nous allons bientt remdier cela.
Reprenons maintenant le schma reprsentant larbre daffichage, que nous avons dtaill plus haut (voir figure 13.17).

Figure 13.17 Larbre daffichage de la voiture


Corrigeons-le pour y inclure notre objet de la classe Main (voir figure 13.18).

Figure 13.18 Larbre daffichage de notre application


232

MANIPULER LES CONTENEURS


Un objet ne peut tre affich deux endroits diffrents ; si jamais vous lajoutez un conteneur alors que lobjet est dj dans un autre conteneur, il sera
automatiquement retir de ce dernier avant dtre ajout dans le nouveau
conteneur.

Lindex daffichage
Cette notion correspond lordre daffichage des enfants dans un conteneur. Si un objet
a un index plus grand quun autre, il sera affich devant, et inversement. Lindex est
compris entre 0 et conteneur.numChildren - 1 (le nombre denfants moins un).
la figure 13.19 par exemple, la voiture bleue est au-dessus des autres car elle a lindex
daffichage le plus lev. En revanche, la voiture orange est tout en dessous car elle a
un index gal zro.

Figure 13.19 Lindex daffichage de trois voitures superposes


Il est impossible de mettre un enfant un index en dehors des bornes que
nous avons dfinies : ainsi, on ne peut pas mettre un objet un index infrieur
0 ou suprieur conteneur.numChildren - 1.
On peut obtenir lindex dun enfant en utilisant la mthode getChildIndex():int
(renvoyant un int), qui prend en paramtre lobjet enfant en question :
1
2

// On cr e la rue
var rue : Sprite = new Sprite () ;

3
4
5
6

// On ajoute trois voiture dans la rue


var voiture1 : Sprite = new Sprite () ;
rue . addChild ( voiture1 ) ;

7
8

var voiture2 : Sprite = new Sprite () ;

233

CHAPITRE 13. LES OBJETS DAFFICHAGE


9

rue . addChild ( voiture2 ) ;

10
11
12

var voiture3 : Sprite = new Sprite () ;


rue . addChild ( voiture3 ) ;

13

trace ( " La
) ) ; //
trace ( " La
) ) ; //
trace ( " La
) ) ; //

14
15
16

voiture1
Affiche
voiture2
Affiche
voiture3
Affiche

est l ' index " + rue . getChildIndex ( voiture1


0
est l ' index " + rue . getChildIndex ( voiture2
1
est l ' index " + rue . getChildIndex ( voiture3
2

Ajouter un enfant un index prcis


Il existe une variante de la mthode addChild que nous avons vue il y a peu de temps.
Il sagit de la mthode addChildAt(enfant:DisplayObject, index:int):void, qui
prend deux paramtres : lenfant ajouter, puis lindex daffichage o il faut lajouter.
Voici un exemple, o lon ajoute chaque nouvelle voiture en arrire-plan :
1
2

// On cr e la rue
var rue : Sprite = new Sprite () ;

3
4
5
6

// On ajoute des voitures la rue , en les mettant l ' arri re plan chaque fois
var voiture1 : Sprite = new Sprite () ;
rue . addChildAt ( voiture1 , 0 ) ;

7
8
9

var voiture2 : Sprite = new Sprite () ;


rue . addChildAt ( voiture2 , 0 ) ;

10
11
12

var voiture3 : Sprite = new Sprite () ;


rue . addChildAt ( voiture3 , 0 ) ;

13
14
15
16

trace ( " La
) ) ; //
trace ( " La
) ) ; //
trace ( " La
) ) ; //

voiture1
Affiche
voiture2
Affiche
voiture3
Affiche

est l ' index " + rue . getChildIndex ( voiture1


2
est l ' index " + rue . getChildIndex ( voiture2
1
est l ' index " + rue . getChildIndex ( voiture3
0

Comme vous pouvez le constater, lindex daffichage de chaque objet varie,


car il reprsente tout instant la position en profondeur de celui-ci ; si jamais
un objet passe derrire un autre par exemple, son index sera automatiquement
modifi en consquence !

234

MANIPULER LES CONTENEURS

Oprations sur les enfants


Nombre denfants
Pour obtenir le nombre denfants que contient un conteneur, vous pouvez utiliser le
getter numChildren de type int.
Attention, cest un attribut en lecture seule car aucun setter nest dfini dans
la classe DisplayObjectContainer !

1
2

// On cr e une rue
var rue : Sprite = new Sprite () ;

3
4
5
6
7
8
9
10

// On ajoute trois voitures dans la rue


var voiture1 : Sprite = new Sprite () ;
rue . addChild ( voiture1 ) ;
var voiture2 : Sprite = new Sprite () ;
rue . addChild ( voiture2 ) ;
var voiture3 : Sprite = new Sprite () ;
rue . addChild ( voiture3 ) ;

11
12

trace ( " Il y a " + rue . numChildren + " voitures dans la rue . " ) ;
// Affiche 3 .

Accder au parent dun objet daffichage


Lattribut parent permet daccder au conteneur parent qui contient lobjet daffichage.
Cette proprit est notamment utile lintrieur dune classe, quand on ne peut pas
savoir quel est le conteneur.
1

trace ( rue == voiture1 . parent ) ; // Affiche true

2
3
4

trace ( " Nombre de voitures : " + rue . numChildren ) ; // Affiche 3


trace ( " Nombre de voitures : " + voiture1 . parent . numChildren ) ;
// Affiche 3 galement

Modifier lindex dun enfant


Une fois un objet daffichage enfant ajout un conteneur, il est possible de modifier son
index daffichage. Pour cela, nous utiliserons la mthode setChildIndex(enfant:DisplayObject,
index:int):void qui prend en paramtre lenfant en question puis son nouvel index.
1
2
3
4

// On met successivement les voitures au premier - plan


rue . setChildIndex ( voiture1 , 2 ) ;
rue . setChildIndex ( voiture2 , 2 ) ;
rue . setChildIndex ( voiture3 , 2 ) ;

235

CHAPITRE 13. LES OBJETS DAFFICHAGE


5

trace ( " La
) ) ; //
trace ( " La
) ) ; //
trace ( " La
) ) ; //

6
7
8

voiture1
Affiche
voiture2
Affiche
voiture3
Affiche

est l ' index " + rue . getChildIndex ( voiture1


0
est l ' index " + rue . getChildIndex ( voiture2
1
est l ' index " + rue . getChildIndex ( voiture3
2

Rappel : la valeur de lindex


conteneur.numChildren - 1 !

doit

tre

situe

entre

et

changer les index daffichage de deux enfants


Il existe deux mthodes de la classe DisplayObjectContainer pour changer la profondeur de deux objets enfants : swapChildren() qui prend en paramtre deux rfrences
des enfants du conteneur et swapChildrenAt() qui prend en paramtre deux index
diffrents changer.
1
2
3
4

rue . swapChildren ( voiture1 , voiture2 ) ;


trace ( " La voiture1 est l ' index " + rue . getChildIndex ( voiture1
) ) ; // Affiche 1
trace ( " La voiture2 est l ' index " + rue . getChildIndex ( voiture2
) ) ; // Affiche 0
// La voiture 1 est affich e devant la voiture 2

5
6
7
8
9

rue . swapChildrenAt (0 , 1 ) ;
trace ( " La voiture1 est l ' index " + rue . getChildIndex ( voiture1
) ) ; // Affiche 0
trace ( " La voiture2 est l ' index " + rue . getChildIndex ( voiture2
) ) ; // Affiche 1
// La voiture 1 est affich e en dessous de la voiture 2

Dterminer si un objet est enfant dun conteneur


Une mthode trs pratique de la classe DisplayObjectContainer renvoie un boolen
pour le savoir : jai nomm contains() ! Elle prend en paramtre un objet de la classe
DisplayObject et retourne true si cet objet est dans la liste daffichage du conteneur
(y compris parmi les petits-enfants, parmi les enfants des petits-enfants, etc.), ou sil
sagit du conteneur lui-mme (nous considrons que le conteneur se contient lui-mme).
Sinon, elle renvoie false.
1
2
3
4

var
var
var
var

236

sprite1 : Sprite
sprite2 : Sprite
sprite3 : Sprite
sprite4 : Sprite

=
=
=
=

new
new
new
new

Sprite () ;
Sprite () ;
Sprite () ;
Sprite () ;

MANIPULER LES CONTENEURS


6
7

sprite1 . addChild ( sprite2 ) ;


sprite2 . addChild ( sprite3 ) ;

8
9
10
11
12

trace ( sprite1 . contains ( sprite1 ) ) ;


trace ( sprite1 . contains ( sprite2 ) ) ;
trace ( sprite1 . contains ( sprite3 ) ) ;
trace ( sprite1 . contains ( sprite4 ) ) ;

//
//
//
//

Affiche :
Affiche :
Affiche :
Affiche :

true
true
true
false

Retirer des enfants


Pour retirer un enfant dun parent, la mthode removeChild(enfant:DisplayObject):void
est toute indique ! linstar de la mthode addChild(), cette fonction prend en paramtre lenfant enlever de laffichage.
1
2
3
4

// On enl ve les trois voitures de la rue


rue . removeChild ( voiture1 ) ;
rue . removeChild ( voiture2 ) ;
rue . removeChild ( voiture3 ) ;

Il est galement possible de supprimer un enfant un certain index, sans savoir prcisment duquel il sagit, laide de la mthode removeChildAt(index:int):void.
Le paramtre que nous passons correspond lindex de lenfant que nous souhaitons
enlever.
1
2

// On cr e la rue
var rue : Sprite = new Sprite () ;

3
4
5
6

// On ajoute des voitures la rue , en les mettant l ' arri re plan chaque fois
var voiture1 : Sprite = new Sprite () ;
rue . addChildAt ( voiture1 , 0 ) ;

7
8
9

var voiture2 : Sprite = new Sprite () ;


rue . addChildAt ( voiture2 , 0 ) ;

10
11
12

var voiture3 : Sprite = new Sprite () ;


rue . addChildAt ( voiture3 , 0 ) ;

13
14
15
16

trace ( " La
) ) ; //
trace ( " La
) ) ; //
trace ( " La
) ) ; //

voiture1
Affiche
voiture2
Affiche
voiture3
Affiche

est l ' index " + rue . getChildIndex ( voiture1


2
est l ' index " + rue . getChildIndex ( voiture2
1
est l ' index " + rue . getChildIndex ( voiture3
0

17
18
19

// On enl ve a voiture le plus au fond


rue . removeChildAt ( 0 ) ; // voiture3 enlev e !

20
21

// On peut enlever les deux autres de la m me mani re

237

CHAPITRE 13. LES OBJETS DAFFICHAGE


22
23

rue . removeChildAt ( 0 ) ; // voiture2 enlev e !


rue . removeChildAt ( 0 ) ; // voiture1 enlev e !

Et si on souhaite enlever tous les enfants du conteneur, ny a-t-il pas un


moyen moins fastidieux ?
La rponse est oui, grce la mthode removeChildren(beginIndex:int = 0, endIndex:int
= 0x7fffffff):void qui permet de supprimer plusieurs enfants dun coup dun seul !
Les deux paramtres facultatifs spcifient partir de quel index on supprime, et jusqu quel index. Par dfaut, tous les enfants sont supprims, donc si cest ce que vous
souhaitez faire, laissez les parenthses vides.
1

rue . removeChildren () ; // Toutes les voitures sont enlev es d ' un


coup !

Proprits utiles des objets daffichage


Nous allons maintenant aborder des proprits communes tous les objets daffichage,
qui savreront trs utiles ! Toutefois, nous nous limiterons pour linstant laffichage
2D dans le repre mentionn en dbut de chapitre.
Les attributs et mthodes que nous allons voir sont des proprits de la classe
DisplayObject, dont la documentation est disponible en ligne.

Documentation
B DisplayObject
Code web : 329657


Position
Tout dabord, commenons par la position de lobjet daffichage : deux attributs, x et y,
permettent de contrler respectivement la position horizontale et verticale de lorigine
dun objet daffichage.
Reprenons lexemple de lintroduction, visible la figure 13.20.
Pour dplacer lorigine dun objet cet endroit prcis (5, 6), nous crirons ceci :
1
2
3
4
5

var monObjet : Sprite = new Sprite () ;


// Modifions la position de l ' objet !
monObjet . x = 5 ;
monObjet . y = 6 ;
addChild ( monObjet ) ;

238

PROPRITS UTILES DES OBJETS DAFFICHAGE

Figure 13.20 Exemple de position sur lcran

La position par dfaut de tout nouvel objet daffichage est (0, 0), cest--dire
que x vaut 0 et que y vaut 0 si vous ny touchez pas.

Un mot sur lorigine


Lorigine dun objet daffichage est le point qui reprsente sa position actuelle. Par
dfaut, elle est situe en haut gauche (voir figure 13.21), et elle ne peut pas tre
dplace (voir figure 13.22).

Figure 13.21 Lorigine est en haut gauche par dfaut

Comment modifier lorigine de notre conteneur si on ne peut pas la dplacer ?

239

CHAPITRE 13. LES OBJETS DAFFICHAGE

Figure 13.22 Rotation du conteneur avec lorigine par dfaut


Et bien, cest trs simple, il suffit de dplacer les enfants lintrieur de notre conteneur,
pour donner lillusion de modifier lorigine (voir figure 13.23) !

Figure 13.23 On dplace limage de voiture lintrieur du conteneur


Et cest gagn (voir figure 13.24) !

Figure 13.24 Rotation du conteneur avec la nouvelle origine


Laffichage lcran de la voiture la position (0, 0) ressemblerait alors la figure
13.25 ou bien 13.26.
Par exemple, si vous ajoutez un objet daffichage voiture dans votre conteneur rue, et
que vous positionnez la voiture en ngatif 100 pixels de lorigine de la rue, une partie
de votre voiture sera trs certainement en dehors de lcran. Mais lorigine de la rue na
240

PROPRITS UTILES DES OBJETS DAFFICHAGE

Figure 13.25 Dans le cas de lorigine par dfaut

Figure 13.26 Dans le cas o lon a centr lorigine

241

CHAPITRE 13. LES OBJETS DAFFICHAGE


pas chang entre-temps : elle est toujours sa position de dpart (0, 0). Maintenant,
vous pouvez faire rapparatre la voiture en entier en dplaant la rue de 100 pixels
vers la droite ! Son origine va ainsi changer et devenir (100, 0), ainsi la position de la
voiture par rapport la scne sera (0, 0) ! Tout est relatif !

Taille
Taille absolue
La taille absolue dun objet daffichage, cest--dire la taille quil prend lcran, peut
tre lue ou modifie laide des attributs width (longueur) et height (hauteur), en
pixels. La taille est toujours exprime en valeurs positives.
1
2
3
4
5

var maVoiture : Voiture = new Voiture () ;


// Modifions la taille de la voiture pour qu ' elle fasse 100x100
pixels !
maVoiture . width = 100 ;
maVoiture . height = 100 ;
addChild ( maVoiture ) ;

Modifier la taille dun conteneur vide et sans dessin na aucun sens, et ne


donnera aucun rsultat. Ses deux attributs width et height seront toujours
gaux 0.

Taille relative
On peut galement redimensionner un objet daffichage laide de pourcentages, grces
aux attributs scaleX pour redimensionner en longueur, et scaleY en hauteur. Les
pourcentages ne sont pas directement exprims en tant que tel : par exemple, scaleX
= 1 signifie que la longueur de lobjet est 100%, scaleY = 2 signifie que lobjet est
deux fois plus haut que sa taille absolue dorigine et scaleY = 0.5 signifie que lobjet
est moiti moins haut.
1
2
3
4

var maVoiture : Voiture = new Voiture () ;


// Modifions la taille de la voiture pour qu ' elle fasse 100x100
pixels !
maVoiture . width = 100 ;
maVoiture . height = 100 ;

5
6
7
8
9
10

// R duisons la taille de la voiture de moiti !


maVoiture . scaleX = 0 . 5 ;
maVoiture . scaleY = 0 . 5 ;
trace ( maVoiture . width ) ; // Affiche : 50
trace ( maVoiture . height ) ; // Affiche : 50

11
12

// Remettons - l sa taille normale :

242

PROPRITS UTILES DES OBJETS DAFFICHAGE


13
14
15
16
17

maVoiture . scaleX = 1 ;
maVoiture . scaleY = 1 ;
trace ( maVoiture . width ) ; // Affiche : 100
trace ( maVoiture . height ) ; // Affiche : 100
addChild ( maVoiture ) ;

Avec ses proprits, il est possible dinverser un objet daffichage laide de valeurs
ngatives :
1
2
3
4

var maVoiture : Voiture = new Voiture () ;


// Modifions la taille de la voiture pour qu ' elle fasse 100x100
pixels !
maVoiture . width = 100 ;
maVoiture . height = 100 ;

5
6
7
8
9
10

// Inversons horizontalement la voiture !


maVoiture . scaleX = -1 ;
trace ( maVoiture . width ) ; // Affiche : 100
trace ( maVoiture . height ) ; // Affiche : 100
addChild ( maVoiture ) ;

Rappel : les attributs de taille width et height sont toujours positifs.

Rotation
Lattribut rotation permet de faire tourner des objets daffichage autour de leur origine (voir figure 13.27), en utilisant des degrs. Les valeurs comprises entre 0 et 180
reprsentent la rotation en sens horaire ; les valeurs comprises entre 0 et -180 reprsentent la rotation en sens antihoraire. Les valeurs hors de cette plage sont alors rajustes (ajoutes ou soustraites de 360) pour obtenir une valeur comprise dans la plage.
Par exemple, linstruction voiture.rotation = 400 correspond voiture.rotation
= 40 (car 400 - 360 = 40).
Si vous voulez utiliser des valeurs en radians, il ne faut pas oublier de les
convertir en degrs avant dutiliser lattribut rotation : on crira par exemple
voiture.rotation = maValeurEnRadians / Math.PI * 180; en utilisant la constant Math.PI qui contient une valeur assez prcise du nombre
pi.

243

CHAPITRE 13. LES OBJETS DAFFICHAGE

Figure 13.27 Rotation dun objet (avec lorigine par dfaut)

Transparence
Visibilit
Lattribut visible vaut true si lobjet est visible, false sil est invisible. Par dfaut,
sa valeur est true (lobjet est visible).
1
2
3
4

var maVoiture : Voiture = new Voiture () ;


// Rien ne sera affich l ' cran
maVoiture . visible = false ;
addChild ( maVoiture ) ;

Un objet daffichage avec une visibilit faux nest pas du tout rendu lcran,
et ne peut donc pas interagir avec la souris par exemple. Cela permet toutefois
dconomiser des ressources de lordinateur pour amliorer les performances.
Un bon conseil : si un objet doit tre invisible, utilisez cette proprit chaque
fois que vous le pouvez !

Opacit
Lattribut alpha de type Number dtermine lopacit dun objet daffichage, cest--dire
sil est plus ou moins transparent. Les valeurs vont de 0 (invisible) 1 (opaque).
244

SUPPRIMER UN OBJET DAFFICHAGE DE LA MMOIRE


1
2
3
4

var maVoiture : Sprite = new Sprite () ;


// La voiture sera moiti transparente
maVoiture . alpha = 0 . 5 ;
addChild ( maVoiture ) ;

Lopacit dun conteneur est un multiplicateur de lopacit de tous ces enfants, et ainsi
de suite. Par exemple, si un enfant a une opacit de 0.5, et que le conteneur a une
opacit de 0.5, lopacit relle de lenfant sera de 0.5 x 0.5 = 0.25 : lenfant est donc
trois quarts transparent.
1
2
3

var enfant : Sprite = new Voiture () ;


// L ' enfant sera moiti transparent
enfant . alpha = 0 . 5 ;

4
5
6
7
8

var conteneur : Sprite = new Sprite () ;


// Le conteneur sera aussi moiti transparent
conteneur . alpha = 0 . 5 ;
conteneur . addChild ( maVoiture ) ;

9
10

// Au final , l ' opacit de l ' enfant vaut 0 . 25

Il est possible de mettre une valeur suprieure 1 : cela aura pour effet
daugmenter lopacit des enfants de lobjet. Par exemple, si un enfant a
pour opacit 0.5, et que lon met lopacit de son conteneur 2, lopacit de
lenfant relle sera 0.5 x 2 = 1 : lenfant est donc entirement opaque.
Un objet visible mais transparent (cest--dire que sa visibilit est vrai mais
que son opacit est 0) est quand mme rendu lcran, et donc consomme
des ressources de lordinateur. Toutefois, il reste interactif, il est possible de
cliquer dessus par exemple.

Supprimer un objet daffichage de la mmoire


ce stade du cours, pour supprimer un objet daffichage de la mmoire, il est ncessaire
de respecter les points suivants :
lobjet ne doit pas faire partie de la liste daffichage, cest--dire quil ne doit pas
tre lenfant dun conteneur ;
il ne doit plus y avoir une seule rfrence cet objet.
Nous tofferons cette liste au fur-et--mesure du cours, lorsque nous aborderons de
nouvelles notions, afin que vous soyez experts en mmoire non-sature !
Pour supprimer un objet de la liste daffichage, vous pouvez utiliser la mthode removeChild()
de la classe DisplayObjectContainer :
1

var maVoiture : Voiture = new Voiture () ;

245

CHAPITRE 13. LES OBJETS DAFFICHAGE


2
3
4

rue . addChild ( maVoiture ) ;


// Supprimons la voiture de la liste d ' affichage
rue . removeChild ( maVoiture ) ;

Lobjet en question doit tre un enfant du conteneur, sinon, une erreur sera
envoye lappel de la mthode removeChild().
Si jamais vous voulez supprimer lobjet daffichage depuis sa propre classe, il faut
utiliser lattribut parent et ruser un peu :
1
2
3

package
{
import flash . display . Sprite ;

public class Voiture extends Sprite


{
public function Voiture ()
{

5
6
7
8
9

10
11
12
13
14

15
16
17
18
19
20

21

public function removeFromParent () : void


{
// V rifions que la voiture est sur la liste d '
affichage ( cad . que le parent existe ) avant d '
appeler removeChild ()
if ( parent != null )
{
// Supprimons l ' objet de la liste d ' affichage
parent . removeChild ( this ) ;
}
}

22
23

Mais comment supprimer une rfrence un objet ?

Cest trs simple : il suffit daffecter la variable en question avec le mot-cl null :
1
2
3
4
5
6

var maVoiture : Voiture = new Voiture () ;


rue . addChild ( maVoiture ) ;
// Supprimons la voiture de la liste d ' affichage
rue . removeChild ( maVoiture ) ;
// Supprimons la r f rence la voiture !
maVoiture = null ;

246

SUPPRIMER UN OBJET DAFFICHAGE DE LA MMOIRE


ce stade, lobjet de la classe Voiture na pas encore t supprim : il est encore dans la
mmoire de votre ordinateur. Il sera effectivement supprim lorsque le ramasse-miette
(garbage-collector en anglais) sera pass pour nettoyer la mmoire. Seulement, pour
que le ramasse-miette puisse faire son travail, et dterminer quels objets doivent tre
supprims, il faut respecter les points numrs ci-dessus. On dit alors que ces objets
sont ligibles au nettoyage par le ramasse-miette.
Vous remarquerez ainsi quil nexiste aucun moyen de supprimer un objet
directement de la mmoire, sauf pour quelques rares exceptions. La plupart
du temps, il faut laisser le ramasse-miette le faire notre place. Cela marche
donc pour tous les objets, pas seulement les objets daffichage ; mais dans ce
cas, inutile dessayer de retirer de la liste daffichage des objets qui nont rien
voir ! Supprimer leurs rfrences suffit pour linstant.

En rsum
En ActionScript 3, les couleurs sont dcrites en notation hexadcimale, prcdes des caractres 0x (zro et x).
Laffichage sur un cran se fait dans un repre partant du coin suprieur gauche de
lcran. Les coordonns en x vont de gauche droite, et en y de haut en bas.
Les objets daffichage sont contenus dans un arbre : ils peuvent contenir
chacun des enfants pouvant eux-mme contenir dautres enfants.
On peut manipuler les enfants des conteneurs laide des proprits de la classe
DisplayObjectContainer.
Une multitude de proprits de la classe DisplayObject permet de manipuler les
objets daffichage.
Il faut respecter quelques consignes pour quun objet daffichage soit supprim de
la mmoire par le ramasse-miette.

247

CHAPITRE 13. LES OBJETS DAFFICHAGE

248

Chapitre

14

Afficher du texte
Difficult :
Mesdames, Messieurs, jai lhonneur de vous prsenter le premier chapitre o nous allons
pouvoir afficher quelque chose sur notre fentre encore jusqu prsent si dsesprment
vide ! Et il sagit rien de moins que du texte, grce une classe que nous allons retourner
dans tous les sens : TextField.
Que le spectacle commence !

249

CHAPITRE 14. AFFICHER DU TEXTE

Une histoire de TextField


La classe
Comme vous laurez srement compris, nous allons utiliser dans ce chapitre la classe
TextField. Pour vous aidez vous situer, reprenons le diagramme des classes des
objets daffichage la figure 14.1.

Figure 14.1 TextField parmi larbre des classes daffichage

Comme vous pouvez le voir, la classe TextField est une sous-classe de InteractiveObject,
elle hrite donc de toutes les fonctionnalits qui permettent lutilisateur dinteragir
avec les objets TextField (clic, slection de texte, frappe au clavier, etc.). Mais cest
aussi un objet daffichage comme les autres car la classe InteractiveObject est fille
de la classe DisplayObject : nous pouvons donc bouger, redimensionner ou tourner
nos champs de texte comme bon nous semble, voir les rendre semi-transparents !
Comme dhabitude, je vous conseille de lire la documentation sur la classe
disponible en ligne.

Documentation TextField
B
Code web : 535015

250

UNE HISTOIRE DE TEXTFIELD

Utilisation de base
Crer un champ de texte
Comme toutes les classes des objets daffichage, la classe TextField dispose dun
constructeur sans paramtre. Nous allons donc lutiliser pour crer des champs
de texte comme suit :
1

var monSuperTexte : TextField = new TextField () ;

Du texte brut
Lattribut text contient le texte brut (cest--dire non format) qui est affich dans le
champ de texte. Par dfaut, le texte est vide, cest--dire que lattribut contient une
chane de caractres vide : "".
Il sutilise comme nimporte quel autre attribut :
1
2

// Affectation d ' un texte brut


monSuperTexte . text = ' Hello World ! ';

3
4
5
6

// Avec une variable :


var maSuperChaine : String = ' Je m \ ' apelle Zozor ! ';
monSuperTexte . text = maSuperChaine ;

7
8
9

// Lecture du contenu brut du champ de texte :


trace ( ' Zozor a dit : " ' + monSuperTexte . text + '" ') ; // Affiche
: Zozor a dit : " Je m ' appelle Zozor !"

ne pas oublier !
Pour que notre champ de texte soit affich, il ne faut surtout pas oublier de lajouter
sur la liste daffichage, cest--dire quil faut lajouter parmi les enfants dun conteneur !
Ainsi, dans notre classe Main, crivons ceci :
1
2

// Ajoutons le champ de texte sur la sc ne principale :


addChild ( monSuperTexte ) ;

Rappel : la classe Main est une sous-classe de la classe Sprite, elle-mme


une sous-classe de la classe DisplayObjectContainer ! Nous pouvons donc
y ajouter des objets daffichage (nous serions bien embts sinon).

Le rsultat
Par dfaut, la couleur du texte est le noir et sans dcoration (bordure ou fond), la
police utilise est une police par dfaut de votre systme (Times New Roman sur
251

CHAPITRE 14. AFFICHER DU TEXTE


Windows/Linux et Times sur Mac), la taille est de 12 points et le texte nest pas
ditable. Mais ne vous inquitez pas, tout ceci est entirement paramtrable comme
certains ont pu le remarquer en lisant la documentation en ligne.
Pour que vous puissiez vrifier votre code, voici lensemble de la classe Main permettant
dafficher du texte lcran :
1
2
3
4
5

package
{
import flash . display . Sprite ;
import flash . events . Event ;
import flash . text . TextField ;

/* *
* Cette application sait afficher du texte !
*/
[ SWF ( width = " 800 " , height = " 600 " , backgroundColor = " # ffffff " ) ]

7
8
9
10
11

public class Main extends Sprite


{

12
13
14

public function Main () : void


{
if ( stage )
init () ;
else
addEventListener ( Event . ADDED_TO_STAGE , init ) ;
}

15
16
17
18
19
20
21
22

private function init ( e : Event = null ) : void


{
removeEventListener ( Event . ADDED_TO_STAGE , init ) ;
// entry point

23
24
25
26
27
28
29
30
31
32

33

// Mon premier champ de texte ! \ o /


var monSuperTexte : TextField = new TextField () ;
monSuperTexte . text = ' Hello World ! ';
addChild ( monSuperTexte ) ;

34
35

Pour que vous puissiez voir quelque chose, vrifiez que


la couleur de fond de votre animation est en blanc :
[SWF(width="800",height="600",backgroundColor="#ffffff")].
Du texte noir sur fond noir par exemple, ce nest pas ce quil y a de plus
lisible.
La figure 14.2 vous montre ce que cela donne lcran.
252

UNE HISTOIRE DE TEXTFIELD

Figure 14.2 Notre premier champ de texte !


Javoue que ce nest pas trs joli, mais nous allons amliorer cela dans peu de temps.
La taille par dfaut dun champ de texte est 100 pixels de largeur et 100 pixels
de hauteur. Il est bien entendu possible de la modifier.
Pour le vrifier visuellement, nous pouvons afficher une bordure autour du champ de
texte :
1

monSuperTexte . border = true ;

Ce qui donne lcran la figure 14.3.

Figure 14.3 Le champ de texte, avec sa bordure


Ce nest pas ce quil y a de plus esthtique, alors enlevons la bordure en commentant
la ligne que nous venons dajouter :
1

// monSuperTexte . border = true ;

Maintenant que nous avons un vritable objet daffichage sous la main, exerons-nous
utiliser ses proprits.
Commenons par dplacer notre champ de texte la position (200, 100) :
1
2

monSuperTexte . x = 200 ;
monSuperTexte . y = 100 ;

Vous devriez maintenant avoir quelque chose ressemblant la figure 14.4.


Je le trouve un peu trop petit, pas vous ? Allez, triplons sa taille :
253

CHAPITRE 14. AFFICHER DU TEXTE

Figure 14.4 Position (200, 100)


1
2
3

// Taille x3 !
monSuperTexte . scaleX = 3 ;
monSuperTexte . scaleY = 3 ;

Ce qui donne lcran la figure 14.5.


Dsormais, la taille de notre champ de texte est 300 pixels de largeur et 300 pixels de
hauteur. Pour mieux le voir, nous pouvons remettre la bordure notre champ de texte
en dcommentant cette ligne :
monSuperTexte . border = true ;

Ce qui donne lcran la figure 14.6.


Pour rcapituler (voir figure 14.7), nous avons :

Cr une instance de la classe TextField.


Dfini le texte du champ de texte.
Ajout le champ de texte laffichage.
Modifi sa position.
Modifi son chelle de taille.
Il est impossible de faire tourner du texte ou de changer son opacit dans
ltat actuel, car nous utilisons le systme pour rendre les caractres, ce qui
implique ces limitations. Si vous changez tout de mme la rotation ou lopacit
du champ de texte, les caractres ne seront plus affichs. Pour contourner ce
problme, il faut utiliser des polices de caractres embarques afin que les
caractres soient rendus directement par le lecteur Flash. Nous apprendrons
comment faire la fin de ce chapitre.

254

UNE HISTOIRE DE TEXTFIELD

Figure 14.5 Notre champ de texte, quatre fois plus grand

Figure 14.6 Le champ de texte agrandi, avec sa bordure

255

CHAPITRE 14. AFFICHER DU TEXTE

Figure 14.7 Rcapitulatif des oprations

Slection du texte
Curseur dinsertion
Tous les champs de texte disposent dun curseur dinsertion, reprsent par une
barre verticale. Lorsque le champ de texte nest pas ditable, on dit quil est statique.
Dans ce cas, le curseur dinsertion est toujours invisible. Jusquici, notre champ de
texte est statique.
Dfinir une slection
Il est possible de slectionner une portion de texte directement laide de la mthode
setSelection() de la classe TextField, qui prend en paramtre la position du premier
caractre slectionner et la position du caractre aprs le dernier caractre de la
slection. Par exemple, pour slectionner les deux premires lettres, on crira ceci :
1

monSuperTexte . setSelection (0 , 2 ) ;

Nous mettons 2 en deuxime paramtre, car il faut passer la position du


caractre aprs le dernier caractre slectionner, cest--dire la position du
dernier caractre slectionner (le numro 1) plus une.
256

UNE HISTOIRE DE TEXTFIELD


Si vous testez le programme maintenant, vous ne verrez pas le texte slectionn : cest
normal, car par dfaut les champs de texte qui nont pas le focus, cest--dire qui ne
sont pas actifs, naffichent pas la slection du texte. Pour rendre un champ de texte
actif, la manire la plus simple est de cliquer dessus. Il existe cependant un moyen
dafficher tout de mme la slection, mme si le champ de texte na pas le focus : on
met lattribut alwaysShowSelection true :
1

monSuperTexte . alwaysShowSelection = true ;

Ce qui nous donne lcran la figure 14.8.

Figure 14.8 Les deux premires lettres sont slectionnes.

Accder la slection
Il est possible de savoir quelles positions le texte slectionn dbute et se termine. Nous
disposons pour cela des attributs selectionBeginIndex, position du premier caractre
slectionn, et selectionEndIndex, position du dernier caractre slectionn :
1

trace ( " S lection : " + monSuperTexte . selectionBeginIndex + " ->


" + monSuperTexte . selectionEndIndex ) ; // Affiche 0 -> 2

Pour obtenir le texte slectionn, nous utiliserons la mthode substring de lattribut


text:String du champ de texte :
1

trace ( " Texte s lectionn : " + monSuperTexte . text . substring (


monSuperTexte . selectionBeginIndex , monSuperTexte .
selec tionEndIndex ) ) ; // Affiche : He

La valeur renvoye par selectionEndIndex correspond la position du


caractre aprs le dernier caractre slectionn (autrement dit, la position
du dernier caractre slectionn + 1). Cela tombe bien car la mthode
substring prend les caractres jusqu la deuxime position passe en paramtre moins une. Nous obtenons donc le bon texte.

Empcher la slection du texte


Par dfaut, le texte contenu par un champ de texte peut tre slectionn par lutilisateur, puis ventuellement copi. Le curseur se change alors en curseur de texte.
Ce comportement peut tre gnant, par exemple, si vous utilisez un champ de texte
pour crer un bouton. Pour le dsactiver, il suffit de mettre lattribut selectable de
la classe TextField false :
257

CHAPITRE 14. AFFICHER DU TEXTE


1

monSuperTexte . selectable = false ;

Centrer le champ de texte


De la manire dont nous lavons plac jusquici, notre texte nest pas exactement au
centre de la fentre. Pour remdier cela, il nous faut connatre la taille exacte de la
scne !

Un mot sur la scne principale


La classe Stage
Comme nous lavons vu prcdemment, une instance de la classe Stage est automatiquement cre au lancement de notre programme : il sagit de la scne principale.
La scne principale est un objet daffichage comme on peut le voir sur le schma des
classes daffichage la figure 14.9.

Figure 14.9 La classe Stage parmis les autres classes daffichage


La classe Stage est donc une sous-classe de la classe DisplayObjectContainer : elle
hrite donc de toutes ses proprits et sapparente un conteneur comme ceux que
nous avons vu au chapitre prcdent. Il y a tout de mme quelques diffrences :
On ne peut pas crer de scnes principales nous-mme car la classe Stage est
abstraite.
La plupart des proprits de la classe DisplayObjectContainer ne fonctionnent pas.
La classe Stage dispose de nouvelles proprits spcifiques.
Voici une liste des proprits que nous avons dj abordes et qui sont sans effet pour
la classe Stage :
258

CENTRER LE CHAMP DE TEXTE

alpha
rotation
scaleX
scaleY
visible
x
y

Inutile donc dessayer de modifier ces attributs, cela naura aucun impact sur la scne
principale. Par contre, il est toujours possible dutiliser les attributs de linstance de
notre classe Main afin davoir un impact sur lensemble de notre arbre daffichage. Par
exemple, si lon veut rendre la scne invisible, nous pouvons mettre ce code dans notre
classe Main :
1
2

// Dans la classe Main


this . visible = false ; // Toute la sc ne est invisible !

3
4

visible = false ; // On peut omettre le mot - cl this

Il est possible daccder la scne principale grce lattribut stage disponible sur
nimporte quel objet daffichage driv de la classe DisplayObject, condition que cet
objet soit prsent dans larbre daffichage.
1
2
3
4
5

// On ne peut acc der la sc ne depuis notre objet voiture


seulement s ' il est pr sent dans l ' arbre d ' affichage :
var voiture : Sprite = new Sprite () ;
trace ( voiture . stage ) ; // Affiche null
addChild ( voiture ) ;
trace ( voiture . stage ) ; // Affiche [ object Stage ]

Cela signifie que lon peut accder la scne principale depuis notre classe Main
comme ceci :
1
2

// Dans la classe Main , dans la m thode init ()


trace ( this . stage ) ; // Affiche [ object Stage ]

3
4
5

// Comme d ' habitude , il est possible d ' omettre le mot - cl this


:
trace ( stage ) ; // Affiche [ object Stage ]

Le code par dfaut propos par FlashDevelop


Il est temps de vous expliquer pourquoi le code par dfaut de notre classe Main contient
plus de choses que pour les autres classes que nous avons cres lorsque nous utilisons
FlashDevelop. Comme nous lavons vu prcdemment, on ne peut accder la scne
daffichage que si notre objet est prsent dans larbre daffichage. Ainsi, le code
par dfaut de notre classe Main permet de vrifier si notre objet de la classe est bien
prsent dans larbre avant dappeler la mthode init(). Si jamais ce ntait pas encore
le cas (par exemple, si le lecteur Flash met un peut de temps lancer le programme),
259

CHAPITRE 14. AFFICHER DU TEXTE


nous aurions des problmes pour utiliser les proprits de la scne principale : en
effet, lattribut stage serait null ! Reprenons le code par dfaut de la classe Main et
commentons un peu pour mieux comprendre :

1
2
3
4
5

package
{
// Classes n cessaires
import flash . display . Sprite ;
import flash . events . Event ;

/* *
* La classe de base sans modification .
*/
[ SWF ( width = " 640 " , height = " 480 " , backgroundColor = " # ffffff " ) ]

7
8
9
10
11

public class Main extends Sprite


{
// Constructeur
public function Main () : void
{
if ( stage ) // Si l ' attribut stage est d fini ( c 'est
- - dire , si il est diff rent de null )
init () ; // Alors , on appelle la m thode init ()
tout de suite
else // Sinon
addEventListener ( Event . ADDED_TO_STAGE , init ) ;
// On attend que notre instance de la classe
Main soit ajout e l ' arbre de l ' affichage
}

12
13
14
15
16
17
18
19
20

21
22

private function init ( e : Event = null ) : void


{
removeEventListener ( Event . ADDED_TO_STAGE , init ) ; //
On arr te d ' attendre

23
24
25
26
27
28

29

// Nous pouvons commencer coder ici en tout s r


nit

30
31

Le code qui permet dattendre que lobjet soit ajout larbre daffichage
utilise la notion dvnement, notion que nous aborderons dans la partie
suivante.

260

CENTRER LE CHAMP DE TEXTE


La taille de la scne
Revenons nos moutons et intressons-nous la taille de la fentre de notre programme.
On peut y accder grce deux attributs de la classe Stage (voir figure 14.10) :
stageWidth pour connatre la largeur de la scne.
stageHeight pour la hauteur.

Figure 14.10 La taille de la scne principale


Par exemple, nous pouvons crire ceci dans notre classe Main pour afficher la taille de
la scne principale :
1

trace ( " La sc ne principale a pour dimensions " + stage .


stageWidth + " x " + stage . stageHeight ) ;

La console affichera alors :


La sc ne principale a pour dimensions 640 x480

Cela correspond la configuration de notre programme qui se trouve cette ligne :


1

[ SWF ( width = " 640 " , height = " 480 " , backgroundColor = " # ffffff " ) ]

261

CHAPITRE 14. AFFICHER DU TEXTE


Il ne faut pas confondre les attributs stageWidth et stageHeight qui
donnent les dimensions de la scne principale, avec les attributs width et
height qui donnent la taille du contenu de la scne !
En effet, nous nobtenons pas le mme rsultat dans les deux cas. Pour le vrifiez,
ajoutons ce code :
trace ( " Le contenu de la sc ne principale a pour taille " +
stage . width + " x " + stage . height ) ;

Ensuite, la console affiche ceci :


La sc ne principale a pour dimensions 640 x480
Le contenu de la sc ne principale a pour taille 300 x300

Comme le montre la figure 14.11, la taille du contenu de la scne est souvent diffrente
des dimensions de la scne.

Figure 14.11 La taille du contenu de la scne par rapport aux dimensions de la scne

Adapter la taille du champ de texte au texte


Pour centrer le champ de texte, il serait intressant que celui-ci fasse la mme taille
que celle du texte lintrieur. Pour linstant, notre champ de texte fait 300 pixels de
262

CENTRER LE CHAMP DE TEXTE


largeur et 300 pixels de hauteur, ce qui est beaucoup trop. Nous pouvons dire au champ
de texte dadapter sa taille grce son attribut autoSize :
1

monSuperTexte . autoSize = TextFieldAutoSize . LEFT ;

Sans oublier dimporter la classe TextFieldAutoSize (qui contient les valeurs autorises
pour lattribut autoSize) :
1

import flash . text . TextFieldAutoSize ;

Petite astuce si vous programmez avec FlashDevelop : appuyez simultanment sur Ctrl + Alt + Espace (au lieu de lhabituel Ctrl + Espace)
et commencez taper Text, lauto-compltion va vous proposer toutes les
classes possibles dont celle qui nous intresse ici.
Dsormais, nous avons lcran la figure 14.12.

Figure 14.12 La taille du champ de texte correspond la taille du texte


Nous pouvons afficher la taille du champ de texte pour tre sr de nous :
1

trace ( " Taille : " + monSuperTexte . width + " x " + monSuperTexte .


height ) ; // Affiche 199 . 95x52 . 95

263

CHAPITRE 14. AFFICHER DU TEXTE

Modifier la position du champ de texte


Il est temps de centrer notre champ de texte ! Nous allons procder en trois tapes pour
bien dtailler lopration.
Etape 1
Commenons par placer lorigine de notre champ de texte au centre de lcran. Pour
cela, il suffit dutiliser les attributs stageWidth et stageHeight que nous venons de
voir :
1
2

monSuperTexte . x = stage . stageWidth / 2 ;


monSuperTexte . y = stage . stageHeight / 2 ;

Ce qui nous donne lcran la figure 14.13.

Figure 14.13 Lorigine du champ de texte est centre


Notre champ de texte nest pas encore entirement centr, mais nous y sommes presque !
Etape 2
Nous allons maintenant retrancher la moiti de la largeur de notre champ de texte
sa position x pour centrer notre champ de texte horizontalement :
264

CENTRER LE CHAMP DE TEXTE


1

monSuperTexte . x -= monSuperTexte . width / 2 ;

Ce qui nous donne lcran la figure 14.14.

Figure 14.14 Notre champ de texte, centr horizontalement

Etape 3
Pour finir, nous rptons la mme chose, mais verticalement : nous retranchons la
moiti de la hauteur de notre champ de texte sa position y :
1

monSuperTexte . y -= monSuperTexte . height / 2 ;

Ce qui nous donne la figure 14.15.


En rsum
Lopration sest donc droule en trois tapes :
On centre lorigine de lobjet en utilisant stage.stageWidth et stage.stageHeight.
On retranche la moiti de sa largeur sa position horizontale x.
On retranche la moiti de sa hauteur sa position verticale y.
Et voici le code complet concernant notre champ de texte :
265

CHAPITRE 14. AFFICHER DU TEXTE

Figure 14.15 Notre champ de texte, au centre de la scne !

266

CENTRER LE CHAMP DE TEXTE


1
2
3
4

// Cr ons notre champ de texte


var monSuperTexte : TextField = new TextField () ;
monSuperTexte . text = ' Hello World ! ';
addChild ( monSuperTexte ) ;

5
6
7
8

// Multiplions sa taille par quatre


monSuperTexte . scaleX = 4 ;
monSuperTexte . scaleY = 4 ;

9
10
11

// Activons la bordure
monSuperTexte . border = true ;

12
13
14

// Adaptons la taille du champ de texte au texte


monSuperTexte . autoSize = TextFieldAutoSize . LEFT ;

15
16
17
18

// Centrons l ' origine


monSuperTexte . x = stage . stageWidth / 2 ;
monSuperTexte . y = stage . stageHeight / 2 ;

19
20
21
22

// Retranchons la moiti de sa taille sa position


monSuperTexte . x -= monSuperTexte . width / 2 ;
monSuperTexte . y -= monSuperTexte . height / 2 ;

Nous pouvons compacter la dernire partie de notre code qui permet de centrer le
champ de texte :
1
2
3

// Centrons le champ de texte


monSuperTexte . x = stage . stageWidth / 2 - monSuperTexte . width /
2;
monSuperTexte . y = stage . stageHeight / 2 - monSuperTexte . height
/ 2;

Nous pouvons encore simplifier en factorisant :


1
2
3

// Centrons le champ de texte


monSuperTexte . x = ( stage . stageWidth - monSuperTexte . width ) / 2 ;
monSuperTexte . y = ( stage . stageHeight - monSuperTexte . height ) /
2;

Cette mthode pour aligner au centre de la scne fonctionne bien videmment


avec tous les objets daffichage, pas seulement les champs de texte.

Pour linstant, il nous est impossible de faire tourner notre champ de texte
car il utilise une police de votre systme pour le rendu. Pour contourner ce
problme, il nous faut embarquer notre propre police de caractre, comme
nous le verrons dans un prochain chapitre.

267

CHAPITRE 14. AFFICHER DU TEXTE

La mise en forme
Formatons notre champ de texte
Mise en forme par dfaut
Formater du texte est possible grce la classe TextFormat (dont la documentation est disponible en ligne). Tout objet de classe TextField dispose dun attribut
defaultTextFormat de type TextFormat. Cet attribut permet de modifier la mise en
forme par dfaut du texte contenu dans le champ de texte, cela signifie quun texte qui
na pas de mise en forme spcifique recevra automatiquement cette mise en forme par
dfaut.


Documentation TextFormat
B
Code web : 348025


La mise en forme par dfaut doit tre applique avant de dfinir le texte.

Pour modifier la mise en forme par dfaut de notre champ de texte, nous procderons
ainsi :
1
2

// Cr ation de l ' instance du champ de texte


var monSuperTexte : TextField = new TextField () ;

3
4
5

// Cr ation de l ' instance de la classe TextFormat


var format : TextFormat = new TextFormat () ;

6
7

// Modifications du format ici

8
9
10

// Application du format au champ de texte


monSuperTexte . defaultTextFormat = format ;

11
12
13

// Texte afficher - apr s la mise en forme par d faut


monSuperTexte . text = " Hello World ! " ;

14
15
16

// Ajout du champ de texte l ' affichage


addChild ( monSuperTexte ) ;

La mise en forme par dfaut nest mise jour que si nous affectons un objet
de classe TextFormat lattribut defaultTextFormat. Si nous modifions
directement les attributs de defaultTextFormat, il ne se passera rien. Noubliez pas quil faut que le texte soit dfini aprs avoir mis jour la mise en
forme par dfaut.

268

LA MISE EN FORME
Lheure du changement est arrive
Nous allons dans un premier temps modifier la taille, la police de caractre et la couleur de notre texte. En se renseignant dans la documentation, nous pouvons noter les
diffrents attributs correspondants :
size:Object (entier) pour la taille du texte en pixels.
font:String (chane de caractre) pour le nom de la police de caractre utiliser.
color:Object (entier positif) pour la couleur du texte.
Avant de commencer, rendons sa taille normale notre champ de texte en supprimant
(ou commentant) les lignes qui modifient son chelle :
1
2

// monSuperTexte . scaleX = 3 ;
// monSuperTexte . scaleY = 3 ;

Exerons-nous modifier la mise en forme de notre champ de texte : notre texte doit
tre de taille 42, utilisant la police de caractre Arial et colori en bleu (dont le code
hexadcimal est 0x0000ff).
1
2

// Cr ation de l ' instance du champ de texte


var monSuperTexte : TextField = new TextField () ;

3
4
5

// Cr ation de l ' instance de la classe TextFormat


var format : TextFormat = new TextFormat () ;

6
7
8
9
10

// Mise en forme
format . size = 42 ;
format . font = " Arial " ;
format . color = 0x0000ff ;

11
12
13

// Application du format au champ de texte


monSuperTexte . defaultTextFormat = format ;

14
15
16

// Texte
monSuperTexte . text = " Hello World ! " ;

17
18
19

// Bordure
monSuperTexte . border = true ;

20
21
22

// Taille adaptative
monSuperTexte . autoSize = TextFieldAutoSize . LEFT ;

23
24
25
26

// Centrons le champ de texte


monSuperTexte . x = ( stage . stageWidth - monSuperTexte . width ) / 2 ;
monSuperTexte . y = ( stage . stageHeight - monSuperTexte . height ) /
2;

27
28
29

// Ajout du champ de texte l ' affichage


addChild ( monSuperTexte ) ;

Ce qui nous donne la figure 14.16.


269

CHAPITRE 14. AFFICHER DU TEXTE

Figure 14.16 Le texte bleu, en Arial et en taille 42


Vous remarquerez quil est possible de positionner lobjet daffichage avant
quil ne soit ajout larbre daffichage.

Si vous vous trompez en crivant le nom de la police, ou que celle-ci nest


pas installe sur le systme de lutilisateur, la police par dfaut sera utilise
la place.

Pourquoi certains de ces attributs ont pour type Object au lieu de int ou
uint ?
Cest trs simple : les attributs de la classe TextFormat ont pour valeur par dfaut
null, pour signifier quil faut utiliser les valeurs par dfaut de mise en forme (que lon
peut trouver dans la documentation, en haut de la page). Or, les attributs de type int
ou uint ne peuvent pas valoir null, donc on est oblig dutiliser le type Object (type
indfini, dont les variables peuvent valoir null). On aurait aussi pu utiliser le type *,
quivalent au type Object.
Le constructeur de la classe TextFormat permet de dfinir directement certains attributs. Ainsi, nous pourrions simplifier notre code en utilisant le constructeur de la classe
TextFormat ainsi que nous lindique la documentation en ligne.
TextFormat ( font : String = null , size : Object = null , color : Object
= null , bold : Object = null , italic : Object = null , underline
: Object = null ,
url : String = null , target : String = null , align : String =
null , leftMargin : Object = null , rightMargin : Object =
null , indent : Object = null , leading : Object = null )

Nous pouvons donc crire :


1
2

// Cr ation de l ' instance de la classe TextFormat


var format : TextFormat = new TextFormat ( " Arial " , 42 , 0x0000ff ) ;

3
4
5

// Application du format au champ de texte


monSuperTexte . defaultTextFormat = format ;

Nous pouvons galement mettre le texte en gras, italique, ou soulign, grce ces
attributs de la classe TextFormat :
bold:Object (boolen) pour mettre le texte en gras.
italic:Object (boolen) pour le mettre en italique.
270

LA MISE EN FORME
underline:Object (boolen) pour le souligner.
Notre code pour la mise en forme ressemble maintenant ceci :
1
2
3
4
5
6
7

// Mise en forme
format . size = 42 ;
format . font = " Arial " ;
format . color = 0x0000ff ;
format . bold = true ;
format . italic = true ;
format . underline = true ;

Nous pouvons galement utiliser le constructeur :


1
2

// Cr ation de l ' instance de la classe TextFormat


var format : TextFormat = new TextFormat ( " Arial " , 42 , 0x0000ff ,
true , true , true ) ;

3
4
5

// Application du format au champ de texte


monSuperTexte . defaultTextFormat = format ;

Ce qui nous donne la figure 14.17.

Figure 14.17 Le texte en gras, italique et soulign


Nous avons seulement vu les principaux attributs, mais rien ne vous empche de jeter
un coup dil la documentation pour voir tout ce quil est possible de faire.
Modifier la mise en forme par dfaut
Une fois la mise en forme par dfaut dfinie, le texte que nous ajoutons notre champ
de texte prend par dfaut cette mise en forme. Ensuite, vous aurez srement envie de
modifier cette mise en forme par dfaut. Avec un peu dastuce, cest possible ! Il suffit
daffecter de nouveau notre objet de classe TextFormat lattribut defaultTextFormat
de notre champ de texte, puis raffecter son texte :
1
2

// Cr ation de l ' instance du champ de texte


var monSuperTexte : TextField = new TextField () ;

3
4
5

// Cr ation de l ' instance de la classe TextFormat


var format : TextFormat = new TextFormat () ;

6
7
8
9
10
11

// Mise en forme
format . size = 42 ;
format . font = " Arial " ;
format . color = 0x0000ff ;
format . bold = true ;

271

CHAPITRE 14. AFFICHER DU TEXTE


format . italic = true ;
format . underline = true ;

12
13
14
15
16

// Application du format au champ de texte


monSuperTexte . defaultTextFormat = format ;

17
18
19

// Texte
monSuperTexte . text = " Hello World ! " ;

20
21
22

// Bordure
monSuperTexte . border = true ;

23
24
25

// Taille adaptative
monSuperTexte . autoSize = TextFieldAutoSize . LEFT ;

26
27
28
29

// Centrons le champ de texte


monSuperTexte . x = ( stage . stageWidth - monSuperTexte . width ) / 2 ;
monSuperTexte . y = ( stage . stageHeight - monSuperTexte . height ) /
2;

30
31
32

// Ajout du champ de texte l ' affichage


addChild ( monSuperTexte ) ;

33
34

// ...

35
36
37

// Changeons en cours de route pour du rouge


format . color = 0xff0000 ;

38
39
40

// Mise jour du format par d faut


monSuperTexte . defaultTextFormat = format ;

41
42
43

// Il faut red finir le texte pour appliquer la nouvelle mise


en forme par d faut
monSuperTexte . text = monSuperTexte . text ;

Ce qui affiche la figure 14.18.

Figure 14.18 Nous avons troqu le bleu pour du rouge

Mise en forme spcifique


Il est possible dcraser la mise en forme par dfaut, pour tout ou une partie du texte,
grce la mthode setTextFormat() de la classe TextField, qui prend en paramtre
un objet de la classe TextFormat, la position du premier caractre et la position du
caractre aprs le dernier caractre du texte dont on souhaite modifier la mise en forme.
272

LA MISE EN FORME
Ces deux positions commencent par zro, comme pour les tableaux.
Rappel : si vous ne souhaitez pas changer des attributs dans la mise en forme
spcifique, il faut que ces attributs valent null. Ainsi ils naurons pas deffet
sur le texte. Ainsi, il est prfrable de crer une nouvelle instance de la classe
TextFormat, pour tre sr que tous les attributs sont null.
Changeons la taille de la premire lettre pour 72. La premire lettre est la position
0, et la lettre aprs elle est la position 1 :
1
2

// Nouvelle instance de la classe TextFormat ( on peut r


utiliser le m me pointeur " format ")
format = new TextFormat () ;

3
4

format . size = 72 ;

5
6
7

// Application du nouveau format la premi re lettre


monSuperTexte . setTextFormat ( format , 0 , 1 ) ;

Ce qui nous donne la figure 14.19.

Figure 14.19 La premire lettre est en taille 72


Comme vous pouver le remarquer, notre lettre est coupe en haut droite ; cest un effet
de bord de litalique. Nous pouvons remdier cela grce lattribut letterSpacing
qui spcifie la largeur de lespace entre les lettres. Mettons-la 3 pixels :
1
2

// Nouvelle instance de la classe TextFormat ( on peut r


utiliser le m me pointeur " format ")
format = new TextFormat () ;

3
4
5

format . size = 72 ;
format . letterSpacing = 3 ;

6
7
8

// Application du nouveau format la premi re lettre


monSuperTexte . setTextFormat ( format , 0 , 1 ) ;

Ainsi, il y aura 3 pixels despace entre la premire lettre et la deuxime (voir figure
14.20).
Essayons de colorier le mot World en bleu et de lui enlever litalique !
1
2

// Je stocke le mot que je veux colorier


var motBleu : String = " World " ;

273

CHAPITRE 14. AFFICHER DU TEXTE

Figure 14.20 Le dfaut est corrig !


4
5
6
7
8

// Je cherche les positions ad quates pour la m thode


setTextFormat
// Position de d but , gr ce la m thode indexOf de la classe
String
var positionDebut : int = monSuperTexte . text . indexOf ( motBleu ) ;
// Position de fin , en ajoutant la longueur du mot
var positionFin : int = positionDebut + motBleu . length ;

9
10
11
12
13

// Je cr le format
format = new TextFormat () ;
format . color = 0x0000ff ;
format . italic = false ;

14
15
16

// J ' applique le format aux positions que nous avons calcul es


monSuperTexte . setTextFormat ( format , positionDebut , positionFin )
;

Ce qui nous donne la figure 14.21.

Figure 14.21 Le mot World en bleu sans litalique

Gestion du multi-ligne
Champ de texte taille fixe
Nous allons maintenant dcouvrir comment grer un champ de texte multi-lignes.
Tout dabord, il nous faut un texte plus long que Hello World ! . Vous pouvez trouver
du Lorem Ipsum (texte latin de remplissage) en ligne.


Lorem Ipsum
B
Code web : 951790

var monSuperTexte : TextField = new TextField () ;

2
3
4

var format : TextFormat = new TextFormat ( " Arial " , 14 , 0x000000 ) ;


monSuperTexte . defaultTextFormat = format ;

274

LA MISE EN FORME
5
6
7

// Texte suffisamment long


monSuperTexte . text = " Lorem ipsum dolor sit amet , consectetur
adipiscing elit . In pharetra magna imperdiet elit pretium a
malesuada nisl pellentesque . " ;

8
9

monSuperTexte . border = true ;

10
11

addChild ( monSuperTexte ) ;

12
13
14
15

// Centre
monSuperTexte . x = ( stage . stageWidth - monSuperTexte . width ) / 2 ;
monSuperTexte . y = ( stage . stageHeight - monSuperTexte . height ) /
2;

Pour linstant, cela donne la figure 14.22.

Figure 14.22 Le texte sort du champ de texte


Nous aimerions bien que le texte revienne automatiquement la ligne. Pour cela, il
faut mettre lattribut multiline de la classe TextField true pour activer les lignes
multiples, et lattribut wordWrap true galement, pour activer le retour la ligne
automatique :
1
2

monSuperTexte . multiline = true ;


monSuperTexte . wordWrap = true ;

275

CHAPITRE 14. AFFICHER DU TEXTE


Ce qui donne lcran la figure 14.23.

Figure 14.23 Retour la ligne automatique


Le texte dpasse dsormais en bas du champ de texte. Toutefois, par dfaut, on peut
dfiler dans le champ de texte avec la molette de la souris. Si vous voulez dsactiver ce
comportement, il faut mettre lattribut mouseWheelEnabled de la classe TextField
false :
monSuperTexte . mouseWheelEnabled = false ;

Le champ de texte est peut-tre un peu trop troit, augmentons sa largeur (avant le
code qui le centre) :
1
2

// Modifions la largeur du champ de texte


monSuperTexte . width = 300 ;

3
4
5
6

// Centre
monSuperTexte . x = ( stage . stageWidth - monSuperTexte . width ) / 2 ;
monSuperTexte . y = ( stage . stageHeight - monSuperTexte . height ) /
2;

Ce qui nous donne la figure 14.24.

Figure 14.24 Largeur de 300 pixels

Aligner le texte
Il est possible de changer lalignement du texte grce lattribut align de la classe
TextFormat. Cet attribut accepte les valeurs constantes dfinies dans la classe TextFormatAlign.
Par exemple, pour que notre texte soit align au centre :
1
2
3

var format : TextFormat = new TextFormat ( " Arial " , 14 , 0x000000 ) ;


format . align = TextFormatAlign . CENTER ; // Texte align au
centre
monSuperTexte . defaultTextFormat = format ;

Sans oublier de bien importer la classe TextFormatAlign au dbut du package :


276

LA MISE EN FORME
1

import flash . text . TextFormatAlign ;

Cela nous donne la figure 14.25.

Figure 14.25 Texte align au centre


Nous pouvons galement centrer le texte droite ou le justifier (voir figures 14.26 et
14.27) :
1
2

// Texte align droite


format . align = TextFormatAlign . RIGHT ;

3
4
5

// Texte justifi
format . align = TextFormatAlign . JUSTIFY ;

Figure 14.26 Texte align droite

Figure 14.27 Texte justifi


Un texte justifi est un texte dont les mots sont espacs de telle sorte que les
lignes de chaque paragraphes remplissent toutes la largeur disponibles, sauf
les dernires lignes. Par exemple, cet alignement est souvent utilis dans
les journaux.

Champ de texte hauteur dynamique


Il est possible dadapter la hauteur du champ de texte son texte sil est multi-ligne,
de la mme manire que nous avions adapt la taille de notre champ de texte contenant
le texte "Hello World!" au chapitre prcdent : avec lattribut autoSize de la classe
TextField :
277

CHAPITRE 14. AFFICHER DU TEXTE


monSuperTexte . autoSize = TextFieldAutoSize . LEFT ;

Ce qui nous donne la figure 14.28.

Figure 14.28 La hauteur est automatiquement adapte au texte


Contrairement ce que nous avons vu au chapitre prcdent, seule la hauteur
est adapte au texte ; la largeur est fixe et cest vous qui la dfinissez. Ceci
est uniquement valable si le champ de texte est multi-lignes, quand lattribut
multiline du champ de texte est true.

Retour la ligne
Il est possible deffectuer des retours la ligne en crivant \n dans le texte :
monSuperTexte . text = " Lorem ipsum dolor sit amet ,\ nconsectetur
adipiscing elit .\ nIn pharetra magna imperdiet elit pretium a
malesuada nisl pellentesque . " ;

Ce qui nous donne la figure 14.29.

Figure 14.29 Deux retours la ligne

En HTML dans le texte


Introduction
Le langage HTML
Le langage HTML est utilis sur les sites web pour structurer le texte, ajouter des
paragraphes, des images, des liens hyper-texte. . . Le langage est un driv du langage
XML, ce qui signifie que sa syntaxe est base sur des balises.
Une balise dispose dun nom, mis entre chevrons, et elle est rpte deux fois :
1

<nom > </ nom >

278

EN HTML DANS LE TEXTE


La premire balise <nom> est la balise ouvrante, et la dernire balise </nom> est la
balise fermante.
Il ne faut pas oublier le slash / pour signifier quil sagit dune balise fermante.

Il est possible dimbriquer des balises dans dautres :


1
2
3
4
5
6

< balise1 >


< balise2 > </ balise2 >
< balise3 >
< balise4 > </ balise4 >
</ balise3 >
</ balise1 >

Ici, la balise 4 est contenue dans la balise 3. Les balises 2 et 3 sont contenues dans la
balise 1.
Attention bien faire correspondre les noms des balises ouvrantes et fermantes !
Chaque balise ouvrante peut disposer dattributs, ayant chacun un nom et une valeur
entre guillemets doubles :
1

< nom attribut1 = " valeur " attribut2 = " valeur " > </ nom >

Si une balise ne contient rien, on peut utiliser sa forme raccourcie :


1

< balise / >

Reprenons lexemple des balises imbriques pour voir ce que cela donnerait :
1
2
3
4
5
6

< balise1 >


< balise2 / >
< balise3 >
< balise4 / >
</ balise3 >
</ balise1 >

Enfin, il est possible de mettre du texte brut lintrieur dune balise :


1

< balise > Quel temps fera -t - il demain ? </ balise >

On peut galement mlanger des balises et du texte brut :


1

< balise1 > Salut ! < balise2 > Comment va la famille ? </ balise2 > </
balise1 >

LHTML est donc du XML avec des balises spciales que nous allons dcouvrir un
peu plus loin.
279

CHAPITRE 14. AFFICHER DU TEXTE


Seule une toute petite partie de ces balises est supporte par la classe
TextField ! Nous ne verrons que celles-ci, mais sachez quil en existe beaucoup dautres. Par ailleurs, il peut y avoir quelques diffrences au niveau des
attributs par rapport au vrai HTML.

Du HTML dans nos champs de texte


Il est possible dutiliser une version trs simplifie de lHTML dans nos champs de
texte en utilisant lattribut htmlText de la classe TextField la place de lattribut
text que nous avons utilis jusque l :
1
2

// Activation du multi - ligne avant de s picifier le texte HTML


monSuperTexte . multiline = true ;

3
4
5

// Texte HTML
monSuperTexte . htmlText = ' Lorem ipsum dolor sit amet ,
consectetur adipiscing elit . In pharetra magna imperdiet
elit pretium a malesuada nisl pellentesque . ';

Il faut mettre lattribut multiline true avant de spcifier le texte HTML,


sinon les retours la ligne seront ignors, mme si vous mettez multiline
true ensuite.

Balises principales
Retour la ligne
Pour effectuer un retour la ligne dans un texte HTML, nous utiliserons la balise
<br/> comme ceci :
1

monSuperTexte . htmlText = ' Lorem ipsum dolor sit amet ,


consectetur adipiscing elit . In pharetra magna imperdiet elit
pretium a malesuada nisl pellentesque . ';

Ce qui nous donne la figure 14.30.

Figure 14.30 Deux retours la ligne

280

EN HTML DANS LE TEXTE


Paragraphe
Un paragraphe est un bloc de texte pouvant tre align, qui se termine par un retour
la ligne. La balise utiliser est la balise <p align="alignement">...</p>. Lattribut
align peut prendre les valeurs suivantes :

left pour aligner le texte gauche.


right pour laligner droite.
center pour le centrer.
justify pour le justifier.

Voici un exemple o notre texte est align droite :


1

monSuperTexte . htmlText = ' <p align =" right " > Lorem ipsum dolor
sit amet , consectetur adipiscing elit . In pharetra magna
imperdiet elit pretium a malesuada nisl pellentesque . </p > ';

Ce qui nous donne la figure 14.31.

Figure 14.31 Paragraphe de texte align droite


Voici un autre exemple avec plusieurs paragraphes :
1

monSuperTexte . htmlText = ' <p align =" right " > Lorem ipsum dolor
sit amet , consectetur adipiscing elit . In pharetra magna
imperdiet elit pretium a malesuada nisl pellentesque . </p > ' +
' <p align =" left " > Lorem ipsum dolor sit amet , consectetur
adipiscing elit . In pharetra magna imperdiet elit
pretium a malesuada nisl pellentesque . </p > ';

Vous remarquerez que jai utilis la concatnation de chanes de caractres


avec loprateur + pour pouvoir crire le texte en plusieurs lignes.
Nous avons alors lcran la figure 14.32.

Figure 14.32 Deux paragraphes aligns diffremment

281

CHAPITRE 14. AFFICHER DU TEXTE


Lien
Un lien est une balise cliquable qui permet deffectuer une action, le plus souvent
permettant de changer de site web ou daller sur une autre page. Nous pouvons crer
un lien laide de la balise <a href="adresse" target="cible">nom du lien</a>.
Lattribut href contient ladresse vers laquelle pointe le lien. Lattribut target permet
de spcifier la cible du lien, cest dire o ladresse va souvrir si lon clique dessus. Il
peut prendre les valeurs suivantes :
_self : ouvre le lien dans la mme page.
_blank : ouvre le lien dans une nouvelle fentr e, ou un nouvel onglet si le navigateur
le permet.
Bien sr, ces valeurs nont dintrt que si votre animation Flash est incorpore dans
un site web. Dans les autres cas (par exemple lorsque lon teste le programme), cela
ouvrira une nouvelle fentre (ou un nouvel onglet) dans votre navigateur, mme si la
valeur de lattribut target est _self.
Voici un exemple de texte HTML disposant dun lien pointant sur le Site du Zro :
1

monSuperTexte . htmlText = ' Voulez - vous apprendre partir de z


ro ? <a href =" http :// www . siteduzero . com /" target =" _blank " >
Cliquez ici ! </a > ';

Ce qui nous donne la figure 14.33.

Figure 14.33 Une partie du texte est cliquable


Pour tester lattribut target, vous pouvez ouvrir votre fichier swf dans votre
navigateur favori ( condition quil dispose du lecteur Flash). Vous verrez
alors la page daccueil du Site du Zro se charger dans la mme page ou
souvrir dans une nouvelle fentre ou un nouvel onglet

Image
Il est possible de charger une image locale dans un champ de texte grce la balise <img src="adresse" width="largeur" height="hauteur" align="alignement"
hspace="espacement horizontal" vspace="espacement vertical"/>.
Essayons dafficher Zozor dans notre champ de texte (voir figure 17.1). Tout dabord,
tlchargez limage de Zozor et placez-la dans le dossier de votre fichier swf.


Tlchargez Zozor
B
Code web : 634351


282

EN HTML DANS LE TEXTE

Figure 14.34 Zozor, la mascotte du Site du Zro


Ensuite, renommez limage en zozor.png. Enfin, crivons ce code pour charger limage
dans notre texte HTML :
1

monSuperTexte . htmlText = ' Voici Zozor ! < img src =" zozor . png "
width =" 150 " height =" 150 " align =" right "/ > ';

Ce qui nous donne la figure 14.35.

Figure 14.35 Zozor est dans notre champ de texte !

Il est impossible daligner une image au centre. Il sagit dune limitation du


champ de texte, on ne peut rien y faire.
Si on met un texte plus long ct de limage, il sera dtour. Pour illustrer ceci,
prenons un texte beaucoup plus long ct de Zozor, et alignons-le en justifi. :
1
2
3

monSuperTexte . htmlText = ' < img src =" zozor . png " width =" 150 "
height =" 150 " align =" right "/ > ' +
' <p align =" justify " > Lorem ipsum dolor sit amet , consectetur
adipiscing elit . Sed pharetra semper ullamcorper . ' +
' Sed at urna in elit mollis egestas eu id lectus . Integer
aliquam urna vitae massa varius sed cursus mauris
aliquam . ' +
' Curabitur mauris massa , imperdiet a venenatis ac , vehicula
eu ipsum . Nulla turpis enim , tincidunt at imperdiet nec
,' +
' mollis vitae nunc . Morbi viverra iaculis neque et
tincidunt . Nullam ultrices mi mi , eu pellentesque leo . </
p>' +

283

CHAPITRE 14. AFFICHER DU TEXTE


6
7
8
9

' <p align =" justify " > Pellentesque sed felis nulla . Phasellus
laoreet sagittis ante at fringilla . ' +
' Duis iaculis , mi sed bibendum posuere , nisi velit cursus
elit , vitae tincidunt augue diam quis elit . ' +
' Sed et nisi risus . Vestibulum lobortis auctor viverra .
Mauris eleifend nisl ut orci ultricies eget egestas ' +
' ante lacinia . Pellentesque ut diam turpis . </p > ';

Ce qui nous donne la figure 14.36.

Figure 14.36 Cela ressemble un article de journal nest-ce pas ?

Liste puces
Il est possible de faire des listes puces grce la balise <li>...</li> rpte
autant de fois quil y a de lignes dans la liste :
1

monSuperTexte . htmlText = ' Voici une liste puces : < li > Ligne 1
</ li > < li > Ligne 2 </ li > < li > Ligne 3 </ li > ';

Ce qui nous donne la figure 14.37.

Figure 14.37 Une liste puce

284

EN HTML DANS LE TEXTE

Balises de mise en forme


Gras
Pour mettre du texte en gras, rien de plus simple ! Il suffit de lencadrer dune balise
<b>...</b> (b comme bold, signifiant gras en anglais) comme ceci :
1

monSuperTexte . htmlText = ' Lorem ipsum dolor sit amet ,


consectetur adipiscing elit . <b > In pharetra magna imperdiet
elit pretium a malesuada nisl pellentesque . </b > ';

Ce qui nous donne la figure 14.38.

Figure 14.38 La deuxime phrase est en gras.

Italique
Pour mettre le texte en italique, cest tout aussi simple : seule la balise change. Cette
fois, il sagit de <i>...</i> :
1

monSuperTexte . htmlText = ' Lorem ipsum dolor sit amet ,


consectetur adipiscing elit . <i > In pharetra magna imperdiet
elit pretium a malesuada nisl pellentesque . </i > ';

Ce qui nous donne la figure 14.39.

Figure 14.39 La deuxime phrase est en italique.

Souligner
Il est possible de souligner du texte grce la balise <u>...</u> comme ceci :
1

monSuperTexte . htmlText = ' Lorem ipsum dolor sit amet ,


consectetur adipiscing elit . <u > In pharetra magna imperdiet
elit pretium a malesuada nisl pellentesque . </u > ';

Ce qui nous donne la figure 14.40.


285

CHAPITRE 14. AFFICHER DU TEXTE

Figure 14.40 La deuxime phrase est souligne.

Police, couleur et taille


Pour modifier la police de caractre, la couleur ou la taille des caractres du
texte, la balise <font face="police" color="couleur" size="taille">...</font>
est tout indique. Lattribut face peut recevoir comme valeur le nom dune police
de caractre, comme par exemple face="Arial". Lattribut color permet de dfinir une couleur en hexadcimal, prcde dun dise. Exemple de couleur orange :
color="#ff8800". Enfin, lattribut size modifie la taille des caractres du texte. On
peut dfinir une taille absolue en pixels, ou une taille relative en ajoutant un + ou un devant. Exemple de taille absolue : size="42". Exemple de taille relative : size="-5",
ce qui signifie la taille actuelle du texte moins cinq pixels.
Par exemple, nous pouvons colorier une partie de notre texte en bleu :

monSuperTexte . htmlText = ' Lorem ipsum dolor sit amet ,


consectetur adipiscing elit . < font color ="# 0000ff " > In
pharetra magna imperdiet elit pretium a malesuada nisl
pellentesque . </ font > ';

Ce qui nous donne la figure 14.41.

Figure 14.41 La deuxime phrase en bleu !

Nous aurions pu, au lieu de cela, augmenter la taille de notre texte :

monSuperTexte . htmlText = ' Lorem ipsum dolor sit amet ,


consectetur adipiscing elit . < font size =" 42 " > In pharetra
magna imperdiet elit pretium a malesuada nisl pellentesque
. </ font > ';

Ce qui aurait donn la figure 14.42.


286

LES POLICES DE CARACTRES EMBARQUES

Figure 14.42 La deuxime phrase en taille 42 cette fois-ci.

Les polices de caractres embarques


Embarquer des polices
Pourquoi ?
Jusqu prsent, les polices que nous utilisons sont des polices fournies par le systme
dexploitation sur lequel notre programme est lanc. Si nous vouons appliquer une police
particulire notre texte, mais quelle nest pas prsente sur le systme, la police par
dfaut sera utilise. De plus, il nous est impossible de faire tourner notre texte ou de
changer son opacit, ce qui est un peu dommage, vous en conviendrez !
Cependant, il existe une solution ces problmes : les polices de caractres embarques ! Il sagit dinclure un fichier contenant une police directement dans notre
programme : ainsi, le lecteur Flash peut la rendre directement lcran, mme si le
systme de dispose pas de cette police en particulier ! De plus, cela permet de lisser les
caractres du texte afin de les rendre plus lisibles et plus attractifs.
Bien videmment, embarquer des fichiers directement dans le programme
augmente sa taille. Cela peut ventuellement tre gnant, mais embarquer
les polices de caractre prsente tant davantages que lon passera souvent
outre cet unique inconvnient.

Prparation
Tout dabord, il faut se munir du fichier de la police de caractre embarquer dans
notre programme. Seules les polices de format TrueType sont reconnues, mais cest
le format le plus rpandu, donc cela pose rarement problme.
287

CHAPITRE 14. AFFICHER DU TEXTE


Par exemple, vous pouvez prendre une police installe sur votre systme. Sur Windows,
les polices sont situes dans le dossier C:\Windows\Fonts. Sur Mac, il peut y en avoir
plusieurs endroits : ~/Library/Fonts/, /Library/Fonts/, /Network/Library/Fonts/,
/System/Library/Fonts/ ou /System Folder/Fonts/. Enfin, sur Linux, on peut les
trouver dans ces dossiers : /usr/share/fonts, /usr/local/share/fonts ou ~/.fonts.
Ou bien vous pouvez vous rendre sur un site proposant gratuitement des polices de
caractres, comme FontSquirrel. Prenons par exemple la police Walkway (voir figure
14.43). Tlchargez-la sur le site en cliquant sur le bouton DOWNLOAD TTF.


Tlchargez Walkway sur
.
B FontSquirrel
Code
web
:
187739


Figure 14.43 Page de tlchargement de la police Walkway


Vous obtenez une archive zip, contenant diffrents fichiers de police (voir figure 14.44).
Nous aurons besoins de quatre de ces fichiers, un par style de notre police, comme le
montre le tableau suivant.
Style
Normal
Gras
Italique
Gras Italique
288

Nom du fichier
Walkway_SemiBold.ttf
Walkway_UltraBold.ttf
Walkway_Oblique_SemiBold.ttf
Walkway_Oblique_UltraBold.ttf

LES POLICES DE CARACTRES EMBARQUES

Figure 14.44 Contenu de larchive tlcharge

289

CHAPITRE 14. AFFICHER DU TEXTE


Vous pouvez incorporer une police de caractres dont il manque certains
styles, mais vous ne pourrez pas utiliser les styles manquant. Par exemple, si
vous navez pas le fichier pour litalique, vous ne pourrez pas mettre de texte
en italique avec cette police.
Dans le rpertoire du projet, crez un dossier lib sil nest pas dj prsent, puis crez
un dossier lintrieur nomm fonts. Enfin, extrayez les quatre fichiers dont nous
avons besoin dans ce dossier (voir figure 14.45).

Figure 14.45 Les fichiers de police prts lemploi

Implmentation
Une fois que nos fichiers sont prts, il faut les incorporer notre programme, puis
les enregistrer sous le nom "walkway" pour pouvoir utiliser la police de caractre
embarque partout dans notre projet. Crez une nouvelle classe EmbedFonts (dans
un fichier nomm EmbedFonts.as) ct de la classe Main et collez-y le code complet
suivant :
1
2
3

package
{
import flash . text . Font ;

4
5
6
7

8
9

290

/* *
* Gestionnaire des polices de caract res embarqu es .
* Pour ajouter une police , placer ces fichiers dans le
dossier lib / fonts ( par exemple : lib / fonts / verdana . ttf )
, incluez - la dans la classe EmbedFonts ainsi :
* [ Embed ( source = '../ lib / fonts / verdana . ttf ', fontName = '
Fverdana ', fontWeight =" normal " , embedAsCFF = false ) ]
* private static var F_VERDANA : Class ;

LES POLICES DE CARACTRES EMBARQUES


* puis enregistrez - la dans la m thode init () ainsi :
* Font . registerFont ( F_VERDANA ) ;
* @author Guillaume CHAU
*/
public class EmbedFonts
{

10
11
12
13
14
15
16

// Incorporation des polices de caract res

17
18

// /// Walkway
// Normal
[ Embed ( source = ' ../ lib / fonts / Walkway_SemiBold . ttf ' ,
fontName = ' walkway ' , fontWeight = " normal " , embedAsCFF =
false ) ]
private static var F_WALKWAY : Class ;
// Gras
[ Embed ( source = ' ../ lib / fonts / Walkway_UltraBold . ttf ' ,
fontName = ' walkway ' , fontWeight = ' bold ' , embedAsCFF =
false ) ]
private static var F_WALKWAY_BOLD : Class ;
// Italique
[ Embed ( source = ' ../ lib / fonts / W a l kw a y _O b l iq u e _S e m iB o l d .
ttf ' , fontName = ' walkway ' , fontStyle = ' italic ' ,
embedAsCFF = false ) ]
private static var F_WALKWAY_ITALIC : Class ;
// Gras Italique
[ Embed ( source = ' ../ lib / fonts / Wa l k w a y _ O b l iq u e _ U l t r a B o ld .
ttf ' , fontName = ' walkway ' , fontStyle = ' italic ' ,
fontWeight = ' bold ' , embedAsCFF = false ) ]
private static var F_W ALKWA Y_BOLD _ITAL IC : Class ;

19
20
21

22
23
24

25
26
27

28
29
30

31
32

/* *
* Initialisation des polices de caract res . A appeler
une fois au lancement de l ' application , afin que
les polices soient prises en compte .
*/
public static function init () : void
{
// Enregistrement des polices de caract res

33
34

35
36
37
38
39
40
41
42
43

44

Font . registerFont ( F_WALKWAY ) ;


Font . registerFont ( F_WALKWAY_BOLD ) ;
Font . registerFont ( F _WALKW AY_BO LD_ITA LIC ) ;
Font . registerFont ( F_WALKWAY_ITALIC ) ;

45

46
47
48

291

CHAPITRE 14. AFFICHER DU TEXTE


Vous
pouvez lafficher pour la copier
 en utilisant le code web ci-dessous.
Classe EmbedFonts
B
Code web : 139762


Nous commenons par importer chaque fichier au dbut de la classe grce une instruction spciale, destine au compilateur :
1

[ Embed ( source = ' ../ lib / fonts / Walkway_SemiBold . ttf ' , fontName = '
walkway ' , fontWeight = " normal " , embedAsCFF = false ) ]

Jai limpression davoir dj vu quelque chose de similaire. . .

Trs juste ! Nous avons dj crit une instruction spciale dans notre classe Main pour
rgler la taille et la couleur de fond de notre fentre :
1

[ SWF ( width = " 640 " , height = " 480 " , backgroundColor = " # ffffff " ) ]

Ici, le mot-cl SWF signifie que nous allons modifier des proprits de notre programme.
Cette fois, le mot-cl Embed signifie que nous allons inclure un fichier dans notre programme. Les fichiers inclus sont directement contenus dans le programme : il sont donc
utilisables tout moment, tant chargs en mme temps.
1

source = ' ../ lib / fonts / Walkway_SemiBold . ttf '

Lattribut source indique le chemin du fichier inclure, ici


../lib/fonts/Walkway_SemiBold.ttf.
1

fontName = ' walkway '

Lattribut fontName spcifie le nom de la police de caractre, nom qui nous servira
lutiliser ensuite.
1

fontWeight = " normal "

Les attributs fontStyle (style) et fontWeight (paisseur) permettent de prciser de


quel style il sagit. En combinant les deux, il est possible de crer un style gras
italique :
1

fontStyle = ' italic ' , fontWeight = ' bold '

Enfin, le dernier attribut embedAsCFF est obligatoire et doit tre mis false. Cela
permet dviter tout problme lors de lutilisation de polices embarques, cause
dun changement entre Flex SDK 3 et Flex SDK 4.
Sur la ligne suivante, nous dclarons un attribut priv de type Class qui contiendra le
fichier de police embarque :
1

private static var F_WALKWAY : Class ;

Ce qui nous donne pour nos quatre fichiers :


292

LES POLICES DE CARACTRES EMBARQUES


1
2
3
4
5
6
7
8
9
10
11
12

13

// /// Walkway
// Normal
[ Embed ( source = ' ../ lib / fonts / Walkway_SemiBold . ttf ' , fontName = '
walkway ' , fontWeight = " normal " , embedAsCFF = false ) ]
private static var F_WALKWAY : Class ;
// Gras
[ Embed ( source = ' ../ lib / fonts / Walkway_UltraBold . ttf ' , fontName = '
walkway ' , fontWeight = ' bold ' , embedAsCFF = false ) ]
private static var F_WALKWAY_BOLD : Class ;
// Italique
[ Embed ( source = ' ../ lib / fonts / W a l kw a y _O b l iq u e _S e m iB o l d . ttf ' ,
fontName = ' walkway ' , fontStyle = ' italic ' , embedAsCFF = false ) ]
private static var F_WALKWAY_ITALIC : Class ;
// Gras Italique
[ Embed ( source = ' ../ lib / fonts / Wa l k w a y _ O b l iq u e _ U l t r a B o ld . ttf ' ,
fontName = ' walkway ' , fontStyle = ' italic ' , fontWeight = ' bold ' ,
embedAsCFF = false ) ]
private static var F_W ALKWA Y_BOLD _ITAL IC : Class ;

Une fois que tous les fichiers sont incorpors, nous dclarons une mthode publique
statique init():void qui nous permet denregistrer la police de caractre, qui sera
appele au tout dbut de notre programme :
1
2

3
4
5
6
7

/* *
* Initialisation des polices de caract res . A appeler une fois
au lancement de l ' application , afin que les polices soient
prises en compte .
*/
public static function init () : void
{
// Enregistrement des polices de caract res
}

Dans cette mthode, nous enregistrons les classes contenant les fichiers des polices de
caractres grce la mthode statique registerFont de la classe Font :
1

Font . registerFont ( F_WALKWAY ) ;

Ce qui donne :
1
2

3
4
5
6

/* *
* Initialisation des polices de caract res . A appeler une fois
au lancement de l ' application , afin que les polices soient
prises en compte .
*/
public static function init () : void
{
// Enregistrement des polices de caract res

7
8
9
10

Font . registerFont ( F_WALKWAY ) ;


Font . registerFont ( F_WALKWAY_BOLD ) ;
Font . registerFont ( F _WALKW AY_BO LD_ITA LIC ) ;

293

CHAPITRE 14. AFFICHER DU TEXTE


Font . registerFont ( F_WALKWAY_ITALIC ) ;

11
12

Enfin, dans notre classe Main, nous appelons la mthode statique init de notre classe
EmbedFonts :
1
2
3
4
5
6

package
{
import
import
import
import

flash . display . Sprite ;


flash . display . StageAlign ;
flash . display . StageScaleMode ;
flash . events . Event ;

/* *
* Notre application embarque des polices de caract res
embarqu es !
*/
[ SWF ( width = " 640 " , height = " 480 " , backgroundColor = " # ffffff " ) ]

8
9
10
11
12

public class Main extends Sprite


{

13
14
15

public function Main () : void


{
if ( stage )
init () ;
else
addEventListener ( Event . ADDED_TO_STAGE , init ) ;
}

16
17
18
19
20
21
22
23

private function init ( e : Event = null ) : void


{
removeEventListener ( Event . ADDED_TO_STAGE , init ) ;
// entry point

24
25
26
27
28

stage . scaleMode = StageScaleMode . NO_SCALE ;


stage . align = StageAlign . TOP_LEFT ;

29
30
31
32
33
34

35

// Polices embarqu es
EmbedFonts . init () ;

36
37

Vous remarquerez quil nest pas ncessaire dimporter la classe EmbedFonts


car elle est dans le package principal (elle est place dans le dossier racine de
la source, ici src/).

294

LES POLICES DE CARACTRES EMBARQUES


Utilisation
Et voil ! Notre police de caractre embarque est prte lemploi ! Pour que
notre champ de texte utilise les polices de caractres embarques au lieu des polices du
systme dexploitation, il faut mettre lattribut embedFonts de la classe TextField
true, sans oublier de changer le nom de la police utilise :
1
2
3

// Police utilis e : walkway


var format : TextFormat = new TextFormat ( " walkway " , 42 , 0x000000 )
;
monSuperTexte . defaultTextFormat = format ;

4
5
6

// On utilise les polices embarqu es


monSuperTexte . embedFonts = true ;

Voici le code complet pour afficher un champ de texte avec une police de caractres
embarque :
1
2

// Enregistrement des polices embarqu es


EmbedFonts . init () ;

3
4
5

// Cr ation de l ' instance du champ de texte


var monSuperTexte : TextField = new TextField () ;

6
7
8
9

// Police utilis e : walkway


var format : TextFormat = new TextFormat ( " walkway " , 42 , 0x000000 )
;
monSuperTexte . defaultTextFormat = format ;

10
11
12

// On utilise les polices embarqu es


monSuperTexte . embedFonts = true ;

13
14
15

// Taille automatique
monSuperTexte . autoSize = TextFieldAutoSize . LEFT ;

16
17
18

// Texte HTML
monSuperTexte . htmlText = " Normal <b > Gras </ b > <i > Italique </ i > <b
> <i > Gras Italique </ i > </b > " ;

19
20
21

// Ajout la sc ne
addChild ( monSuperTexte ) ;

22
23
24
25

// Alignement au centre
monSuperTexte . x = ( stage . stageWidth - monSuperTexte . width ) / 2 ;
monSuperTexte . y = ( stage . stageHeight - monSuperTexte . height ) /
2;

Ce qui nous donne lcran la figure 14.46.


Dsormais, notre texte saffichera avec cette police mme si lutilisateur ne la pas
installe ; de plus, il est possible de rendre le texte transparent et de lui appliquer une
rotation !
295

CHAPITRE 14. AFFICHER DU TEXTE

Figure 14.46 Notre police embarque en action !

296

LES POLICES DE CARACTRES EMBARQUES

Rotation sur soi-mme


Et si nous dcidions de tourner notre champ de texte sur lui-mme ? Disons 50 dans
le sens anti-horaire ? Cest dsormais possible, tant donn que nous utilisons notre
propre police embarque. Commenons par crire le code pour crer un champ de texte
utilisant une police de caractres embarque :
1
2

// Polices embarqu es
EmbedFonts . init () ;

3
4
5
6
7
8
9
10
11

// Cr ation du champ de texte


var monSuperTexte : TextField = new TextField () ;
var format : TextFormat = new TextFormat ( " walkway " , 50 , 0x000000 )
;
monSuperTexte . defaultTextFormat = format ;
monSuperTexte . embedFonts = true ;
monSuperTexte . autoSize = TextFieldAutoSize . LEFT ;
monSuperTexte . text = " Tournez - moi ! " ;
addChild ( monSuperTexte ) ;

12
13
14
15

// Alignement au centre
monSuperTexte . x = ( stage . stageWidth - monSuperTexte . width ) / 2 ;
monSuperTexte . y = ( stage . stageHeight - monSuperTexte . height ) /
2;

Ce qui nous donne la figure 14.47.


Essayons deffectuer une rotation notre champ de texte :
1
2

// Rotation de 50 dans le sens anti - horaire


monSuperTexte . rotation = - 50 ;

Ce qui nous donne la figure 14.48.


Ce nest pas exactement ce que nous voulons accomplir ! En effet, lobjet tourne toujours
par rapport son origine, en haut gauche : cela explique que le champ de texte soit
tourn par rapport la lettre T . Malheureusement, nous ne pouvons pas modifier
directement lorigine dun objet daffichage.
Il est nanmoins possible de changer artificiellement lorigine de lobjet en question,
comme nous lavons vu dans le chapitre prcdent, en lajoutant dans un conteneur
intermdiaire de classe Sprite que jappellerai la bote :
1
2
3

// Conteneur interm diaire


var boite : Sprite = new Sprite () ;
addChild ( boite ) ;

4
5
6
7
8
9

// Cr ation du champ de texte


var monSuperTexte : TextField = new TextField () ;
var format : TextFormat = new TextFormat ( " walkway " , 50 , 0x000000 )
;
monSuperTexte . defaultTextFormat = format ;
monSuperTexte . embedFonts = true ;

297

CHAPITRE 14. AFFICHER DU TEXTE

Figure 14.47 Notre champ de texte tourner

298

LES POLICES DE CARACTRES EMBARQUES

Figure 14.48 Rotation par rapport lorigine de lobjet

299

CHAPITRE 14. AFFICHER DU TEXTE


monSuperTexte . autoSize = TextFieldAutoSize . LEFT ;
monSuperTexte . text = " Tournez - moi ! " ;

10
11
12
13
14

// On ajoute le champ de texte dans le conteneur


boite . addChild ( monSuperTexte ) ;

Une fois que le champ de texte est dans la bote, on dplace le champ de texte de la
moiti de sa taille, la fois vers le haut et vers la gauche, ainsi lorigine de la boite se
trouvera au centre du champ de texte (voir figure 14.49).

Figure 14.49 Origine de la boite centre sur le champ de texte


Ainsi, lorigine de la boite se retrouve au centre du champ de texte. Si on fait abstraction
de la bote, lorigine de notre objet est le centre du champ de texte, donc il tournera
par rapport son centre ! Voici le code de cette opration :
1
2
3

// On modifie artificiellement l ' origine en la pla ant au


centre du champ de texte :
monSuperTexte . x = - monSuperTexte . width / 2 ;
monSuperTexte . y = - monSuperTexte . height / 2 ;

Enfin, on applique toutes les transformations la bote la place de les appliquer au


champ de texte, comme si la bote tait le champ de texte lui-mme :
1
2
3
4

// Alignement au centre
// On aligne le conteneur au lieu du champ de texte
boite . x = stage . stageWidth / 2 ;
boite . y = stage . stageHeight / 2 ;

5
6
7
8

// Rotation de 50 dans le sens anti - horaire


// On tourne le conteneur au lieu du champ de texte
boite . rotation = - 50 ;

Ce qui nous donne ce que nous voulons (voir figure 14.50).


Enfin ! Notre champ de texte a consenti tourner sur lui-mme par rapport son
centre ! Vous serez souvent amen utiliser cette mthode, par exemple si vous voulez
animer une image en la faisant tourner sur elle-mme, tout en la dplaant. . .
Vous auriez peut-tre pens recentrer le champ de texte aprs chaque rotation, mais, croyez-moi, il est beaucoup plus simple de passer par un conteneur
intermdiaire.

300

LES POLICES DE CARACTRES EMBARQUES

Figure 14.50 Le texte tourne sur lui-mme !

301

CHAPITRE 14. AFFICHER DU TEXTE

En rsum
La classe TextField permet dafficher du texte lcran. Il est possible de manipuler
la slection du texte.
On peut centrer un objet grce aux proprits de la scne principale de classe Stage.
La classe TextFormat permet de mettre en forme tout ou des portions du texte,
cest--dire change la police, la taille, la couleur. . .
Il est possible dafficher du texte structur en HTML simplifi avec lattribut htmlText.
Il est trs souvent intressant dembarquer les polices de caractres dans lapplication,
sans oublier de mettre lattribut embedFonts true.
Utiliser un conteneur intermdiaire permet deffectuer la rotation dun objet
autour de son centre (ou dun autre point que son origine initiale).

302

Chapitre

15

Dessiner avec lActionscript


Difficult :
Dans ce chapitre, nous allons apprendre dessiner directement depuis lActionscript ! Je
suis certain que beaucoup parmi vous attendaient ce moment depuis fort longtemps, cest
pourquoi nous essaierons de prsenter un maximum de notions tout en prenant le temps de
bien les expliquer. Nous prsenterons en premier la classe Graphics qui est lorigine de
tout trac en Actionscript. Puis nous prsenterons alors les diffrentes mthodes de dessin
que possde cette classe.
Enfin, je vous proposerais un petit exercice o nous raliserons ensemble une illustration
dun mouton. Ce sera alors loccasion de revenir sur ces mthodes de dessin et mieux
comprendre toute la philosophie qui se cache derrire le dessin en Flash !

303

CHAPITRE 15. DESSINER AVEC LACTIONSCRIPT

Lobjet Graphics
Introduction
Une proprit de type Graphics
Nous avons vu prcdemment quil existait diffrents types dobjets daffichage.
Parmi eux, certains possdent dj tout le ncessaire pour dessiner. Il sagit des classes
Shape, Sprite et MovieClip (voir figure 15.1) !

Figure 15.1 La classe Shape dans larbre des classes daffichage


Ce qui les diffrencie des autres classes cest que celles-ci ont un attribut trs particulier :
une instance de la classe Graphics. En ralit, cest cette dernire classe qui dispose
de lensemble des mthodes permettant de tracer diffrentes formes. Ainsi, en dclarant
des objets de type Shape, Sprite ou MovieClip, vous pourrez dessiner lintrieur de
ceux-ci. En particulier, la classe Shape est spcialement faite pour cela puisque celle-ci
ne contient que cet attribut et laccesseur correspondant comme vous pouvez le voir
la figure 15.2.
Cette classe est allge, ce qui implique de meilleures performances, mais une instance
de la classe Shape ne peut pas contenir denfants et elle nest pas interactive (il est
impossible de savoir si lutilisateur clique dessus).

Pourquoi ne pas utiliser directement lobjet Graphics ?

304

LOBJET GRAPHICS

Figure 15.2 La classe Shape exclusivement utilis pour sa proprit graphics


Il se peut que vous vous soyez dj demand pourquoi ne pas crer directement une
occurrence de la classe Graphics et utiliser ainsi ses diffrentes mthodes de dessin. En
ralit, lActionscript favorise lutilisation des sous-classes de DisplayObject dont
nhrite pas la classe Graphics. Cest pourquoi celle-ci est non instanciable : vous ne
pourrez donc pas utiliser la syntaxe new Graphics() et vous serez donc obligs de
passer par lutilisation de lune des trois classes dcrites plus haut. De plus, elle est
de type final, ce qui signifie que lon ne peut pas crer de sous-classes hritant de la
classe Graphics.
Je vous invite donc crer une instance de la classe Shape que nous utiliserons dans
la suite :
1

var monDessin : Shape = new Shape () ;

Dessin vectoriel
La classe Graphics est utilise pour crer des dessins vectoriels ! Ce terme est peuttre nouveau pour vous, mais ne vous inquitez pas, nous allons ici prsenter ce qui
diffrencie ce type dimages par rapport aux images bitmap . Vous ne vous tes
jamais demands comment les images taient stockes lintrieur de votre ordinateur ?
En fait le stockage des images peut tre ralis de deux manires diffrentes. Lorsque
lon parle dimages bitmap , celles-ci sont enregistres partir des couleurs de
chacun des pixels. En revanche, dans les images vectorielles, ce sont les formes en
elles-mmes qui sont sauvegardes. Cela fait donc une norme diffrence lors de la
lecture du fichier et de laffichage lcran.
Pour mieux comprendre ce dont il sagit, nous allons prendre lexemple de la figure
15.3.

Figure 15.3 Image de base


Cette image est quelconque et pourrait trs bien tre enregistre en tant quimage
bitmap ou vectorielle. Linconvnient du format bitmap est justement quil
305

CHAPITRE 15. DESSINER AVEC LACTIONSCRIPT


retient des pixels. Ainsi, si vous ne respectez plus les dimensions des pixels, limage va
tre dforme. Je mexplique ; imaginez que vous ayez besoin, pour une raison quelconque, dagrandir votre image. Les pixels vont donc tre redimensionns et limage
naura plus laspect lisse quelle avait au dpart. Au contraire, une image vectorielle
est dfinie partir de formes. Ainsi, lorsque celle-ci va tre redimensionne, laffichage
sera adapt pour correspondre nouveau la forme dsire.
Voyez plutt la diffrence la figure 15.4 entre limage bitmap gauche et
limage vectorielle droite, toutes les deux redimensionnes 300%.

Figure 15.4 Redimensionnement de limage de base


Dans ce chapitre, nous allons donc parler exclusivement de dessin vectoriel, lun des
atouts de cette technologie Flash !

Des contours et des remplissages


Le principe
Si vous avez dj utilis des classes de dessin dans dautres langages de programmation,
vous allez voir quici le principe est assez diffrent. Avant dentrer plus avant dans les
dtails, je vous invite dcouvrir les diffrents termes que nous serons amens utiliser
dans la suite de ce chapitre. Pour cela je vous propose tout dabord un petit dessin
dexemple la figure 15.5.

Figure 15.5 Composition dun lment graphique


Dans cet exemple, nous pouvons voir une bulle de pense comme on en trouve dans les
bandes dessines. Cette bulle est compose de 4 objets : un nuage et trois ovales.
Ces objets correspondent des tracs diffrents quil faudrait raliser les uns aprs les
autres. Chaque trac est donc dfini de la faon suivante :
Le remplissage : surface reprsente en bleu sur le dessin prcdent.
Le contour : ligne qui dlimite le remplissage.
306

LOBJET GRAPHICS
La ligne : trait visible qui suit le contour et pouvant avoir diffrentes apparences.
Ainsi, pour raliser un trac en Flash, il nous faut dfinir le contour de celui-ci en
indiquant quel style adopter pour le remplissage et la ligne.
Dfinir le style des lignes
Tout dabord, veuillez noter que nous parlons ici de lignes et non de contours, il sagit
donc uniquement du ct esthtique des traits qui effectivement suivent le contour.
Pour dfinir le style des lignes, nous utiliserons la mthode lineStyle() de la classe
Graphics. Cette mthode possde beaucoup de paramtres, mais tous sont facultatifs.
Cest pourquoi, je ne vous parlerai ici que des trois premiers qui sont les plus intressants. Le premier sert dfinir la largeur de la ligne, le deuxime sa couleur, et enfin
le dernier permet de prciser lopacit de celle-ci. Voici un exemple dans lequel nous
dfinissons des lignes de largeur 2, de couleur noire et transparentes 50% :
1

monDessin . graphics . lineStyle (2 , 0x000000 , 0 . 5 ) ;

Comme nous lavons dit, la mthode lineStyle() ne possde que des paramtres
facultatifs. Ainsi, si vous ne souhaitez pas de lignes sur votre trac mais uniquement
un remplissage, il vous suffit dutiliser cette mthode sans paramtres, comme ceci :
1

monDessin . graphics . lineStyle () ;

Dfinir un remplissage
Contrairement aux lignes, les remplissages ncessitent lutilisation de deux mthodes :
beginFill() et endFill(). La premire permet de dfinir les diffrentes caractristiques du remplissage, savoir sa couleur et son opacit. En revanche, dans notre
cas de figure, la couleur est un paramtre obligatoire et ne peut donc pas tre omise.
Voici par exemple comment dfinir une couleur blanche au remplissage :
1

monDessin . graphics . beginFill ( 0xFFFFFF ) ;

Lutilisation de la seconde mthode est justifie par la dfinition mme dun remplissage. En effet, pour remplir lintrieur dun contour, celui-ci doit tre ferm ! La
mthode endFill() sert donc refermer un contour, pour pouvoir lui appliquer
un remplissage. Ainsi, si lors du trac de votre contour, le point final nest pas identique au premier, une ligne droite sera alors trace entre ces deux points pour fermer
le contour. Cette mthode endFill() ne prend aucun paramtre et sutilise donc simplement de la manire suivante :
1

monDessin . graphics . endFill () ;

Notez que la mthode beginFill() doit tre appele avant endFill(), et


que la dfinition du contour seffectue entre ces instructions. Sachez galement que tout trac effectu lextrieur de ces deux instructions sera
compos uniquement de lignes et donc sera sans remplissage.

307

CHAPITRE 15. DESSINER AVEC LACTIONSCRIPT

Dessinez, cest gagn !


a y est, vous allez enfin pouvoir dessiner en Actionscript ! Nous allons maintenant
voir quelles sont les diffrentes mthodes de la classe Graphics, et apprendre nous
en servir. Ensuite, nous raliserons un petit exercice la fin de ce chapitre qui devrait
vous aider mieux utiliser cette classe.

Les lignes et les courbes


Une histoire de curseur
lorigine, lensemble des tracs en Flash taient conus lintrieur du logiciel Flash
Professionnal. Ceux-ci taient donc raliss graphiquement laide de votre souris,
aussi connue sous le nom de curseur. Depuis larrive de lActionscript 3, il nest
plus ncessaire de possder le logiciel pour pouvoir effectuer des tracs. En effet, il est
maintenant possible de faire exactement la mme chose grce au code. Cependant, les
instructions sexcutent en conservant la logique utilise pour dessiner dans le logiciel.
Ainsi, lorsque vous dessinerez en Actionscript, vous devrez imaginez les diffrents
gestes que vous raliseriez avec la souris de votre ordinateur. Par exemple, si vous
souhaitez tracer une ligne, vous dplacerez dabord votre curseur lendroit o vous
voudrez dmarrer celle-ci, puis vous la tracerez. Une fois celle-ci dessine, votre curseur
se trouverait alors lautre extrmit de la ligne. Vous pourriez alors continuer votre
trac partir du mme point ou bien dplacer avant votre curseur vers une autre partie
de lcran.
Revenons maintenant ce qui nous intresse : lActionscript ! Lorsque vous dessinez
grce la classe Graphics, vous disposez un curseur fictif que vous pouvez dplacer
nimporte o sur lcran. Pour modifier la position de celui-ci, vous devez utiliser la
mthode moveTo() en spcifiant le nouvel emplacement, comme ci-dessous :
1
2
3

var _x : Number = 25 ;
var _y : Number = 50 ;
monDessin . graphics . moveTo ( _x , _y ) ;

Lorsque vous tracerez des lignes et des courbes, rappelez-vous que vous devez
au pralable modifier la position de votre curseur. Noubliez pas galement
quaprs un trac, sa position est automatiquement mise jour, ce qui facilite
la succession de diverses lignes et courbes.

Les lignes droites


Pour raliser des contours, il est possible de crer des lignes droites. Pour cela, la
classe Graphics dispose de la mthode lineTo(), qui trace une ligne entre la position
actuelle du curseur et le nouveau point spcifi en paramtre. Voici un exemple qui
308

DESSINEZ, CEST GAGN !


permet de tracer une droite horizontale dpaisseur 10 entre les points de coordonnes
(10,10) et (10,100) :
1
2
3

monDessin . graphics . lineStyle ( 10 , 0x000000 ) ;


monDessin . graphics . moveTo ( 10 , 10 ) ;
monDessin . graphics . lineTo ( 200 , 10 ) ;

Si vous lancez votre projet, vous verrez apparatre la belle ligne visible la figure 15.6.

Figure 15.6 Une ligne


Remarquez quici nous navons pas utilis les mthodes beginFill() et
endFill(), nous avons donc trac un contour sans remplissage, en utilisant uniquement un style de ligne. Notez galement que nous avons dabord
dplac notre curseur avant de dessiner la ligne.
la suite de votre ligne horizontale, vous pourriez trs bien continuer le trac de votre
contour avec une ligne verticale par exemple :
1

monDessin . graphics . lineTo ( 200 , 200 ) ; // Le curseur est la


position ( 200 , 10 ) avant l ' instruction

Les courbes
Les lignes droites cest bien, mais celles-ci sont vite limites lorsquil sagit de raliser
un dessin complexe avec des formes arrondies. Par consquent, il a t mis en place
ce quon appelle les courbes de Bzier ! Le principe de ces courbes est dutiliser un
point de contrle en plus des deux points dancrage. Ce point de contrle sert
dfinir la courbure de la ligne en direction de ce point. Pour mieux comprendre leffet
de celui-ci sur la courbe, je vous propose un exemple :
1
2
3
4
5

monDessin . graphics . lineStyle (4 , 0x000000 ) ;


monDessin . graphics . beginFill ( 0x55BBFF ) ;
monDessin . graphics . moveTo ( 10 , 100 ) ;
monDessin . graphics . curveTo ( 100 , 10 , 200 , 100 ) ;
monDessin . graphics . endFill () ;

Ici, la mthode curveTo() prend deux paires de coordonnes en paramtres. La premire correspond au point de contrle et la seconde au point dancrage final.
Voyez plutt la figure 15.7 le rsultat du trac o jai ajout les trois points.
Dans lexemple prcdent, nous avons dfini un remplissage laide de la
mthode beginFill(). Vous constaterez alors que le contour a t automatiquement referm par une ligne droite lors de lappel de la mthode
endFill().

309

CHAPITRE 15. DESSINER AVEC LACTIONSCRIPT

Figure 15.7 Une courbe dcrite par trois points

Les formes prdfinies


Pour les formes gomtriques particulires, il existe des mthodes permettant
de simplifier leur trac. Nous pouvons notamment citer les cercles, les ellipses et les
rectangles.
Les formes elliptiques
Lorsquon parle de formes elliptiques, on inclut gnralement les cercles et les ellipses. Nous allons donc voir prsent comment tracer chacune de ces formes. Tout
dabord, occupons-nous des cercles. Nous disposons pour cela dune mthode nomme
drawCircle(), dans laquelle nous devons spcifier les coordonnes x et y du centre du
cercle ainsi que le rayon r de celui-ci :
1

monDessin . graphics . drawCircle (x , y , r ) ;

Pour les ellipses, la mthode a utiliser est drawEllipse(). Celle-ci prend cette fois
quatre paramtres diffrents : la largeur et la hauteur de lellipse ainsi que les coordonnes x et y du coin suprieur gauche de la zone tracer :
1

monDessin . graphics . drawEllipse (x , y , largeur , hauteur ) ;

Nous verrons dans lexercice venir comment utiliser ces fonctions, mais je vous invite
grandement faire des tests de votre ct pour bien voir linfluence des diffrents
paramtres. Noubliez pas galement de dfinir un style de ligne ou un remplissage
avant lutilisation de telles mthodes.
Les rectangles
En plus des formes elliptiques, la classe Graphics vous permet de tracer des formes
rectangulaires. La mthode drawRect() est ainsi dfinie exactement de la mme
faon que drawEllipse(), la seule diffrence quelle trace cette fois un rectangle.
Linstruction ci-dessous ne prsente donc aucune surprise :
1

monDessin . graphics . drawRect (x , y , largeur , hauteur ) ;

Il se peut que vous ayez besoin, un moment ou un autre, de tracer un rectangle dont les angles sont arrondis. Pour cela, vous disposez galement de la mthode
drawRoundRect(), o vous devrez renseigner en plus la valeur de larrondi :
310

DESSINEZ, CEST GAGN !


1

monDessin . graphics . drawRoundRect (x , y , largeur , hauteur ,


arrondi ) ;

La mthode drawRoundRect() prend en ralit un sixime paramtre si vous


dsirez des arrondis non uniformes en hauteur et en largeur. Ainsi, le cinquime
paramtre dfinit la largeur des arrondis et le sixime leur hauteur.

Techniques avances
Dessiner une trajectoire
Lorsque vous crerez des contours laide des mthodes lineTo() et curveTo(), il
est probable que vous ayez une srie dinstructions similaires afin de parcourir lensemble de votre contour. Cest pourquoi, il existe une mthode drawPath() qui permet
deffectuer lensemble de ces tracs en une seule instruction. Cette mthode prend donc
en paramtres deux tableaux de type Vector.<int> et Vector.<Number>. Le premier
permet de dfinir le type de commande, quant au second, il contient lensemble des coordonnes des diffrents points dancrage et points de contrle. En ce qui concerne
les commandes, celles-ci sont dfinies comme suit :
1 moveTo().
2 lineTo().
3 curveTo().
Pour mieux comprendre ce dont il est question, je vous propose de prendre lexemple
suivant :
1
2
3
4

monDessin . graphics . lineStyle (2 , 0x000000 ) ;


monDessin . graphics . moveTo (0 , 0 ) ;
monDessin . graphics . lineTo ( 100 , 0 ) ;
monDessin . graphics . curveTo ( 200 , 0 , 200 , 100 ) ;

Lensemble de ces tracs pourrait galement tre raliss grce la mthode drawPath()
de la faon suivante :
1
2
3
4
5
6
7
8

var commandes : Vector . < int > = new Vector . < int >() ;
commandes . push (1 , 2 , 3 ) ;
var coordonnees : Vector . < Number > = new Vector . < Number >() ;
coordonnees . push (0 , 0 ) ;
coordonnees . push ( 100 , 0 ) ;
coordonnees . push ( 200 , 0 , 200 , 100 ) ;
monDessin . graphics . lineStyle (2 , 0x000000 ) ;
mouton . graphics . drawPath ( commandes , coordonnees ) ;

Vous remarquerez que nous aurions pu ajouter lensemble des coordonnes en


une seule instruction avec la mthode push(). Nanmoins, pour garder un
maximum de lisibilit, je vous conseille de les ajouter par commande, comme
si vous utilisiez directement les mthodes correspondantes.
311

CHAPITRE 15. DESSINER AVEC LACTIONSCRIPT

Nest-ce pas plus compliqu et plus long au final ?

Je vous avoue que cette criture fait peur et est au final plus longue crire que la
version originale. Cependant, mettez-vous en tte que cette nouvelle version sexcute
plus rapidement que la prcdente. Ceci vient du fait que le trac lcran se fait en
une seule fois contrairement au premier code o il faut retracer chaque instruction.
Utilisez donc cette mthode au maximum ds que vous le pouvez.
Superposition de remplissages
Lorsque vous tracez diffrents contours, ceux-ci peuvent tre amens se superposer.
Dans ce cas, il est alors possible de supprimer le remplissage dans la zone de superposition. Pour cela, dfinissez les deux contours lintrieur dun mme remplissage,
cest--dire sans fermeture du contour entre les deux par la fonction endFill(). Pour
vous montrer leffet cr, voici le code que je vous invite tester :
1
2
3
4
5

monDessin . graphics . lineStyle (4 , 0x000000 ) ;


monDessin . graphics . beginFill ( 0x0000FF ) ;
monDessin . graphics . drawCircle ( 100 , 100 , 50 ) ;
monDessin . graphics . drawCircle ( 175 , 100 , 50 ) ;
monDessin . graphics . endFill () ;

Vous verrez alors deux disques de couleur bleu dont lintersection est non remplie
comme sur la figure 15.8.

Figure 15.8 Exclusion des deux cercles

Un petit pas vers la 3D


Avant de terminer la thorie sur cette classe Graphics, je vais rapidement vous parler
dune mthode un peu spciale : drawTriangles(). Comme son nom lindique, cette
mthode permet de dessiner des triangles. Cette manire de dcouper une gomtrie
en faces triangulaires, est une pratique courante lorsquil sagit de 3D. Cela permet
notamment de pouvoir dformer une image en la divisant sur plusieurs faces orientes
diffremment. Ainsi, il est possible dappliquer ce que lon appelle une texture, sur un
objet 3D modlis partir dune multitude de faces.
Dans ce chapitre, nous naborderons pas toutes ces techniques qui sont un peu trop
avances pour nous. Toutefois, je vais vous prsenter tout de mme comment utiliser
312

DESSINEZ, CEST GAGN !


cette mthode drawTriangles() avec des lignes et des remplissages. Le principe est
de crer une liste de points que nous nommerons des sommets, lintrieur dun
tableau de type Vector.<Number> contenant leurs coordonnes. Ces sommets sont
alors numrots dans lordre de leur dclaration avec pour premier indice 0. Un second
tableau de type Vector.<int> permet ensuite crer des triangles en reliant les sommets
par trois. Ainsi, le premier triangle est gnralement constitu des sommets 0, 1 et 2.
Conscient que tout cela est certainement encore flou dans votre tte, je vous propose
un petit exemple o nous aurons 5 sommets. Ensuite, nous allons crer quatre triangles
composs respectivement des sommets (0,1,2), (1,2,3), (2,3,4) et enfin (2,4,5). Voici le
code correspondant ces manipulations :
1
2
3
4
5
6

var sommets : Vector . < Number > = Vector . < Number >([ 10 , 10 , 10 , 100 ,
100 , 10 , 100 , 100 , 190 , 100 , 190 , 10 ]) ;
var indices : Vector . < int > = Vector . < int >([ 0 , 1 , 2 , 1 , 2 , 3 , 2 , 3
, 4 , 2 , 4 , 5 ]) ;
monDessin . graphics . lineStyle (4 , 0x000000 ) ;
monDessin . graphics . beginFill ( 0xAA00FF ) ;
monDessin . graphics . drawTriangles ( sommets , indices ) ;
monDessin . graphics . endFill () ;

Vous verrez donc apparatre nos quatre triangles formant ensemble un rectangle qui
pourrait tre la base de la modlisation dun intrieur quelconque par exemple. Voyez
la figure 15.9 laffichage correspondant, o jai volontairement rajout les indices des
sommets pour que vous puissiez mieux comprendre.

Figure 15.9 Conception base de triangles

Cette mthode drawTriangles() est principalement utilis pour la 3D, cest


pourquoi il nest pas ncessaire que vous compreniez son fonctionnement
dans le dtail. Nanmoins, pour les intresss, un troisime paramtre permet de crer de lUV Mapping. Ainsi, vous pouvez renseigner un vecteur
Vector.<Number> de coordonnes UV pour appliquer une texture chaque
face. Pour chaque sommet de triangles, vous devez alors faire correspondre
un point dune image en coordonnes UV. Ces coordonnes UV sont alors
standardises (0,0) pour le coin suprieur gauche de limage bitmap et
(1,1) pour le coin infrieur droit. Ne pouvant pas mattarder davantage sur
le sujet, jinvite les intresss se rendre dans la rubrique correspondante de
la documentation officielle.
313

CHAPITRE 15. DESSINER AVEC LACTIONSCRIPT



Documentation
B drawTriangles()
Code web : 924409


Exercice : Dessine-moi un mouton


Conception du dessin
Introduction
Dans cet exercice, nous allons raliser une petite illustration reprsentant un mouton,
pas pas.
Avant de nous lancer tte baisse, je vous invite prparer votre projet afin dobtenir un
rsultat similaire au mien la fin de lexercice. Vous allez donc changer les dimensions
de votre scne principale pour que celle-ci fasse 280 x 220 pixels. Vous pouvez laisser
la couleur darrire-plan en blanc tant donn que nous allons redfinir un fond dans
peu de temps. Nous allons galement dclarer deux variables _x et _y pour contrler
la position du mouton, puis une variable Mouton de type Shape qui nous servira
effectuer lensemble de nos tracs. Enfin, noubliez pas dajouter notre Mouton notre
conteneur principal grce la fonction addChild().
Voici donc notre classe Main au dbut de lexercice :
1
2
3
4
5

package
{
import flash . display . Sprite ;
import flash . events . Event ;
import flash . display . Shape ;

6
7
8
9
10

public class Main extends Sprite


{
private var _x : int ;
private var _y : int ;

11
12
13
14
15
16

public function Main () : void


{
if ( stage ) init () ;
else addEventListener ( Event . ADDED_TO_STAGE , init ) ;
}

17
18
19
20
21
22
23
24
25

314

private function init ( e : Event = null ) : void


{
removeEventListener ( Event . ADDED_TO_STAGE , init ) ;
// entry point
_x = 160 ;
_y = 40 ;
var mouton : Shape = new Shape () ;

EXERCICE : DESSINE-MOI UN MOUTON


26

27

this . addChild ( mouton ) ;

28

29
30
31

Le fond
Afin de faire ressortir notre mouton blanc, nous allons tracer une zone rectangulaire
de couleur bleue comme arrire-plan de notre dessin. Pour cela, nous nous servirons de
la fonction drawRoundRect() qui permet dobtenir un rectangle aux coins arrondis, ce
qui rendra lensemble plus esthtique. Ici, aucune difficult, nous aurons donc le code
suivant :
1
2
3
4

// Fond
mouton . graphics . beginFill ( 0x10879D ) ;
mouton . graphics . drawRoundRect (0 , 0 , 280 , 220 , 40 , 40 ) ;
mouton . graphics . endFill () ;

Le corps
La ralisation du corps du mouton est certainement la partie la plus longue et fastidieuse
de cet exercice. Nanmoins, jai dj effectu lopration, vous naurez donc qu suivre
mes instructions. Pour dessiner le corps du mouton, nous allons dans un premier temps
dfinir les diffrents paramtres de remplissage et de contour. Puis, nous commencerons
par tracer une courbe de Bzier qui sera le point de dpart pour la suite. Voici donc
un premier bout de code :
1
2
3
4
5
6

// Corps
mouton . graphics . lineStyle (4 , 0x3A281E , 1 . 0 ) ;
mouton . graphics . beginFill ( 0xFFFFFF ) ;
mouton . graphics . moveTo ( _x , _y ) ;
mouton . graphics . curveTo ( _x + 20 , _y - 20 , _x + 40 , _y ) ;
mouton . graphics . endFill () ;

Comme vous limaginez, nous ne pouvons pas dessiner lintgralit du corps du mouton
dune seule traite. Ainsi, comme vous pouvez le voir aux figures 15.10 et 15.11, il faut
procder tape par tape.
Tracer chaque bosse du corps est une tape qui peut tre extrmement longue
suivant vos talents en dessin. De plus, il est peu probable que vous obteniez rapidement
un rendu proche du mien, cest pourquoi je vous pargne cette tche prilleuse et je
vous propose dj le code final permettant de dessiner lintgralit du corps :
1
2
3

// Corps
mouton . graphics . lineStyle (4 , 0x3A281E , 1 . 0 ) ;
mouton . graphics . beginFill ( 0xFFFFFF ) ;

315

CHAPITRE 15. DESSINER AVEC LACTIONSCRIPT

Figure 15.10 Mise en place du premier arrondi

Figure 15.11 Cration pas pas du corps

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

mouton . graphics . moveTo ( _x , _y ) ;


mouton . graphics . curveTo ( _x + 20 , _y - 20 , _x + 40 , _y ) ;
mouton . graphics . curveTo ( _x + 60 , _y - 10 , _x + 70 , _y + 10 ) ;
mouton . graphics . curveTo ( _x + 90 , _y + 10 , _x + 90 , _y + 30 ) ;
mouton . graphics . curveTo ( _x + 110 , _y + 40 , _x + 100 , _y + 60 ) ;
mouton . graphics . curveTo ( _x + 120 , _y + 80 , _x + 100 , _y + 90 ) ;
mouton . graphics . curveTo ( _x + 110 , _y + 110 , _x + 90 , _y + 110 ) ;
mouton . graphics . curveTo ( _x + 80 , _y + 140 , _x + 60 , _y + 120 ) ;
mouton . graphics . curveTo ( _x + 40 , _y + 150 , _x + 20 , _y + 130 ) ;
mouton . graphics . curveTo ( _x , _y + 150 , _x -20 , _y + 130 ) ;
mouton . graphics . curveTo ( _x -40 , _y + 140 , _x -50 , _y + 120 ) ;
mouton . graphics . curveTo ( _x -70 , _y + 120 , _x -70 , _y + 100 ) ;
mouton . graphics . curveTo ( _x -100 , _y + 90 , _x -90 , _y + 70 ) ;
mouton . graphics . curveTo ( _x -110 , _y + 50 , _x -90 , _y + 40 ) ;
mouton . graphics . curveTo ( _x -90 , _y + 20 , _x -60 , _y + 20 ) ;
mouton . graphics . curveTo ( _x -50 , _y , _x -30 , _y + 10 ) ;
mouton . graphics . curveTo ( _x -20 , _y -10 , _x , _y ) ;
mouton . graphics . endFill () ;

Vous devriez maintenant avoir un beau corps de mouton (voir figure 15.12) qui, je
lavoue, ressemble pour linstant plus un nuage qu autre chose.
316

EXERCICE : DESSINE-MOI UN MOUTON

Figure 15.12 Le corps du mouton


La tte
prsent, nous allons nous occuper de la tte de notre mouton. Nous lui ferons donc
deux oreilles, puis nous ajouterons la forme globale de sa tte. Les yeux, quant eux,
seront raliss plus tard car ils demanderont un peu plus de travail.
Commenons par les oreilles, que nous crerons partir de courbes de Bzier. La
partie haute des oreilles sera dissimule plus tard, il est donc inutile de sattarder
dessus. Cest pourquoi nous tracerons uniquement une courbe pour chaque oreille et
nous laisserons le soin la fonction endFill() de refermer chacun de nos remplissages.
Ainsi, le code prsent ci-dessous permet de raliser les deux oreilles de la bte :
1
2
3
4
5
6
7
8
9

// T te
mouton . graphics . beginFill ( 0xF9D092 ) ;
mouton . graphics . moveTo ( _x - 30 , _y + 50 ) ;
mouton . graphics . curveTo ( _x - 90 , _y + 165 , _x - 10 , _y + 60 ) ;
mouton . graphics . endFill () ;
mouton . graphics . beginFill ( 0xF9D092 ) ;
mouton . graphics . moveTo ( _x + 50 , _y + 50 ) ;
mouton . graphics . curveTo ( _x + 100 , _y + 165 , _x + 30 , _y + 60 ) ;
mouton . graphics . endFill () ;

Bien videmment, nous avons utilis une nouvelle couleur de remplissage pour donner
un effet de peau nos oreilles que vous pouvez voir sur la figure 15.13.

Figure 15.13 Mise en place des oreilles


317

CHAPITRE 15. DESSINER AVEC LACTIONSCRIPT


Je suggre maintenant que nous passions la tte. Pour dessiner celle-ci, nous allons
commencer par tracer une ellipse. Puis nous utiliserons une ligne droite ainsi quune
courbe de Bzier sans remplissage pour reprsenter le museau de lanimal. L
encore, il ny a aucune difficult, il suffit de faire les choses dans lordre :
mouton . graphics . beginFill ( 0xF9D092 ) ;
mouton . graphics . drawEllipse ( _x - 30 , _y + 20 , 80 , 150 ) ;
mouton . graphics . endFill () ;
mouton . graphics . moveTo ( _x - 5 , _y + 155 ) ;
mouton . graphics . curveTo ( _x + 10 , _y + 165 , _x + 25 , _y + 155 ) ;
mouton . graphics . moveTo ( _x + 10 , _y + 160 ) ;
mouton . graphics . lineTo ( _x + 10 , _y + 170 ) ;

1
2
3
4
5
6
7

Voici donc notre mouton qui commence doucement prendre forme comme le montre
la figure 15.14.

Figure 15.14 Notre mouton et sa tte

Les cheveux
Nous allons prsent dessiner ce que jai appel les cheveux , mais qui correspond
en ralit la petite touffe de laine prsente sur le dessus de la tte. La technique
utilise ici est similaire celle employe pour le corps, cependant nous allons utiliser
cette fois la mthode drawPath(). Afin de rendre le code plus lisible, je vous conseille
encore une fois dajouter les diffrentes coordonnes par commande. Voici donc le code
que jai ralis pour tracer les cheveux de notre beau mouton :
1
2
3
4
5
6
7
8
9
10
11

// Cheveux
var commandes : Vector . < int > = new Vector . < int >() ;
commandes . push (1 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 ) ;
var coordonnees : Vector . < Number > = new Vector . < Number >() ;
coordonnees . push ( _x - 20 , _y + 20 ) ;
coordonnees . push ( _x , _y - 10 , _x + 20 , _y + 10 ) ;
coordonnees . push ( _x + 40 , _y , _x + 50 , _y + 30 ) ;
coordonnees . push ( _x + 80 , _y + 30 , _x + 60 , _y + 50 ) ;
coordonnees . push ( _x + 70 , _y + 70 , _x + 40 , _y + 70 ) ;
coordonnees . push ( _x + 20 , _y + 90 , _x , _y + 70 ) ;
coordonnees . push ( _x - 20 , _y + 90 , _x - 30 , _y + 60 ) ;

318

EXERCICE : DESSINE-MOI UN MOUTON


12
13
14
15
16

coordonnees . push ( _x - 60 , _y + 50 , _x - 40 , _y + 30 ) ;
coordonnees . push ( _x - 40 , _y , _x - 20 , _y + 20 ) ;
mouton . graphics . beginFill ( 0xFFFFFF ) ;
mouton . graphics . drawPath ( commandes , coordonnees ) ;
mouton . graphics . endFill () ;

Nous avons cette fois quelque chose qui commence rellement ressembler un mouton
(voir figure 15.15).

Figure 15.15 Mise en place des cheveux

Les pattes
Continuons lexercice en dessinant les pattes pour lesquelles je nai pas russi trouver
leffet que je souhaitais. Ce nest pas grave, contentons-nous de dessiner deux rectangles
arrondis en guise de pieds. Rien de plus simple, ceci est ralisable en quatre instructions :
1
2
3
4
5

// Pattes
mouton . graphics . beginFill ( 0xF9D092 ) ;
mouton . graphics . drawRoundRect ( _x - 60 , _y + 155 , 40 , 20 , 20 , 20
);
mouton . graphics . drawRoundRect ( _x + 40 , _y + 155 , 40 , 20 , 20 , 20
);
mouton . graphics . endFill () ;

Voici donc la figure 15.16 notre mouton qui peut prsent se tenir debout sur ses
pattes.
Les yeux
Notre mouton est trs beau, mais il est pour linstant aveugle ! Nous allons maintenant
nous occuper des yeux. Pour ceux-ci, nous nutiliserons que des cercles, ou plutt
des disques. Il nous en faudra trois pour chaque il : un pour lil en lui-mme, un
pour la pupille et enfin un dernier pour simuler le reflet blanc lintrieur de celle-ci.
Un petit dtail supplmentaire, nous naurons pas besoin de contours pour les deux
derniers disques. Cest pourquoi, nous dfinirons un style de lignes transparent pour
319

CHAPITRE 15. DESSINER AVEC LACTIONSCRIPT

Figure 15.16 Notre mouton se tient debout

ceux-ci. Je vous propose donc de dcouvrir le code correspondant lensemble de ces


manipulations :
1
2
3
4
5
6
7
8
9
10
11
12
13
14

// Yeux
mouton . graphics . beginFill ( 0xFFFFFF ) ;
mouton . graphics . drawCircle ( _x - 10 , _y + 100 , 15 ) ;
mouton . graphics . drawCircle ( _x + 25 , _y + 100 , 20 ) ;
mouton . graphics . endFill () ;
mouton . graphics . lineStyle (1 , 0x3A281E , 0 . 0 ) ;
mouton . graphics . beginFill ( 0x000000 ) ;
mouton . graphics . drawCircle ( _x - 10 , _y + 100 , 8 ) ;
mouton . graphics . drawCircle ( _x + 25 , _y + 100 , 8 ) ;
mouton . graphics . endFill () ;
mouton . graphics . beginFill ( 0xFFFFFF ) ;
mouton . graphics . drawCircle ( _x - 8 , _y + 98 , 2 ) ;
mouton . graphics . drawCircle ( _x + 27 , _y + 98 , 2 ) ;
mouton . graphics . endFill () ;

Cette petite touche finale vient donner vie notre mouton qui nous scrute maintenant
du regard (voir figure 15.17) !

Figure 15.17 Le mouton intgral

320

EXERCICE : DESSINE-MOI UN MOUTON


La bulle
Jaurai pu laisser ce chef-duvre tel quel, mais je trouvais quil manquait un petit
quelque chose. Jai donc ajout une bulle au mouton comme si on se trouvait dans une
bande dessine. Rien de nouveau ici, il sagit presque exclusivement de cercles remplis
ainsi que dun rectangle arrondi. Encore une fois, la seule difficult est de placer les
lments au bon endroit. Voici comment faire :
1
2
3
4
5
6
7
8
9
10
11

// Bulle
mouton . graphics . beginFill ( 0x3A281E ) ;
mouton . graphics . drawCircle ( _x - 60 , _y + 70 , 5 ) ;
mouton . graphics . drawCircle ( _x - 80 , _y + 50 , 10 ) ;
mouton . graphics . drawRoundRect ( _x - 150 , _y - 25 , 90 , 60 , 60 , 60
);
mouton . graphics . endFill () ;
mouton . graphics . beginFill ( 0xFFFFFF ) ;
mouton . graphics . drawCircle ( _x - 120 , _y + 15 , 5 ) ;
mouton . graphics . drawCircle ( _x - 105 , _y + 15 , 5 ) ;
mouton . graphics . drawCircle ( _x - 90 , _y + 15 , 5 ) ;
mouton . graphics . endFill () ;

Cette fois, nous avons la figure 15.18 le rsultat final de notre dessin.

Figure 15.18 Lillustration complte


Malgr ce que vous avez peut-tre ressenti au cours de cet exercice, la ralisation de ce mouton a demand beaucoup de travail, je my suis repris
plusieurs fois pour arriver ce rsultat. Nhsitez pas essayer de raliser
dautres dessins plus simples pour vous faire la main avec les mthodes de
cette classe Graphics !

Code final
Pour terminer ce chapitre, je vous ai rcrit lintgralit du code afin que vous puissiez
effectuer vos propres tests.
1

package

321

CHAPITRE 15. DESSINER AVEC LACTIONSCRIPT


2

3
4
5

import flash . display . Sprite ;


import flash . events . Event ;
import flash . display . Shape ;

6
7
8
9
10

public class Main extends Sprite


{
private var _x : int ;
private var _y : int ;

11
12
13
14
15
16

public function Main () : void


{
if ( stage ) init () ;
else addEventListener ( Event . ADDED_TO_STAGE , init ) ;
}

17
18
19
20
21
22
23
24

private function init ( e : Event = null ) : void


{
removeEventListener ( Event . ADDED_TO_STAGE , init ) ;
// entry point
_x = 160 ;
_y = 40 ;
var mouton : Shape = new Shape () ;

25
26
27
28
29

// Fond
mouton . graphics . beginFill ( 0x10879D ) ;
mouton . graphics . drawRoundRect (0 , 0 , 280 , 220 , 40 ,
40 ) ;
mouton . graphics . endFill () ;

30
31
32
33
34
35
36
37
38
39
40
41
42

322

// Corps
mouton . graphics . lineStyle (4 , 0x3A281E , 1 . 0 ) ;
mouton . graphics . beginFill ( 0xFFFFFF ) ;
mouton . graphics . moveTo ( _x , _y ) ;
mouton . graphics . curveTo ( _x + 20 , _y - 20 , _x + 40 ,
_y ) ;
mouton . graphics . curveTo ( _x + 60 , _y - 10 , _x + 70 ,
_y + 10 ) ;
mouton . graphics . curveTo ( _x + 90 , _y + 10 , _x + 90 ,
_y + 30 ) ;
mouton . graphics . curveTo ( _x + 110 , _y + 40 , _x + 100
, _y + 60 ) ;
mouton . graphics . curveTo ( _x + 120 , _y + 80 , _x + 100
, _y + 90 ) ;
mouton . graphics . curveTo ( _x + 110 , _y + 110 , _x + 90
, _y + 110 ) ;
mouton . graphics . curveTo ( _x + 80 , _y + 140 , _x + 60 ,
_y + 120 ) ;
mouton . graphics . curveTo ( _x + 40 , _y + 150 , _x + 20 ,
_y + 130 ) ;

EXERCICE : DESSINE-MOI UN MOUTON


43
44
45
46
47
48
49
50
51

mouton . graphics . curveTo ( _x , _y + 150 , _x -20 , _y +


130 ) ;
mouton . graphics . curveTo ( _x -40 , _y + 140 , _x -50 ,
_y + 120 ) ;
mouton . graphics . curveTo ( _x -70 , _y + 120 , _x -70 ,
_y + 100 ) ;
mouton . graphics . curveTo ( _x -100 , _y + 90 , _x -90 ,
_y + 70 ) ;
mouton . graphics . curveTo ( _x -110 , _y + 50 , _x -90 ,
_y + 40 ) ;
mouton . graphics . curveTo ( _x -90 , _y + 20 , _x -60 , _y
+ 20 ) ;
mouton . graphics . curveTo ( _x -50 , _y , _x -30 , _y + 10
);
mouton . graphics . curveTo ( _x -20 , _y -10 , _x , _y ) ;
mouton . graphics . endFill () ;

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

// T te
mouton . graphics . beginFill ( 0xF9D092 ) ;
mouton . graphics . moveTo ( _x - 30 , _y + 50 ) ;
mouton . graphics . curveTo ( _x - 90 , _y + 165 , _x - 10 ,
_y + 60 ) ;
mouton . graphics . endFill () ;
mouton . graphics . beginFill ( 0xF9D092 ) ;
mouton . graphics . moveTo ( _x + 50 , _y + 50 ) ;
mouton . graphics . curveTo ( _x + 100 , _y + 165 , _x + 30
, _y + 60 ) ;
mouton . graphics . endFill () ;
mouton . graphics . beginFill ( 0xF9D092 ) ;
mouton . graphics . drawEllipse ( _x - 30 , _y + 20 , 80 ,
150 ) ;
mouton . graphics . endFill () ;
mouton . graphics . moveTo ( _x - 5 , _y + 155 ) ;
mouton . graphics . curveTo ( _x + 10 , _y + 165 , _x + 25 ,
_y + 155 ) ;
mouton . graphics . moveTo ( _x + 10 , _y + 160 ) ;
mouton . graphics . lineTo ( _x + 10 , _y + 170 ) ;

69
70
71
72
73
74
75
76
77
78

// Cheveux
var commandes : Vector . < int > = new Vector . < int >() ;
commandes . push (1 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 ) ;
var coordonnees : Vector . < Number > = new Vector . <
Number >() ;
coordonnees . push ( _x - 20 , _y + 20 ) ;
coordonnees . push ( _x , _y - 10 , _x + 20 , _y + 10 ) ;
coordonnees . push ( _x + 40 , _y , _x + 50 , _y + 30 ) ;
coordonnees . push ( _x + 80 , _y + 30 , _x + 60 , _y + 50
);
coordonnees . push ( _x + 70 , _y + 70 , _x + 40 , _y + 70
);

323

CHAPITRE 15. DESSINER AVEC LACTIONSCRIPT


coordonnees . push ( _x + 20 , _y + 90 , _x , _y + 70 ) ;
coordonnees . push ( _x - 20 , _y + 90 , _x - 30 , _y + 60
);
coordonnees . push ( _x - 60 , _y + 50 , _x - 40 , _y + 30
);
coordonnees . push ( _x - 40 , _y , _x - 20 , _y + 20 ) ;
mouton . graphics . beginFill ( 0xFFFFFF ) ;
mouton . graphics . drawPath ( commandes , coordonnees ) ;
mouton . graphics . endFill () ;

79
80
81
82
83
84
85
86

// Pattes
mouton . graphics . beginFill ( 0xF9D092 ) ;
mouton . graphics . drawRoundRect ( _x - 60 , _y + 155 , 40
, 20 , 20 , 20 ) ;
mouton . graphics . drawRoundRect ( _x + 40 , _y + 155 , 40
, 20 , 20 , 20 ) ;
mouton . graphics . endFill () ;

87
88
89
90
91
92

// Yeux
mouton . graphics . beginFill ( 0xFFFFFF ) ;
mouton . graphics . drawCircle ( _x - 10 , _y + 100 , 15 ) ;
mouton . graphics . drawCircle ( _x + 25 , _y + 100 , 20 ) ;
mouton . graphics . endFill () ;
mouton . graphics . lineStyle (1 , 0x3A281E , 0 . 0 ) ;
mouton . graphics . beginFill ( 0x000000 ) ;
mouton . graphics . drawCircle ( _x - 10 , _y + 100 , 8 ) ;
mouton . graphics . drawCircle ( _x + 25 , _y + 100 , 8 ) ;
mouton . graphics . endFill () ;
mouton . graphics . beginFill ( 0xFFFFFF ) ;
mouton . graphics . drawCircle ( _x - 8 , _y + 98 , 2 ) ;
mouton . graphics . drawCircle ( _x + 27 , _y + 98 , 2 ) ;
mouton . graphics . endFill () ;

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

// Bulle
mouton . graphics . beginFill ( 0x3A281E ) ;
mouton . graphics . drawCircle ( _x - 60 , _y + 70 , 5 ) ;
mouton . graphics . drawCircle ( _x - 80 , _y + 50 , 10 ) ;
mouton . graphics . drawRoundRect ( _x - 150 , _y - 25 , 90
, 60 , 60 , 60 ) ;
mouton . graphics . endFill () ;
mouton . graphics . beginFill ( 0xFFFFFF ) ;
mouton . graphics . drawCircle ( _x - 120 , _y + 15 , 5 ) ;
mouton . graphics . drawCircle ( _x - 105 , _y + 15 , 5 ) ;
mouton . graphics . drawCircle ( _x - 90 , _y + 15 , 5 ) ;
mouton . graphics . endFill () ;

108
109
110
111
112
113
114
115
116
117
118
119
120

121
122
123

324

this . addChild ( mouton ) ;

EXERCICE : DESSINE-MOI UN MOUTON


124
125

Vous
 en utilisant le code web ci-dessous.
pouvez lafficher pour le copier
Code final
B
Code web : 285951

En rsum
La classe Graphics renferme toutes les mthodes permettant de dessiner directement
depuis le code.
Pour accder cette classe Graphics, il est ncessaire de passer par linstanciation
de lune de ces trois classes : Shape, Sprite ou MovieClip.
En Flash, les dessins raliss sont de type vectoriels et sadaptent la taille de
laffichage.
Pour dessiner en Actionscript, nous devons dfinir un contour puis spcifier les
styles de remplissages et de lignes qui doivent lui tre appliqus.
Les contours peuvent tre raliss grce des lignes droites ou des courbes de
Bzier.
Des formes prdfinies facilitent le trac de formes gomtriques simples, telles que
les cercles, les ellipses et les rectangles.

325

CHAPITRE 15. DESSINER AVEC LACTIONSCRIPT

326

Chapitre

16

Utilisation des matrices


Difficult :
Nous allons prsent nous pencher sur les matrices ! Nayez pas peur, ce chapitre ne
sera pas aussi complexe quil en lair. En fait, lutilisation de ces matrices est grandement facilite en Actionscript. En effet, vous verrez que nous disposons dune classe
nomme Matrix qui permet de manipuler une matrice sans besoin de comprendre comment elle fonctionne rellement. L encore, je pense que nous pouvons remercier la POO
et lencapsulation.
Nous verrons donc comment utiliser cette classe pour dcrire comment appliquer un dgrad
dans un trac ou encore faire effectuer des transformations gomtriques nos objets
daffichage.

327

CHAPITRE 16. UTILISATION DES MATRICES

Les matrices ou la classe Matrix


Introduction aux matrices
Les bases
Avant daller plus loin, je pense quil serait bien de vous expliquer un peu ce quest une
matrice, si vous ne le savez pas dj. Ne vous inquitez pas, il ne sagit pas dun cours
de mathmatiques ! Nous ne verrons donc pas de longues formules o vous risqueriez
de vous arracher les cheveux !
Malgr son nom barbare, une matrice nest en ralit rien dautre quun tableau de
valeurs. Les nombres qui y sont stocks peuvent reprsenter tout un tas de choses suivant lutilisation que lon peut en avoir. Les matrices peuvent donc tre utilises pour
des applications simples, mais permettent galement de reprsenter des concepts mathmatiques complexes. Toutefois, en ce qui nous concerne, nous nous contenterons de
dire quune matrice est un tableau de nombres et nous nous limiterons aux matrices
bidimensionnelles. Ainsi, toute matrice est de taille m n o m est le nombre de
lignes et n le nombre de colonnes. Voici par exemple une matrice 3 3 quelconque :

1
4
7

2
5
8

3
6
9

Comme dans un tableau, il est alors possible de dsigner un lment particulier grce
un couple dindices not (i, j). Dans lexemple prcdent, supposons que nous nommions
la matrice A. Nous pourrions par exemple prciser que A(2, 1) = 4. En mathmatiques,
il est possible de raliser tout un tas doprations avec les matrices. Cependant, dans
le cadre de ce cours, lobjectif nest pas de vous les prsenter toutes, cela serait bien
trop long et naurait pas vraiment dutilit dans notre cas. Toutefois, retenez quil
existe une matrice un peu particulire o les coefficients diagonaux sont gaux 1 et
les autres coefficients sont tous nuls : la matrice identit. En voici une :

1
0
0

0
1
0

0
0
1

Pour les dbutants en la matire, vous retiendrez donc quune matrice peut globalement
se manipuler comme un tableau de nombres.
Thorie pour les initis
Malgr le titre, jinvite galement les novices en termes de matrices lire la suite ne
serait-ce que pour le plaisir ! En deux dimensions, nous avons lhabitude dutiliser un
couple de coordonnes not (x, y) pour reprer un point sur le plan. Lorsque lon utilise
la notation matricielle, il est alors prfrable de noter ces coordonnes en vertical et
nous appellerons cette nouvelle notation un vecteur. Voici donc notre vecteur :
328

LES MATRICES OU LA CLASSE MATRIX

x
y

Une des proprits des matrices est la multiplication. Elle permet ainsi de multiplier
deux matrices entre elles mais galement une matrice avec un vecteur. Toutefois, les
dimensions des deux entits de lopration doivent tre cohrentes. Dans notre cas,
pour pouvoir multiplier notre vecteur de dimension 2 1, nous devrons utiliser une
matrice 2 2. Lintrt de tout cela est qu lintrieur de notre matrice 2 2, nous
pouvons dfinir diffrentes transformations gomtriques :


sx
0

0
sy

x
y

Lexemple ci-dessus est une opration de mise lchelle o sx correspond au redimensionnement horizontal et sy au vertical. Ainsi, aprs multiplication, nous obtenons
un nouveau vecteur o les nouvelles coordonnes ont t modifies suivant la transformation. Une opration qui, sans doute, vous fera certainement peur est la rotation.
Nous y retrouvons nos fonctions prfrs : sinus et cosinus. Voici donc comment se
ralise une rotation dun angle :


sin
cos

cos
sin

x
y

Nous arrivons maintenant au petit point pour lequel il nous a fallu faire toutes ces
prcisions. Lorsque lon utilise une matrice de dimension 2 2, il est possible de
raliser beaucoup de transformations. Toutefois, la translation ne peut pas tre prise
en compte dans ces conditions. Cest pourquoi, il est impratif dajouter une dimension
supplmentaire lensemble de lopration. Il devient alors possible de raliser une
translation de la manire suivante :

1
0
0

0
1
0

tx
x
ty y
1
1

Dans lexemple prcdent, les valeurs tx et ty reprsentent les dplacements respecti

vement suivant les axes


x et
y.
Le fait de rajouter une dimension au vecteur de coordonnes na de sens que
pour lopration mathmatique. Ainsi, les coordonnes 2D du point considr
seront toujours les deux premires, la troisime tant tout simplement ignore.
Vous noterez que toute cette thorie sur les matrices permet de vous aider
mieux cerner leur intrt. Dans la suite, vous verrez que toutes ces oprations
sont simplifies grce lencapsulation de la classe Matrix, qui dispose
de mthodes simples pour dfinir ces transformations. Ce nest donc pas
dramatique si vous navez pas tout compris sur la thorie des matrices !
329

CHAPITRE 16. UTILISATION DES MATRICES

Lobjet Matrix
Suite cette petite introduction aux matrices, vous devriez maintenant tre plus
laise et, surtout, vous ne devriez pas tre surpris par tout ce qui va suivre.

Introduction
Comme vous limaginez maintenant, la classe Matrix permet de dfinir une matrice
lintrieur du code. Celle-ci permettra donc de dfinir lensemble des transformations
appliquer un objet. Si vous avez bien suivi tout ce qui a t dit sur les matrices prcdemment, vous ne devriez donc pas tre surpris par la forme des matrices manipules
par cette classe :

a
b
0

c
d
0

tx
ty
1

Nous retrouvons donc quatre coefficients a, b, c et d qui permettent de raliser les


transformations classiques telles que le redimensionnement, la rotation mais galement
linclinaison. Nous disposons galement des valeurs de translation tx et ty , permettant
de dplacer un objet. Cette classe Matrix va donc nous permettre de dfinir une matrice
qui combinera une ou plusieurs de ces transformations en mme temps.

Dclaration et initialisation
Comme toute classe, un objet Matrix sinitiale grce au constructeur de la classe
dans une variable. Voici donc comment procder :
1

var maTransformation : Matrix = new Matrix () ;

Lorsque vous initialisez une matrice comme ceci, le constructeur cre une matrice identit, qui, en termes de transformations, ne fait strictement rien. En fait,
ce constructeur possde les diffrents paramtres facultatifs suivant : a, b, c, d, tx et
ty. Toutefois, comme nous ne voulons pas nous prendre la tte avec les mathmatiques,
nous utiliserons plutt les mthodes de la classe qui simplifient normment la gestion
des transformations.

Cration de dgrads
Dans le chapitre prcdent, jai volontairement omis de vous parler des dgrads. Nous
verrons dans la suite de ce chapitre que lutilisation des matrices permet de mieux
contrler le dgrad en lui-mme et ainsi parvenir plus facilement au rendu dsir.
330

CRATION DE DGRADS

Prsentation des dgrads


La gestion des dgrads en Actionscript peut paratre complexe au premier abord,
cependant ses possibilits sont larges. Vous verrez au fil des explications que la cration
dun dgrad se fait par tapes, de la mme manire quon le ferait dans un logiciel
de graphisme. Nous allons donc dans un premier temps dfinir le dgrad laide
de diffrents tableaux Array, comme ceci :
1
2
3

var couleurs : Array = [ 0xFF0000 , 0x00FF00 ];


var alphas : Array = [1 , 1 ];
var ratios : Array = [0 , 255 ];

Dans lexemple prcdent, nous avons dclar et initialis trois tableaux : couleurs,
alphas et ratios. Comme son nom lindique, le premier sert lister les diffrentes
couleurs du dgrad, ici rouge et vert. Le deuxime permet de dfinir lopacit de
chacune des couleurs prcdentes dans le mme ordre. Enfin, la variable ratios nous
permet de grer la position des couleurs les unes par rapport aux autres. Pour comparer,
vous pouvez imaginer quil sagit des petits curseurs que vous pourriez dplacer dans
un diteur de dgrad, ici reprsents par des valeurs comprises entre 0 lextrmit
gauche et 255 lextrmit droite, comme le montre la figure 16.1.

Figure 16.1 Un dgrad et des curseurs


Un des intrts de lutilisation de tableaux vient du fait que leur taille peut
tre quelconque. Ainsi, vous pouvez rajouter autant de couleurs que vous souhaitez, en rajoutant autant valeurs dans chacun des trois tableaux prcdents.
Cest principalement en ajoutant de nouvelles couleurs que la variable ratios
prend de limportance et permet alors de bien situer les couleurs entre elles.
En thorie, il est possible dappliquer un dgrad tel quel un remplissage par exemple.
Nous reviendrons dessus plus tard, mais vous pourriez trs bien utiliser le code suivant :
1
2
3
4

var monDessin : Shape = new Shape ;


monDessin . graphics . beginGradientFill ( GradientType . LINEAR ,
couleurs , alphas , ratios ) ;
monDessin . graphics . drawRect (0 , 0 , 100 , 100 ) ;
addChild ( monDessin ) ;

Nanmoins, il est quasiment indispensable de se servir des matrices pour dcrire comment les dgrads doivent tre appliqus. Hormis les valeurs GradientType.LINEAR
et GradientType.RADIAL qui permettent de dfinir le dgrad de type linaire ou radial, il est ncessaire de prciser la largeur, la hauteur ou encore langle de ce dernier
lintrieur du futur remplissage. Ainsi un objet de type Matrix va permettre de mettre
en place ces diffrents paramtres lintrieur dune mme matrice.
331

CHAPITRE 16. UTILISATION DES MATRICES

Ajouter une matrice de description


Pr-requis
Vous noterez que lutilisation des matrices ici nest pas tout fait identique aux
transformations dcrites auparavant. Toutefois, vous verrez quau final, la description
des dgrads y est trs similaire et que les matrices seront alors dfinies de la mme
manire.
Dans la suite de ce cours, nous partirons du dgrad blanc et noir dfini ci-dessous :
1
2
3

var couleurs : Array = [ 0xFFFFFF , 0x000000 ];


var alphas : Array = [1 , 1 ];
var ratios : Array = [0 , 255 ];

Prparation de la matrice
Comme nous lavons dit, la classe Matrix possde des mthodes qui facilitent la
dfinition dune matrice. Parmi elles, la mthode createGradientBox() est particulirement utile pour dcrire la mise en place dun dgrad. Les diffrents paramtres
de cette mthode sont lists dans le code dexemple ci-dessous :
1
2
3
4
5
6
7

var matrix : Matrix = new Matrix () ;


var largeur : Number = 100 ;
var hauteur : Number = 100 ;
var rotation : Number = 0 ;
var tx : Number = 0 ;
var ty : Number = 0 ;
matrix . createGradientBox ( largeur , hauteur , rotation , tx , ty ) ;

Notez que seuls la largeur et la hauteur sont des paramtres obligatoires.


Vous pouvez donc aisment vous passer des derniers paramtres si ceux-ci
sont nuls, et ainsi allger votre code. Ce sera notamment souvent le cas pour
les valeurs de dcalage du dgrad tx et ty.
Le nom des variables dans lexemple prcdent est assez explicite, cependant je vous
propose la figure 16.2 un tableau montrant linfluence de ces diffrents paramtres
sur le remplissage final.
Comme cest souvent le cas en programmation, les angles sont exprims en
radians. Toutefois, lutilisation de la classe Math vous permet de rcuprer la
valeur de \pi et donc dexprimer facilement les angles dans cette unit. Ainsi,
la conversion en radians se fait laide du facteur \frac{\pi}{180} .

332

CRATION DE DGRADS

Figure 16.2 Les paramtres modifient laffichage


Appliquer un dgrad
Pour appliquer un dgrad un remplissage, vous devez utiliser la mthode
beginGradientFill() que nous avions rapidement vu prcdemment. Vous pouvez
alors dfinir le remplissage en renseignant les diffrents paramtres dans lordre suivant :
1

monDessin . graphics . beginGradientFill ( GradientType . LINEAR ,


couleurs , alphas , ratios , matrix ) ;

Je rappelle quun dgrad peut tre linaire ou radial, dfini par les constantes
GradientType.LINEAR et GradientType.RADIAL. Comme pour la mthode beginFill(),
le remplissage est termin lors de lappel de la fonction endFill() qui termine le trac
dun contour.
Contrairement ce que vous pourriez croire, un dgrad peut tout autant sappliquer
aux lignes. Pour cela, utilisez la mthode lineGradientStyle() exactement de la
mme manire que beginGradientFill(). Toutefois, noubliez pas de dfinir la largeur
de la ligne laide de la mthode lineStyle(), sans quoi celle-ci ne sera pas visible.
Voici donc comment procder :
1
2

monDessin . graphics . lineStyle ( 2 ) ;


monDessin . graphics . lineGradientStyle ( GradientType . LINEAR ,
couleurs , alphas , ratios , matrix ) ;

333

CHAPITRE 16. UTILISATION DES MATRICES

Exemple : cration dun bouton


Pour terminer les explications sur les dgrads, je vous propose de raliser un petit
bouton comme vous pourriez en trouver sur nimporte quelle page web. Pour ce faire,
nous allons donc utiliser un dgrad linaire vertical que nous utiliserons comme
remplissage. Nous dessinerons alors un rectangles aux coins arrondis avec une ligne de
couleur pour marquer le contour de notre bouton. Sans plus attendre, voici le code
correspondant la dfinition du dgrad et au trac de ce bouton :
1
2
3
4

// D grad de base
var couleurs : Array = [ 0xEEBBBB , 0xDD0000 ];
var alphas : Array = [1 , 1 ];
var ratios : Array = [0 , 255 ];

5
6
7
8
9
10
11
12
13

// Matrice de description
var matrix : Matrix = new Matrix () ;
var largeur : Number = 100 ;
var hauteur : Number = 15 ;
var rotation : Number = Math . PI / 2 ;
var tx : Number = 0 ;
var ty : Number = 0 ;
matrix . createGradientBox ( largeur , hauteur , rotation , tx , ty ) ;

14
15
16
17
18
19
20

// Trac du bouton
var monBouton : Shape = new Shape ;
monBouton . graphics . lineStyle (1 , 0x880000 ) ;
monBouton . graphics . beginGradientFill ( GradientType . LINEAR ,
couleurs , alphas , ratios , matrix ) ;
monBouton . graphics . drawRoundRect (0 , 0 , 100 , 25 , 10 ) ;
addChild ( monBouton ) ;

Nous avons donc ici ralis la base dun bouton typique dune page Internet. Il manque
encore le texte par-dessus celui-ci mais vous devriez normalement pouvoir vous en
occuper vous-mmes. La figure 16.3 montre quoi ressemble notre bouton.

Figure 16.3 Notre bouton

Pour ajouter du texte grce lobjet TextField, vous devrez utiliser un


conteneur de type Sprite pour raliser ce bouton. Vous pourrez alors insrer lobjet Shape lintrieur ou dessiner directement depuis la proprit
graphics du conteneur.

334

LES TRANSFORMATIONS MATRICIELLES

Les transformations matricielles


Un objet transformer
Cration de lobjet
Nous allons dabord crer une forme que nous pourrons dformer plus tard. Pour ne
pas se compliquer la vie, nous tracerons donc un carr dans un objet de type Shape.
Nous partirons du code ci-dessous pour la suite de ce chapitre :
1
2
3
4

var monObjet : Shape = new Shape () ;


monObjet . graphics . beginFill ( 0x6688FF ) ;
monObjet . graphics . drawRect (0 , 0 , 100 , 100 ) ;
this . addChild ( monObjet ) ;

Pour que vous puissiez mieux comparer les effets des diffrentes transformations, voici,
la figure 16.4, loriginal que nous venons de crer.

Figure 16.4 Notre image originale


Lorsque vous crez nimporte quel objet daffichage, il lui est associ un centre
de transformation. Par dfaut, le centre dun objet est plac au point (0,0).
Veillez donc en tenir compte lors de la cration de vos affichages car ce
point influera sur la transformation, et il est probable que vous ayez alors
besoin de replacer vos objets aprs chacune delles.

La matrice de transformation
Tout objet hritant de la classe DisplayObject possde une matrice de transformation. Celle-ci na aucune incidence sur laffichage sil sagit dune matrice identit
ou si sa valeur est null. Pour y accder, vous devez atteindre la proprit matrix dune
proprit de votre objet nomme transform. Voici donc comment y parvenir :
1

monObjet . transform . matrix = matrix ;

Notez que la proprit de type Transform possde galement une matrice de


type Matrix3D qui permet de grer les transformations en trois dimensions.
Nous nen parlerons pas ici, mais sachez que vous ne pouvez utiliser ces deux
matrices simultanment. La modification de lune des deux entrane forcment
lautre une valeur null.
335

CHAPITRE 16. UTILISATION DES MATRICES


Bien quil soit possible de modifier directement les valeurs lintrieur dune matrice,
nous prfrerons utiliser les mthodes de la classe Matrix pour effectuer nos transformations.

Cration dune matrice de transformation


Mthodes de transformations individuelles
Pour commencer, nous allons voir revenir trs souvent une matrice identit. Cela
correspond une matrice nappliquant aucune transformation lobjet. Pour cela,
utilisez la fonction identity() simplement comme ceci :
matrix . identity () ;

Ensuite, voyons comment redimensionner notre objet daffichage. Pour cela, nous utiliserons la mthode scale() o nous pouvons spcifier les valeurs de redimensionnement
horizontal sx et vertical sx, la taille dorigine tant fixe 1. Voici donc comment procder :
matrix . scale ( sx , sy ) ;

Je vais maintenant vous prsenter la mthode rotate() permettant de faire pivoter un


objet par rapport son centre. Il suffit alors uniquement de prciser langle de rotation
en radians :
matrix . rotate ( angle ) ;

Voyons prsent ensemble la translation. Rien de plus simple, il suffit de prciser les
dcalages dx et dy la mthode translate() de la faon suivante :
matrix . translate ( dx , dy ) ;

Enfin, je vous propose une srie de transformations dans lexemple suivant :


1
2
3
4
5
6
7

var matrix : Matrix = new Matrix () ;


matrix . identity () ;
matrix . scale (2 , 1 ) ;
matrix . rotate ( Math . PI / 4 ) ;
matrix . translate ( 72 , 0 ) ;
// Application des transformations
monObjet . transform . matrix = matrix ;

Dans lexemple prcdent, nous avons donc doubl notre objet dans le sens horizontal.
Puis nous lavons fait tourner de 45 par rapport son centre confondu au coin suprieur gauche du rectangle. Enfin, nous avons translat lobjet afin quil soit nouveau
entirement dans la zone visible de lcran. Regardez le rsultat final la figure 16.5.
336

LES TRANSFORMATIONS MATRICIELLES

Figure 16.5 Le rsultat final


Noubliez pas que lorsque vous effectuez des transformations, celles-ci sont
toujours ralises par rapport au centre de votre objet. Ainsi, si celui-ci nest
positionn en (0,0), vous verrez sans nul doute votre objet de dplacer galement en rapport des transformations que vous pourrez lui appliquer. Soyez
donc prvoyant au moment de la cration de objet pour essayer danticiper
ces repositionnements.

Une petite exception : linclinaison


Il est aussi possible de dformer rellement votre objet en linclinant. Toutefois, la classe
Matrix ne possde pas de mthode pour ce genre de transformations. Cependant, il
est possible de modifier directement les valeurs lintrieur de la matrice. Cest donc
ce que nous ferons pour raliser ceci, en agissant sur la valeur b pour une inclinaison
verticale et sur la c pour une horizontale. Voici donc comment faire :
1

matrix . c = - Math . tan ( 2 ) ;

Dans cet exemple, nous inclinons notre objet dune valeur de 2 horizontalement. Ainsi,
chaque pixel va tre dcal vers la droite de deux fois sa distance verticale au centre
de lobjet. Voyez plutt le rsultat la figure 16.6.

Figure 16.6 Le rsultat final

Plusieurs transformations la fois


Contrairement ce que pourrait vous laissez croire le titre, les mthodes prcdentes
permettent galement de combiner plusieurs transformations en une seule matrice. Nous
337

CHAPITRE 16. UTILISATION DES MATRICES


allons crer une matrice combinant plusieurs transformations laide dune unique
mthode : createBox().
Cette mthode permet de combiner un redimensionnement avec une rotation
et une translation. Nanmoins, il faut tre vigilant quant lordre dapplication de chacune de ces transformations. Lordre des oprations est le suivant :
identit -> rotation -> redimensionnement -> translation.
Ainsi, lorsque vous utiliserez cette mthode, la matrice sera rinitialise et effacera
donc toute transformation de la matrice. Voici donc comment sutilise cette mthode :
matrix . createBox ( sx , sx , angle , dx , dy ) ;

Je vous propose donc un petit exemple dutilisation :


1
2
3

var matrix : Matrix = new Matrix () ;


matrix . createBox (2 , 1 , Math . PI /4 , 150 , 0 ) ;
monObjet . transform . matrix = matrix ;

Les oprations sont donc insres en une seule fois lintrieur de la matrice et produisent la figure 16.7.

Figure 16.7 Le rsultat final


Remarquez que les transformations nont pas t effectues dans le mme
ordre que prcdemment, notamment la rotation qui est ralise avant le
redimensionnement. Il est donc normal que notre objet ait t dform et
quil ressemble maintenant davantage un losange qu un carr.

Pour finir avec les matrices


Ajouter des transformations
Depuis le dpart, nous ne faisons quaffecter une matrice de transformation un
objet. Pour faire a, nous utilisons donc linstruction suivante :
1

monObjet . transform . matrix = matrix ;

Cependant, en effectuant cette affectation, vous effacez galement dventuelles transformations dj appliques lobjet. Or vous souhaiteriez peut-tre conserver ces anciennes transformations et appliquer en plus les nouvelles. Pour faire cela, vous aurez
338

LES TRANSFORMATIONS MATRICIELLES


donc besoin de rcuprer la matrice existante, avant dy ajouter de nouvelles oprations
de transformation. Voil donc comment nous pourrions rajouter une rotation de 45
notre objet, sans rinitialiser lensemble des transformations dj existantes :
1
2
3
4
5
6
7

// R cup ration de la matrice de l ' objet


var matrix : Matrix = new Matrix () ;
matrix = monObjet . transform . matrix ;
// Ajout d ' une transformation
matrix . rotate ( Math . PI / 4 ) ;
// Application des transformations
monObjet . transform . matrix = matrix ;

Si vous avez bien suivi, vous devriez vous rappeler quen utilisant la mthode createBox(),
vous commencez par redfinir lobjet Matrix comme matrice identit, liminant ainsi
toute trace danciennes transformations. Il faut donc procder diffremment si vous souhaitez conserver ces transformations. Pour cela, la classe Matrix dispose dune mthode
nomme concat() qui permet de concatner une matrice avec une autre, cest--dire
de combiner les effets gomtriques des deux matrices. Voil donc comment je vous
suggre de procder :
1
2
3
4
5
6
7
8
9
10

// R cup ration de la matrice de l ' objet


var matrix : Matrix = new Matrix () ;
matrix = monObjet . transform . matrix ;
// Cr ation de la matrice de transformation
var transformation : Matrix = new Matrix () ;
transformation . createBox (2 , 1 , Math . PI /4 , 150 , 0 ) ;
// Combinaison des matrices
matrix . concat ( transformation ) ;
// Application des transformations
monObjet . transform . matrix = matrix ;

Soyez attentif toutefois la manire de concatner vos deux matrices. En


effet, il faut bien ici ajouter les modifications de la matrice transformation
la matrice dorigine matrix. Cest pourquoi nous utilisons la mthode
concat() de matrix et non celle de transformation, qui aurait pour effet
dappliquer les nouvelles transformations avant les anciennes.

Intrt des transformations matricielles


Il est probable que vous vous demandiez depuis le dbut quel est lintrt dutiliser les
matrices alors que les proprits x, y, rotation, scaleX et scaleY permettent de faire
la mme chose.
En ralit, les transformations matricielles sont plus puissantes, notamment car
elles permettent les dformations impossibles avec les proprits prcdentes. Un autre
avantage est galement de limiter les modifications lies laffichage. En effet, lorsque
vous modifiez les proprits dun objet daffichage, celui-ci doit tre entirement retrac,
cest--dire pixel par pixel. Cette opration peut donc tre longue suivant les dimensions
339

CHAPITRE 16. UTILISATION DES MATRICES


de vos tracs et autres objets daffichage. Cest pourquoi, utiliser les transformations
matricielles acclre cette tape en combinant plusieurs oprations en une seule instruction de mise jour de laffichage. Ainsi, il est prfrable dutiliser cette technique
pour diminuer le temps dexcution de ces transformations et fluidifier au maximum
votre affichage.

En rsum
Une matrice est un tableau de nombres m lignes et n colonnes.
La classe Matrix sert crer et manipuler des matrices plus simplement.
Cette classe permet notamment de faciliter la mise en place des dgrads grce sa
mthode createGradientBox().
Lobjet Matrix est beaucoup utilis pour effectuer des transformations matricielles.
Pour les transformations classiques, il existe les diffrentes mthodes scale(), rotate()
et translate().
Il est possible de combiner plusieurs oprations gomtriques grce la mthode
createBox()
Lutilisation des matrices pour les transformations gomtriques permet dacclrer
le rendu de laffichage.

340

Chapitre

17

Manipuler des images


Difficult :
Il est temps dembellir notre application laide dimages. Dans ce chapitre, nous verrons
comment incorporer des images notre application, comment les afficher sur la scne,
nous aborderons galement quelques manipulations utiles. Toutefois, nous nvoquerons
pas ici le chargement dynamique dimages.

341

CHAPITRE 17. MANIPULER DES IMAGES

Embarquer des images


Prparation de limage
Dans un premier temps, il faut prparer limage que nous voulons incorporer dans notre
application. Reprenons limage de Zozor (voir figure 17.1) que nous avons utilise pour
afficher une image dans un champ de texte.

Figure 17.1 Zozor, la mascotte du Site du Zro


Crez un dossier lib sil nexiste pas dj dans le rpertoire de votre projet, puis crez-y
un dossier img. Enfin, copiez dans ce dossier img limage de Zozor. Voil ! Notre image
de Zozor est prte tre incorpore dans notre application !

Librairie dimages
Une nouvelle classe
Pour que notre projet soit un peu organis, nous allons embarquer nos images dans
une classe qui reprsentera notre bibliothque dimages. Crez une nouvelle classe
ImageLibrary ct de notre classe Main :
1
2
3
4
5
6
7
8

package
{
/* *
* Librairie contenant nos images embarqu es .
* @author Guillaume CHAU
*/
public class ImageLibrary
{

10
11
12

Incorporer une image


Pour embarquer une image, nous allons utiliser une instruction spciale pour le
compilateur, de la mme manire que nous avons embarqu une police de caractre,
grce au mot-cl Embed :
342

EMBARQUER DES IMAGES


1

[ Embed ( source = " ../ lib / img / zozor . png " ) ]

Le code est plus simple : il suffit dindiquer le chemin de limage dans le paramtre
source. Petite astuce si vous utilisez FlashDevelop : dans larborescence du projet,
faites un clic droit sur limage incorporer, puis slectionnez Generate Embed Code,
comme la figure 17.2.

Figure 17.2 FlashDevelop facilite lincorporation dimages


FlashDevelop insre alors linstruction spciale automatiquement, lendroit o votre
curseur dinsertion se trouve dans la classe.
Puis, sur la ligne suivante, il faut dclarer un attribut statique de type Class, comme
pour les polices de caractres embarques :
1

public static var Zozor : Class ;

Voici le code complet de la classe :


1
2
3
4
5
6
7
8

package
{
/* *
* Librairie contenant nos images embarqu es .
* @author Guillaume CHAU
*/
public class ImageLibrary
{

9
10

[ Embed ( source = " ../ lib / img / zozor . png " ) ]

343

CHAPITRE 17. MANIPULER DES IMAGES


public static var Zozor : Class ;

11
12

13
14
15

Notre librairie dimages embarques est maintenant prte lemploi !

Afficher des images


La classe Bitmap
Pour afficher une image, nous allons utiliser la classe Bitmap (voir figure 17.3).

Figure 17.3 La classe Bitmap dans larbre des classes daffichage


Si nous utilisons maintenant le constructeur de la classe Bitmap, nous obtiendrons une
image vide :
1
2

// Image vide
var zozor : Bitmap = new Bitmap () ;

la place, nous allons utiliser la classe contenue dans lattribut statique que nous
avons dclar dans notre classe ImageLibrary :
1

var zozor : Bitmap = new ImageLibrary . Zozor () ;

Voici le code complet pour afficher notre image de Zozor :


344

AFFICHER DES IMAGES


1
2
3

// Cr ation de l ' image


var zozor : Bitmap = new ImageLibrary . Zozor () ;
addChild ( zozor ) ;

4
5
6
7

// Alignement au centre
zozor . x = ( stage . stageWidth - zozor . width ) / 2 ;
zozor . y = ( stage . stageHeight - zozor . height ) / 2 ;

Ce qui nous donne lcran la figure 17.4.

Figure 17.4 Zozor !

Redimensionnement
Je vous propose dessayer de redimensionner notre image de Zozor : doublez sa taille
sans regarder la solution pour vrifier que vous vous souvenez bien des attributs ncessaires.
Vous devriez obtenir la figure 17.5.
Voici une solution possible :
1

// Cr ation de l ' image

345

CHAPITRE 17. MANIPULER DES IMAGES

Figure 17.5 Zozor a pris du poids.

346

AFFICHER DES IMAGES


2
3

var zozor : Bitmap = new ImageLibrary . Zozor () ;


addChild ( zozor ) ;

4
5
6
7

// Redime nsionnement
zozor . scaleX = 2 ;
zozor . scaleY = zozor . scaleX ;

8
9
10
11

// Alignement au centre
zozor . x = ( stage . stageWidth - zozor . width ) / 2 ;
zozor . y = ( stage . stageHeight - zozor . height ) / 2 ;

laide des attributs scaleX et scaleY de la classe DisplayObject dont hrite la classe
Bitmap, nous pouvons trs facilement appliquer un coefficient multipliant la taille de
notre objet daffichage.
Limage est devenue affreuse avec ces gros pixels. . . Peut-on y remdier ?

Plus ou moins. En vrit, il ny a pas de formule magique pour rendre limage aussi
nette quelle ntait sa taille dorigine, mais il est nanmoins possible damliorer le
rendu obtenu lors de tels redimensionnements jusqu une certaine mesure. Pour cet
effet, la classe Bitmap dispose dun attribut smoothing qui indique si les pixels de
limage doivent tre lisss si elle est redimensionne :
1
2

// Lissage des pixels


zozor . smoothing = true ;

Ce qui nous donne lcran la figure 17.6.


Cest dj un peu mieux ! Mais leffet de cet attribut se fait surtout ressentir lorsque
lon diminue la taille des images. Au lieu de doubler la taille de Zozor, mettons-la
70%, sans utiliser le lissage :
1
2
3

// Cr ation de l ' image


var zozor : Bitmap = new ImageLibrary . Zozor () ;
addChild ( zozor ) ;

4
5
6

// Lissage des pixels


// zozor . smoothing = true ;

7
8
9
10

// Redime nsionnement
zozor . scaleX = 0 . 7 ;
zozor . scaleY = zozor . scaleX ;

11
12
13
14

// Alignement au centre
zozor . x = ( stage . stageWidth - zozor . width ) / 2 ;
zozor . y = ( stage . stageHeight - zozor . height ) / 2 ;

Ce qui nous donne la figure 17.7.


347

CHAPITRE 17. MANIPULER DES IMAGES

Figure 17.6 Les pixels sont lisss.

Figure 17.7 Taille 70% de loriginal

348

OPRATIONS SUR LES IMAGES


Comme vous pouvez le constater, le rendu que nous avons obtenu est loin dtre
agrable. Pour remdier cela, ractivons le lissage :
1
2
3

// Cr ation de l ' image


var zozor : Bitmap = new ImageLibrary . Zozor () ;
addChild ( zozor ) ;

4
5
6

// Lissage des pixels


zozor . smoothing = true ;

7
8
9
10

// Redime nsionnement
zozor . scaleX = 0 . 7 ;
zozor . scaleY = zozor . scaleX ;

11
12
13
14

// Alignement au centre
zozor . x = ( stage . stageWidth - zozor . width ) / 2 ;
zozor . y = ( stage . stageHeight - zozor . height ) / 2 ;

Ce qui nous donne lcran la figure 17.8.

Figure 17.8 Taille 70% avec lissage


Cest tout de mme beaucoup mieux ! Pour mieux voir les diffrences entre les deux
rendus, voici la figure 17.9 une comparaison avec zoom.
Nabusez pas du lissage si vous affichez beaucoup dimages, cela risquerait
de dgrader les performances de votre application.

Oprations sur les images


La classe BitmapData
Tout objet de la classe Bitmap dispose dun attribut bitmapData de la classe BitmapData
(voir figure 17.10). Cet objet reprsente les pixels de limage stocks en mmoire. Linstance de la classe Bitmap ne contient pas de pixels, elle nest l que pour les afficher.
349

CHAPITRE 17. MANIPULER DES IMAGES

Figure 17.9 Comparaison avec et sans lissage

Figure 17.10 Tout objet de la classe Bitmap dispose dun attribut bitmapData de
la classe BitmapData

350

OPRATIONS SUR LES IMAGES


Il est possible dutiliser un seul objet BitmapData pour plusieurs images
Bitmap. Nhsitez pas le faire si vous devez afficher plusieurs fois la mme
image, cette astuce amliore grandement les performances daffichage des
images concernes.

Crer notre premire image


Pour crer une image vide, nous pouvons crer une instance de la classe Bitmap
sans lui passer de paramtre :
1
2
3

// Cr ation de l ' image


var image : Bitmap = new Bitmap () ;
addChild ( image ) ;

Notre objet image na aucun pixel sa disposition, donc il naffiche rien et a une taille
nulle :
1

trace ( " taille de l ' image : " + image . width + " x " + image .
height ) ;

Nous obtenons ceci dans la console :


taille de l image : 0 x 0

Ne nous arrtons pas l et crons notre premire image grce la classe BitmapData :
1
2

// Cr ation des donn es de l ' image ( les pixels )


var imageData : BitmapData = new BitmapData ( 300 , 300 , false ,
0x0000ff ) ;

Le premier paramtre est la largeur du tableau de pixel (donc de limage), le deuxime


est sa hauteur. Ensuite, un boolen nous permet dindiquer si limage vide est transparente ou non. Pour finir, nous devons passer la couleur de remplissage initiale. Ici,
notre image sera donc un carr de 300 pixels de ct, rempli de couleur bleue.
Ensuite, il faut dire notre objet image dutiliser les donnes contenues dans notre
objet imageData :
1
2

// Donn es pour l ' image


image . bitmapData = imageData ;

Nous avons dsormais la figure 17.11 lcran.


Nous avons cr une image partir de rien !

Dessiner sur des images


Nous allons maintenant nous atteler rendre ce morne carr bleu un peu plus intressant en manipulant les pixels qui le composent.
351

CHAPITRE 17. MANIPULER DES IMAGES

Figure 17.11 Un carr bleu

352

OPRATIONS SUR LES IMAGES


Pipette
Nous avons disposition dune sorte de pipette, comme dans les logiciels de dessin,
qui nous permet de connatre la couleur dun pixel. Cette pipette est la mthode
getPixel(x, y) de la classe BitmapData. En paramtre, nous lui fournissons les coordonnes du pixel dont nous voulons la couleur et elle nous la renvoie (si nous donnons
des coordonnes qui sortent de limage, elle nous renvoie 0).
1
2
3

// Prenons la couleur d ' un de nos pixels ( celui du centre )


var couleur : uint = imageData . getPixel ( 150 , 150 ) ;
trace ( " couleur du pixel : " + couleur . toString ( 16 ) ) ; // Affiche
: ff ( quivalent de 0000ff )

Il existe une deuxime pipette qui nous renvoie la couleur dun pixel avec son opacit :
getPixel32(x, y).
1
2
3

// Avec l ' opacit


couleur = imageData . getPixel32 ( 150 , 150 ) ;
trace ( " couleur ARVB du pixel : " + couleur . toString ( 16 ) ) ; //
Affiche : ff0000ff

Comme vous pouvez le remarquer, il y a deux caractres supplmentaires par rapport


une couleur classique : ce sont les deux premiers. Ils reprsentent lopacit de la
couleur en quelque sorte, note en hexadcimal de 00 ff, comme pour le rouge, le
vert et le bleu. Ainsi, 0x00000000 est une couleur totalement transparente, 0x880000ff
reprsente du bleu moiti transparent et 0xff0000ff du bleu totalement opaque.
Colorier un pixel
Il est grand temps de barbouiller notre carr de couleur ! Commenons avec la mthode
setPixel(x, y, couleur), qui permet de colorier un pixel aux coordonnes que nous
passons en paramtre, avec une certaine couleur (sans gestion de lopacit) :
1
2
3

// Colorions le pixel du centre en rouge


couleur = 0xff0000 ;
imageData . setPixel ( 150 , 150 , couleur ) ;

Nous obtenons la figure 17.12 (jai agrandi limage pour que lon puisse mieux voir).
Comme nous lavons vu prcdemment, il existe galement la mthode setPixel32(x,
y, couleur) qui permet de colorier un pixel avec une couleur contenant une
valeur de transparence.
Exercice
Essayons-nous plus de fantaisies ! Je vous propose un petit exercice : coloriez chaque
pixel de notre carr avec une couleur alatoire opaque. Essayez de ne pas regarder la
solution trop vite !
Quelques conseils :
353

CHAPITRE 17. MANIPULER DES IMAGES

Figure 17.12 Pixel rouge au milieu de pixels bleus.

354

OPRATIONS SUR LES IMAGES


Utilisez deux boucles imbriques pour parcourir les pixels de limage.
Utilisez la mthode Math.random() pour gnrer un nombre alatoire de 0 1 (que
vous pouvez multiplier par 0xffffff pour avoir une couleur alatoire).
La classe BitmapData dispose des attributs width et height permettant dobtenir
la taille de limage stocke dans lobjet, un peu comme pour les objets daffichage.
Jobtiens la figure 17.13.

Figure 17.13 Un beau tas de pixels.


Ne regardez pas tout de suite la solution que je vous propose si vous navez pas rflchi
au code quil faut crire. Essayez dobtenir un bon rsultat et, mme si vous ny arrivez
pas, rassurez-vous, le simple fait davoir essay est dj un grand pas vers la matrise
du langage.
Si vous avez russi (ou que vous tes sur le point de vous jeter par la fentre !), vous
pouvez comparer votre code avec le mien (je nai vraiment pas envie davoir votre mort
sur la conscience) :
1
2
3

// Cr ation de l ' image


var image : Bitmap = new Bitmap () ;
addChild ( image ) ;

4
5
6

// Cr ation des donn es de l ' image ( les pixels )


var imageData : BitmapData = new BitmapData ( 300 , 300 , false ,
0x0000ff ) ;

7
8
9

// Donn es pour l ' image


image . bitmapData = imageData ;

10
11
12
13
14
15
16
17

// /// Barbouillage !
// On parcourt chaque pixel de l ' image
// Lignes
for ( var x : int = 0 ; x < imageData . width ; x ++)
{
// Colonnes
for ( var y : int = 0 ; y < imageData . height ; y ++)

355

CHAPITRE 17. MANIPULER DES IMAGES


{

18
19
20

// Couleur al atoire
couleur = Math . random () * 0xffffff ;

21
22
23
24
25

// Colorions le pixel actuel


imageData . setPixel32 (x , y , couleur ) ;

Et cest tout ! Finalement, cest plutt simple non ?


Exercice : variante
Et si nous corsions un peu les choses ? Modifions lexercice : il faut dsormais que tous
les pixels de limage soient remplis avec une couleur choisie alatoirement parmi un
choix limit : rouge, vert, bleu.
Quelques conseils :
Utilisez un tableau pour stocker les couleurs autorises.
Rutilisez la mthode Math.random() et la proprit length de votre tableau pour
choisir alatoirement une couleur parmi celle du tableau.
Jobtiens cette fois-ci la figure 17.14.

Figure 17.14 Pixels de trois couleurs


Solution :
1
2
3

// /// Barbouillage v 2 . 0
// On d finit d ' abord les couleurs possibles
var couleurs : Array = [ 0xff0000 , 0x00ff00 , 0x0000ff ];

4
5
6
7
8

// On parcourt chaque pixel de l ' image


// Lignes
for ( var x : int = 0 ; x < imageData . width ; x ++)
{

356

OPRATIONS SUR LES IMAGES


// Colonnes
for ( var y : int = 0 ; y < imageData . height ; y ++)
{
// Choix de la couleur
var choix : int = Math . random () * couleurs . length
;

9
10
11
12
13
14

// Couleur choisie
couleur = couleurs [ choix ];

15
16
17
18
19
20
21

// Colorions le pixel actuel


imageData . setPixel32 (x , y , couleur ) ;

Remplissage un rectangle de couleur


Une autre mthode bien utile permet de remplir une zone rectangulaire avec une
couleur (avec transparence), ce qui nous simplifie tout de mme la vie. Il sagit de
fillRect(rectangle, couleur) de la classe BitmapData, qui prend en paramtre un
objet de la classe Rectangle et une couleur avec transparence.
1
2

// Tra ons un rectangle rouge


imageData . fillRect ( new Rectangle (0 , 0 , 150 , 100 ) , 0xffff0000 ) ;

Notre image ressemble dsormais la figure 17.15.

Figure 17.15 Un rectangle rouge sur fond bleu

Exercice : deuxime variante


Encore le mme exercice ! Mais cette fois-ci, remplissons notre image avec de gros carrs
de 25 pixels de ct dune couleur choisie alatoirement parmi le mme choix limit :
rouge, vert, bleu.
357

CHAPITRE 17. MANIPULER DES IMAGES


Quelques conseils :
Utilisez un objet de la classe Rectangle pour stocker les coordonnes et la taille des
carrs.
Bien entendu, utilisez la mthode que nous venons de voir, fillRect() !
Jobtiens la figure 17.16.

Figure 17.16 Le rendu


Et voici ce que jai crit :
1
2
3
4

// /// Barbouillage v 3 . 0
// On d finit d ' abord les couleurs possibles
var couleur : uint ;
var couleurs : Array = [ 0xff0000 , 0x00ff00 , 0x0000ff ];

5
6
7

// On d finit la taille des rectangles


var rectangle : Rectangle = new Rectangle (0 , 0 , 25 , 25 ) ;

8
9
10
11
12
13
14
15
16
17

// On parcourt l ' image pour la remplir de rectangles


// Lignes
for ( rectangle . x = 0 ; rectangle . x < imageData . width ; rectangle .
x += rectangle . width )
{
// Colonnes
for ( rectangle . y = 0 ; rectangle . y < imageData . height ;
rectangle . y += rectangle . height )
{
// Choix de la couleur
var choix : int = Math . random () * couleurs . length ;

18
19
20

// Couleur choisie
couleur = couleurs [ choix ];

21
22
23

358

// Colorions le rectangle actuel


imageData . fillRect ( rectangle , couleur ) ;

OPRATIONS SUR LES IMAGES


24
25

Comme vous pouvez le remarquer, jai utilis lobjet rectangle directement dans les
boucles for : le code en est dautant plus logique et lisible.

En rsum
Pour embarquer une image, il suffit dutiliser linstruction spciale Embed et dfinir
un attribut de type Class, comme pour les polices embarques.
Laffichage dune image se fait via la classe Bitmap dont la dfinition peut se faire
grce aux images embarques.
La classe Bitmap dispose dune proprit smoothing qui permet de lisser les pixels
dune image, principalement utile aprs une transformation.
Lensemble des pixels dune image sont stocks en mmoire laide une instance de
la classe BitmapData.
La classe Bitmap possde donc une proprit nomme bitmapData de type BitmapData
dont ldition est possible.

359

CHAPITRE 17. MANIPULER DES IMAGES

360

Chapitre

18

Filtres et modes de fusion


Difficult :
Dans ce chapitre, nous allons introduire les filtres et les modes de fusion ! Ils permettent
de modifier facilement lapparence de vos lments graphiques votre guise. Si certains
en ont dj entendu parler dans divers logiciels de graphisme, vous ne serez pas perdus
puisque le principe est le mme et les effets sont assez semblables.
Avant de vous lancer dans la lecture de ce chapitre, je dois vous mettre en garde. Effectivement, celui-ci est compos de deux glossaires qui regroupent lensemble des filtres et
modes de fusion. Leur but est de pouvoir vous tre utile plus tard lorsque vous en aurez
besoin, ne passez donc pas trop de temps dessus pour le moment, retenez simplement le
principe gnral de ces effets.

361

CHAPITRE 18. FILTRES ET MODES DE FUSION

Les filtres
Introduction
Pour amliorer simplement le visuel de vos animations, vous pouvez utiliser les diffrents filtres proposs par lActionscript. Il sagit deffets graphiques que vous pouvez
ajouter lensemble de vos lments visuels. Vous disposez donc de neuf filtres que
vous pouvez combiner selon vos prfrences pour changer lapparence dun objet. Voici,
par exemple, la figure 18.1 une combinaison de deux filtres ajoute une image.

Figure 18.1 Deux filtres ont t ajouts une image


Vous constaterez donc quil est alors possible de transformer radicalement le rendu final
dune scne. Parmi les filtres, vous trouverez plusieurs effets :

Le flou.
Lombre porte.
La lueur.
Le biseau.
Etc.

Avant de vous numrer lensemble des filtres disponibles je vous propose de voir ensemble le principe dutilisation de ceux-ci.

Cration dun exemple


Pour comprendre le fonctionnement des filtres, nous allons prendre un exemple.
Je suggre donc que nous reprenions limage ainsi que leffet prcdent. La figure 18.2
reprsente limage originale telle quelle est charge lintrieur de lanimation. Vous
pouvez videmment travailler sur une image diffrente.
Nous allons donc charger notre image comme vous savez maintenant le faire :
1
2

[ Embed ( source = ' images / Photo . png ') ]


private var Photo : Class ;

Puis nous allons linstancier et lajouter la liste daffichage :


1
2

var maPhoto : Bitmap = new Photo () ;


this . addChild ( maPhoto ) ;

362

LES FILTRES

Figure 18.2 Limage originale

Ajout de filtres
Chacun des neufs filtres est en fait dfini par sa propre classe. Ainsi, ils possdent chacun leurs propres proprits permettant de paramtrer leffet correspondant. Dans lexemple prcdent, nous avons utilis les deux classes BlurFilter et
ColorMatrixFilter. Nous apprendrons utiliser ces classes plus tard, cest pourquoi,
je vous propose directement le code de ces deux effets.

Flou
1
2
3
4

var flou : BlurFilter = new BlurFilter () ;


flou . blurX = 2 ;
flou . blurY = 2 ;
flou . quality = BitmapFilterQuality . HIGH ;

Correction colorimtrique
1
2
3
4
5
6

var matrix : Array = new Array () ;


matrix . push ( 0 . 75 , 0 . 75 , 0 . 75 , 0 , 0 ) ; //
matrix . push ( 0 . 50 , 0 . 50 , 0 . 50 , 0 , 0 ) ; //
matrix . push ( 0 . 25 , 0 . 25 , 0 . 25 , 0 , 0 ) ; //
matrix . push (0 , 0 , 0 , 1 , 0 ) ; // Alpha
var corr ectionCouleur : ColorMatrixFilter
( matrix ) ;

Rouge
Vert
Bleu
= new ColorMatrixFilter

363

CHAPITRE 18. FILTRES ET MODES DE FUSION

Application des filtres


Tout objet DisplayObject possde une proprit filters de type Array. Il est ainsi
possible dajouter des filtres sa guise en manipulant ce tableau. Ajoutons donc nos
deux filtres linitialisation de notre tableau filters :
maPhoto . filters = new Array ( correctionCouleur , flou ) ;

Nous obtenons ainsi notre image avec une correction de couleur et un flou comme le
montre la figure 18.3.

Figure 18.3 Limage a t modifie

Glossaire des filtres


Les filtres de base
Flou
Pour flouter un lment graphique, nous disposons de la classe BlurFilter :
1
2
3
4

var flou : BlurFilter = new BlurFilter () ;


flou . blurX = 5 ;
flou . blurY = 5 ;
flou . quality = BitmapFilterQuality . MEDIUM ;

Le flou est ainsi dfinit par les proprits suivantes :


blurX : quantit de flou horizontal.
364

GLOSSAIRE DES FILTRES


blurY : quantit de flou vertical.
quality : qualit du flou dfinie par les valeurs de la classe BitmapFilterQuality.
Le rsultat se trouve la figure 18.4.

Figure 18.4 Limage est floute

Ombres portes
Les ombres portes sont dfinies grce la classe DropShadowFilter :
1
2
3
4

var ombre : DropShadowFilter = new DropShadowFilter () ;


ombre . color = 0x333333 ;
ombre . distance = 5 ;
ombre . angle = - 30 ;

Pour paramtrer votre ombre porte, utilisez les proprits suivantes :


color : couleur de lombre.
distance : distance fictive de lobjet la surface derrire elle.
angle : orientation de la lumire et donc de lombre.
Le rsultat se trouve la figure 18.5.

Figure 18.5 Une ombre porte a t ajoute

365

CHAPITRE 18. FILTRES ET MODES DE FUSION


Lueur simple
Il est possible de crer une lueur ou un rayonnement derrire lobjet grce la classe
GlowFilter :
1
2
3
4
5

var lueur : GlowFilter = new GlowFilter () ;


lueur . color = 0xFFAA66 ;
lueur . blurX = 15 ;
lueur . blurY = 15 ;
lueur . quality = BitmapFilterQuality . MEDIUM ;

Nous retrouvons ici des proprits semblables celles que nous avons dj vu prcdemment, auxquelles vous pouvez en ajouter de nouvelles :

alpha : opacit de la lueur.


strength : intensit du rayonnement.
inner : indique si lombre est interne ou non.
hideObject : indique si lobjet doit tre visible ou non.

Le rsultat se trouve la figure 18.6.

Figure 18.6 Une lueur simple

Lueur en dgrad
Leffet de rayonnement que nous venons daborder peut tre personnalis en ajoutant un dgrad la lueur. Pour cela, nous disposons de la classe GradientGlowFilter :
1
2
3
4
5
6
7
8
9
10
11

var lueur : GradientGlowFilter = new GradientGlowFilter () ;


lueur . distance = 0 ;
lueur . angle = 45 ;
lueur . colors = [ 0xFF0000 , 0x333333 ];
lueur . alphas = [0 , 1 ];
lueur . ratios = [0 , 255 ];
lueur . blurX = 15 ;
lueur . blurY = 15 ;
lueur . strength = 2 ;
lueur . quality = BitmapFilterQuality . HIGH ;
lueur . type = BitmapFilterType . OUTER ;

366

GLOSSAIRE DES FILTRES


Dans ce cas de figure, nous observons plusieurs nouveauts comme la dfinition du
dgrad grce aux proprits colors, alphas et ratios ainsi que la dfinition de la
lueur en interne ou en externe par le biais de la classe BitmapFilterType.
Le rsultat se trouve la figure 18.7.

Figure 18.7 Une lueur en dgrad

Biseau simple
Pour donner du relief un objet, vous pouvez dfinir un biseau laide de la classe
BevelFilter :
1
2
3
4
5
6
7
8
9
10
11
12

var biseau : BevelFilter = new BevelFilter () ;


biseau . distance = 5 ;
biseau . angle = 45 ;
biseau . highlightColor = 0xFFFFFF ;
biseau . highlightAlpha = 0 . 5 ;
biseau . shadowColor = 0x000000 ;
biseau . shadowAlpha = 0 . 5 ;
biseau . blurX = 3 ;
biseau . blurY = 3 ;
biseau . strength = 3 ;
biseau . quality = BitmapFilterQuality . HIGH ;
biseau . type = BitmapFilterType . INNER ;

Pour dfinir ce filtre, vous aurez principalement besoin de dfinir la distance de leffet
ainsi que des effets de lueurs et dombres dfinis par les couleurs et opacits highlightColor,
highlightAlpha, shadowColor et shadowAlpha.
Le rsultat se trouve la figure 18.8.
Biseau en dgrad

Une variante de biseau existe grce lutilisation dun dgrad dans la classe GradientBevelFilter :
1

var biseau : G r adientBevelFilter = new GradientBevelFilter () ;

367

CHAPITRE 18. FILTRES ET MODES DE FUSION

Figure 18.8 Un biseau simple


2
3
4
5
6
7
8
9

biseau . distance = 6 ;
biseau . angle = 60 ;
biseau . colors = [ 0x000000 , 0x006666 , 0xFFFFFF ];
biseau . alphas = [1 , 0 , 1 ];
biseau . ratios = [0 , 128 , 255 ];
biseau . blurX = 6 ;
biseau . blurY = 6 ;
biseau . quality = BitmapFilterQuality . HIGH ;

L encore, la principale diffrence par rapport la version simple est la dfinition dun
dgrad de couleurs.
Le rsultat se trouve la figure 18.9.

Figure 18.9 Un biseau en dgrad

Correction de couleurs
Un peu de thorie
Pour effectuer des corrections au niveau des couleurs, il existe la classe ColorMatrixFilter.
Comme son nom lindique, elle est compose dune matrice qui permet de redfinir
la couleur dun pixel. Ainsi, les lignes redfinissent, dans lordre, les composantes suivantes dun pixel : rouge, vert, bleu et alpha. Les diffrentes composantes de celles-ci
peuvent alors scrire suivant la forme suivante :
368

GLOSSAIRE DES FILTRES


fcanal (x, y) = R srouge (x, y) + V svert (x, y) + B sbleu (x, y) + A salpha (x, y) + .
O :
srouge (x, y), svert (x, y), sbleu (x, y) et salpha (x, y) sont les composantes rouge, vert,
bleu et alpha du pixel source.
R , V , B et A reprsentent leur contribution dans la valeur du canal de sortie.
est une constante.
En ralit, cette matrice est dcrite lintrieur dun tableau de 20 lments. Chaque
ligne est alors dfinie par une succession de 5 coefficients. Voici donc notre pseudomatrice A dans laquelle les colonnes correspondent aux composantes du pixel dorigine
et les lignes aux composantes du pixel final :

frouge
fvert
fbleu
falpha

srouge
A[0]
A[5]
A[10]
A[15]

svert
A[1]
A[6]
A[11]
A[16]

sbleu
A[2]
A[7]
A[12]
A[17]

En suivant cette logique, limage serait inchange


vante :
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

salpha
A[3]
A[8]
A[13]
A[18]

A[4]
A[9]
A[14]
A[19]

par application de la matrice sui0


0
0
0

Afin de mieux comprendre ce dont il est question, je vous propose la suite divers
exemples dutilisation de cette classe ColorMatrixFilter.
Saturation
Cette technique consiste saturer les couleurs afin dobtenir une image finale en noir
et blanc. Il faut alors que chaque pixel dispose au final de la mme quantit de rouge,
de vert et de bleu. Voici comment raliser cela :
1
2
3
4
5
6

var matrix : Array = new Array () ;


matrix . push ( 0 . 33 , 0 . 33 , 0 . 33 , 0 , 0 ) ; //
matrix . push ( 0 . 33 , 0 . 33 , 0 . 33 , 0 , 0 ) ; //
matrix . push ( 0 . 33 , 0 . 33 , 0 . 33 , 0 , 0 ) ; //
matrix . push (0 , 0 , 0 , 1 , 0 ) ; // Alpha
var corr ectionCouleur : ColorMatrixFilter
( matrix ) ;

Rouge
Vert
Bleu
= new ColorMatrixFilter

Le rsultat se trouve la figure 18.10.


Pour ne pas modifier la luminosit globale de limage, veillez obtenir un
total de 1 sur lensemble dune ligne. Autrement, les valeurs originalement
comprise entre 0 et 255 seront disproportionnes et limage naura pas le
rendu dsir.
369

CHAPITRE 18. FILTRES ET MODES DE FUSION

Figure 18.10 Un effet de saturation

Luminosit
En parlant de luminosit, il est justement possible de la contrler en jouant sur la
valeur de ces coefficients. Nous pouvons alors diminuer cette luminosit par exemple :
1
2
3
4
5
6

var matrix : Array = new Array () ;


matrix . push ( 0 .5 , 0 , 0 , 0 , 0 ) ; // Rouge
matrix . push (0 , 0 .5 , 0 , 0 , 0 ) ; // Vert
matrix . push (0 , 0 , 0 .5 , 0 , 0 ) ; // Bleu
matrix . push (0 , 0 , 0 , 1 , 0 ) ; // Alpha
var corr ectionCouleur : ColorMatrixFilter = new ColorMatrixFilter
( matrix ) ;

Le rsultat se trouve la figure 18.11.

Figure 18.11 Il est possible de jouer sur la luminosit

Le rglage de la luminosit est le seul cas o vous pouvez modifier la somme


totale des coefficients. Pour tout le reste, respectez au maximum cette rgle.

370

GLOSSAIRE DES FILTRES


Teinte
La teinte est plus difficile grer car la rotation des couleurs est gnralement
suivie dune saturation. Toutefois, je vous donne lexemple dun dcalage de 120 dans
les couleurs, ce qui revient dcaler le vert au rouge, le bleu au vert, etc. :
1
2
3
4
5
6

var matrix : Array = new Array () ;


matrix . push (0 , 0 , 1 , 0 , 0 ) ; // Rouge
matrix . push (1 , 0 , 0 , 0 , 0 ) ; // Vert
matrix . push (0 , 1 , 0 , 0 , 0 ) ; // Bleu
matrix . push (0 , 0 , 0 , 1 , 0 ) ; // Alpha
var corr ectionCouleur : ColorMatrixFilter = new ColorMatrixFilter
( matrix ) ;

Le rsultat se trouve la figure 18.12.

Figure 18.12 Il est possible de dcaler les couleurs

Pour ce genre de manipulations, je vous conseille plutt de passer par votre


logiciel de graphisme prfr.

Ngatif
Un effet ngatif consiste inverser les couleurs, cest--dire soustraire les valeurs
dorigine la valeur maximale 255. Dans ce cas, nous aurons alors besoin dutiliser une
constante, comme vous pouvez le voir ci-dessous :
1
2
3
4
5
6

var matrix : Array = new Array () ;


matrix . push ( -1 , 0 , 0 , 0 , 255 ) ; // Rouge
matrix . push (0 , -1 , 0 , 0 , 255 ) ; // Vert
matrix . push (0 , 0 , -1 , 0 , 255 ) ; // Bleu
matrix . push (0 , 0 , 0 , 1 , 0 ) ; // Alpha
var corr ectionCouleur : ColorMatrixFilter = new ColorMatrixFilter
( matrix ) ;

Le rsultat se trouve la figure 18.13.


371

CHAPITRE 18. FILTRES ET MODES DE FUSION

Figure 18.13 Limage en ngatif


Les constantes ne sont pas des coefficients comme les prcdents. Ainsi,
ceux-ci ne sutilisent pas entre -1 et 1 comme les autres, mais plutt entre
-255 et 255.

Convolution
Introduction
La convolution utilise par la classe ConvolutionFilter fonctionne galement laide
dune matrice. Nanmoins, celle-ci est une reprsentation dun pixel et de ses voisins
proches. Cette matrice peut thoriquement tre de dimension quelconque, toutefois
nous nous contenterons dune matrice 3 3 pour la suite. Ainsi, la valeur centrale
reprsente le pixel actuel et les autres valeurs, les pixels alentours. La couleur finale
dun pixel est alors dtermine partir de sa valeur initiale et de celles des pixels
voisins. Une image intacte est donc compos uniquement de la valeur 1 au centre de la
matrice :
0 0 0
0 1 0
0 0 0
Ici, la valeur de chaque pixel est une combinaison de la valeurs de plusieurs
pixels. Ainsi, il est important davoir un total gal 1 pour conserver la
luminosit globale de limage initiale.
Avant de vous montrer diffrents exemples dapplication, je vous prsente ici la manire
dutiliser ce filtre en Actionscript :
1
2
3
4
5
6

var matrix : Array = new Array () ;


// D finition de la matrice
var convolution : ConvolutionFilter = new ConvolutionFilter () ;
convolution . matrixX = 3 ;
convolution . matrixY = 3 ;
convolution . matrix = matrix ;

372

GLOSSAIRE DES FILTRES


Vous remarquerez alors que la matrice est galement dfinie laide dun tableau de
type Arraydont il est ncessaire de spcifier les dimensions laide des proprits
matrixX et matrixY.
Flou
Lapplication la plus simple est donc de gnrer un flou en moyennant la valeur du
pixel central celle des pixels voisins :
1
2
3
4

var matrix : Array = new Array () ;


matrix . push (0 , 0 .2 , 0 ) ;
matrix . push ( 0 .2 , 0 .2 , 0 . 2 ) ,
matrix . push (0 , 0 .2 , 0 ) ;

Le rsultat se trouve la figure 18.14.

Figure 18.14 Limage est floue


Il pourrait galement tre possible de prendre en compte la valeur des pixels en diagonale pour la gnration de ce flou.
Dtection de contours
La convolution est principalement utile pour dtecter les contours lintrieur
dune image. Le principe est alors de retrancher la valeur des pixels voisins et ainsi rvler les zones o les pixels proches nont pas une valeur identique. Voici donc comment
dtecter des contours :
1
2
3
4

var matrix : Array =


matrix . push (0 , -1 ,
matrix . push ( -1 , 4 ,
matrix . push (0 , -1 ,

new Array () ;
0);
-1 ) ,
0);

Le rsultat se trouve la figure 18.15.


Notez que cette opration peut galement tre effectue uniquement en horizontal ou en vertical, on mme en diagonal !

373

CHAPITRE 18. FILTRES ET MODES DE FUSION

Figure 18.15 Dtection des contours


Accentuation de contours
Si vous avez bien regard la matrice de dtection de contours, vous noterez que
la somme des valeurs est nulle. Nous avons alors perdu des informations concernant
limage. Ainsi, en rajoutant 1 au centre, il est possible de transformer cette dtection
de contours en accentuation de contours. Voyez donc ce que cette nouvelle matrice
provoque :
1
2
3
4

var matrix : Array =


matrix . push (0 , -1 ,
matrix . push ( -1 , 5 ,
matrix . push (0 , -1 ,

new Array () ;
0);
-1 ) ,
0);

Le rsultat se trouve la figure 18.16.

Figure 18.16 Accentuation des contours


Estampage
Cette dtection de contours permet galement de crer un effet destampage pour
faire ressortir le relief de limage. Voici comment procder :
1
2
3
4

var matrix : Array = new Array () ;


matrix . push ( -2 , -1 , 0 ) ;
matrix . push ( -1 , 1 , 1 ) ,
matrix . push (0 , 1 , 2 ) ;

374

GLOSSAIRE DES FILTRES


Le rsultat se trouve la figure 18.17.

Figure 18.17 Estampage de limage


Dans lexemple prcdent, nous avions des valeurs ngatives dans le coin suprieur
gauche et des valeurs positives dans le coin oppos, ce qui a pour effet de creuser
limage. En inversant ces valeurs, vous obtiendrez donc leffet inverse.

Mappage de dplacement
Enfin, la classe DisplacementMapFilter est le dernier filtre en Flash. Celui-ci permet
dutiliser ce quon appelle une carte de dplacement pour dformer une image.
Le dplacement est alors cr partir des diffrents canaux de cette carte . Dans
lexemple que nous verrons par la suite, nous avons ainsi dfini le canal de couleur bleue
pour laffectation de la position en x, et le canal de couleur rouge de celui en y. Voici
donc notre image de mappage du dplacement la figure 18.18.

Figure 18.18 Mappage du dplacement


Vous noterez que le dplacement se fait suivant la valeur du canal de couleur
correspondant. Cest pourquoi, la valeur 127 naffecte aucun dplacement,
contrairement aux valeurs 255 et 0 qui provoquent un dplacement maximal
dans des directions opposes.
Voici donc comment utiliser cette image de mappage du dplacement charge grce
la classe Class sous le nom de Deplacement :
1
2
3

var monDeplacement : Bitmap = new Deplacement () ;


// D finition de la carte de d placement
var map : BitmapData = new BitmapData ( monDeplacement . width ,
monDeplacement . height ) ;

375

CHAPITRE 18. FILTRES ET MODES DE FUSION


4
5
6
7
8
9
10
11
12

map . draw ( monDeplacement ) ;


// Cr ation du filtre
var deplacement : Displa cemen tMapFi lter = new
D i s p l acem entMap Filte r () ;
deplacement . mapBitmap = map ;
deplacement . componentX = BitmapDataChannel . BLUE ;
deplacement . componentY = BitmapDataChannel . RED ;
deplacement . scaleX = 60 ;
deplacement . scaleY = 60 ;
deplacement . mode = Di s p l a c e m e n t Ma p F i l t e r M o de . IGNORE ;

Comme vous lavez certainement devin, les canaux de couleurs sont choisis grce la
classe BitmapDataChannel et lchelle daffectation est spcifie laide des proprits scaleX et scaleY. Enfin, les constantes de la classe DisplacementMapFilterMode
permettent de grer laffectation des pixels sur les bords de limage.
Le rsultat se trouve la figure 18.19.

Figure 18.19 Image modifie

Les modes de fusion


Dfinition
Un autre moyen damliorer rapidement et facilement le rendu final de vos objets
visuels est lutilisation de modes de fusion ! Lorsquon parle de fusion, il sagit en
fait de mixer diffrents lments graphiques ensemble. Le principe est alors de grer
la manire dont ces diffrents objets seront fusionns dans le rendu final. Les modes
de fusion sont donc galement une manire rapide de transformer lapparence de vos
objets daffichage.
376

LES MODES DE FUSION


Fusion de calque
La premire utilit de ces modes de fusion est de pouvoir combiner diffrents objets
superposs, nomms communment calques, en fusionnant leurs couleurs. Voici la
figure 18.20 un exemple de fusion entre deux calques.

Figure 18.20 Fusion de deux images


Pour bien distinguer les filtres et les modes de fusions, retenez quun filtre
sapplique un unique objet, contrairement aux modes de fusions qui ncessitent au moins deux objets pour pouvoir tre actifs.

Fusion de transparence
La seconde utilisation de ces modes de fusion est la fusion de transparence. Le
principe est dutiliser les niveaux de transparence dun calque pour masquer certaines
parties dun second lment. Voici un exemple la figure 18.21.

Figure 18.21 Fusion de transparence

Une autre manire de grer lopacit de certaines zones dun lment est
lutilisation de masques, comme nous le verrons dans le chapitre suivant.

377

CHAPITRE 18. FILTRES ET MODES DE FUSION

Mise en place
La fusion de calques peut tre ralise entre nimporte quels objets hritant de la
classe DisplayObject. Ceux-ci disposent alors dune proprit nomme blendMode
pour dfinir le mode de fusion dsir. Cette dfinition est alors ralise laide des
constantes de la classe BlendMode.
La dfinition dun mode de fusion se fait en ralit uniquement sur un seul
calque. Vous devez alors lappliquer sur lobjet possdant lindex daffichage
le plus grand, autrement leffet de sera pas visible.
Voici donc comment ajouter le mode de fusion nomme DARKEN lobjet monCalque :
monCalque . blendMode = BlendMode . DARKEN ;

Toutefois, en ce qui concerne les fusions de transparence, vous aurez galement


besoin dimposer la cration dun groupe de transparences pour lobjet daffichage.
Cela consiste appliquer un mode de fusion de type LAYER au conteneur :
1

this . blendMode = BlendMode . LAYER ;

Voil, vous connaissez tout sur les modes de fusion prsent. Il ne nous reste plus
qu faire un tour des treize modes de fusion disponibles. Pour vous aider, je vous
propose un petit glossaire.

Glossaire de modes de fusion


Le mode de fusion par dfaut
Tout objet daffichage possde obligatoirement un seul et unique mode de fusion.
Ainsi, il existe un mode de fusion nomm NORMAL qui est appliqu par dfaut tout
objet. Voici donc comment redfinir le mode de fusion :
1

monCalque . blendMode = BlendMode . NORMAL ;

Le rsultat se trouve la figure 18.22.


Ce mode na aucune utilit, si ce nest de revenir au mode de fusion par
dfaut.

Les fusions de calques


Addition
Comme son nom lindique, ce mode de fusion va additionner les diffrents canaux
de couleurs du calque ceux de larrire-plan. Pour utiliser celui-ci, vous disposez le la
378

GLOSSAIRE DE MODES DE FUSION

Figure 18.22 Fusion par dfaut

constante ADD :
1

monCalque . blendMode = BlendMode . ADD ;

Le rsultat se trouve la figure 18.23.

Figure 18.23 Fusion par addition


Ce mode de fusion aura donc tendance claircir larrire-plan. Celui-ci peut tre
utilis pour crer des transitions entre deux objets en utilisant un fondu dclaircissement.

Obscurcir
Ce mode de fusion permet de slectionner les valeurs les plus faibles des canaux de
couleurs entre le calque et larrire-plan. Il est dfini par la constante DARKEN :
1

monCalque . blendMode = BlendMode . DARKEN ;

Le rsultat se trouve la figure 18.24.


Bien videment, en lutilisant vous allez obscurcir larrire plan. Lassombrissement est
toutefois moins intense quavec le mode de fusion MULTIPLY.
379

CHAPITRE 18. FILTRES ET MODES DE FUSION

Figure 18.24 Limage est obscurcie


Diffrence
Le principe ici est de soustraire, pour chacun des canaux de couleurs, la valeur la plus
sombre des deux de la plus claire. Voici la constante concerne :
1

monCalque . blendMode = BlendMode . DIFFERENCE ;

Le rsultat se trouve la figure 18.25.

Figure 18.25 Fusion par diffrence de couleur


Lutilisation de ce mode de fusion nest pas trs courante car il est difficile de prvoir
lapparence finale. Utilisez donc celui-ci avec prcaution !
Lumire crue
Le principe de ce mode de fusion est relativement complexe. Nanmoins, vous pouvez
retenir quil permet de faire ressortir et dassombrir les ombrages dune image. Le nom
de la constante qui le dfinit est HARDLIGHT :
1

monCalque . blendMode = BlendMode . HARDLIGHT ;

Le rsultat se trouve la figure 18.26.


Notez que celui-ci a tendance a masquer les couleurs claires de larrire-plan.
380

GLOSSAIRE DE MODES DE FUSION

Figure 18.26 Les ombres sont mises en valeur


Ngatif
Le principe de cet effet, que nous avons dj vu auparavant, est dinverser les valeurs
sur chacun des canaux de couleurs. Il est dfini par la constante INVERT :
1

monCalque . blendMode = BlendMode . INVERT ;

Le rsultat se trouve la figure 18.27.

Figure 18.27 Inversion de la couleur de chaque pixel


La couleur dorigine du calque o le mode de fusion est appliqu na ici aucun effet sur
le rendu final. Il sagit galement dun mode de fusion peu courant.
claircir
Dans ce mode de fusion, les valeurs de canaux de couleurs de couleurs retenues sont
celles qui sont les plus claires entre le calque et larrire-plan. Il sagit du mode de
fusion oppos DARKEN. Voici sa constante :
1

monCalque . blendMode = BlendMode . LIGHTEN ;

Le rsultat se trouve la figure 18.28.


Ce dernier est galement moins claircissant que le mode de fusion ADD.
381

CHAPITRE 18. FILTRES ET MODES DE FUSION

Figure 18.28 claicissement de limage


Produit
Dans ce mode de fusion, les valeurs des canaux de couleurs du calque et de larrireplan sont multiplies entre elles puis sont normalises . La constante correspondante
est MULTIPLY :
1

monCalque . blendMode = BlendMode . MULTIPLY ;

Le rsultat se trouve la figure 18.29.

Figure 18.29 Multiplication des couleurs


Leffet produit est un assombrissement de larrire-plan. Ce mode de fusion proche de
DARKEN est toutefois plus radical dans lobscurcissement.
Incrustation
Le principe de fonctionnement de ce mode de fusion est plutt complexe. La constante
utilise est OVERLAY :
1

monCalque . blendMode = BlendMode . OVERLAY ;

Le rsultat se trouve la figure 18.30.


Proche de HARDLIGHT, ce mode de fusion est gnralement trs utilis. Le rendu final
est nanmoins lgrement diffrent de ce dernier dans les couleurs claires qui restent
quasi-intactes.
382

GLOSSAIRE DE MODES DE FUSION

Figure 18.30 Incrustation des couleurs


cran
La particularit de ce mode de fusion est de supprimer toute nuance de noir du
calque. Il ne reste ensuite plus que la couleur brute de celui-ci. La constante qui le
dfinit est SCREEN :
1

monCalque . blendMode = BlendMode . SCREEN ;

Le rsultat se trouve la figure 18.31.

Figure 18.31 Mode de fusion cran


Ce mode de fusion a donc pour effet dclaircir larrire-plan.
Soustraction
Comme vous vous en doutez, ce mode de fusion va soustraire les diffrents canaux de couleurs du calque ceux de larrire-plan. Celui-ci correspond la constante
SUBTRACT :
1

monCalque . blendMode = BlendMode . SUBTRACT ;

Le rsultat se trouve la figure 18.32.


Ce mode de fusion est donc loppos de ADD. Ainsi, il peut tre utilis pour crer des
transitions en utilisant cette fois un fondu dassombrissement.
383

CHAPITRE 18. FILTRES ET MODES DE FUSION

Figure 18.32 Soustration des couleurs

Les fusions de transparence


Transparence
Ce mode de fusion permet dappliquer les niveaux de transparence du calque
larrire-plan. Comme nous lavons dit, ce type de fusion ncessite de modifier galement le mode de fusion du conteneur. Voici donc comment raliser cette opration
grce la constante ALPHA :
1
2

this . blendMode = BlendMode . LAYER ;


monCalque . blendMode = BlendMode . ALPHA ;

Le rsultat se trouve la figure 18.33.

Figure 18.33 Transfert de la transparence


Je rappelle quil existe une autre mthode qui consiste dfinir des masques
que nous introduirons dans le chapitre suivant. Personnellement, je vous
conseillerai dutiliser les masques plutt que la fusion de transparence.

Suppression
Le principe ici est loppos de ALPHA. Ainsi, les niveaux de transparence du calque sont
maintenant soustraits de larrire-plan. Le nom de la constante correspondant est donc
384

GLOSSAIRE DE MODES DE FUSION


ERASE :
1
2

this . blendMode = BlendMode . LAYER ;


monCalque . blendMode = BlendMode . ERASE ;

Le rsultat se trouve la figure 18.34.

Figure 18.34 Suppression de lopacit


Ce mode de fusion est galement moins courant. vitez de lutiliser si vous
pouvez contourner le problme en ajustant lordre daffichage des diffrents
lments graphiques.

En rsum
Les filtres sont des effets qui sont applicables tout objet graphique.
Il existe neuf filtres en Actionscript, regroups dans le package flash.filters.
Chaque filtre est associ une classe, dont les proprits permettent de dcrire
leffet correspondant.
Ceux-ci sont ensuite ajouts la proprit filters de type Array de tout objet
DisplayObject.
Les modes de fusion permettent de dfinir la manire dont plusieurs lments
doivent tre fusionner lors de laffichage final.
Chaque lment hritant de DisplayObject dispose dun unique mode de fusion
dfini dans la proprit blendMode.
Tous ces modes de fusion sont dfinis laide des constantes de la classe BlendMode.

385

CHAPITRE 18. FILTRES ET MODES DE FUSION

386

Chapitre

19

Les masques
Difficult :
Pour le dernier chapitre thorique de cette partie sur laffichage, je vous propose de dcouvrir les masques ! Ce concept qui permet de cacher certaines zones dun objet affichage, est
spcifique lActionscript et la technologie Flash. Pour ceux qui utilisent des logiciels
de graphisme comme Gimp ou Photoshop, vous devriez vite cerner la chose. En revanche,
pour les autres, suivez attentivement ce que va tre dit ici car cette technique est vraiment
trs pratique et trs utilise.

387

CHAPITRE 19. LES MASQUES

Un masque. . . qui ne masque pas


Le principe des masques
Lorsque vous crez des lments graphiques, il est possible que vous ayez besoin disoler
une certaine partie de lobjet daffichage en question. Cest pourquoi vous aurez besoin
de sparer la zone visible de la zone cacher. Pour cela, nous utilisons ce quon appelle
des masques !
Quest-ce quun masque ?

Un masque est un lment graphique comme un autre. On retrouve alors des masques
de type Shape, Sprite ou encore Bitmap. Celui-ci sert alors dlimiter la zone visible
dun autre objet daffichage, dfinie par lopacit du masque.
Pour bien comprendre cette notion, je vous propose la figure 19.1 un petit schma.

Figure 19.1 Principe dutilisation des masques


Comme vous pouvez le voir, nous avons donc dfini un masque circulaire qui laisse
apparatre la photo uniquement lintrieur de celui-ci. Bien videmment, un masque
peut tre extrmement complexe et compos de diffrentes formes. Par exemple, nous
aurions pu suivre les courbes du serpent pour pouvoir lisoler du reste de limage.
Dans lexemple prcdent, comme dans la suite du chapitre, jutiliserai exclusivement des masques de couleur verte. Cela vous permettra de bien discerner
les masques des objets daffichage classiques .

Les masques en Flash


Dfinition du masque
Avant dappliquer un masque un objet visuel quelconque, il est ncessaire de dfinir
ces deux lments. Pour commencer, je vous suggre un exemple relativement simple.
Nous allons donc dmarrer par deux objets Shape o nous dessinerons des formes
basiques.
388

UN MASQUE. . . QUI NE MASQUE PAS


Dans ce chapitre, nous nous contenterons de dfinir des masques dessins
grce aux mthodes de la classe Graphics. Toutefois, le principe avec des
images bitmap est strictement identique. Il faudra nanmoins prendre en
compte le canal alpha, comme nous le verrons dans la suite du chapitre.
Voici donc nos deux lments monObjet et masque contenant respectivement un rectangle orange et un cercle vert :
1
2
3
4

var monObjet : Shape = new Shape () ;


var masque : Shape = new Shape () ;
this . addChild ( monObjet ) ;
this . addChild ( masque ) ;

5
6
7
8

monObjet . graphics . beginFill ( 0xFF8800 ) ;


monObjet . graphics . drawRect (0 , 0 , 100 , 100 ) ;
monObjet . graphics . endFill () ;

9
10
11
12

masque . graphics . beginFill ( 0x00FF00 ) ;


masque . graphics . drawCircle ( 50 , 50 , 50 ) ;
masque . graphics . endFill () ;

Nous avons ici plac lobjet masque au premier plan, ce qui donne la figure 19.2.

Figure 19.2 Lobjet et son masque


Lorsque vous dfinissez un masque avec les mthodes de la classe Graphics,
seuls les remplissages sont utiliss pour dfinir le masque. Les lignes seront
alors tout simplement ignores.
Lobjectif consiste donc maintenant dfinir lobjet de couleur verte comme masque
pour llment monObjet.
Une proprit mask
En fait, la notion de masque est lie tout objet visuel, cest--dire tout objet de
la classe DisplayObject ou plutt dune de ses sous-classes. Nous avons dj vu
quune classe peut possder un attribut delle-mme ; la classe DisplayObject est justement lune delles. En effet, celle-ci possde une proprit nomme mask de type
DisplayObject !
Ainsi, avec les objets de type Shape dclars prcdemment, il est possible de faire
ceci :
389

CHAPITRE 19. LES MASQUES


1

monObjet . mask = masque ;

Dans cette instruction, nous passons bien lobjet masque la proprit mask de llment
monObjet. Si vous relancez alors lexcution du projet, vous verrez la magie soprer
(voir figure 19.3).

Figure 19.3 Effet du masque sur lobjet


Comme vous pouvez le constater, le masque nest maintenant plus visible.
Cest pourquoi, linstruction this.addChild(masque) est en ralit facultative. Toutefois, si vous najoutez pas le masque la liste daffichage, celui-ci
ne sera alors pas affect par les ventuelles transformations du conteneur.
Pour viter tout problme, je vous conseille donc de lajouter chaque fois
la liste daffichage.
Pour finir, veuillez noter quil est possible de supprimer le masque dun objet simplement en dfinissant sa proprit mask null.

Niveaux de transparence multiples


Prsentation du concept
Comme nous lavons vu prcdemment, nous pouvons dfinir la forme dun masque
pour isoler certaines zones dun objet daffichage. Toutefois, il est galement possible
de dfinir la transparence de celui-ci en grant lopacit du masque. Rien ne nous
empche alors dutiliser des niveaux de transparence multiples. Pour illustrer
cela, je vous propose la figure 19.4 un exemple de masque plusieurs niveaux de
transparence.

Figure 19.4 Principe des niveaux de transparence multiples


Comme le montre lillustration prcdente, lobjet daffichage adapte donc sa transparence lopacit du masque qui lui est associ. Nous verrons alors quil est possible
390

NIVEAUX DE TRANSPARENCE MULTIPLES


dutiliser des dgrads pour dfinir un masque ou bien utiliser directement une image
bitmap dont le format supporte la transparence.

Place au code
Cration du masque
Pour dfinir diffrents niveaux de transparence, il est ncessaire de jouer avec
lopacit des remplissages. Je suggre alors que nous ralisions un masque compos de
trois disques qui se superposent partiellement. Voici le code que je vous propose pour
faire cela :
1
2
3
4
5
6
7
8
9
10
11
12
13
14

// Objet masquer
monObjet . graphics . beginFill ( 0xFF00FF ) ;
monObjet . graphics . drawRect (0 , 0 , 160 , 150 ) ;
monObjet . graphics . endFill () ;
// Masque
masque . graphics . beginFill ( 0x00FF00 , 0 . 5 ) ;
masque . graphics . drawCircle ( 80 , 50 , 50 ) ;
masque . graphics . endFill () ;
masque . graphics . beginFill ( 0x00FF00 , 0 . 5 ) ;
masque . graphics . drawCircle ( 50 , 100 , 50 ) ;
masque . graphics . endFill () ;
masque . graphics . beginFill ( 0x00FF00 , 0 . 5 ) ;
masque . graphics . drawCircle ( 110 , 100 , 50 ) ;
masque . graphics . endFill () ;

Nous avons donc ici ralis un masque compos de trois niveaux de transparence diffrents comme vous pouvez le voir la figure 19.5.

Figure 19.5 Un masque plusieurs niveaux de transparence

Mise en place du masque


Redfinissons maintenant la proprit mask de monObjet comme nous avons appris
le faire :
1

monObjet . mask = masque ;

391

CHAPITRE 19. LES MASQUES


Vous serez alors surpris de dcouvrir que ce masque ne fonctionne pas comme nous
lavions prvu, mais ragit comme si nous avions laiss une opacit maximale pour nos
remplissages. Regardez plutt la figure 19.6.

Figure 19.6 Mauvaise application dun masque plusieur niveaux de transparence


En ralit, pour pouvoir grer la transparence dun masque, nous devons
utiliser une mise en cache sous forme de bitmap. Llment graphique est
alors gr comme sil sagissait dune image bitmap en tenant compte du
niveau de transparence de chacun de ses pixels.

Le cache bitmap
Tout objet de type DisplayObject possde une proprit nomme cacheAsBitmap.
Celle-ci permet dactiver la mise en cache sous forme de bitmap , en la dfinissant tout simplement true. Habituellement, les objets daffichage sont manipuls
par le lecteur Flash comme sil sagissait dobjets vectoriels, ce qui donne de bonnes
performances la plupart du temps, mais implique quelques limitations, comme celle
que nous venons de rencontrer. Lorsquun objet daffichage est mis en cache sous
forme de bitmap, il est dabord rendu sous forme dimage contenant des pixels, puis
manipul par le lecteur Flash. Cela nous permet donc deffectuer des oprations plus
complexes (comme les masques plusieurs niveaux de transparence). Ainsi, il nous faut
activer ce cache sur le masque, mais galement sur lobjet auquel il est appliqu. Voici
comment procder pour appliquer le masque lobjet :
1
2
3

monObjet . cacheAsBitmap = true ;


masque . cacheAsBitmap = true ;
monObjet . mask = masque ;

Cette fois, vous verrez apparatre les diffrents niveaux de transparence tels quils ont
t dfinis durant la cration du masque. Nous obtenons la figure 19.7.
Cette mise cache est galement ncessaire lorsquon travaille avec des objets
de type Bitmap. Le format dimage choisi doit nanmoins utiliser un canal
alpha, comme cest le cas des formats GIF ou PNG. La transparence est
alors utilise pour dfinir le masque partir de cette image.
392

EXERCICE : UNE LAMPE TORCHE

Figure 19.7 Application correcte dun masque plusieurs niveaux de tranparence


Mettre un objet daffichage en cache bitmap a un impact sur les performances : ainsi, il est plus rapide de dplacer lobjet en cache bitmap, mais
les transformations comme la rotation ou le redimensionnement ralentissent
lapplication de faon significative. Pour rsumer, si vous voulez afficher un
grand nombre dobjets qui se dplacent, vous pouvez amliorer les performances de votre application en activant la mise en cache bitmap, condition
de ne pas leur appliquer de transformations.

Exercice : une lampe torche


Pour terminer ce chapitre, nous allons raliser un petit exercice ensemble. Nous allons
crer une lampe torche partir de deux images et dun masque. Cet exercice ne comporte aucune difficult, contentez-vous uniquement de suivre ces diffrentes tapes avec
moi.

Prparation des images


Rue de nuit
Pour commencer, je vous invite crer un dossier nomm images o nous placerons
nos deux images. Dans un premier temps, nous aurons besoin de limage dune rue
sombre qui servira de fond pour notre projet. Voici la figure 19.8 limage que jai
nomme RueSombre.png .
Cette image sera ainsi notre rue lorsquelle nest pas claire par la lampe torche. Nous
viendrons donc ajouter une partie lumineuse par dessus pour simuler leffet dune lampe
torche.
Rue claire par la lampe
Lorsque notre lampe torche passera sur une zone, celle-ci sera claire presque comme en
plein jour. Nous aurons alors besoin dune seconde image de cette mme rue, mais cette
fois beaucoup plus lumineuse. Voici donc notre seconde image RueEclairee.png
(figure 19.9).
393

CHAPITRE 19. LES MASQUES

Figure 19.8 RueSombre.png

394

EXERCICE : UNE LAMPE TORCHE

Figure 19.9 RueEclairee.png

395

CHAPITRE 19. LES MASQUES


La lampe torche nagissant que sur une certaine partie de la rue, cest cette image qui
subira leffet du masque que nous crerons juste aprs.
Chargement des images
En premier lieu, nous allons importer nos images dans notre animation Flash. Pour
cela, nous crerons deux variables de type Class que nous appellerons RueSombre et
RueEclairee comme vous avez appris le faire. Voici toutefois le code correspondant
pour ceux qui auraient dj oubli :
1
2
3
4
5

// Chargement des images


[ Embed ( source = ' images / RueSombre . png ') ]
private var RueSombre : Class ;
[ Embed ( source = ' images / RueEclairee . png ') ]
private var RueEclairee : Class ;

Noubliez pas dajouter les images dans le dossier de votre projet pour que
celui-ci puisse compiler. Si jamais vous navez pas plac les images dans un
dossier images, pensez alors mettre jour les liens ci-dessous.

Mise en place des images


L encore, il ny a aucune difficult pour la mise en place des images. La seule chose
vrifier est de placer linstance de la classe RueEclairee par dessus celle de la classe
RueSombre. Sinon, vous ne verrez absolument rien dans le rendu final de lanimation.
Voici ce que je vous propose de faire :
1
2
3
4
5

// Mise en place des images


var maRueSombre : Bitmap = new RueSombre () ;
var maRueEclairee : Bitmap = new RueEclairee () ;
this . addChild ( maRueSombre ) ;
this . addChild ( maRueEclairee ) ;

Mise en place du masque


prsent, nous allons nous occuper du masque que nous appliquerons limage de
la rue claire. Cela devrait donc donner au final un effet de lampe torche, que vous
pourrez dplacer pour clairer la zone de la rue que vous souhaiterez.
Prparation du dgrad
La premire tape est la prparation du dgrad qui nous servira tracer notre masque.
Voici donc le code suggr :
396

EXERCICE : UNE LAMPE TORCHE


1
2
3
4
5
6

// Pr paration du d grad
var couleurs : Array = [ 0x00FF00 , 0x00FF00 ];
var alphas : Array = [1 , 0 ];
var ratios : Array = [ 192 , 255 ];
var matrix : Matrix = new Matrix () ;
matrix . create GradientBox ( 200 , 200 , 0 , -100 , - 100 ) ;

Ce quil est important de noter, cest que nous utiliserons une seule couleur o lopacit
diminuera sur les bords pour donner un effet dattnuation de la lumire. Nous voulons
galement un dgrad rapide sur lextrieur de la forme, cest pourquoi nous avons
augment la premire valeur du tableau ratios.
Cration de la lampe
Nous pouvons maintenant dessiner la forme du masque dans un objet de type Sprite.
Nous allons donc dfinir un remplissage dgrad, puis nous tracerons un cercle pour
reprsenter la forme du faisceau de lumire sortant de la lampe. Voici comment raliser
ceci :
1
2
3
4
5
6

// Cr ation de la lampe
var lampe : Sprite = new Sprite () ;
lampe . graphics . beginGradientFill ( GradientType . RADIAL , couleurs ,
alphas , ratios , matrix ) ;
lampe . graphics . drawCircle (0 , 0 , 100 ) ;
lampe . graphics . endFill () ;
this . addChild ( lampe ) ;

La figure 19.10 vous montre quoi ressemble le masque nous allons utiliser.

Figure 19.10 Aperu du masque

Application du masque
Le masque ralis prcdemment va nous permettre dafficher limage de la rue claire
uniquement dans la zone o la lampe pointe. Pour faire cela, nous allons dfinir linstance lampe comme masque pour lobjet maRueEclairee. Nous allons donc procder
comme nous avons appris le faire :
397

CHAPITRE 19. LES MASQUES


1
2
3
4

// Mise en place du masque


maRueEclairee . cacheAsBitmap = true ;
lampe . cacheAsBitmap = true ;
maRueEclairee . mask = lampe ;

Nous avons prsent ralis leffet souhait. Pour donner un peu plus dintrt ce
projet, nous allons animer celui-ci.
Animation de la lampe
Pour animer le masque, nous allons utiliser la mthode startDrag() de la classe
Sprite. En indiquant son paramtre true, on impose lobjet en question de coller la position de la souris. Ainsi, notre lampe va suivre les mouvements de la souris,
pour imiter les gestes du poignet. Voici donc comment procder :
1
2

// Animation de la lampe
lampe . startDrag ( true ) ;

Projet final
Le rendu
Nous avons maintenant termin cet exercice sur les masques. Je vous propose la figure
19.11 un aperu de lanimation finale.
Le code complet
Enfin, pour vous aider avoir une vision densemble de ce que nous venons de raliser
ensemble, voici ci-dessous lintgralit du code de ce projet :
1
2
3
4
5
6
7
8

package
{
import
import
import
import
import
import

flash . display . Sprite ;


flash . display . Shape ;
flash . display . Bitmap ;
flash . events . Event ;
flash . geom . Matrix ;
flash . display . GradientType ;

9
10
11
12
13
14
15
16
17

398

/* *
* ...
* @author Guillaume
*/
public class Main extends Sprite
{
// Chargement des images
[ Embed ( source = ' images / RueSombre . png ') ]

EXERCICE : UNE LAMPE TORCHE

Figure 19.11 Rendu final de lexercice

399

CHAPITRE 19. LES MASQUES


private var RueSombre : Class ;
[ Embed ( source = ' images / RueEclairee . png ') ]
private var RueEclairee : Class ;

18
19
20
21

public function Main () : void


{
if ( stage ) init () ;
else addEventListener ( Event . ADDED_TO_STAGE , init ) ;
}

22
23
24
25
26
27

private function init ( e : Event = null ) : void


{
removeEventListener ( Event . ADDED_TO_STAGE , init ) ;

28
29
30
31

// Mise en place des images


var maRueSombre : Bitmap = new RueSombre () ;
var maRueEclairee : Bitmap = new RueEclairee () ;
this . addChild ( maRueSombre ) ;
this . addChild ( maRueEclairee ) ;

32
33
34
35
36
37

// Pr paration du d grad
var couleurs : Array = [ 0x00FF00 , 0x00FF00 ];
var alphas : Array = [1 , 0 ];
var ratios : Array = [ 192 , 255 ];
var matrix : Matrix = new Matrix () ;
matrix . createGradientBox ( 200 , 200 , 0 , -100 , - 100 ) ;

38
39
40
41
42
43
44

// Cr ation de la lampe
var lampe : Sprite = new Sprite () ;
lampe . graphics . beginGradientFill ( GradientType .
RADIAL , couleurs , alphas , ratios , matrix ) ;
lampe . graphics . drawCircle (0 , 0 , 100 ) ;
lampe . graphics . endFill () ;
this . addChild ( lampe ) ;

45
46
47
48
49
50
51

// Mise en place du masque


maRueEclairee . cacheAsBitmap = true ;
lampe . cacheAsBitmap = true ;
maRueEclairee . mask = lampe ;

52
53
54
55
56
57
58

59
60

61
62
63

400

// Animation de la lampe
lampe . startDrag ( true ) ;

EXERCICE : UNE LAMPE TORCHE

En rsum
Un masque est un objet daffichage qui sert dlimiter une zone visible dun
autre objet.
Lorsquon utilise la classe Graphics, seuls les remplissages sont pris en compte dans
les masques.
Le masque dun objet se dfinit par sa proprit mask.
Pour grer les niveaux de transparence, la proprit cacheAsBitmap du masque
et de lobjet doit tre passe true.
Pour supprimer le masque dun objet, sa proprit mask doit tre redfinie la
valeur null.

401

CHAPITRE 19. LES MASQUES

402

Chapitre

20

TP : Mauvais temps
Difficult :
Aprs ces trois longues parties plutt thoriques, il est temps de passer un peu la pratique !
Au cours de ce TP, vous aurez donc loccasion de revenir sur lensemble des notions que vous
avez vues jusqu prsent. tant donn la quantit de choses que vous avez d assimiler
jusqu maintenant, il est normal que vous ayez quelques difficults. Ne soyez donc pas
gns daller relire un chapitre ou deux qui vous ont sembl flous la premire lecture.
Toutefois, vous tes parfaitement en mesure de russir ce TP, cest pourquoi, je vous invite
fortement essayer par vous-mmes avant daller voir directement la correction.

403

CHAPITRE 20. TP : MAUVAIS TEMPS

Le cahier des charges


Lobjectif du chapitre
Le projet
Lobjectif du chapitre est de concevoir une animation reprsentant une chute de neige !
Pour obtenir un rendu un peu plus raliste, nous ajouterons galement quelques petits
dtails que je vous prsenterais dans la suite de ce TP. Avant de vous en dire plus, je
vous propose la figure 20.1 un petit aperu de lanimation que nous obtiendrons la
fin de ce chapitre.

Figure 20.1 Aperu de lanimation Mauvais temps .


Comme vous pouvez le voir, nous allons crer un certain nombre de flocons que nous
animerons afin de donner lillusion dune chute de neige. Nous ajouterons galement
une image de fond ainsi quun masque pour cacher les flocons derrire la branche au
premier plan. Par ailleurs, vous avez peut tre remarqu que les bords de limage ont
t assombris afin de mettre en valeur le centre de limage.
Bien videmment, votre but est dobtenir un rendu le plus proche possible
du mien. Toutefois, il est impossible que vous obteniez exactement la mme
chose. Lobjectif est de pratiquer et darriver un rsultat convenable et non
de reproduire exactement la mme image. Ne passez donc pas des jours
tenter dobtenir des flocons quasi identiques ceux prsents juste au-dessus.
Sachez quil y a des dizaines de faons diffrentes de raliser une telle animation. Je vous
prsenterais donc ici la mthode que jai choisie, mais nayez pas peur si la votre est
diffrente. Avant de vous lancer tte baisse, lisez bien toutes les consignes et pr-requis,
sans quoi vous narriverez certainement pas au bout !
404

LE CAHIER DES CHARGES


Intrt du projet
Ce projet a t choisi pour diverses raisons que voici :
Tout dabord, il sagit dune animation trs rpandu en Flash et que beaucoup de
dbutants dsirent raliser.
Dans ce projet, nous allons utiliser la quasi-totalit des connaissances acquises jusqu
prsent savoir : variables, conditions, boucles, fonctions, tableaux, classes ,
Programmation Oriente Objet et quasiment tout ce qui est li laffichage.
Enfin, cette animation ne ncessite pas normment de lignes de code, ce qui est
plutt favorable pour lun de vos premiers TP.
Bien entendu, nous allons dtailler davantage la manire de procder pour concevoir
ce projet.

Le travail raliser
Pour raliser cette animation, je vous invite procder pas pas. Cest pourquoi, je
vous ai prsent les diffrentes tapes de la conception de ce projet.
Cration de laspect dun flocon
La premire tape va consister dessiner un flocon. Vous avez dj toutes les connaissances pour parvenir dessiner celui-ci, vous devriez donc y arriver sans problme. Il
est possible de raliser des formes de flocons extrmement complexes, nanmoins un
simple disque fera trs bien laffaire. Le fait quil y aura des milliers de flocons dans
notre future animation devrait faire natre des ides dans votre esprit quant la manire de les concevoir . Je nen dis pas plus, vous de rflchir dores et dj, la
meilleure faon de faire !
La gnration des flocons
Ensuite, vous allez devoir gnrer lensemble de vos flocons que nous rutiliserons
linfini. Une fois gnr, chaque flocon devra tre positionn alatoirement lcran. Il
vous faudra galement dfinir alatoirement son aspect ainsi que sa vitesse de chute.
Pensez galement que vous pouvez donner de la profondeur votre scne, sachant que
les flocons les plus gros seront au premier plan et les plus rapides de notre point de
vue.
Lanimation des flocons
Tout ce qui concerne lanimation sera regroup lintrieur dune mthode qui sera
appele intervalles rguliers grce la fonction setInterval(). lintrieur de cette
mthode, vous ferez lensemble des modifications ncessaires lanimation des flocons.
Vous pourrez ainsi mettre jour la position de chaque flocon, et ventuellement, rini405

CHAPITRE 20. TP : MAUVAIS TEMPS


tialiser un flocon sorti de la scne. Cette fonction sera donc appele rgulirement et,
linfini, se chargera ainsi de lanimation de la scne.
Cest un peu prmatur puisquil sagit de lobjet du prochain chapitre, mais vous
utiliserez pour cela ce quon appelle une fonction de rappel. Sans plus dexplications,
voici comment utiliser cette fonction setInterval() :
1

var monInterval : uint = setInterval ( maMethode , intervalle ) ;

Dans linstruction prcdente, maMethode reprsente une mthode, donc de type Function,
et intervalle correspond au temps espaant deux excutions conscutives de la fonction prcdente.

Association des diffrents lments graphiques


Lorsque que toute la gestion des flocons aura t termine, vous pourrez alors passer
la composition de la scne finale. Vous devrez donc ajouter limage de fond et le
masque la scne. Vous pourrez galement tenter de crer cet effet dassombrissement
des bords de la scne en tant imaginatif. Cette tape devrait normalement se drouler
relativement bien si vous tre parvenu jusque l !

Les images
Enfin, je vous suggre de tlcharger les deux images dont vous aurez besoin pour
raliser ce TP (voir les figures 20.2 et 20.3). Il y a donc limage de fond intitule
Paysage.png ainsi que le masque nomm Masque.png .

Figure 20.2 Paysage.png

406

LA CORRECTION

Figure 20.3 Masque.png

La correction
La structure du programme
Avant de nous lancer tte baisse dans les lignes de code, je vais vous prsenter un peu
la manire dont jai conu et organis le code au sein du projet. Si vous avez ralis ce
projet par vous-mme, il est probable que vous nayez pas structur votre projet de la
mme faon. Je rappelle quil ny a pas quune seule et unique manire de concevoir
une telle animation.
La figure 20.4 vous montre comment jai procd pour programmer ce TP.
Ainsi, dans lorganisation prcdente, nous avons divis le code en trois classes diffrentes :
La classe Flocon est celle qui va principalement vous permettre de dessiner un flocon.
Elle hrite donc de Shape pour avoir accs aux mthodes de la classe Graphics. Vous
pouvez galement associer cette classe un attribut _vitesse qui correspond la
vitesse de chute du flocon et qui lui est donc propre.
Ensuite, nous avons la classe Neige qui hrite de Sprite et est donc un conteneur.
Elle va donc nous permettre de gnrer et danimer lensemble des flocons.
Enfin, notre classe principale va nous servir composer la scne finale laide de
limage de fond, du masque et dun dernier objet que nous crerons et qui servira
assombrir les bords de la scne.
Dans la suite de la correction de ce TP, nous allons donc dtailler lensemble de ses
classes en partant de la classe Flocon pour aller vers la classe principale.
407

CHAPITRE 20. TP : MAUVAIS TEMPS

Figure 20.4 La structure du projet telle quelle est dfinie dans la correction

La classe Flocon
Cration de la classe
La premire classe que nous allons crer est la classe Flocon ! Voici donc la structure
de base de cette classe :
1
2
3

package
{
import flash . display . Shape ;

public class Flocon extends Shape


{
public function Flocon ()
{
super () ;

5
6
7
8
9
10

11
12

13
14
15

Celle-ci permet tout dabord de crer le visuel du flocon. Pour cela, nous utiliserons
les mthodes de la classe Graphics puisque notre classe hrite de Shape. Rien de
plus facile maintenant pour vous, il suffit de tracer un disque blanc lintrieur du
constructeur de la manire suivante :
408

LA CORRECTION
1
2

this . graphics . beginFill ( 0xFFFFFF ) ;


this . graphics . drawCircle (0 , 0 , 1 . 5 ) ;

Sachant que nos flocons ne tomberont pas tous la mme vitesse, nous allons donc
crer un attribut _vitesse pour retenir celle-ci :
1

private var _vitesse : Number ;

Enfin, noubliez pas dinitialiser cet attribut et de lui associer des accesseurs, que nous
ne dtaillerons pas ici. Jetez simplement un coup dil au code complet de cette classe
qui, soit dit entre nous, est plutt succinct.

La classe Neige
Cration de la classe
prsent, nous allons nous occuper de la classe Neige qui sera donc notre conteneur
pour lensemble des flocons. Pour commencer, je vous invite donc crer une nouvelle
classe si ce nest dj fait. lintrieur, nous aurons besoin des trois constantes que jai
nomm LARGEUR_SCENE, HAUTEUR_SCENE et NOMBRE_FLOCONS. Pour faciliter la suite,
jai dj fait lintgralit des importations ainsi que la mise en place de la structure
globale de la classe. Voici donc notre classe Neige, prte tre remplie :
1
2
3
4
5
6

package
{
import
import
import
import

flash . display . Sprite ;


flash . filters . BlurFilter ;
flash . filters . BitmapFilterQuality ;
flash . utils .*;

public class Neige extends Sprite


{
private const LARGEUR_SCENE : int = 480 ;
private const HAUTEUR_SCENE : int = 320 ;
private const NOMBRE_FLOCONS : int = 3000 ;

8
9
10
11
12
13

public function Neige ()


{
super () ;
// G n ration des flocons
}

14
15
16
17
18
19
20
21
22
23

24

public function animerFlocons () : void


{
// Animation des flocons
}

25
26

409

CHAPITRE 20. TP : MAUVAIS TEMPS


Gnration des flocons
Nous allons ici nous intresser la cration des flocons et leur mise en place sur la
scne au dmarrage de lanimation. Pour commencer, nous allons crer nos flocons en
utilisant un tableau de Flocon de type Array. Ce tableau devra tre accessible depuis
la fonction animerFlocons(), cest pourquoi, jai dcid de crer un nouvel attribut
nomm MesFlocons :
1
2

// Tableau de Flocon
private var mesFlocons : Array ;

Dans ce paragraphe, nous nous occuperons de la gnration des flocons. Plaons-nous


donc lintrieur du constructeur de la classe Neige. Commenons tout de suite par
initialiser notre tableau Array en dfinissant sa taille NOMBRE_FLOCONS dfini juste
avant :
mesFlocons = new Array () ;

prsent, nous devons instancier nos flocons et leur apporter quelques modifications
un par un. Il se trouve que les boucles sont justement trs recommandes pour parcourir
les lments dun tableau :
1
2
3

for ( var i : uint = 0 ; i < NOMBRE_FLOCONS - 1 ; i ++) {


// Cr ation et modification de chaque flocon
}

Nous pouvons maintenant instancier nos flocons, les uns aprs les autres :
mesFlocons . push ( new Flocon () ) ;

Lors du dmarrage de lanimation, il serait prfrable que les flocons soient rpartis
alatoirement sur lcran. Nous allons donc modifier la position horizontale et la position verticale en utilisant la mthode random() de la classe Math. Voici comment
raliser cette opration :
1
2
3

// Placement al atoire des flocons sur l ' cran


mesFlocons [ i ]. x = Math . random () * LARGEUR_SCENE ;
mesFlocons [ i ]. y = Math . random () * HAUTEUR_SCENE ;

Pour donner une impression de profondeur notre scne, nous allons modifier laspect
de nos flocons ainsi que leur vitesse. Pour cela, nous allons dfinir une variable aspect
qui reprsentera la taille du flocon, mais galement sa distance lcran, le zro
correspondant une distance infinie, cest--dire loin de lcran. tant donn quavec
la distance, la vitesse de chute des flocons semble diminuer galement, nous rutiliserons cette variable pour dfinir la vitesse du flocon. Voici le code correspondant ces
manipulations :
1
2
3
4

// D finition d ' un aspect al atoire


var aspect : Number = Math . random () * 1 . 5 ;
// Modification de l ' aspect du flocon
mesFlocons [ i ]. scaleX = aspect ;

410

LA CORRECTION
5
6
7
8

mesFlocons [ i ]. scaleY = aspect ;


mesFlocons [ i ]. alpha = aspect ;
// Modification de la vitesse du flocon
mesFlocons [ i ]. vitesse = 2 * ( aspect + Math . random () ) ;

Suivant la distance du flocon lcran, celui-ci sera galement plus ou moins net. Nous
allons donc rutiliser notre variable aspect pour crer un filtre de flou, simulant la
profondeur de champ de la camra. Pour accentuer cet effet de profondeur, jai utilis
une formule mathmatique avec des puissances. Je vous donne directement le code
correspondant :
1
2
3
4
5
6
7

// G n ration du filtre
var flou : BlurFilter = new BlurFilter () ;
flou . blurX = Math . pow ( 10 * aspect , 4 ) / 10000 ;
flou . blurY = Math . pow ( 10 * aspect , 4 ) / 10000 ;
flou . quality = BitmapFilterQuality . MEDIUM ;
// Application du filtre au flocon
mesFlocons [ i ]. filters = new Array ( flou ) ;

Enfin, il ne nous reste plus qu ajouter notre flocon la liste daffichage de la classe
Neige :
1

this . addChild ( mesFlocons [ i ]) ;

La gnration des flocons est maintenant termine et notre application est prte tre
anime ! Pour cela, noubliez pas de mettre linstruction suivante lextrieur de la
boucle :
1

var monInterval : uint = setInterval ( animerFlocons , 40 ) ;

Lanimation des flocons


Dans ce paragraphe, nous allons nous occuper de toute la partie animation du programme. Nous travaillerons donc lintrieur de la mthode animerFlocons() qui, je
le rappelle, sera excute toutes les 40 millisecondes grce la fonction setInterval().
Encore une fois, nous allons manipuler les flocons individuellement. Nous utiliserons
donc nouveau une boucle for :
1
2
3

for ( var i : uint = 0 ; i < mesFlocons . length ; i ++) {


// Mise jour de chaque flocon
}

Le principe de lanimation consiste modifier la position de chaque flocon. Pour faire


cela, nous utiliserons la proprit vitesse de la classe Flocon que nous viendrons
ajouter la position verticale du flocon. Voici comment il faut procder :
1

mesFlocons [ i ]. y += mesFlocons [ i ]. vitesse ;

Pour viter de crer des flocons linfini, nous allons rutiliser les flocons qui sont sortis
de la zone visible de lcran pour les renvoyer en haut de celui-ci. Vous vous en doutez
411

CHAPITRE 20. TP : MAUVAIS TEMPS


peut-tre, nous utiliserons une condition if en testant la valeur de la position verticale
dun flocon comme ceci :
1
2
3

if ( mesFlocons [ i ]. y > HAUTEUR_SCENE ) {


// R initialisation du flocon en haut de la sc ne .
}

lintrieur, nous pouvons alors remettre la position verticale du flocon zro et


ventuellement replacer alatoirement le flocon horizontalement :
mesFlocons [ i ]. x = Math . random () * LARGEUR_SCENE ;
mesFlocons [ i ]. y = 0 ;

1
2

Aussi surprenant que cela puisse paratre, nous avons prsent termin lanimation
des flocons !

La classe principale
Cration des objets daffichage
Nous voici de retour dans la classe principale ! Nous allons donc ici grer la mise en
place des diffrents lments lcran. Dans un premier temps, je vous propose dimporter les deux images externes, savoir Paysage.png et Masque.png que vous avez
d normalement tlcharger prcdemment. Voici comment jai ralis ceci :
1
2
3
4
5

// Pr paration des images


[ Embed ( source = ' images / Paysage . png ') ]
private var Paysage : Class ;
[ Embed ( source = ' images / Masque . png ') ]
private var Masque : Class ;

Jai donc utilis quatre lments diffrents pour composer la scne finale. Jai tout
dabord pris deux occurrences monPaysage et monMasque des images prcdentes. Ensuite jai instanci notre classe Neige qui contient lensemble des flocons de lanimation.
Enfin, jai cr une nouvelle variable nomme maVignette de type Shape. Celle-ci va
nous permettre de crer un effet de vignette , comme nous le verrons juste aprs.
Voil donc nos quatre objets :
1
2
3
4
5

// Cr ation des objets d ' affichage


var monPaysage : Bitmap = new Paysage () ;
var monMasque : Bitmap = new Masque () ;
var maNeige : Neige = new Neige () ;
var maVignette : Shape = new Shape () ;

Dans la suite, nous allons alors grer l interconnexion entre ces diffrents lments
pour aboutir au rendu final que vous avez vu en dbut de chapitre.
412

LA CORRECTION
Cration dun effet de vignette
Un effet de vignette est une technique qui permet de mettre en valeur ce qui se
trouve au centre dune image. En fait, cela consiste assombrir les bords et les angles
de limage. Pour faire cela, le plus simple est crer un dgrad elliptique, de couleur
blanche au centre et sombre lextrieur. Ainsi, par application dun mode de fusion,
le centre de limage se voit devenir plus lumineuse et ressort davantage. Voici donc
la figure 20.5 le vignettage que nous allons raliser.

Figure 20.5 Dgrad radial pour un effet de vignette


Pour raliser cet effet, nous allons crer un dgrad de type radial lintrieur dun
remplissage de forme rectangulaire. Pour commencer, nous nous occuperons des rglages du dgrad en termes de couleurs. Nous aurons donc un dgrad du blanc au
noir, comme vous pouvez le voir ci-dessous :
1
2
3
4

// Param trage du d grad


var couleurs : Array = [ 0xFFFFFF , 0x000000 ];
var alphas : Array = [1 , 1 ];
var ratios : Array = [ 96 , 255 ];

Ensuite, il nous faut gnrer la matrice permettant de contrler laspect gnral du


dgrad. Pour cela, nous allons donc crer un dgrad radial plus large que la taille
de la scne afin de ne pas avoir de noir absolu, puis nous recentrerons celui-ci. Voici
comment jai ralis ceci :
1
2
3
4
5
6
7
8

// Cr ation de la matrice de description


var matrix : Matrix = new Matrix () ;
var largeur : Number = 2 * LARGEUR_SCENE ;
var hauteur : Number = 2 * HAUTEUR_SCENE ;
var rotation : Number = 0 ;
var tx : Number = -0 . 5 * LARGEUR_SCENE ;
var ty : Number = -0 . 5 * HAUTEUR_SCENE ;
matrix . create GradientBox ( largeur , hauteur , rotation , tx , ty ) ;

413

CHAPITRE 20. TP : MAUVAIS TEMPS


Ltape suivante consiste alors tracer le remplissage correspondant la taille de la
scne :
1
2
3

// Trac du remplissage
maVignette . graphics . beginGradientFill ( GradientType . RADIAL ,
couleurs , alphas , ratios , matrix ) ;
maVignette . graphics . drawRect (0 , 0 , LARGEUR_SCENE , HAUTEUR_SCENE
);

Enfin, nous allons appliquer un mode de fusion de type multiplier qui va permettre
dassombrir les bords de limage en laissant le centre de celle-ci intact.
1
2

// Application du mode de fusion


maVignette . blendMode = BlendMode . MULTIPLY ;

Nous avons prsent lintgralit de nos lments graphiques quil va falloir agencer
les uns avec les autres pour obtenir le rendu final dsir.
Mise en place des lments lcran
Maintenant, nous devons ajouter chacun de nos lments la liste daffichage. Mis
part le masque qui ne sera pas visible, les objets daffichage doivent tre ajouts
dans un certain ordre. En arrire-plan, nous aurons donc limage de fond prsente
dans la variable monPaysage. Ensuite, nous placerons lobjet maNeige par-dessus qui
sera masqu par monMasque. Enfin, nous placerons maVignette au premier plan pour
que son mode de fusion sapplique tous les objets derrire elle. Voil donc lordre
respecter :
1
2
3
4
5

// Ajout des l ments la liste d ' affichage


this . addChild ( monPaysage ) ;
this . addChild ( monMasque ) ;
this . addChild ( maNeige ) ;
this . addChild ( maVignette ) ;

Pour finir, appliquez le masque lobjet maNeige :


1
2
3
4

// Application du masque
maNeige . cacheAsBitmap = true ;
monMasque . cacheAsBitmap = true ;
maNeige . mask = monMasque ;

a y est, cest termin ! Nous avons prsent fini lintgralit de cette animation qui
demandait quelques efforts, je vous laccorde.

Le code source complet


La classe Flocon
Flocon.as
414

LE CODE SOURCE COMPLET


1
2
3

package
{
import flash . display . Shape ;

public class Flocon extends Shape


{
private var _vitesse : Number ;

5
6
7
8

public function Flocon ()


{
super () ;
_vitesse = 0 ;
this . graphics . beginFill ( 0xFFFFFF ) ;
this . graphics . drawCircle (0 , 0 , 1 . 5 ) ;
}

9
10
11
12
13
14
15
16

public function get vitesse () : Number


{
return _vitesse ;
}

17
18
19
20
21

public function set vitesse ( value : Number ) : void


{
_vitesse = value ;
}

22
23
24
25
26

27
28
29

La classe Neige
Neige.as
1
2
3
4
5
6

package
{
import
import
import
import

flash . display . Sprite ;


flash . filters . BlurFilter ;
flash . filters . BitmapFilterQuality ;
flash . utils .*;

7
8
9
10
11
12
13
14

public class Neige extends Sprite


{
private const LARGEUR_SCENE : int = 480 ;
private const HAUTEUR_SCENE : int = 320 ;
private const NOMBRE_FLOCONS : int = 3000 ;
// Tableau de Flocon
private var mesFlocons : Array ;

15

415

CHAPITRE 20. TP : MAUVAIS TEMPS


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

public function Neige ()


{
super () ;
mesFlocons = new Array () ;
for ( var i : uint = 0 ; i < NOMBRE_FLOCONS - 1 ; i ++) {
// Cr ation et modification de chaque flocon
mesFlocons . push ( new Flocon () ) ;
// Placement al atoire des flocons sur l ' cran
mesFlocons [ i ]. x = Math . random () * LARGEUR_SCENE
;
mesFlocons [ i ]. y = Math . random () * HAUTEUR_SCENE
;
// D finition d ' un aspect al atoire
var aspect : Number = Math . random () * 1 . 5 ;
// Modification de l ' aspect du flocon
mesFlocons [ i ]. scaleX = aspect ;
mesFlocons [ i ]. scaleY = aspect ;
mesFlocons [ i ]. alpha = aspect ;
// Modification de la vitesse du flocon
mesFlocons [ i ]. vitesse = 2 * ( aspect + Math .
random () ) ;
// G n ration du filtre
var flou : BlurFilter = new BlurFilter () ;
flou . blurX = Math . pow ( 10 * aspect , 4 ) / 10000 ;
flou . blurY = Math . pow ( 10 * aspect , 4 ) / 10000 ;
flou . quality = BitmapFilterQuality . MEDIUM ;
// Application du filtre au flocon
mesFlocons [ i ]. filters = new Array ( flou ) ;
// Ajout du flocon la liste d ' affichage
this . addChild ( mesFlocons [ i ]) ;
}

44
45
46

var monInterval : uint = setInterval ( animerFlocons ,


25 ) ;

47
48
49
50
51
52
53
54
55
56
57
58
59

416

public function animerFlocons () : void


{
for ( var i : uint = 0 ; i < mesFlocons . length ; i ++) {
// Mise jour de chaque flocon
mesFlocons [ i ]. y += mesFlocons [ i ]. vitesse ;
if ( mesFlocons [ i ]. y > HAUTEUR_SCENE ) {
// R initialisation du flocon en haut de la
sc ne .
mesFlocons [ i ]. x = Math . random () *
LARGEUR_SCENE ;
mesFlocons [ i ]. y = 0 ;
}
}
}

LE CODE SOURCE COMPLET


}

60
61
62

La classe principale
Main.as
1
2
3
4
5
6
7
8
9

package
{
import
import
import
import
import
import
import

flash . display . Shape ;


flash . display . Sprite ;
flash . events . Event ;
flash . display . Bitmap ;
flash . geom . Matrix ;
flash . display . GradientType ;
flash . display . BlendMode ;

10
11
12
13
14
15
16
17
18
19
20

[ SWF ( width = " 480 " , height = " 320 " ) ]


public class Main extends Sprite
{
private const LARGEUR_SCENE : int = 480 ;
private const HAUTEUR_SCENE : int = 320 ;
// Pr paration des images
[ Embed ( source = ' images / Paysage . png ') ]
private var Paysage : Class ;
[ Embed ( source = ' images / Masque . png ') ]
private var Masque : Class ;

21
22
23
24
25
26

public function Main () : void


{
if ( stage ) init () ;
else addEventListener ( Event . ADDED_TO_STAGE , init ) ;
}

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

private function init ( e : Event = null ) : void


{
removeEventListener ( Event . ADDED_TO_STAGE , init ) ;
// Cr ation des objets d ' affichage
var monPaysage : Bitmap = new Paysage () ;
var monMasque : Bitmap = new Masque () ;
var maNeige : Neige = new Neige () ;
var maVignette : Shape = new Shape () ;
// Param trage du d grad
var couleurs : Array = [ 0xFFFFFF , 0x000000 ];
var alphas : Array = [1 , 1 ];
var ratios : Array = [ 96 , 255 ];
// Cr ation de la matrice de description
var matrix : Matrix = new Matrix () ;

417

CHAPITRE 20. TP : MAUVAIS TEMPS


var largeur : Number = 2 * LARGEUR_SCENE ;
var hauteur : Number = 2 * HAUTEUR_SCENE ;
var rotation : Number = 0 ;
var tx : Number = -0 . 5 * LARGEUR_SCENE ;
var ty : Number = -0 . 5 * HAUTEUR_SCENE ;
matrix . createGradientBox ( largeur , hauteur , rotation
, tx , ty ) ;
// Trac du remplissage
maVignette . graphics . beginGradientFill ( GradientType .
RADIAL , couleurs , alphas , ratios , matrix ) ;
maVignette . graphics . drawRect (0 , 0 , LARGEUR_SCENE ,
HAUTEUR_SCENE ) ;
Application du mode de fusion
maVignette . blendMode = BlendMode . MULTIPLY ;
// Ajout des l ments la liste d ' affichage
this . addChild ( monPaysage ) ;
this . addChild ( monMasque ) ;
this . addChild ( maNeige ) ;
this . addChild ( maVignette ) ;
// Application du masque
maNeige . cacheAsBitmap = true ;
monMasque . cacheAsBitmap = true ;
maNeige . mask = monMasque ;

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

63
64

65
66
67

418

Quatrime partie

Interaction et animation

419

Chapitre

21

Les vnements
Difficult :
Nous voici dans une nouvelle partie portant sur linteractivit et lanimation en Actionscript. Ces deux concepts sont troitement lis la notion dvnement qui est lobjet de
ce chapitre. Il sera malheureusement le plus thorique et le plus complexe de cette partie.
Une fois que vous aurez acquis les bases de la programmation vnementielle, les autres
chapitres seront beaucoup plus pratiques et faciles aborder.

421

CHAPITRE 21. LES VNEMENTS

Quest ce quun vnement ?


Introduction
Dans ce chapitre, nous allons aborder la programmation vnementielle. A linstar
de la POO, cette manire de programmer sinspire dlments du quotidien, savoir :
les vnements.
Attention, jen vois dj certains penser aux festivals de cet t : il ne sagit pas de
cela bien videmment ! Les vnements, tels que nous allons les voir, sont dfinis
comme des lments non prvisibles, gnralement dclench par un changement dtat
quelconque. Par exemple, dans la vie courante, nous pouvons citer :

Un rveil qui sonne.


Un accident de voiture.
Une panne de courant.
La rception dun fax.

Pour complter la dfinition prcdente, nous pourrions dire quil sagit dvnements
soudains qui surgissent lorsque lon ne sy attend pas. Dans lexemple du rveil, il est
vrai quon sattend forcment ce quil sonne, cependant, vous devez avouer que vous
tes toujours surpris lorsque ce dernier se met sonner !
En programmation, le principe est le mme. Dans le cas de lActionScript 3, nous
pourrions citer comme vnements :

Un clic laide de la souris.


Le dplacement du curseur de la souris.
Lenfoncement dune touche du clavier.
La fin de chargement dune image depuis un serveur.
Une erreur lors du chargement de cette image.

lapparition de lun des vnements, il est alors possible dexcuter des instructions
spcifiques, pour mettre jour laffichage par exemple. tant donn que nous ne savons
pas lavance quand ceux-ci se produiront, il serait possible, mais trs fastidieux,
dinclure des instructions au milieu de votre programme qui bouclent indfiniment
pour dtecter ces vnements : ctait la mthode avant lentre en scne du concept
de gestion des vnements, qui facilite grandement ce processus.
Pour introduire ce concept, nous allons maintenant faire une analogie en prenant lide
de la rception dun fax.

Un jour au bureau. . .
Aujourdhui, vous travaillez pour une grande entreprise de renomme internationale.
Votre compagnie dispose ainsi de diffrentes agences rparties sur plusieurs continents.
En tant que responsable produits, vous allez devoir prochainement prsenter un nouveau concept lensemble du groupe. Il est donc prvu que vous assistiez une runion
avec des collaborateurs de diverses agences. En revanche, les dtails pratiques tels que
lheure et lendroit de cette runion ne sont pas encore fixs.
422

QUEST CE QUUN VNEMENT ?


Fonction dcouteur
Monsieur Gumble, directeur dune agence nord-amricaine, a promis quil vous enverrait les informations concernant la runion daujourdhui par fax. Comme votre
habitude, ce matin-l vous arrivez au bureau lgrement en avance. Vous en profitez
alors pour sortir une feuille et commencez noter diffrentes choses dessus.
Machinalement, vous avez commenc anticiper et vous avez not les diffrentes tches
faire la rception de ce fameux fax : cela ressemble une fonction contenant une srie
dinstructions, non ? Cette fonction qui devra tre appele ds que vous recevrez le
fax est dsigne comme tant une fonction dcouteur.
En ActionScript 3, elle sera donc une fonction quelconque ou une mthode de classe
regroupant des instructions excuter lors de lapparition dun vnement. Gnralement, les actions qui en dcouleront dpendent de paramtres lis lvnement. Par
exemple, savoir quelle touche a t
 enfonce permettrait dexcuter des instructions
diffrentes suivant sil sagit dun A ou dun S .

couter un vnement
a y est ! Vous tes prts recevoir votre fax. Vous jetez rgulirement un coup dil
sur le tlcopieur qui se trouve dans le coin.
Attendre quun vnement survienne est appel couter un vnement. On coute
toujours sur un objet dsign comme tant la cible de lvnement. On dit galement
que cet objet dclenchera lvnement lorsque celui-ci surviendra. Ici, le tlcopieur
est la cible de lvnement qui se produira la rception dun fax.
En programmation, on coute un vnement particulier en renseignant une sorte de
signature , appele type dvnement, dcrite par une chane de caractres : il
est alors possible de distinguer un clic de souris du dplacement du curseur au-dessus
dun objet identique. couter un vnement quun objet sera susceptible de dclencher
consiste donc associer une fonction dcouteur un type dvnements tout
en ciblant cet objet. Ainsi, chaque fois que ledit objet dclenchera lvnement correspondant au type en question, la ou les fonctions dcouteur impliques seront
appeles.
Seul un objet peut faire apparatre un vnement. Nous couterons donc
toujours des vnements relatifs des objets (ici, notre tlcopieur).
Cependant, le fax narrive toujours pas et lennui pointe le bout de son nez. Vous
levez alors la tte et parcourez votre bureau du regard : vous apercevez un collgue et
vous remarquez que ce dernier semble galement attendre un fax devant la machine.
Toutefois, il est peu probable quil provienne de Monsieur Gumble. De la mme faon,
votre voisin neffectuera pas les mmes tches que vous aprs rception de son fax, sa
fonction dcouteur est donc probablement diffrente.
423

CHAPITRE 21. LES VNEMENTS


Il est possible quun vnement soit cout par plusieurs fonctions dcouteur mme si elles sont diffrentes. Elles seront toutes appeles lorsque lvnement sera dclench.

Lvnement
Aprs la pause djeuner, vous revenez votre poste pour poursuivre votre travail de la
matine. Vous navez alors pas le temps de vous asseoir quun fax arrive ! Vous regardez
celui-ci de plus prs, il sagit bien du fax de monsieur Gumble. Vous le parcourez donc
des yeux et voyez que celui-ci regorge dinformations. Vous y trouvez le nom de toutes
les personnes qui seront prsentes, lobjet de la runion, mais galement la date, lheure
et le lieu de la runion. a tombe bien, ce sont exactement les donnes quil vous
manquait !
Vous ressortez alors votre feuille puis commencez les rservations. Parmi les diffrentes
informations fournies dans le fax, vous en avez extrait celles qui vous taient utiles pour
pouvoir excuter les tches que vous vous tiez fixs. On dit que le fax reprsente
lvnement sous la forme dun objet qui contient diffrentes donnes sur ce qui sest
produit.
En programmation vnementielle , comme tout le reste en en Actionscript,
les vnements sont donc reprsents par des objets qui renferment galement des
informations concernant lvnement en question. De la mme faon, il est possible
dinterroger cette classe, pour pouvoir grer et traiter correctement ce dernier en
fonction de son type et de ses attributs. Ces objets sont tous issus de la classe Event,
dont nous reparlerons plus loin.

Les couteurs en POO


Nous allons prsent revenir et nous pencher plus srieusement sur les couteurs
et leur gestion. Comme nous lavons dit plus haut, les couteurs sont associs aux
objets. Ainsi, tout objet peut thoriquement utiliser les couteurs pour rpondre
aux vnements, une condition nanmoins : lobjet doit implmenter linterface
IEventDispatcher.

Linterface IEventDispatcher
Linterface IEventDispatcher dfinit donc le jeu de mthodes servant la gestion
des couteurs. Sans plus attendre, voici la figure 21.1 lensemble des dfinitions de
mthodes que propose cette interface.
Comme vous pouvez le voir, cette interface propose cinq dfinitions de mthodes pour
la gestion des couteurs. La mthode addEventListener() est celle que nous utiliserons le plus, sa signature complte est la suivante :
424

LES COUTEURS EN POO

Figure 21.1 Linterface IEventDispatcher


1

addEventListener ( type : String , listener : Function , useCapture :


Boolean = false , priority : int = 0 , useWeakReference : Boolean
= false ) : void

Nanmoins, dans un premier temps, nous allons laisser de ct les paramtres facultatifs. Ce qui nous donne donc :
1

addEventListener ( type : String , listener : Function ) : void

Avant de vous montrer un exemple dutilisation, nous allons revenir sur la notion
dcouteurs. Si vous tes pointilleux, vous aurez alors remarqu la prsence du mot anglais add dans le nom cette mthode, qui signifie ajout. Ainsi, lorsque nous utilisons
cette mthode nous ajoutons un nouvel couteur notre objet. En effet, il est possible
de dfinir plusieurs couteurs pour un mme objet et de pouvoir ainsi rpondre divers
vnements. Grce cela, il est donc possible dtre lcoute la fois dvnements
provenant de la souris et dautres provenant du clavier.
Tout comme il est possible dajouter des couteurs un objet, il est possible den
retrancher. Cest donc la mthode removeEventListener() qui sen charge, et voici
sa signature complte :
1

rem o v eE v en t Li stener ( type : String , listener : Function , useCapture :


Boolean = false ) : void

Nous retiendrons pour linstant cette mthode sous sa forme simplifi :


1

rem o v eE v en t Li stener ( type : String , listener : Function ) : void

Dans un premier temps, nous allons oublier les mthodes dispatchEvent() et willTrigger().
En revanche, vous pouvez noter la prsence de la mthode hasEventListener() qui
permet de vrifier si un couteur est enregistr auprs dun objet pour un type dvnement spcifique. Cette mthode renvoie donc un boolen.

La classe EventDispatcher
Comme nous lavons dit plus haut, cest linterface IEventDispatcher qui dfinit le
jeu de mthodes servant la gestion des couteurs. Nanmoins, cest lintrieur
de la classe EventDispatcher que le contenu de lensemble de ces mthodes est dfini.
Bien entendu, cette classe implmente linterface IEventDispatcher, et cest elle qui
va rellement servir de classe de base pour toute classe voulant distribuer des
425

CHAPITRE 21. LES VNEMENTS


vnements. Par hritage, cette classe permet donc tout objet dutiliser les mthodes
de linterface IEventDispatcher et dtre lcoute dvnements ; on dit alors que
lobjet devient une cible dvnements.
Ainsi, toutes les classe filles de EventDispatcher hritent donc de ces mthodes lies
la gestion des couteurs. linstar de nombreux objets, nous retrouvons parmi
elles la classe DisplayObject que nous avons dj vue. Donc, si vous vous souvenez
bien, lensemble des classes daffichage sont, par hritage, des sous-classes de la classe
EventDispatcher (voir figure 21.2).

Figure 21.2 Extrait de larbre dhritage des classes daffichage


Cela tombe bien, tous les lments de notre liste daffichage vont donc pouvoir rpondre
divers vnements. Nous verrons que les objets appartenant la liste daffichage
rpondent aux vnements dune manire assez spcifique : on appelle cela le flux
dvnements. Nous aborderons cette notion au cours de ce chapitre.

Mise en place dun couteur


Introduction aux fonctions de rappel
La thorie
En regardant la mthode addEventListener() de plus prs, vous vous apercevrez que
celle-ci dispose dun paramtre de type Function :
1

426

addEventListener ( type : String , listener : Function ) : void

MISE EN PLACE DUN COUTEUR


Dans ce cas, la fonction listener est ce quon appelle une fonction de rappel (ou
callback en anglais). Il sagit donc dune fonction, ou dune mthode, qui est passe
en paramtre une autre fonction. Ainsi, lintrieur de cette dernire, il est possible
de faire appel la fonction de rappel sa guide.
Quel est lintrt de cette fonction de rappel ? Nest-il pas plus simple de
dfinir les instructions directement dans la seconde fonction ?
Lintrt ici est justement de pouvoir se servir dune fonction sachant quon ne la
connat pas lavance. De cette manire, il est alors possible dexcuter des instructions dynamiquement sans avoir besoin de les dfinir directement. Le plus souvent, les
fonctions de rappel sont appels suite une condition, comme lapparition dun
vnement par exemple. En utilisant ce concept, vous pouvez ainsi crer une classe
et laisser lutilisateur la libert dexcuter les instructions quil souhaite sans quil
ait accs la classe elle-mme. Cela est extrmement pratique lorsquon conoit son
programme par hritage ou lorsque lon cre une bibliothque de classes.
Une fonction de rappel est une fonction appele lintrieur dune autre. Son utilisation et sa signature sont donc dfinies et figes lors de son appel. Ainsi, la dfinition
de la fonction de rappel, il est ncessaire dajouter les points suivants :
Le nombre et le type des paramtres.
Le type de la valeur renvoye.
Vous pouvez donc tout fait utiliser ce concept lintrieur de vos fonctions et ainsi
amliorer la r-utilisabilit de votre code.

Un exemple
Pour mieux comprendre cette notion, voici un exemple basique de fonction utilisant
une fonction de rappel suivant une condition :
1
2
3
4
5
6

function uneFonction ( condition : Boolean , fonction : Function ) : void


{
if ( condition ) {
fonction . call () ;
}
}

Et voici la dfinition de la fonction de rappel :


1
2
3
4

function fonctionDeRappel () : void


{
trace ( " Ceci est une fonction de rappel . " ) ;
}

427

CHAPITRE 21. LES VNEMENTS


Pour utiliser au mieux ce concept, je vous conseille de vous rendre sur la documentation officielle de la classe Function. Vous verrez notamment comment
vous servir de la mthode call() suivant les paramtres dfinies pour votre
fonction.

Documentation Function
B
Code web : 171723


Si vous souhaitez tester cet exemple, vous pouvez alors excuter linstruction suivante
aprs avoir dfini les deux fonctions prcdentes :
uneFonction ( true , fonctionDeRappel ) ;

Ce qui donne naturellement lexcution du code :


Ceci est une fonction de rappel .

Crer une fonction dcouteur


Lorsquon parle de gestion dvnements, les fonctions de rappel sont alors plus
communment appeles fonction dcouteur, comme nous lavons voqu plus haut.
La gestion de cette fonction est alors du ressort de la superclasse EventDispatcher.
Lors de la mise en place dun couteur, nous avons donc uniquement nous proccuper
de la dfinition de la fonction dcouteur.
Les fonctions dcouteur doivent donc rpondre aux exigences fixes par la classe
EventDispatcher. Voici donc la signature type dune fonction dcouteur :
1
2
3
4

function uneFonction ( event : Event ) : void


{
// Instructions ex cut es lors de l ' apparition d ' un v
nement de type donn
}

Le paramtre event renseigner ici est de type Event, cependant, dans la


pratique, il sagira plus gnralement dune sous-classe de cette dernire. La
classe utilise pour ce paramtre dpendra directement du type dvnement
spcifi lors de la mise en place de lcouteur.
Comme exemple, je vous propose cette fonction dcouteur qui pourrait servir la
gestion dvnements lis la souris :
1
2
3
4

function monEcouteur ( event : MouseEvent ) : void


{
trace ( " Vous avez cliqu sur la souris . " ) ;
}

Comme vous pouvez le voir ici, le paramtre de cette fonction est de type MouseEvent,
dont nous reparlerons ds le prochain chapitre. Il sagit donc dune sous-classe de la
428

MISE EN PLACE DUN COUTEUR


classe Event spcifique aux vnements gnrs par votre souris. Bien videmment,
cette classe aurait t diffrente sil sagissait dvnements provenant du clavier par
exemple.

Grer les couteurs dun objet


Ajouter un couteur
Comme vous laurez compris, pour ajouter un couteur un objet, nous aurons
besoin de la mthode addEventListener(). Parce que mieux vaut deux fois quune, je
vous rappelle lallure de la signature de cette dernire :
1

addEventListener ( type : String , listener : Function ) : void

prsent, vous savez donc comment dfinir la fonction passer en paramtre de cette
mthode. Quant au type dvnement, ici sous forme de String, celui-ci peut tre
renseign via les constantes dfinies lintrieur de la classe Event ou de lune de ses
sous-classes.
Encore une fois, lutilisation de ces constantes facilitent grandement la lisibilit et le
dbogage du code. Par exemple, la chane de caractres "click" peut tre remplace par lexpression MouseEvent.CLICK. De cette manire, le code est plus clair. Par
ailleurs, le compilateur peut alors dtecter une ventuelle faute de frappe, ce qui nest
pas le cas pour la chane en brut .
La constante MouseEvent.CLICK permet de faire rfrence aux vnements gnrs par
le clic de votre souris. En outre, nous sommes capables de terminer la mise en place
de notre couteur. Voici donc comment enregistrer lvnement monEcouteur() dfinie
plus haut lobjet stage :
1

stage . addEventListener ( MouseEvent . CLICK , monEcouteur ) ;

Si vous le dsirez, vous pouvez prsent tester le code complet suivant :


1
2
3
4
5

function monEcouteur ( event : MouseEvent ) : void


{
trace ( " Vous avez cliqu sur la sc ne principale . " ) ;
}
stage . addEventListener ( MouseEvent . CLICK , monEcouteur ) ;

Une fois lapplication lance et si vous cliquez plusieurs reprise lintrieur de votre
scne, vous verrez apparatre ceci :
Vous avez cliqu sur la sc ne principale .
Vous avez cliqu sur la sc ne principale .
Vous avez cliqu sur la sc ne principale .

429

CHAPITRE 21. LES VNEMENTS


Dans cet exemple, nous avons enregistr lcouteur auprs de lobjet stage,
cest--dire la scne principale. Nous aurions trs bien pu le faire pour notre
classe Main de type Sprite. Cependant, si vous navez rien ajout celle-ci,
ses dimensions sont nulles et il nest pas possible dy cliquer lintrieur.

Supprimer un couteur
tout moment, il est possible de retirer un couteur enregistr auprs dun objet. Pour
cela, nous disposons de la mthode removeEventListener() dfinie par linterface
IEventDispatcher :
1

r em o v eE v entListener ( type : String , listener : Function ) : void

Une fois cette mthode appele, lobjet ne rpond alors plus aux vnements en question. Nous nallons pas piloguer plus longtemps sur cette mthode qui sutilise de la
mme faon que addEventListener().
Voici donc comment retirer lcouteur ajout plus haut :
1

stage . r em oveEventListener ( MouseEvent . CLICK , monEcouteur ) ;

Le flux dvnements
Prsentation du concept de flux dvnements
Introduction
Lorsque survient un vnement, Flash Player distribue celui-ci directement lobjet
cible. Ce dernier peut alors grer lvnement comme il le souhaite, grce un ventuel
couteur. En revanche, ceci est plus complexe sil sagit dun objet daffichage. Pour
vous en convaincre, nous allons reprendre nos histoires de voitures !
Souvenez-vous de notre voiture organise comme la figure 21.3 dans la liste daffichage.
Il sagit donc de la hirarchie lintrieur de notre programme. Ceci dit, une fois que
vous aurez lanc lexcution du code, vous obtiendrez la fentre visible la figure 21.4.
Dans limage prcdente, vous voyez que le curseur est positionn sur lune des deux
roues. Au hasard, nous dirons quil sagit de lobjet roue2. Si vous cliquez laide de
votre souris, un objet MouseEvent va donc tre gnr pour que lvnement puisse
tre trait. Cependant, une petite question se pose alors !

qui doit tre distribu lvnement gnr par la souris ?

Certains diront quil semble plus logique de distribuer lvnement auprs de lobjet
roue2. En effet, cest bien lobjet qui rellement la cible de lvnement puisque cest
430

LE FLUX DVNEMENTS

Figure 21.3 Larbre daffichage de la voiture

Figure 21.4 Les diffrents objets de la voiture lintrieur du Flash Player

431

CHAPITRE 21. LES VNEMENTS


sur lui que le clic est effectu. premire vue, il est normal de faire de lobjet roue2
la cible de lvnement.
Toutefois, en y rflchissant bien, ceci nest finalement pas ce quil y a de plus pratique.
Imaginons que dans notre application, nous voulions non pas dtecter un clic sur lune
des roues ou mme sur la carrosserie, mais sur la voiture elle-mme. Comment allonsnous pouvoir grer cette situation au niveaux des vnements ? Allons nous devoir
dfinir un couteur pour chacun des objets enfants de notre objet voiture ? Heureusement, non ! Le Flash Player intgre ce quon appelle le flux dvnements qui largit
grandement les possibilits de la gestion des vnements.
Quest-ce que le flux dvnements ?
Pour faciliter la gestion des vnements pour les objets daffichage, le Flash Player
utilise une technique qui consiste acheminer lobjet dvnement dans toute la hirarchie de la liste daffichage, depuis la scne principale jusqu lobjet cible. Pour tre
plus prcis, lobjet vnement effectue en ralit un aller-retour sur le chemin dcrit
prcdemment. Nous pouvons alors distinguer trois phases :
La phase de capture : cette phase comprend la distribution de lobjet vnement
depuis la scne principale jusqu lobjet parent de la cible.
La phase cible : il sagit de la gestion de lvnement par lobjet cible.
La phase de propagation : cette dernire phase est la remonte jusqu la
scne principale, il sagit donc du chemin inverse la phase de capture.
Appliqu au cas dun clic sur lobjet roue2 de notre voiture, le flux dvnements peut
alors tre dcompos comme la figure 21.5.

Figure 21.5 La diffusion dans le flux dvnements


Avec cette manire de procder, il devient possible de grer lvnement tous les
tages de la hirarchie de notre liste daffichage. Ainsi, nous pouvons alors enregistrer
un couteur pour cet vnement auprs du conteneur voiture. Pour mieux comprendre
432

LE FLUX DVNEMENTS
tous les mcanismes du flux dvnements, nous allons maintenant raliser quelques
manipulations.

Bien comprendre le fonctionnement


Dans le flux dvnements, lobjet dvnements est distribu chaque nud
ou objet de la liste daffichage. Pour bien cerner comment cela fonctionne, nous allons
tester quelques petits bouts de code. Nous allons donc reprendre notre voiture.
Commenons par dfinir nos lments :
1
2
3
4
5
6
7

// D finition des objets d ' affichage


var voiture : Sprite = new Sprite () ;
voiture . name = " voiture " ;
var roue2 : Sprite = new Sprite () ;
roue2 . name = " roue2 " ;
voiture . addChild ( roue2 ) ;
addChild ( voiture ) ;

Pour simplifier lexemple, nous limiterons le trac de notre voiture une unique roue.
Cest un peu ridicule, je sais ! Mais cela ne nous empchera pas de comprendre les
mcanismes lis au flux dvnements.
Voici donc le code propos pour dessiner cette roue :
1
2
3
4
5
6
7

// Tra age de la roue


roue2 . graphics . lineStyle (2 , 0x000000 ) ;
roue2 . graphics . beginFill ( 0xCCE5FF ) ;
roue2 . graphics . drawCircle (0 ,0 , 25 ) ;
roue2 . graphics . endFill () ;
roue2 . x = stage . stageWidth / 2 ;
roue2 . y = stage . stageHeight / 2 ;

En guise de fonction dcouteur, nous nous contenterons de citer le nom de lobjet daffichage qui reoit lobjet vnement. Cest pour cela que nous avons dfini la
proprit name pour chacun de nos objets.
Pour rappel, le nom des variables est arbitraire et na de sens qu lintrieur du code. Une fois le code compil, Flash Player gre directement les
variables en mmoire sans utiliser le nom que vous avez dfini dans votre
code. Cest pourquoi la proprit name dfinie pour toutes les sous-classes de
DisplayObject, permet facilement de distinguer nos objets daffichage lors
de lexcution du code.
Voici donc notre fonction dcouteur :
1
2
3
4

// D finition de la fonction d ' couteur


function monEcouteur ( event : MouseEvent ) : void
{
trace ( " v nement en cours de traitement par l ' objet " +
event . currentTarget . name ) ;

433

CHAPITRE 21. LES VNEMENTS


5

Appliquons alors cette fonction dcouteur nos deux objets voiture et roue2, pour
les vnements de type MouseEvent.CLICK :
1
2
3

// Mise en place des couteurs


voiture . addEventListener ( MouseEvent . CLICK , monEcouteur ) ;
roue2 . addEventListener ( MouseEvent . CLICK , monEcouteur ) ;

Je vous propose prsent de lancer lexcution du code puis de cliquer sur votre roue
laide de votre souris. Vous verrez alors apparatre ceci dans la console :
v nement en cours de traitement par l objet roue2
v nement en cours de traitement par l objet voiture

Attendez ! Pourquoi lvnement est-il distribu lobjet voiture aprs avoir


t trait par lobjet roue2 ? Et sachant que le flux dvnements reprsente
un aller-retour dans la liste daffichage, ne devrait-il pas y avoir deux traitement de la fonction dcouteur par lobjet stage ?
En toute rigueur, si ! Toutefois, lors de la mise en place dun couteur avec la mthode
addEventListener(), nous dfinissons en ralit la phase durant laquelle lcouteur
est actif. Pour cela, il faut revenir sur la dfinition de cette fonction :
addEventListener ( type : String , listener : Function , useCapture :
Boolean = false , priority : int = 0 , useWeakReference : Boolean
= false ) : void

Dans cette mthode, le troisime paramtre nomm useCapture, de type Boolean,


permet de dfinir les phases durant lesquelles lcouteur est actif. Voil donc comment
ce paramtre influe sur le flux dvnements :
true : lcouteur est actif uniquement pendant la phase de capture.
false : lcouteur est actif pendant les phases cible et de propagation.
Par dfaut, ce paramtre vaut false. Dans le cas de notre objet voiture, lcouteur
est donc actif seulement pendant la phase de propagation.
Essayons maintenant de dfinir lcouteur de notre objet voiture pendant la phase de
capture :
voiture . addEventListener ( MouseEvent . CLICK , monEcouteur , true ) ;

Cette fois-ci, notre voiture voit bien lvnement avant lobjet roue2 :
v nement en cours de traitement par l objet voiture
v nement en cours de traitement par l objet roue2

Si vous avez bien compris la logique du flux dvnements, vous aurez alors devin
que lobjet voiture peut intervenir la fois durant la phase de capture et la phase de
434

LOBJET EVENT
propagation. Cependant, cela ncessite denregistrer deux couteurs diffrents auprs
de lobjet en question.
Mme si cela semble superflu, voil les instructions de dfinition des couteurs :
1
2
3

voiture . addEventListener ( MouseEvent . CLICK , monEcouteur , true ) ;


roue2 . addEventListener ( MouseEvent . CLICK , monEcouteur ) ;
voiture . addEventListener ( MouseEvent . CLICK , monEcouteur ) ;

prsent, nous pouvons donc agir tous les niveaux, ou disons durant toutes les phases
du flux dvnements, comme le montre la console de sortie :
v nement en cours de traitement par l objet voiture
v nement en cours de traitement par l objet roue2
v nement en cours de traitement par l objet voiture

Enfin, avant de passer la suite, notez que le passage en paramtre de la valeur true
la mthode addEventListener() de lobjet cible a pour effet de dsactiver lcouteur
pendant la phase cible. Voici un exemple illustrant ces propos :
1
2
3

voiture . addEventListener ( MouseEvent . CLICK , monEcouteur , true ) ;


roue2 . addEventListener ( MouseEvent . CLICK , monEcouteur , true ) ;
voiture . addEventListener ( MouseEvent . CLICK , monEcouteur ) ;

Ce qui donne videmment dans la console de sortie :


v nement en cours de traitement par l objet voiture
v nement en cours de traitement par l objet voiture

Lobjet Event
Prsentation de la classe Event
Avant de clturer ce chapitre, nous allons brivement parler de la classe Event. Nous
avons dj vu que cette dernire est la superclasse de tout objet vnement. Ainsi, les
sous-classes hriteront de toutes ses proprits. Ses accesseurs et mthodes serviront
principalement la gestion de lvnement, nous allons donc rapidement les tudier.
Voici la figure 21.6 lheureuse lue que nous allons tudier.
Bien entendu, nous ne verrons et ne dtaillerons pas toutes ces proprits. Nous nous
focaliserons uniquement sur celles qui ont le plus dintrt pour nous pour linstant.
Parmi les attributs, certains sont plutt dordre gnral, nous retiendrons donc les
deux suivants :
type : cet accesseur dfinit le type de lvnement sous la forme dune chane de
caractres. Il sagit de cette mme chane qui est transmise en paramtre la
mthode addEventListener().
target : cet attribut fait rfrence lobjet cible de lvnement.
435

CHAPITRE 21. LES VNEMENTS

Figure 21.6 La classe Event


Voici un petit code dexemple dutilisation de ces proprits :
1
2
3
4
5
6

stage . addEventListener ( MouseEvent . CLICK , monEcouteur ) ;


function monEcouteur ( event : MouseEvent ) : void
{
trace ( " v nement de type " + event . type ) ;
trace ( " Cible de l ' v nement " + event . target ) ;
}

Ce qui donne :
v nement de type click
Cible de l v nement [ object Stage ]

Les proprits lis au flux dvnements


Certaines proprits de la classe Event sont en lien direct avec le flux dvnements.
Celles-ci permettent alors de situer et de contrler lobjet Event tout au long du flux
dvnements. Nous pouvons donc citer les deux attributs suivant :
eventPhase : cette proprit indique la phase en cours dans le flux dvnements.
currentTarget : cet attribut est une rfrence lobjet cible provisoire qui peut
se situer nimporte o dans la hirarchie de la liste daffichage.
Afin de mieux comprendre ce dont il est question, nous allons reprendre nos objets
voiture et roue2. Puis nous allons redfinir la fonction dcouteur pour faire apparatre les valeurs de ces attributs :
1
2
3
4
5
6

// D finition de la fonction d ' couteur


function monEcouteur ( event : MouseEvent ) : void
{
trace ( " v nement en cours de traitement par l ' objet " +
event . currentTarget . name ) ;
trace ( " Phase du flux d ' v nements en cours : " + event .
eventPhase ) ;
}

436

LOBJET EVENT
Maintenant, enregistrons un couteur pour chacune des phases du flux dvnements :
1
2
3
4

// Mise en place des couteurs


voiture . addEventListener ( MouseEvent . CLICK , monEcouteur , true ) ;
voiture . addEventListener ( MouseEvent . CLICK , monEcouteur ) ;
roue2 . addEventListener ( MouseEvent . CLICK , monEcouteur ) ;

prsent, il ny a plus aucun doute sur la manire dont est gr lobjet vnement
travers les diffrentes phases :
v nement en cours de traitement par l objet voiture
Phase du flux d v nements en cours : 1
v nement en cours de traitement par l objet roue2
Phase du flux d v nements en cours : 2
v nement en cours de traitement par l objet voiture
Phase du flux d v nements en cours : 3

Comme vous le voyez, les phases sont reprsents par un nombre entier
allant de 1 3. Comme souvent en Actionscript, lutilisation de ces valeurs est simplifie par la classe EventPhase et ses constantes respectives
CAPTURING_PHASE, AT_TARGET et BUBBLING_PHASE.
La classe Event dispose de deux mthodes stopImmediatePropagation() et stopPropagation()
qui servent stopper la diffusion de lvnement dans le flux dvnements, respectivement partir du nud actuel ou du nud suivant. Ces mthodes permettent donc
de grer directement la propagation de lobjet vnement.
Pour visualiser ceci, je vous invite remplacer la fonction dcouteur monEcouteur()
par la suivante :
1
2
3
4
5
6
7

function monEcouteur ( event : MouseEvent ) : void


{
trace ( " v nement en cours de traitement par l ' objet " +
event . currentTarget . name ) ;
if ( event . eventPhase == EventPhase . AT_TARGET ) {
event . stopPropagation () ;
}
}

La propagation est alors stoppe la fin de lexcution de la fonction dcouteur associe


lobjet roue2 :
v nement en cours de traitement par l objet voiture
v nement en cours de traitement par l objet roue2

437

CHAPITRE 21. LES VNEMENTS

En rsum
Un vnement est gnr de manire imprvisible, comme le clic dune souris par
exemple.
Les mthodes de gestion des couteurs sont dfinies par linterface IEventDispatcher
et la classe EventDispatcher.
La mthode addEventListener() sert associer une fonction de rappel ou fonction dcouteur un type dvnements pour un objet donn.
Le flux dvnements dfinit le parcours effectu par un vnement dans la hirarchie de la liste daffichage, entre la scne principale et lobjet cible.
Le flux dvnements est compos de la phase de capture, la phase cible et la
phase de propagation.
Les objets vnement sont reprsents par la classe Event, ou lune de ses classesfilles.

438

Chapitre

22

Interagir avec lutilisateur


Difficult :
Maintenant que toutes les bases de la programmation vnementielle sont poses, nous
allons pouvoir mettre tout ceci en pratique au cours de ce chapitre. Nous apprendrons
comment utiliser et manipuler des donnes saisies par lutilisateur. Cela pourra tre des
donnes issues de la souris ou du clavier.

439

CHAPITRE 22. INTERAGIR AVEC LUTILISATEUR

La souris
Lobjet MouseEvent
Introduction
Nous allons apprendre grer et manipuler des vnements provenant de la
souris. Lorsque quun tel vnement se produit, un objet de la classe MouseEvent est
gnr. Comme nous lavons vu, tous les objets vnements hritent de la classe
Event et de ses proprits (voir figure 22.1).

Figure 22.1 La classe MouseEvent


Dans le chapitre prcdent, javais mentionn le fait que les objets renfermaient des
informations lies lvnement. Ainsi, la classe MouseEvent dispose principalement
de proprits contenant des informations en lien avec la souris, notamment la position
du curseur au moment de la gnration de lvnement. tant donn que les interactions
avec la souris sont troitement lies linterface graphique, cette classe sera videmment
distribue dans le flux dvnements.
Nous allons maintenant faire un tour des principales constantes et proprits de
cette classe. Nanmoins, nous ne les verrons pas toutes, et je vous conseille donc de
vous rendre sur la page de la classe du guide de rfrence pour davantage dinformations.


Documentation MouseEvent
.
B
Code web : 462867


440

LA SOURIS
Les diffrents types dvnements
Les types dvnements lis la souris sont dfinis sous forme de constantes
statiques de la classe MouseEvent. On les utilise ainsi :

MouseEvent . NO M_DE_LA_CONSTANTE

2
3
4

// Par exemple :
MouseEvent . CLICK

Voici ces constantes :


CLICK : cette constante dfinit un clic avec le bouton gauche de la souris (il faut que
le bouton soit successivement enfonc puis relch tout en tant au-dessus de la cible
chaque fois).
DOUBLE_CLICK : celle-ci dfinit un double-clic de la souris. Toutefois, la gestion de ce
type dvnements ncessite daffecter la valeur true la proprit doubleClickEnabled
de lobjet en question.
MOUSE_DOWN : cette constante dcrit lenfoncement du bouton gauche de la souris.
MOUSE_UP : loppos de MOUSE_DOWN, MOUSE_UP est produit par le relchement du
bouton gauche de la souris.
MIDDLE_CLICK : cette fois-ci, il sagit dun clic laide du bouton du milieu de la
souris (qui est en gnral la molette de la souris).
MIDDLE_MOUSE_DOWN : cette constante dcrit lenfoncement du bouton du milieu de
la souris.
MIDDLE_MOUSE_UP : comme pour MOUSE_UP, MIDDLE_MOUSE_UP est produit par le
relchement du bouton du milieu de la souris, loppos de MIDDLE_MOUSE_DOWN.
RIGHT_CLICK : pour ce type dvnement, il sagit dun clic laide du bouton droit
de la souris.
RIGHT_MOUSE_DOWN : cette constante dcrit lenfoncement du bouton droit de la souris.
RIGHT_MOUSE_UP : RIGHT_MOUSE_UP est produit par le relchement du bouton droit
de la souris, loppos de RIGHT_MOUSE_DOWN.
MOUSE_MOVE : un tel vnement se produit chaque dplacement de la souris, mme
dun seul et unique pixel !
MOUSE_WHEEL : cette constante dfinit une action de dfilement laide de la molette
de la souris. La direction de la molette est dfinie dans lattribut delta de lobjet de
lvnement, qui est alors un entier positif ou ngatif.
ROLL_OVER : cette constante dfinit le survol de lobjet courant, ou de lun de ses
enfants, par la souris.
ROLL_OUT : linverse de MOUSE_OVER, cet vnement est gnr lorsque la souris
quitte la zone de trac dun objet daffichage et de lensemble de ses enfants.
Grce toutes ces constantes que vous pouvez combiner, il vous est maintenant possible
de prendre en compte les commande de lutilisateur avec la souris.
441

CHAPITRE 22. INTERAGIR AVEC LUTILISATEUR


Il existe galement les constantes MOUSE_OVER et MOUSE_OUT, trs semblables
au couple ROLL_OVER / ROLL_OUT. La diffrence se situe au niveau des objets
daffichage enfants de la cible de lvnement : dans le cas de MOUSE_OVER
et MOUSE_OUT, lvnement sera dclench chaque fois que la souris quitte
la surface dun enfant pour aller sur un autre, mme sil ny a pas despace
vide entre eux. A linverse, pour ROLL_OVER et ROLL_OUT, la cible est ses
enfants sont considrs comme tant une unique surface : lvnement nest
dclench quune seule fois. Il est donc fortement conseill de toujours utiliser
ROLL_OVER et ROLL_OUT.
Imaginons que vous ayez cr un bouton constitu dune image de fond assez grande et
dun champ de texte au milieu et que vous vouliez lanimer au passage de la souris. En
utilisant MOUSE_OVER et MOUSE_OUT, un vnement de type MOUSE_OVER se dclenchera
dabord lorsque la souris arrivera sur limage de fond. Mais si la souris passe ensuite
sur le champ de texte, un vnement de type MOUSE_OUT apparatra (la souris a quitt
la surface dun enfant du bouton) puis, immdiatement aprs, un autre vnement de
type MOUSE_OVER sera dclench (la souris arrive au-dessus du champ de texte) et viceversa. Cela nest pas vraiment optimal et cela peut provoquer des bugs danimation
pas trs agrables sur le bouton lorsque la souris passe dessus.
Si vous utilisez ROLL_OVER et ROLL_OUT, un vnement de type ROLL_OVER se dclenchera une seule fois lorsque la souris entrera sur la surface de limage de fond, mme
si la souris passe de limage au champ de texte. Enfin, un unique vnement de type
ROLL_OUT sera dclench lorsque la souris quittera limage de fond. En effet, les surfaces
de chaque enfant ne sont pas considres comme indpendantes : elles forment un tout
(la surface totale du bouton).
Quelques proprits utiles
La classe MouseEvent possde un certain nombre dattributs ou de proprits. En
voici quelques unes qui pourront vous tes trs utiles :
stageX : contient la position horizontale globale o sest produit lvnement.
stageY : contient la position verticale globale o sest produit lvnement.
localX : contient la position horizontale locale par rapport au conteneur parent o
sest produit lvnement.
localY : contient la position verticale locale par rapport au conteneur parent o sest
produit lvnement.
buttonDown : indique si le bouton est enfonc, principalement utile pour les vnements de type MOUSE_MOVE. 
altKey : indique si la touche Alt  est enfonce en parallle de lvnement de la
souris.


ctrlKey : indique si la touche Ctrl  (ou Cmd  pour les utilisateurs de Mac) est
enfonce en parallle de lvnement
 de la souris.
shiftKey : indique si la touche Shift est enfonce en parallle de lvnement de


la souris.
delta (uniquement pour les vnements de type MOUSE_WHEEL) : contient un entier
442

LA SOURIS
positif si la molette est dfile vers le haut, ngatif dans le cas contraire.
Les trois proprits altKey, ctrlKey et shiftKey sont uniquement des indicateurs permettant de dterminer si les touches correspondantes sont enfonces lors de la gnration de lvnement. Des actions sur ces boutons
nengendrent en aucun cas lmission dun objet MouseEvent.

Exemple : bouton simple


Pour illustrer ce que nous venons de voir, crons notre premier bouton ensemble ! Voici
le code crire pour le bouton :
1
2
3
4
5
6
7
8
9
10
11

// Bouton
var bouton : Sprite = new Sprite () ;
// Autorisation du double - clic
bouton . d oub le ClickEnabled = true ;
// Curseur de bouton ( g n ralement en forme de main )
bouton . buttonMode = true ;
bouton . useHandCursor = true ;
// Les enfants ne sont pas g r s par la souris afin qu ' ils n '
interf rent pas avec le curseur de la souris
// ( sinon le champ de texte pourrait annuler le curseur de
bouton )
bouton . mouseChildren = false ;
addChild ( bouton ) ;

12
13
14
15
16
17
18
19
20
21
22
23
24

// Texte
var texte : TextField = new TextField () ;
// Pour viter que le texte soit s lectionn
texte . selectable = false ;
// Taille automatique
texte . autoSize = TextFieldAutoSize . LEFT ;
// Format du texte
texte . de faultTextFormat = new TextFormat ( ' Arial ' , 32 , 0xffffff )
;
// Contenu
texte . text = " Je suis un bouton " ;
// Ajout du texte dans le bouton
bouton . addChild ( texte ) ;

25
26
27
28
29
30
31
32

// Fond bleu
var fond : Shape = new Shape () ;
// Ligne
fond . graphics . lineStyle (2 , 0x9999ff , 1 , true ) ;
// Remplissage
fond . graphics . beginFill ( 0x0000ff ) ;
// Dessin d ' un rectangle coins arrondis

443

CHAPITRE 22. INTERAGIR AVEC LUTILISATEUR


33
34
35

fond . graphics . drawRoundRect (0 , 0 , texte . width , texte . height , 12


);
// Ajout du fond bleu dans le bouton , en dessous du texte ( cad ,
l ' index 0 )
bouton . addChildAt ( fond , 0 ) ;

36
37
38
39

// Alignement du bouton au centre de la sc ne


bouton . x = ( stage . stageWidth - bouton . width ) / 2 ;
bouton . y = ( stage . stageHeight - bouton . height ) / 2 ;

Nous crons en premier lieu un sprite qui va reprsenter le bouton. On active le double
clic laide de lattribut doubleClickEnabled, puis on active le curseur de bouton (gnralement en forme de main) en mettant les attributs buttonMode et useHandCursor
true.
Pourquoi dsactiver la gestion de la souris sur les enfants du bouton ?

Si nous ne le faisons pas, le champ de texte aura le fcheux comportement de mal


faire fonctionner le curseur, qui sera remis en pointeur par dfaut (au lieu du curseur de bouton en forme de main). Ainsi, par scurit, il vaut mieux mettre lattribut
mouseChildren false pour les enfants soient plus directement grs par la souris.
Toutefois, ils comptent quand mme dans la surface totale du bouton.
Puis nous crons le champ de texte qui affichera ltiquette du bouton, suivie dun
dessin de rectangle arrondi bleu pour embellir tout ceci.
Ensuite, crivons les fonctions dcouteur qui nous permettront de tester diffrents
vnements de la souris :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

// Fonctions d ' couteurs


function onOver ( e : MouseEvent ) : void
{
trace ( " La souris est entr e au - dessus du
}
function onOut ( e : MouseEvent ) : void
{
trace ( " La souris n ' est plus au - dessus du
}
function onDown ( e : MouseEvent ) : void
{
trace ( " Le bouton gauche de la souris est
du bouton . " ) ;
}
function onUp ( e : MouseEvent ) : void
{
trace ( " Le bouton gauche de la souris est
du bouton . " ) ;
}
function onClick ( e : MouseEvent ) : void

444

bouton . " ) ;

bouton . " ) ;

enfonc au - dessus

rel ch au - dessus

LA SOURIS
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

trace ( " Le bouton a t cliqu . " ) ;


}
function onDoubleClick ( e : MouseEvent ) : void
{
trace ( " Le bouton a t double - cliqu . " ) ;
}
function onMiddleClick ( e : MouseEvent ) : void
{
trace ( " Le bouton a t cliqu milieu . " ) ;
}
function onRightClick ( e : MouseEvent ) : void
{
trace ( " Le bouton a t cliqu droit . " ) ;
}
function onMove ( e : MouseEvent ) : void
{
trace ( " La souris s ' est d plac e au - dessus du bouton . " ) ;
}

Enfin, nous coutons les diffrents vnements de la souris sur le bouton, qui en sera
alors la cible :
1
2
3
4
5
6
7
8
9
10

// Ev nements de la souris
bouton . addEventListener ( MouseEvent . ROLL_OVER , onOver ) ;
bouton . addEventListener ( MouseEvent . ROLL_OUT , onOut ) ;
bouton . addEventListener ( MouseEvent . MOUSE_DOWN , onDown ) ;
bouton . addEventListener ( MouseEvent . MOUSE_UP , onUp ) ;
bouton . addEventListener ( MouseEvent . CLICK , onClick ) ;
bouton . addEventListener ( MouseEvent . DOUBLE_CLICK , onDoubleClick )
;
bouton . addEventListener ( MouseEvent . MIDDLE_CLICK , onMiddleClick )
;
bouton . addEventListener ( MouseEvent . RIGHT_CLICK , onRightClick ) ;
bouton . addEventListener ( MouseEvent . MOUSE_MOVE , onMove ) ;

Nous avons lcran quelque chose comme la figure 22.2.

Figure 22.2 Notre bouton bleu !


Si vous jouez un peu avec, vous obtiendrez des informations dans la console sur les
diffrents vnements qui se dclenchent :
La souris est entr e au - dessus du bouton .
La souris s est d plac e au - dessus du bouton .
La souris s est d plac e au - dessus du bouton .

445

CHAPITRE 22. INTERAGIR AVEC LUTILISATEUR


La
Le
Le
Le
Le
Le
La
La
La
La

souris
bouton
bouton
bouton
bouton
bouton
souris
souris
souris
souris

s est d plac e au - dessus du bouton .


gauche de la souris est enfonc au - dessus du bouton .
gauche de la souris est rel ch au - dessus du bouton .
a t cliqu .
a t cliqu milieu .
a t cliqu droit .
s est d plac e au - dessus du bouton .
s est d plac e au - dessus du bouton .
s est d plac e au - dessus du bouton .
n est plus au - dessus du bouton .

La technique du glisser-dposer
Le glisser-dposer (ou drag and drop en anglais) est une mthode qui consiste
dplacer un lment graphique dun endroit un autre. Il sagit du mme principe que
lorsque que vous dplacez une icne sur votre bureau. Pour cela, vous effectuez un clic
que vous maintenez le temps du dplacement. Le dplacement sarrte lorsque vous
relchez le bouton de la souris.
En Actionscript, ce concept est beaucoup plus pouss et puissant puisquil est possible
de contrler souhaits ce fameux glisser-dposer. Une manire de raliser ceci serait de combiner intelligemment les trois types dvnements MOUSE_DOWN, MOUSE_MOVE
et MOUVE_UP. Mais lActionscript facilite davantage la mise en place de cette technique. Cest pourquoi la classe Sprite dispose des deux mthodes startDrag() et
stopDrag() permettant respectivement dactiver ou de dsactiver le glisser-dposer
sur cet objet.
Nous allons utiliser un exemple qui sera beaucoup plus parlant. Commenons par dessiner un carr violet dans notre scne :
1
2
3
4

var objet : Sprite = new Sprite () ;


addChild ( objet ) ;
objet . graphics . beginFill ( 0x8800FF ) ;
objet . graphics . drawRect (0 , 0 , 50 , 50 ) ;

En utilisant ces fameuses mthodes startDrag() et stopDrag(), il nest maintenant


plus ncessaire de se proccuper des dplacements de la souris. Seuls le dmarrage et
larrt du glisser-dposer doivent tre contrls. Nous pouvons alors trs facilement
mettre ceci en place grce aux deux couteurs suivants :
1
2
3
4
5
6
7
8
9

objet . addEventListener ( MouseEvent . MOUSE_DOWN , glisser ) ;


function glisser ( event : MouseEvent ) : void
{
objet . startDrag () ;
}
objet . addEventListener ( MouseEvent . MOUSE_UP , deposer ) ;
function deposer ( e : MouseEvent ) : void
{
objet . stopDrag () ;

446

LA SOURIS
10

lintrieur du Flash Player, il est maintenant possible de dplacer notre objet


volont !

Exercice : Crer et animer un viseur


Dessiner le viseur
Dans cet exercice, nous allons voir comment dessiner et animer un viseur tel que
nous pourrions en trouver dans un jeu de tir. Nous commencerons donc par tracer
llment qui vous servira de viseur.
Voici la figure 22.3 le viseur que je vous propose de dessiner.

Figure 22.3 Le viseur


Crons donc un objet viseur de type Shape, et traons les diffrents lments qui
compose celui-ci :
1
2
3
4
5
6
7
8
9
10
11
12

var viseur : Shape = new Shape () ;


addChild ( viseur ) ;
viseur . graphics . lineStyle (2 , 0x000000 ) ;
viseur . graphics . drawCircle (0 , 0 , 20 ) ;
viseur . graphics . lineStyle (1 , 0x550000 ) ;
viseur . graphics . drawCircle (0 , 0 , 16 ) ;
viseur . graphics . moveTo ( - 25 , 0 ) ;
viseur . graphics . lineTo ( 25 , 0 ) ;
viseur . graphics . moveTo (0 , - 25 ) ;
viseur . graphics . lineTo (0 , 25 ) ;
viseur . x = stage . stageWidth / 2 ;
viseur . y = stage . stageHeight / 2 ;

Comme vous pouvez le voir, il ny a rien de bien compliqu dans ce code. Nous avons
uniquement trac deux cercles concentriques et deux segments perpendiculaires.
En ralit, pour cet exercice, nous nallons pas rellement remplacer le curseur. Nous
allons nous contenter de suivre la position de la souris et nous masquerons la souris
elle-mme. Cela donnera alors lillusion que le curseur est un viseur.
Pour masquer la souris, utilisez linstruction suivante :
1

Mouse . hide () ;

La fonction hide() est une mthode statique de la classe Mouse. Noubliez


donc pas dimporter cette classe dans votre projet. Pour faire rapparatre
votre curseur, vous pouvez utiliser la mthode statique inverse : show().

447

CHAPITRE 22. INTERAGIR AVEC LUTILISATEUR


Grer les vnements
prsent, occupons-nous de la gestion des vnements ! Nous allons procder en
deux temps. Premirement, nous allons faire en sorte que le viseur suive le curseur en
mettant jour sa position. Ensuite, nous ajouterons un second couteur pour simuler
un tir. Bien sr tout cela reste un niveau basique, mais lide est l.
Pour mettre jour la position du viseur, nous allons utiliser les vnements de type
MOUSE_MOVE. Les proprits stageX et stageY de la classe MouseEvent nous serviront
replacer le viseur.
Voil donc la mise en place de notre couteur :
1
2
3
4
5
6

stage . addEventListener ( MouseEvent . MOUSE_MOVE ,


r ep o s itionnerViseur ) ;
function repositionnerViseur ( event : MouseEvent ) : void
{
viseur . x = event . stageX ;
viseur . y = event . stageY ;
}

Nous allons maintenant nous concentrer sur la gestion des vnements de type
tirs . Je vous propose pour cela, dutiliser le clic de la souris, ou plutt lenfoncement
du bouton de gauche. Il sagit bien videmment de lvnement MOUSE_DOWN.
lintrieur de la fonction dcouteur associe, nous crerons un petit rond rouge,
grossirement semblable une tche de sang, puis nous la positionnerons au niveau du
viseur. Rien de bien complexe ici, voici le code correspondant :
1
2
3
4
5
6
7
8
9
10

stage . addEventListener ( MouseEvent . MOUSE_DOWN , tirer ) ;


function tirer ( event : MouseEvent ) : void
{
var impact : Shape = new Shape () ;
impact . graphics . beginFill ( 0xFF0000 ) ;
impact . graphics . drawCircle (0 , 0 , 4 ) ;
impact . x = event . stageX ;
impact . y = event . stageY ;
addChildAt ( impact , 0 ) ;
}

Nous avons utilis un vnement de type MOUSE_DOWN, mais nous pourrions trs bien pu
le faire laide des vnements MOUSE_UP ou CLICK. Lorsque vous programmez votre
interface, cest vous de choisir le type dvnements qui correspond le mieux ce que
vous souhaitez faire.

Le rendu
Pour admirer le magnifique rendu de cette application (voir figure 22.4), je ne peux
que vous inviter excuter le code et tirer dans tous les sens !
448

LA SOURIS

Figure 22.4 Les prmices dun jeu de tir

Curseurs personnaliss
Il est possible de remplacer le curseur de la souris par une image ou une animation de
notre choix, ce qui prsente des avantages par rapport la technique que nous venons
de voir pour le viseur : le curseur sera un curseur natif, cest--dire quil sera directement gr par le systme dexploitation de lutilisateur. Cela implique de meilleures
performances : moins de ressources seront consommes pour afficher le curseur et mme
si votre application est victime de ralentissement, votre curseur personnalis nen sera
pas affect, ce qui amliore grandement lexprience utilisateur. De plus, le curseur ne
sera pas coup aux bords de la zone daffichage de votre application : il pourra dpasser
en dehors de la fentre (par exemple, sil se situe en bas de votre application, il continuera dtre affich, mme en dehors de la scne). Il est donc trs fortement conseill
dutiliser les curseurs natifs personnaliss si vous voulez remplacer le curseur de la
souris, cest la meilleure mthode.
Il est possible que le systme sur lequel votre application est lance ne supporte
pas les curseurs natifs (cest par exemple le cas pour les smartphones) : vous
pouvez le savoir avec lattribut statique supportsNativeCursor de la classe
Mouse.
Ainsi, nous nutiliserons de curseur natif que si cette fonctionnalit est supporte :
1
2
3

if ( Mouse . su p p ortsNativeCursor )
{
// Cr ation du curseur natif personnalis ici

449

CHAPITRE 22. INTERAGIR AVEC LUTILISATEUR


4

Un curseur natif ne peut pas dpasser une taille de 32 pixels sur 32 pixels.

Prparer son curseur


Il faut savoir quun curseur personnalis ne peut tre quune image bitmap (ou une
srie dimages dans le cas des curseurs anims). Ce qui signifie quil nous est impossible
dutiliser directement un objet daffichage comme le dessin (de la classe Shape) que
nous avons cr pour afficher notre viseur. Toutefois, il existe un moyen de prendre une
capture de nimporte quel objet daffichage pour obtenir une image bitmap !
Il est bien entendu galement possible dutiliser directement des images que
vous aurez incorpores au pralable.
Reprenons le code que nous avons utilis pour crer notre viseur sans lajouter la
scne :
1
2
3
4
5
6
7
8
9

var viseur : Shape = new Shape () ;


viseur . graphics . lineStyle (2 , 0x000000 ) ;
viseur . graphics . drawCircle (0 , 0 , 20 ) ;
viseur . graphics . lineStyle (1 , 0x550000 ) ;
viseur . graphics . drawCircle (0 , 0 , 16 ) ;
viseur . graphics . moveTo ( - 25 , 0 ) ;
viseur . graphics . lineTo ( 25 , 0 ) ;
viseur . graphics . moveTo (0 , - 25 ) ;
viseur . graphics . lineTo (0 , 25 ) ;

Nous ne pouvons pas utiliser ce dessin pour en faire un curseur natif, mais nous pouvons en prendre une capture (comme vous prendriez une capture dcran). Pour cela,
nous allons dabord crer une image vide avec la classe BitmapData et utiliser sa mthode draw() (qui signifie dessiner). Cette mthode prend en paramtre nimporte
quel objet qui implmente linterface IBitmapDrawable. Comme nous pouvons le voir
dans la documentation, il sagit de tous les objets ayant pour classe (ou super-classe)
BitmapData ou DisplayObject.
Pour crer limage bitmap, il nous faut les bornes daffichage de notre viseur : en effet,
notre dessin est centr par rapport son origine, donc si nous en faisons une capture
sans en tenir compte, il sera coup partir de son origine (donc nous nobtiendrons
quun quart du viseur). Nous calculons les bornes daffichage de notre dessin grce la
mthode getBounds() de la classe DisplayObject, qui prend en paramtre un objet
daffichage servant de rfrence. Nous passons donc le viseur lui-mme pour savoir de
combien il dpasse par rapport sa propre origine :
450

LA SOURIS
1
2
3

// Bornes d ' affichage de l ' objet


var bornes : Rectangle = viseur . getBounds ( viseur ) ;
trace ( " bornes : " + bornes ) ;

Si vous testez votre code tout de suite, vous obtiendrez ceci dans la console :
bornes :( x = -25.5 , y = -25.5 , w =51 , h =51)

Nous pouvons alors remarquer que notre dessin dpasse de 25 pixels et demi par rapport
son origine, verticalement et horizontalement. Sa taille totale est de 51 pixels sur 51
pixels.
Crons notre image vide :
1
2

// Image vide de bonne taille


var capture : BitmapData = new BitmapData ( 32 , 32 , true , 0 ) ;

Ensuite, pour prendre en compte le fait que notre dessin dpasse de son origine, nous
allons dplacer la capture pour compenser laide dune matrice de transformation :
1
2
3

// D placement de la capture en fonction des bornes d ' affichage


var transformation : Matrix = new Matrix () ;
transformation . translate ( - bornes .x , - bornes . y ) ;

Comme un curseur natif ne peut dpasser une taille de 32 pixels de ct, nous allons
rduire la taille du viseur :
1
2

// La taille maximale d ' un curseur natif est de 32 pixels


transformation . scale ( 32 / bornes . width , 32 / bornes . height ) ;

Enfin, il ne nous reste plus qu prendre la capture de notre viseur :


1
2

// Capture
capture . draw ( viseur , transformation ) ;

Dsormais, notre image contient une capture bitmap de notre viseur, utilisable pour
crer un curseur personnalis !
Pour vrifier que nous ne nous sommes pas tromps, affichons la capture avec un objet
de la classe Bitmap :
1
2
3

// Affichage de la capture pour v rification


var apercu : Bitmap = new Bitmap ( capture ) ;
addChild ( apercu ) ;

Nous obtenons alors la figure 22.5.


Pour bien comprendre quil sagit dune capture bitmap, agrandissons laperu quatre
fois :
1
2

apercu . scaleX = 4 ;
apercu . scaleY = apercu . scaleX ;

451

CHAPITRE 22. INTERAGIR AVEC LUTILISATEUR

Figure 22.5 Laperu de la capture

Figure 22.6 Il sagit bien dune image bitmap


Ce qui nous donne la figure 22.6.
Les gros pixels nous confirment que nous avons l une image bitmap et non plus un
dessin vectoriel.
Crer le curseur natif
Chaque curseur natif est cr laide dun objet de la classe MouseCursorData contenant les images et autres informations propos du curseur. Commenons donc par en
crer une instance :
1
2

// Donn es du curseur natif personnalis


var curseur : MouseCursorData = new MouseCursorData () ;

Ensuite, il nous faut un vecteur contenant une ou plusieurs images (ici nous lui insrons
la capture du viseur) :
1
2
3
4

// Images du curseur ( s ' il y en a plusieurs , le curseur sera


anim )
var images : Vector . < BitmapData > = new Vector . < BitmapData >() ;
images . push ( capture ) ;
curseur . data = images ;

Puis nous renseignons le point actif du curseur, cest--dire la position qui reprsente
le point o lutilisateur va cliquer. Dans notre cas, nous voulons que le point actif soit
452

LA SOURIS
le centre du viseur :
1
2

// Point actif du curseur -> centre de notre viseur


curseur . hotSpot = new Point ( capture . width / 2 , capture . height /
2);

Enfin, il faut enregistrer notre curseur natif en lui donnant un nom, grce la
mthode statique registerCursor de la classe Mouse :
1
2

// Enregistrement du cuseur natif personnalis


Mouse . registerCursor ( " viseur " , curseur ) ;

Notre curseur est fin prt tre utilis !


Activer un curseur natif
Pour activer notre nouveau curseur natif, il faut affecter lattribut statique
cursor de la classe Mouse le nom de notre curseur :
1
2

// Activons notre cuseur


Mouse . cursor = " viseur " ;

Et voil que notre curseur de souris sest transform en viseur, comme le montre la
figure 22.7.

Figure 22.7 Notre curseur natif personnalis


Comme vous pouvez le remarquer, le curseur nest plus coup par les bords de notre
application et il est trs fluide quelque soit la frquence de rafrachissement de lapplication.
Voici le code complet permettant de crer ce curseur natif :
1
2
3
4
5
6
7

if ( Mouse . s u pportsNativeCursor )
{
// Dessin
var viseur : Shape = new Shape () ;
viseur . graphics . lineStyle (2 , 0x000000 ) ;
viseur . graphics . drawCircle (0 , 0 , 20 ) ;
viseur . graphics . lineStyle (1 , 0x550000 ) ;

453

CHAPITRE 22. INTERAGIR AVEC LUTILISATEUR


viseur . graphics . drawCircle (0 , 0 , 16 ) ;
viseur . graphics . moveTo ( - 25 , 0 ) ;
viseur . graphics . lineTo ( 25 , 0 ) ;
viseur . graphics . moveTo (0 , - 25 ) ;
viseur . graphics . lineTo (0 , 25 ) ;

8
9
10
11
12
13

// Bornes d ' affichage de l ' objet


var bornes : Rectangle = viseur . getBounds ( viseur ) ;
trace ( " bornes : " + bornes ) ;

14
15
16
17

// Image vide de bonne taille


var capture : BitmapData = new BitmapData ( 32 , 32 , true , 0 ) ;
// D placement de la capture en fonction des bornes d '
affichage
var transformation : Matrix = new Matrix () ;
transformation . translate ( - bornes .x , - bornes . y ) ;
// La taille maximale d ' un curseur natif est de 32 pixels
transformation . scale ( 32 / bornes . width , 32 / bornes . height )
;
// Capture
capture . draw ( viseur , transformation ) ;

18
19
20
21
22
23
24
25
26
27

// Affichage de la capture pour v rification


/* var apercu : Bitmap = new Bitmap ( capture ) ;
addChild ( apercu ) ;
apercu . scaleX = 4 ;
apercu . scaleY = apercu . scaleX ; */

28
29
30
31
32
33
34

// Donn es du curseur natif personnalis


var curseur : MouseCursorData = new MouseCursorData () ;
// Images du curseur ( s ' il y en a plusieurs , le curseur
sera anim )
var images : Vector . < BitmapData > = new Vector . < BitmapData >() ;
images . push ( capture ) ;
curseur . data = images ;
// Point actif du curseur -> centre de notre viseur
curseur . hotSpot = new Point ( capture . width / 2 , capture .
height / 2 ) ;
// Enregistrement du cuseur natif personnalis
Mouse . registerCursor ( " viseur " , curseur ) ;

35
36
37
38
39
40
41
42
43
44
45

// Activons notre cuseur


Mouse . cursor = " viseur " ;

46
47
48
49

454

LE CLAVIER
Dsactiver le curseur natif personnalis
Si vous navez plus besoin de votre curseur natif en forme de viseur, vous pouvez trs
simplement revenir au curseur par dfaut du systme dexploitation de lutilisateur
laide de linstruction suivante :
1

Mouse . cursor = MouseCursor . AUTO ;

Le clavier
Lobjet KeyboardEvent
Tout comme ceux qui proviennent de la souris, les vnements issus du clavier
gnrent leur propre classe, savoir KeyboardEvent. Celle-ci hrite videmment de la
classe Event, en y ajoutant ses propres proprits.
Voici la figure 22.8 un schma UML qui permet de rsumer un peu toutes les
proprits ou mthodes fournies par ces deux classes.

Figure 22.8 La classe KeyboardEvent


Contrairement la souris, les types dvnements produits par le clavier sont beaucoup
moins nombreux, puisquils ne sont que deux ! Voici donc les constantes de la classe
KeyboardEvent qui les dfinissent :
KEY_DOWN : cette constante dcrit lenfoncement de nimporte quelle touche du clavier.
KEY_UP : celle-ci reprsente le relchement de nimporte quelle touche du clavier.
455

CHAPITRE 22. INTERAGIR AVEC LUTILISATEUR


Mme sil est possible de trouver un grand nombre dapplications ncessitant la combinaison de ces deux types dvnements, vous nen utiliserez quun la majorit du temps.
Et comme cela semble souvent plus naturel, il sagira de lvnement KEY_DOWN.
Les attributs ou proprits associes la classe KeyboardEvent ne sont galement
pas trs nombreuses, et les voici :
charCode : cet attribut reprsente la lettre, ou plutt le caractre de la touche concerne par lvnement. Ce caractre est dfinit par un code numrique.
keyCode : cette proprit contient le code de la touche enfonce ou relche.
keyLocation : indique lemplacement
de la touche sur le clavier.

altKey : indique si la touche Alt  est enfonce en parallle de lvnement de la
souris.


ctrlKey : indique si la touche Ctrl  (ou Cmd  pour les utilisateurs de Mac) est
enfonce en parallle de lvnement
la souris.
 de 
shiftKey : indique si la touche Shift est enfonce en parallle de lvnement de


la souris.
Pour savoir sur quelle touche lutilisateur a appuy, nous pouvons utiliser la classe
Keyboard qui contient le code de chaque touche du clavier.
Par exemple, pour effectuer

une action sur lutilisateur qui appuie sur la touche A , nous procderons ainsi :
1
2
3
4

if ( event . keyCode == Keyboard . A )


{
trace ( " Appui sur la touche [ A ] " ) ;
}

Il est important de bien distinguer les deux proprits charCode et keyCode.


La premire dsigne le code de la touche dans le jeu de caractres actuel.
Chaque caractre est associ une valeur numrique : on parle alors de
codage de caractres ou encore encodage. Par dfaut, il sagit de lUTF8, qui prend en charge le clbre code ASCII. En revanche, keyCode fait
rfrence la touche en elle-mme indpendamment du codage utilis. Ainsi
les lettres a et A sont associes deux codes diffrent en UTF-8, mais
la touche reste la mme, et donc keyCode aussi. Inversement la touche 1 du
pav numrique est diffrente du 1 du clavier central, pourtant le caractre
est strictement le mme.
Enfin, avant de basculer vers des exemples, nous allons revenir sur la proprit keyLocation.
Si vous regardez
 que celui-ci est compos de
 votre clavier de plus prs, vous verrez alors
deux touches Ctrl distincts, ou encore de deux touches Shift diffrentes. Aussi surprenant que cela puisse paratre, chaque couple possde exactement les mmes attributs
charCode et keyCode.

Mais comment les diffrencier alors ?

456

LE CLAVIER
Cest l quentre en scne cette fameuse proprit keyLocation. Sous forme de nombre,
cette proprit permet de dfinir lemplacement de la touche sur le clavier. Pour cela, la
classe KeyLocation propose un jeu de constantes relativement explicite. Jugez plutt :
STANDARD, LEFT, RIGHT et NUM_PAD.

Exercice : grer laffichage de lanimation


Cest lheure de passer un peu la pratique travers un petit exemple, simple certes,
mais trs intressant. Lobjectif est
 donc de basculer lanimation en mode plein
 cran
avec la combinaison Shift  + Entre  (et uniquement laide la touche 
Shift 

de gauche). Pour revenir laffichage normal, un simple appui sur la touche chap


devrait suffire.
Pour raliser le basculement dun mode daffichage un autre, nous aurons besoin dutiliser la proprit displayState dfini par la classe Stage. Cette proprit peut alors
prendre les valeurs des constantes NORMAL, FULL_SCREEN et FULL_SCREEN_INTERACTIVE
de la classe StageDisplayState.
Le mode FULL_SCREEN_INTERACTIVE permet le support complet du clavier
contrairement au mode FULL_SCREEN qui se limite quelques touches utiles
(comme les touches flches). Seulement, le support complet du clavier peut
introduire des failles de scurits (un site web imitant votre bureau en plein
cran pour vous demander et voler vos identifiants par exemple), cest pourquoi un message informatif et une demande de confirmation sont affichs
lutilisateur si votre application est sur une page web dans un navigateur.
Ce nest pas le cas pour le mode FULL_SCREEN qui restreint lutilisation du
clavier.
Avant de nous lancer tte baisse, rflchissons un peu et analysons ce que nous voulons
faire. Grce aux proprits
keyCode
et shiftKey, il est possible de dtecter la com

binaison des touches Shift  et Entre . En revanche, dans ce cas l, la gestion de
lvnement qui engendrera
le basculement en plein cran sera faite lors de lenfonce
ment de la touche Entre . Cest pourquoi, ce moment, nous
 naurons pas accs la
proprit keyLocation ni gnr lenfoncement de la touche Shift . Pour pouvoir grer correctement ce cas de figure, nous serons dans lobligation de dclarer une variable
charge de conserver la valeur de la proprit keyLocation de lvnement prcdent.
Pour commencer, nous pouvons donc mettre en place lcouteur suivant :
1
2
3
4
5
6
7

var lastKeyLocation : uint = 0 ;


stage . addEventListener ( KeyboardEvent . KEY_DOWN ,
chang erDAffichage ) ;
function ch angerDAffichage ( event : KeyboardEvent ) : void
{
// Gestion du changement du mode d ' affichage
lastKeyLocation = event . keyLocation ;
}

457

CHAPITRE 22. INTERAGIR AVEC LUTILISATEUR


Ensuite, nous devons dfinir la condition de mise
 en plein cran. Pour cela, nous allons donc dtecter lenfoncement de la touche Entre par sa proprit
keyCode qui

vaudra Keyboard.ENTER (quivalent 13), en prsence de la touche Shift , et utiliser
galement notre variable lastKeyLocation, comme ceci :
1
2
3
4

if ( event . keyCode == Keyboard . ENTER && event . shiftKey == true


&& lastKeyLocation == KeyLocation . LEFT )
{
// Mise en plein cran
}

La remise en mode daffichage normal sera beaucoup plus simple puisquil suffit de
dtecter une valeur Keyboard.ESCAPE
(quivalent 27) de la proprit keyCode qui


correspond la touche Echap .


Au final, cela nous donne le code suivant :
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

var lastKeyLocation : uint = 0 ;


stage . addEventListener ( KeyboardEvent . KEY_DOWN ,
chang erDAffichage ) ;
function changerDAffichage ( event : KeyboardEvent ) : void
{
if ( event . keyCode == Keyboard . ENTER && event . shiftKey ==
true && lastKeyLocation == KeyLocation . LEFT )
{
if ( stage . allowsFullScreen )
{
// Plein cran support
if ( stage . a l l o w s F u l l S c r e e n I n t e r a c t i v e )
{
// Plein cran avec support complet du clavier
stage . displayState = StageDisplayState .
F UL L_ SC R EE N_ I NT ER AC T IV E ;
}
else
{
// Plein cran restreint
stage . displayState = StageDisplayState .
FULL_SCREEN ;
}
}
}
if ( event . keyCode == Keyboard . ESCAPE )
{
stage . displayState = StageDisplayState . NORMAL ;
}
trace ( " Etat de l ' cran : " + stage . displayState ) ;

27
28
29

458

lastKeyLocation = event . keyLocation ;

CHAMPS DE SAISIE
Ne pas oublier de vrifier que les diffrents modes daffichage
sont disponibles laide des attributs allowsFullScreen et
allowsFullScreenInteractive de la classe Stage.
Si tout se passe bien, nous obtenons ceci dans la console en basculant entre laffichage
normal et le plein cran :
Etat de l cran : normal
Etat de l cran : full Scree nInter activ e
Etat de l cran : normal

Champs de saisie
Retour sur lobjet TextField
Introduction
Un champ de saisie est particulier : on y peut entrer du texte, le modifier ou leffacer.
Par exemple, vous pouvez demander le nom de lutilisateur grce un champ de saisie.
Il est possible de rendre un champ de texte ditable pour le transformer en champ de
saisie. Pour cela, rien de plus simple ! Il suffit de mettre lattribut type dun objet de
la classe TextField TextFieldType.INPUT comme ceci :
1

monSuperTexte . type = TextFieldType . INPUT ;

Comme dhabitude, ne pas oublier dimporter chaque classe que vous utilisez,
ici TextFieldType.
Reprenons un code base de TextField puis faisons en sorte de crer un champ de
saisie :
1
2

// Cr ation de l ' objet TextField


var monSuperTexte : TextField = new TextField () ;

3
4
5
6

// Formatage du texte
var format : TextFormat = new TextFormat ( " Arial " , 14 , 0x000000 ) ;
monSuperTexte . defaultTextFormat = format ;

7
8
9

// Ajout d ' une bordure


monSuperTexte . border = true ;

10
11
12
13

// Taille
monSuperTexte . width = 200 ;
monSuperTexte . height = 20 ;

14

459

CHAPITRE 22. INTERAGIR AVEC LUTILISATEUR


15
16
17

// Centrage
monSuperTexte . x = ( stage . stageWidth - monSuperTexte . width ) / 2 ;
monSuperTexte . y = ( stage . stageHeight - monSuperTexte . height ) /
2;

18
19
20

// Ajout l ' affichage


addChild ( monSuperTexte ) ;

21
22
23

// Il faut pouvoir s lectionner le texte ( ligne falcutative )


monSuperTexte . selectable = true ;

24
25
26

// Type du champ de texte : saisie


monSuperTexte . type = TextFieldType . INPUT ;

Je peux maintenant crire ce que je veux dans le champ de texte ditable, comme le
montre la figure 22.9.

Figure 22.9 Un champ de saisie !


Bien entendu, il est tout fait possible de rendre un champ de saisie multi-lignes. Cela
fonctionne exactement de la mme faon que pour un champ de texte basique :
1
2
3

// Basculement en mode multi - lignes


monSuperTexte . multiline = true ;
monSuperTexte . autoSize = TextFieldAutoSize . LEFT ;

Ce qui nous donne la figure 22.10.


460

CHAMPS DE SAISIE

Figure 22.10 Un champ de saisie multi-lignes


Restriction de la saisie
Lorsque nous dfinissons un objet TextField en tant que champ de saisie de texte,
lutilisateur peut crire ce quil souhaite lintrieur. Dans certains cas, cela peut
savrer inappropri. Imaginons que nous voulions crer un formulaire dans lequel lutilisateur peut renseigner des informations personnelles, telles que son nom, son prnom,
sa date de naissance, etc. Il peut alors devenir gnant de se retrouver avec un nom de
famille comportant des chiffres, ou encore avec une date de naissance contenant des
caractres tels que # , @ ou & .
En Actionscript, il est possible de restreindre la saisie du texte, cest--dire
nautoriser la saisie que certains caractres. Pour effectuer cela, nous devons nous servir
de la proprit restrict de la classe TextField. Il suffit alors de renseigner la liste
des caractres autoriss, comme ceci :
1
2

// Restriction de la saisie du texte


monSuperTexte . restrict = " ABC " ;

Une fois le programme lanc, essayez de saisir divers caractres. Vous verrez alors quil
est possible de saisir uniquement les trois caractres que nous avons prcis au-dessus,
comme le montre la figure 22.11.

Figure 22.11 Restriction de la saisie aux trois caractres A , B ou C


461

CHAPITRE 22. INTERAGIR AVEC LUTILISATEUR


Je pense que certains simaginent dj quautoriser la saisie dun grand nombre de
caractres va tre une galre colossale ! Heureusement, il existe des raccourcis pour
faciliter la restriction une plage de caractres. Par exemple, voici comment autoriser
seulement la saisie de chiffres :
monSuperTexte . restrict = "0 - 9 " ;

Ce qui nous donne la figure 22.12.

Figure 22.12 Restriction de la saisie aux caractres numriques


Pour les lettres, cela fonctionne exactement de la mme manire. Voici comment faire,
avec en prime lajout de lespace (drlement pratique pour sparer les mots) :
monSuperTexte . restrict = "A - Z " ;

Si vous entrez des caractres alphabtiques, ceux-ci sont alors automatiquement saisis
en majuscule comme vous voir sur la figure 22.13.

Figure 22.13 Restriction de la saisie aux majuscules

Pour restreindre la saisie lensemble des caractres alpha-numriques, vous


devrez alors renseigner la chane de caractres suivante : "A-Za-z0-9 ".

Quelques autres proprits utiles


Il arrive parfois que nous ayons besoin de masquer le contenu de la saisie dun
texte, linstar des mots de passe. Comme dhabitude, lActionscript a tout prvu :
un attribut de la classe TextField, nomm displayAsPassword, permet de faire ceci.
Cette proprit est un boolen quil suffit donc de mettre la valeur true :
1
2

// D finition de la saisie en mode mot de passe


monSuperTexte . displayAsPassword = true ;

prsent, si vous saisissez du texte, le contenu du champ de texte sera remplac par
une srie de * , comme sur la figure 22.14.

Figure 22.14 La saisie de mot de passe


462

CHAMPS DE SAISIE
Contrairement un champ de texte, disons traditionnel, seul laffichage est
diffrent. Vous pouvez ainsi utiliser la proprit text comme son habitude.
Cette dernire contient toujours le contenu de la saisie et non la srie de
* .
Enfin, vous pouvez galement noter la prsence de lattribut maxChars permet de dfinir
le nombre de caractres maximal saisir. Une fois cette limite atteinte, plus aucun
caractre ne peut tre ajout.
Pour utilise cette fonction, il vous suffit de prciser simplement le nombre de caractres
autoriss pour la saisie :
1

monSuperTexte . maxChars = 10 ;

vnements et TextField
Dtecter une modification
Il est possible de dtecter la moindre modification du texte contenu dans le
champ de saisie car ce dernier dclenche alors un vnement de type Event.CHANGE.
Cela se produit lorsque :

Un caractre est entr.


Un caractre est supprim.
Du texte est coll dans le champ de saisie.
Une partie du texte est supprime.
Une partie du texte est coupe.
De manire gnrale, le type dvnement Event.CHANGE est utilis sur les
objets qui disposent dune valeur importante susceptible dtre modifie :
champs de saisie, barre de dfilement, compteur. . . Vous pouvez vous-mme
dclencher des vnements de ce type dans vos classes si besoin.

Ajoutons donc un couteur dvnement notre champ de saisie :


1
2
3
4
5

monSuperTexte . addEventListener ( Event . CHANGE ,


d e t e c t e r M odification ) ;
function d e t e cterModification ( event : Event ) : void
{
trace ( monSuperTexte . text ) ;
}

Si vous entrez du texte dans notre champ de saisie, vous obtiendrez une sortie similaire
dans la console :
C
Ce
Cec
Ceci

463

CHAPITRE 22. INTERAGIR AVEC LUTILISATEUR


Ceci
Ceci
Ceci
Ceci
Ceci
Ceci
Ceci
Ceci
Ceci
Ceci
Ceci
Ceci
Ceci
Ceci
Ceci
Ceci

e
es
est
est
est
est
est
est
est
est
est
est
est
est
est

m
ma
ma
ma
ma
ma
ma
ma
ma
ma
ma

s
sa
sai
sais
saisi
saisie
saisie
saisie !

Lobjet TextEvent
En Actionscript, il existe un objet vnement particulirement bien adapt aux
champs de texte : il sagit de la classe TextEvent ! Cet vnement sera donc troitement li ce qui ce passe au niveau du clavier, mais pas uniquement. Toutefois, lors
de la saisie dun texte dans un champ laide du clavier, cet vnement sera distribu, disons, en doublon de lobjet KeyboardEvent. Vous aurez alors la possibilit
dutiliser lun ou lautre de ces vnements, mais aussi pourquoi pas les deux !
La figure 22.15 reprend lensemble des proprits de cette classe et de sa super-classe
Event.

Figure 22.15 La classe TextEvent


464

CHAMPS DE SAISIE
Cette classe dvnements ajoute donc un unique attribut nomm text par rapport
sa super-classe. Il vous sera donc srement utile !
Pour comprendre lutilit de cet vnement, je vous propose maintenant de dcouvrir
les deux manires dont peut tre gnr celui-ci. Les constantes qui servent dfinir le
type de ce dernier sont les suivantes :
LINK : est distribu lorsque que vous cliquez sur un lien prsent dans un objet
TextField.
TEXT_INPUT : est gnr avant chaque modification dun champ de saisie, donc
chaque enfoncement dune touche, mais galement lors de la rptition dun caractre
si celle-ci reste enfonce.
Lvnement LINK est relativement simple mettre en place. Comme nous lavons
dit plus haut, ce type dvnements est gnr lorsque vous cliquez sur un lien lintrieur dun champ de texte. Souvenez-vous, pour crer un lien dans un champ de texte,
nous utilisons du texte sous forme HTML. Un lien scrit alors de la faon suivante :
1

<a href = " adresse " > lien </ a >

Pour utiliser lvnement FOCUS, nous devons nanmoins spcifier dans le code HTML
auquel nous souhaitons faire appel pour cet vnement. Pour cela, il est ncessaire de
rajouter la chane de caractres event : en en-tte du lien, comme cela :
1

monSuperTexte . htmlText = " <a href = ' event : adresse '> lien </ a > " ;

Ensuite, nous pouvons dfinir notre fonction dcouteur, comme vous savez maintenant
le faire :
1
2
3
4
5

monSuperTexte . addEventListener ( TextEvent . LINK , capterLien ) ;


function capterLien ( event : TextEvent ) : void
{
trace ( event . text ) ;
}

En cliquant sur le lien dans Flash Player, vous pourrez alors voir apparatre ceci dans
la console de sortie :
adresse

Le second vnement propos par la classe TextEvent est donc TEXT_INPUT ! Pour
commencer, je vous invite tester lcouteur suivant, afin de bien voir comment Flash
Player ragit cet vnement :
1
2
3
4
5

monSuperTexte . addEventListener ( TextEvent . TEXT_INPUT ,


detecterSaisie ) ;
function detecterSaisie ( event : TextEvent ) : void
{
trace ( event . text ) ;
}

Essayez alors de saisir quelques caractres au clavier :


465

CHAPITRE 22. INTERAGIR AVEC LUTILISATEUR

C
e
c
i
e
s
t
m
a
s
a
i
s
i
e
!

Quel est lintrt de cet vnement ? Ne pouvons-nous pas faire la mme


chose avec KeyboardEvent.Key_DOWN ?
Il est vrai que vu dici, ce type dvnements napporte rien de plus par rapport un
vnement issu de la classe KeyboardEvent. Nanmoins, pour juger de son utilit, il est
ncessaire de bien comprendre la diffrence de gnration de ces deux vnements. Le
premier est gnr ds lors quune touche est enfonce, quelle que soit cette touche. En
revanche, le second est distribu uniquement dans le cas dune entre de texte.
Dans
ce


dernier
cas,
nous
pouvons
donc
exclure
lappui
sur
les
touches
suivantes
:
Alt
,
Ctrl


,



Shift
,
Tab
,
ou
encore
Entre
.
Par
ailleurs,
la
classe
TextEvent
facilite
norm




ment la gestion du texte. Par exemple, dans le cas prsent, pas question dencodage !
La proprit text contient directement le caractre et non son code numrique.
Enfin, une dernire petite subtilit rend lutilisation de cet vnement trs pratique. Il
faut savoir que ce nest quune fois que lvnement TextEvent.TEXT_INPUT a termin
son aller-retour dans le flux dvnements que le champ de saisie est mis jour. Ceci va
donc nous permettre de revenir sur des proprits de la super-classe Event. Rappelezvous, cette classe disposait dun attribut nomm cancelable. Soyez bien attentif ce
qui va suivre ! Cet attribut indique si le comportement associ lvnement peut tre
vit. Dans notre cas, il sagit de la mise jour du contenu du champ de texte actif.
Si ce comportement par dfaut peut tre vit, la mthode preventDefault() permet
quant elle de lannuler.
Essayez donc le code suivant :
1

466

monSuperTexte . addEventListener ( TextEvent . TEXT_INPUT ,

CHAMPS DE SAISIE

2
3
4
5
6
7
8

detecterSaisie ) ;
function detecterSaisie ( event : TextEvent ) : void
{
if ( event . cancelable == true ) {
trace ( event . text ) ;
event . preventDefault () ;
}
}

Voyez plutt le rsultat, plus aucun caractre nest affich lintrieur du champ de
saisie de texte.

La gestion du focus
Dans une interface graphique complexe, compose par exemple de plusieurs champs de
saisie, un seul objet peut tre actif la fois. Je veux dire par l quun seul champ de
texte doit tre rempli lorsque vous tapez au clavier. Cela introduit donc la notion de
focus, qui dsigne alors lobjet cible actif. Pour reprer cet objet daffichage au sein de
lensemble de la liste daffichage, une rfrence ce dernier est stock dans lattribut
focus de stage. Nous avons accs cet attribut par un getter et un setter. Il est
donc tout fait possible de dfinir nous-mmes lobjet qui a le focus.
Lorsque le focus est modifi, un vnement de type FocusEvent est alors distribu.
Pour un objet donn, deux types dvnements sont distincts :
FOCUS_IN : gnr lorsque que lobjet interactif prend le focus.
FOCUS_OUT : gnr lorsque que lobjet interactif perd le focus.
Sachant que lexercice qui suit utilise ces types dvnements, nous nous passerons
dexemples ici.

Exercice : un mini formulaire


Pour conclure ce chapitre, je vais vous prsenter un petit exercice consistant raliser
un formulaire. Ce sera loccasion de revenir sur certains points importants tout en
utilisant les vnements fournis par Flash Player.
Pour raliser ce mini formulaire, nous utiliserons quatre champs de saisie de texte
afin de pouvoir renseigner les informations suivantes pour un quelconque traitement :

Nom.
Prnom.
Date de naissance.
Lieu de naissance.

Une particularit de notre formulaire sera de prsenter les intituls, ou tiquettes,


lintrieur des champs de saisie eux-mmes. Pour tre plus prcis, le concept est de
pr-remplir les champs de texte par leur tiquette. Puis nous utiliserons les vnements
FOCUS_IN et FOCUS_OUT pour effacer ou remettre en place ces intituls.
467

CHAPITRE 22. INTERAGIR AVEC LUTILISATEUR


Pour mieux visualiser la chose, voici, la figure 22.16, un aperu de ce que nous
obtiendrons la fin de lexercice.

Figure 22.16 Un formulaire avec libell intgr


tant donn que nous serons amens utiliser plusieurs champs de saisie similaires, il
peut tre intressant de dfinir une nouvelle classe. Je suggre donc de crer un objet
daffichage personnalis partir dun TextField.
Dans un premier temps, je vous propose de dcouvrir cette classe que jai nomme
EditableTextField, puis nous lanalyserons ensuite :
1
2
3
4
5
6

package
{
import
import
import
import

flash . text . TextField ;


flash . text . TextFormat ;
flash . text . TextFieldType ;
flash . events . FocusEvent ;

7
8
9
10
11
12
13

public class EditableTextField extends TextField


{
// Attributs
private var _etiquette : String ;
private var _formatEtiquette : TextFormat ;
private var _formatEdition : TextFormat ;

14
15
16
17
18
19
20
21
22
23
24

468

public function EditableTextField ( etiquette : String )


{
_etiquette = etiquette ;
_formatEtiquette = new TextFormat ( " Arial " , 14 ,
0x999999 ) ;
_formatEdition = new TextFormat ( " Arial " , 14 ,
0x000000 ) ;
defaultTextFormat = _formatEtiquette ;
type = TextFieldType . INPUT ;
selectable = true ;
border = true ;
text = _etiquette ;

CHAMPS DE SAISIE
25
26

27

addEventListener ( FocusEvent . FOCUS_IN ,


effacerEtiquette ) ;
addEventListener ( FocusEvent . FOCUS_OUT ,
remettreEtiquette ) ;

28

// M thodes d ' couteurs


private function effacerEtiquette ( event : FocusEvent ) :
void
{
if ( text == _etiquette )
{
defaultTextFormat = _formatEdition ;
text = " " ;
}
}

29
30
31
32
33
34
35
36
37
38

private function remettreEtiquette ( event : FocusEvent ) :


void
{
if ( text == " " )
{
defaultTextFormat = _formatEtiquette ;
text = _etiquette ;
}

39
40
41
42
43
44
45
46

47
48

49
50
51

Pour analyser cette classe, prenons les choses telles quelle viennent. En premier, jai
dclar les trois attributs suivants :
_etiquette : contient lintitul ou ltiquette du champ de texte.
_formatEtiquette : dfinit le formatage utiliser lors de laffichage de lintitul.
_formatEdition : dfinit le formatage adopter lors de ldition du champ de texte.
lintrieur du constructeur de la classe, il ny a rien de bien compliqu. Nous initialisons lensemble des attributs et en profitons pour regrouper les diffrentes instructions communes, touchant aux proprits de la super-classe TextField. Pour clturer
ce constructeur, deux couteurs sont mis en place afin de grer la transition entre
laffichage de ltiquette et son effacement avant ldition du champ de saisie. Je ne vais
pas entrer plus avant dans les dtails car je juge que vous tes prsent suffisamment
dous pour comprendre le fonctionnement de cette classe tout seuls.
469

CHAPITRE 22. INTERAGIR AVEC LUTILISATEUR


En dfinissant les couteurs de cette manire, lintrieur dune classe, vous
pouvez facilement simplifier et allger le code. Effectivement, si vous aviez
d le faire depuis lextrieur de la classe, vous auriez trs certainement dfini
deux fonctions dcouteurs pour chacun des champs de saisie de linterface
graphique. Nhsitez pas utiliser cette technique pour simplifier et organiser
au mieux votre code.
Maintenant, il ne reste plus qu disposer les champs de texte lcran et ajuster les
derniers dtails :
1
2
3
4
5
6
7
8

// Champ de saisie du nom de famille


var nom : EditableTextField = new EditableTextField ( " Nom " ) ;
nom . restrict = "A - Za - z \\ - " ;
nom . width = 185 ;
nom . height = 20 ;
nom . x = 10 ;
nom . y = 10 ;
addChild ( nom ) ;

9
10
11
12
13
14
15
16
17

// Champ de saisie du pr nom


var prenom : EditableTextField = new EditableTextField ( " Pr nom " ) ;
prenom . restrict = "A - Za - z \\ - " ;
prenom . width = 185 ;
prenom . height = 20 ;
prenom . x = 205 ;
prenom . y = 10 ;
addChild ( prenom ) ;

18
19
20
21
22
23
24
25
26
27

// Champ de saisie de la date de naissance


var dateDeNaissance : EditableTextField = new EditableTextField ( "
JJ / MM / AAAA " ) ;
dateDeNaissance . restrict = "0 - 9 / " ;
dateDeNaissance . maxChars = 10 ;
dateDeNaissance . width = 100 ;
dateDeNaissance . height = 20 ;
dateDeNaissance . x = 10 ;
dateDeNaissance . y = 40 ;
addChild ( dateDeNaissance ) ;

28
29
30
31
32
33
34
35
36

// Champ de saisie du lieu de naissance


var lieuDeNaissance : EditableTextField = new EditableTextField ( "
Lieu de naissance " ) ;
lieuDeNaissance . restrict = "A - Za - z0 - 9 \\ - " ;
lieuDeNaissance . width = 270 ;
lieuDeNaissance . height = 20 ;
lieuDeNaissance . x = 120 ;
lieuDeNaissance . y = 40 ;
addChild ( lieuDeNaissance ) ;

470

CHAMPS DE SAISIE
Vous remarquerez, travers cet exemple, que la dfinition de la proprit
restrict naffecte que la saisie de texte depuis lextrieur du programme.
Cela explique pourquoi laffichage de lintitul de lobjet dateDeNaissance
ne pose aucun problme.

En rsum
Les actions produites par lutilisateur sur la souris gnrent des objets de la classe
MouseEvent.
Laffichage de la souris peut tre gr via les mthodes de la classe Mouse.
Le glisser-dposer est une technique qui peut tre contrl par les mthodes startDrag()
et stopdrag().
Un objet KeyboardEvent est gnr aprs toute action produite sur le clavier.
Un objet TextField est transformable en champ de saisie, en redfinissant la valeur
de la proprit type laide les constantes de la classe TextFieldType.
Diffrentes proprits de la classe TextField servent paramtrer la saisie dun
texte, telles que restrict, displayAsPassword ou maxChars.
Les vnements issus des classes TextEvent et FocusEvent augmentent les possibilits de la gestion dvnements provenant de la souris ou du clavier.

471

CHAPITRE 22. INTERAGIR AVEC LUTILISATEUR

472

Chapitre

23

Animer des objets


Difficult :
Dans le chapitre prcdent, nous avons commenc donner vie nos applications en interagissant avec lutilisateur au moyen du clavier et de la souris. Grce cela, les programmes
peuvent agir suivant les dcisions prises par lutilisateur. Nanmoins, il nest pas toujours
ncessaire dattendre une action de la part de lutilisateur avant de devoir mettre jour
laffichage.
Comme vous laurez devin, nous allons ici apprendre crer des animations. Cela vous
permettra damliorer la jouabilit de vos jeux ou la fluidit de votre site web. Dans ce
chapitre, nous allons donc voir comment animer des objets en utilisant diffrentes techniques.

473

CHAPITRE 23. ANIMER DES OBJETS

Lanimation par images-cls


Lvnement Event.ENTER_FRAME
Pour bien comprendre ce qui va suivre, nous allons faire un petit point sur les animations Flash et leur fonctionnement. Une application Flash est une animation
cadence un nombre dimages par seconde constant. Toute modification lie un
objet prsent sur lcran entrane donc une mise jour de laffichage limage suivante
tout en gnrant un nouveau rendu.
lorigine, ce systme danimation par images successives permettait de raliser des
animations complexes laide de Flash Professionnal. En utilisant les MovieClip, il
tait alors possible danimer des objets laide dimages-cls. Comme nous lavons dj
dit prcdemment dans ce cours, cette classe, drive de la classe Sprite, ajoute une
ligne de temps (ou timeline en anglais). Voici, la figure 23.1, un exemple ddition
dun MovieClip lintrieur du logiciel Adobe Flash Professionnal.

Figure 23.1 Une ligne de temps dun MovieClip


Revenons maintenant nos moutons, ou plutt lActionscript ! Le principe est le
mme que dans Flash Professionnal, laffichage est mis jour automatiquement
partir des vnements qui se produisent et dventuelles modifications ralises
lintrieur du code. Les rendus sont donc crs frquence constante, dfinie par le
nombre dimages par seconde paramtr pour le projet. Bien entendu, tout ceci est
gr directement par Flash Player !
Pour dfinir le cadencement de lanimation, nous pouvons paramtrer la proprit
frameRate li au fichier SWF, comme dans la ligne suivante :
1

[ SWF ( width = " 400 " , height = " 200 " , backgroundColor = " # ffffff " ,
frameRate = " 25 " ) ]

Il est possible de procder autrement pour modifier la cadence danimation du programme, il suffit de changer la valeur de la proprit frameRate de lobjet stage
comme ceci :
1

stage . frameRate = 30 ;

Crer une animation basique


Animer un objet consiste faire voluer au moins lune de ses proprits au cours
du temps. Par exemple, lors dun mouvement, la position dun objet est dcompose
474

LANIMATION PAR IMAGES-CLS


en petits incrments rpartis tout au long de sa trajectoire au fil du temps. Une bonne
ide serait alors de synchroniser lexcution du code avec la cadence du fichier SWF.
En effet, il est inutile de modifier la position dun objet toutes les millisecondes si un
rendu est gnr seulement toutes les 40 millisecondes.
Lors de lexcution du programme, un vnement de type Event.ENTER_FRAME est
gnr avant chaque nouveau rendu. Il est ainsi possible de raliser des modifications
avant chaque mise jour de laffichage. Je vous propose donc de raliser une petite
animation utilisant ce principe.
Dans un premier temps, nous allons crer un petit carr au centre de notre application :
1
2
3
4
5
6

var objet : Shape = new Shape () ;


objet . graphics . beginFill ( 0xAA00FF ) ;
objet . graphics . drawRect ( -25 , -25 , 50 , 50 ) ;
objet . x = stage . stageWidth / 2 ;
objet . y = stage . stageHeight / 2 ;
addChild ( objet ) ;

Pour suivre la cadence de lanimation, nous pouvons alors ajouter un couteur


lvnement Event.ENTER_FRAME en associant une fonction dcouteur qui servira
animer notre objet. Voici notre instruction :
1

objet . addEventListener ( Event . ENTER_FRAME , animerObjet ) ;

lintrieur de notre fonction, nous pouvons ensuite animer notre carr. Par exemple,
en incrmentant la proprit rotation, nous forons lobjet tourner chaque nouveau
rendu, comme ceci :
1
2
3
4

function animerObjet ( event : Event ) : void


{
objet . rotation ++;
}

Au final, nous obtenu un objet en perptuelle rotation comme illustr sur limage 23.2.

Figure 23.2 Un objet en rotation


475

CHAPITRE 23. ANIMER DES OBJETS


Ce type de manipulation est bien videmment ralisable avec nimporte quel
attribut ou mthode dun objet. Il est alors possible de modifier sa position,
son orientation, sa taille, ou encore les filtres associs cet objet. La seule
limite est votre imagination !
Je vous propose maintenant daller un peu plus loin et danimer un flou sur notre
objet. Nous allons galement en profiter pour apprendre stopper une animation
grce la mthode removeEventListener().
Dans un premier temps, plaons un filtre de type BlurFilter sans effet apparent :
1
2

var flou : BlurFilter = new BlurFilter (0 , 0 , BitmapFilterQuality .


HIGH ) ;
objet . filters = new Array ( flou ) ;

Puis, nous allons retravailler notre fonction animer(), afin dincrmenter le flou horizontal avant chaque nouveau rendu de notre application. Il nous faudra aussi mettre
jour la proprit filters de notre objet, pour que le filtre prenne effet. Pour finir, nous
supprimerons notre couteur lvnement Event.ENTER_FRAME pour stopper lanimation. Dans notre exemple, nous arrterons daugmenter le flou horinzontal lorsque
celui-ci aura atteint la valeur 50.
Voyez plutt :
1
2
3
4
5
6
7
8

function animerObjet ( event : Event ) : void


{
flou . blurX ++;
objet . filters = new Array ( flou ) ;
if ( flou . blurX > 50 ) {
objet . removeEventListener ( Event . ENTER_FRAME ,
animerObjet ) ;
}
}

En lanant lanimation, vous verrez alors notre carr se flouter progressivement puis se
figer au bout dun certain temps, comme sur limage 23.3.

Figure 23.3 Animation dun filtre dun objet


476

LUTILISATION DE TIMER

Lutilisation de Timer
La classe Timer
Lorsquune animation Flash est lance, les instructions du programme sont excutes
une vitesse qui est dfinie par votre machine. Ainsi, quand vous passerez dune machine une autre, les instructions ne seront pas excutes au mme rythme. Il est donc
impossible lintrieur du code de synchroniser correctement les instructions avec le
temps. Thoriquement, il serait possible dutiliser les vnements Event.ENTER_FRAME
pour raliser cela, mais je vous recommande trs fortement dutiliser plutt les Timer !
Comme vous ntes pas obligs de me croire sur parole, je vais essayer de vous donner diverses raisons qui justifient ce choix. Tout dabord, les vnements Event.ENTER_FRAME
ne sont pas gnrs de manire extrmement prcise. En effet, un rendu trop charg
ou un calcul un peu complexe pourrait ralentir lgrement la cadence de votre animation. Par ailleurs, une modification de la cadence de votre fichier SWF suffirait
drgler lintgralit de votre programme. Vous seriez alors dans lobligation deffectuer
de lourdes modifications lintrieur de votre code source, mme si limpact peut tre
limit en utilisant des constantes. Enfin, il est probable que vous ayez besoin dexcuter
des instructions une cadence leve, cela ne justifie pas lacclration du rythme de
rendu de laffichage pour autant.
Ainsi, lorsque lon souhaite grer le temps de manire significative, il est prfrable
dutiliser la classe Timer. Le contrle sur les intervalles temporels en sera amlior et
vous facilitera la vie pour la cration de moteurs physiques par exemple.
Comme nous lavons dit prcdemment, lutilisation de lvnement
Event.ENTER_FRAME est le meilleur moyen de synchroniser vos actions
lintrieur du code avec la cadence danimation du fichier SWF. Nanmoins, lvnement Event.ENTER_FRAME doit tre utilis uniquement des
fins danimation et non pour grer le temps en tant que tel. Prfrez alors
lutilisation de Timer.
La figure 23.4 dcrit cette classe Timer.
Sans surprise, lutilisation dun Timer se base sur le concept des vnements. Son
principe de fonctionnement consiste donc gnrer des vnements intervalles temporels rguliers. Ces vnements sont alors de type TimerEvent et sont produits
intervalles spcifis par la proprit delay de la classe Timer. La proprit repeatCount
permet de dfinir le nombre total dvnements qui doivent tre crs.
Linstruction suivante est un exemple qui dfinit un Timer paramtr 5 vnements
gnrs toutes les secondes :
1

var minuteur : Timer = new Timer ( 1000 , 5 ) ;

La proprit delay reprsente un intervalle de temps en millisecondes. Par


ailleurs, la valeur 0 pour repeatCount sert rpter la cration dvnements
un nombre infini de fois.
477

CHAPITRE 23. ANIMER DES OBJETS

Figure 23.4 La classe Timer hritant de EventDispatcher

Lors de linstanciation dun objet de la classe Timer, le dcompte du temps nest toutefois pas encore lanc. Pour contrler cela, nous disposons des trois mthodes start(),
stop() et reset(). Enfin, sachant que la classe Timer hrite de EventDispatcher,
nous pouvons assigner un couteur notre objet de type Timer.
Voici donc le code complet permettant de lancer la gnration dvnements TimerEvent.
1
2
3
4
5
6
7

var minuteur : Timer = new Timer ( 1000 , 5 ) ;


minuteur . addEventListener ( TimerEvent . TIMER , maFonction ) ;
minuteur . start () ;
function maFonction ( event : TimerEvent ) : void
{
// Instructions
}

Comme vous laurez compris, lvenement TIMER de TimerEvent est le type dvnements gnrs chaque intervalle de temps dcompt. Mais il existe galement le type
COMPLETE qui est produit lorsque le nombre ditrations repeatCount est atteint et que
le Timer arrive terme.

Exercice : une horloge


Prsentation des graphismes
Comme le titre lindique, nous allons raliser une horloge analogique. Cet exercice va
nous permettre de mettre en pratique tout ce que nous avons vu sur les classes Timer
et TimerEvent. Mais avant den dire plus sur le fonctionnement et la gestion des
couteurs, je vous prsente le rsultat de lexercice sur la figure 23.5.
478

LUTILISATION DE TIMER

Figure 23.5 Une horloge analogique


Sachant que lobjectif nest pas la partie visuelle, mais plutt la gestion du temps,
jai dcid de placer une bonne partie du code li laffichage lintrieur de deux
classes Cadran et Aiguille. La premire permet de dessiner le cadran de lhorloge en
spcifiant le rayon de celui-ci dans le constructeur. La seconde classe sert tracer une
aiguille en fonction de son type : HEURE, MINUTE ou SECONDE.
Je vous laisse dcouvrir ces deux classes. Voici la premire nomme Cadran :
1
2
3
4

package
{
import flash . display . Sprite ;
import flash . display . Shape ;

public class Cadran extends Sprite


{

6
7
8

public function Cadran ( rayon : Number )


{
super () ;
for ( var i : int = 0 ; i < 60 ; i ++) {
var point : Shape = new Shape () ;
point . graphics . beginFill ( 0x888888 ) ;
if (( i % 5 ) == 0 ) {
point . graphics . drawCircle (0 , 50 , 2 ) ;
} else {
point . graphics . drawCircle (0 , 50 , 1 ) ;
}
point . rotation = i * 6 ;
addChild ( point ) ;
}
}

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

Et voici la classe Aiguille :


1
2
3

package
{
import flash . display . Shape ;

4
5
6

public class Aiguille extends Shape


{

479

CHAPITRE 23. ANIMER DES OBJETS


// Constantes
public static const HEURE : String = " heure " ;
public static const MINUTE : String = " minute " ;
public static const SECONDE : String = " seconde " ;

7
8
9
10
11

// Constructeur
public function Aiguille ( type : String )
{
super () ;
var longueur : Number ;
if ( type == HEURE ) {
longueur = 30 ;
} else {
longueur = 45 ;
}
if ( type == SECONDE ) {
graphics . beginFill ( 0x880000 ) ;
} else {
graphics . beginFill ( 0x000000 ) ;
}
graphics . moveTo ( - 1 .5 , 0 ) ;
graphics . lineTo ( - 0 .5 , longueur / 4 ) ;
graphics . lineTo ( 0 .5 , longueur / 4 ) ;
graphics . lineTo ( 1 .5 , 0 ) ;
graphics . lineTo ( 0 .5 , - longueur ) ;
graphics . lineTo ( - 0 .5 , - longueur ) ;
graphics . endFill () ;
}

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

Si vous souhaitez tester le code de cette horloge, je vous invite alors crer deux
nouvelles classes et y insrer les lignes de code que je viens de vous fournir.
Mise en place des lments lcran
Maintenant, il est temps de placer les diffrents lments qui composent lhorloge sur
la scne principale. Nous aurons donc besoin dun cadran, ainsi que trois aiguilles, une
de chaque type. Enfin, nous centrerons le tout pour avoir lhorloge au milieu de lcran.
Il ny a rien de compliqu pour faire cela, cest pourquoi je vous expose le code directement :
1
2
3
4
5

// Mise en place des objets d ' affichage l ' cran


x = stage . stageWidth / 2 ;
y = stage . stageHeight / 2 ;
var cadran : Cadran = new Cadran ( 50 ) ;
var aiguilleHeures : Aiguille = new Aiguille ( Aiguille . HEURE ) ;

480

LUTILISATION DE TIMER
6
7
8
9
10
11

var aiguilleMinutes : Aiguille = new Aiguille ( Aiguille . MINUTE ) ;


var aiguilleSecondes : Aiguille = new Aiguille ( Aiguille . SECONDE ) ;
addChild ( cadran ) ;
addChild ( aiguilleHeures ) ;
addChild ( aiguilleMinutes ) ;
addChild ( aiguilleSecondes ) ;

ce stade, nous avons alors notre horloge entirement dessine avec les aiguilles en
position initiale, cest--dire indiquant linstant 00 :00 :00 .
Mettre lhorloge lheure
Il serait grand temps de mettre jour lheure affiche sur notre horloge. Pour cela,
nous allons faire une brve introduction la gestion des dates et des heures.
Pour pouvoir manipuler les dates et les heures, nous avons notre disposition la classe
Date. Cette dernire intgre tout un tas de proprits et mthodes servant notamment
rcuprer des informations sur la date en question.
Voil comment instancier un objet Date, en rfrence au jour et lheure actuels :
1

var maDate : Date = new Date () ;

Parmi lensemble des mthodes fournies par cette classe, nous allons avoir recours
aux trois suivantes : getHours(), getMinutes() et getSeconds(), dont les noms sont
relativement explicites.
Si vous voulez en apprendre davantage sur lobjet Date, je vous conseille
daller visiter sa page officielle.

Documentation Date
B
Code web : 496063


Pour en revenir notre horloge, voici comment nous pouvons rcuprer lheure actuelle
pour mettre celle-ci jour :
1
2
3
4
5

// Mise l ' heure des aiguilles


var heureActuelle : Date = new Date () ;
aiguilleSecondes . rotation = 360 * heureActuelle . getSeconds () /
60 ;
aiguilleMinutes . rotation = 360 * heureActuelle . getMinutes () /
60 ;
aiguilleHeures . rotation = 360 * heureActuelle . getHours () / 12 ;

Animer lhorloge
Cest maintenant que nous allons utiliser la classe Timer afin de gnrer un vnement intervalle rgulier. Dans notre cas, nous voulons pouvoir mettre jour
481

CHAPITRE 23. ANIMER DES OBJETS


nos aiguilles chaque seconde. Nous devrons galement faire en sorte que nos aiguilles
tournent indfiniment.
Si vous avez bien suivi ce qui a t dit auparavant, vous tes alors capables de trouver
ce code tout seul :
1
2
3
4

// Mise en place du Timer


var minuteur : Timer = new Timer ( 1000 , 0 ) ;
minuteur . addEventListener ( TimerEvent . TIMER , bougerAiguilles ) ;
minuteur . start () ;

Pour animer notre horloge, nous devrons donc mettre jour lorientation de chacune
des aiguilles toutes les secondes. La seule difficult est de ne pas se tromper sur la
valeur des angles appliquer pour chaque aiguille.
Notre fonction dcouteur ressemble alors ceci :
1
2
3
4
5
6
7

// Fonction d ' couteur


function bougerAiguilles ( event : TimerEvent ) : void
{
aiguilleSecondes . rotation += 360 / 60 ;
aiguilleMinutes . rotation += 360 / ( 60 * 60 ) ;
aiguilleHeures . rotation += 360 / ( 60 * 60 * 24 ) ;
}

Voil qui est fait !

Les interpolations avec TweenMax


Enfin, il est possible dutiliser ce que lon appelle des interpolations (ou tweens
en anglais) pour animer des objets. Il nest dans ce cas pas ncessaire de rpter des
instructions, les interpolations vont faire tout le travail notre place !
Une interpolation est un calcul effectu lavance de lanimation dun ou plusieurs
objets, sur un ou plusieurs de leurs attributs. On spcifie la dure de lanimation et
les valeurs finales des attributs. Une fois lanimation de linterpolation lance,
ces attributs varieront selon ces paramtres pour crer une animation fluide. Pour nous,
tout ceci tient en une ligne de code !

La librairie TweenMax
Prsentation et installation
Nous allons utiliser une librairie dinterpolation cre par Greensock qui sappelle
TweenMax ou GSAP (GreenSock Animation Platform) et qui est trs connue
et utilise dans le milieu, car elle prsente de nombreux avantages en plus dtre facile
dutilisation. Le seul inconvnient de cette librairie est quelle est payante pour certains
projets commerciaux.
482

LES INTERPOLATIONS AVEC TWEENMAX


Il existe dautres librairies dinterpolations trs diffrentes auxquelles vous
pouvez galement jeter un coup dil si vous tes curieux. Je citerais en
exemple Actuate, GTween, Tweener, et bien dautres. . .
Commenons par tlcharger la librairie sur le site de GreenSock. Cliquez sur le bouton
Get GSAP gauche puis sur le bouton Download AS3 et enfin sur le bouton
Download zip (voir figure 23.6).


GreenSock
B
Code web : 797993

Figure 23.6 Page de tlchargement de GSAP


Une fois larchive rcupre, ouvrez-l et extrayez le dossier com dans le dossier des
sources de votre projet,par exemple, src (voir figure 23.7).
Voil ! La librairie est prte tre utilise !
Importation dans les classes
Pour pouvoir utiliser TweenMax dans une de vos classes, il faut ajouter ces deux
lignes en haut du package de la classe :
1
2

import com . greensock .*;


import com . greensock . easing .*;

La premire ligne importe toutes les classes de base de TweenMax, tandis que la
seconde importe les classes des courbes danimation permettant de modifier les interpolations. Nous les dtaillerons un peu plus loin.
483

CHAPITRE 23. ANIMER DES OBJETS

Figure 23.7 Contenu de larchive de GSAP

Les bases de lanimation avec TweenMax


Mise en place
Avant de rellement utiliser TweenMax, nous allons prparer un peu le terrain : il
nous faut bien quelque chose animer ! Commenons par crer un beau carr :
1
2
3
4
5
6

var carre : Sprite = new Sprite () ;


carre . graphics . beginFill ( 0xAA00FF ) ;
carre . graphics . drawRect ( - 25 , -25 , 50 , 50 ) ;
carre . x = stage . stageWidth / 2 ;
carre . y = stage . stageHeight / 2 ;
addChild ( carre ) ;

Pour linstant, nous obtenons la figure 23.8.


Notre objectif est danimer le carr au passage de la souris. Ajoutons des couteurs
dvnement comme nous lavons vu dans les chapitres prcdents :
carre . addEventListener ( MouseEvent . ROLL_OVER , onOver ) ;
carre . addEventListener ( MouseEvent . ROLL_OUT , onOut ) ;

1
2
3
4
5

function onOver ( e : MouseEvent ) : void


{

484

LES INTERPOLATIONS AVEC TWEENMAX

Figure 23.8 Un beau petit carr !

485

CHAPITRE 23. ANIMER DES OBJETS


7

8
9
10

function onOut ( e : MouseEvent ) : void


{

11
12

Utilisation de TweenMax
La librairie Tweenmax sutilise principalement avec la classe TweenMax (du package
com.greensock). Il y a galement des versions allges de cette classe pour rduire
la taille de votre application : TweenLite et TweenNano. Nous ne les dtaillerons pas
ici car elles fonctionnent exactement de la mme manire, certaines fonctionnalits en
moins. Les mthodes de la classe TweenMax que nous allons manipuler sont statiques :
il nest donc pas ncessaire dinstancier la classe laide du mot-cl new.
La premire (et sans doute la plus utilise) est la mthode statique TweenMax.to (langlais to signifie vers en franais). Voici sa signature :
TweenMax . to ( cible : Object , duree : Number , parametres : Object ) :
TweenMax

Cette mthode anime les attributs spcifis de la ou les cibles pendant une certaine
dure, vers les valeurs que lon a spcifies. Le premier paramtre que lon doit passer
est lobjet animer ; il est galement possible de passer un tableau dobjets pour en
animer plusieurs en mme temps. Le second spcifie la dure en secondes de lanimation.
Enfin, on passe en troisime paramtre un objet anonyme (de classe Object) contenant
la configuration de lanimation, avec notamment les attributs animer et leurs valeurs
finales.
Notez que vous ntes pas obligs de passer un objet daffichage : tout objet
est accept. Par exemple, vous pouvez animer lattribut pv dun objet
de classe Personnage pour le faire varier pendant 10 secondes si cela vous
chante, mme si ce nest pas un objet daffichage.

Lobjet de configuration
Le dernier paramtre est donc un objet anonyme (pas besoin de classe spcifique) qui
va contenir les attributs animer et leur valeur finale. Par exemple, si nous voulons
animer lopacit de notre carr pour quelle passe 0.5 en 1 seconde :
1
2
3

var parametrages : Object = new Object () ;


parametrages . alpha = 0 . 5 ;
TweenMax . to ( carre , 1 , parametrages ) ;

Nous pouvons aussi crire lobjet sous forme abrge avec des accolades :
486

LES INTERPOLATIONS AVEC TWEENMAX


1
2

var parametrages : Object = { alpha : 0 . 5 };


TweenMax . to ( carre , 1 , parametrages ) ;

Ou en se passant de variable intermdiaire :


1

TweenMax . to ( carre , 1 , { alpha : 0 . 5 }) ;

Animons notre carr


Maintenant que notre carr est prt, nous pouvons lanimer au passage de la souris
laide de la mthode statique to de la classe TweenMax comme nous venons de le voir :
1
2

// Anime l ' opacit vers 50 %


TweenMax . to ( carre , 1 , { alpha : 0 . 5 } ) ;

Lorsque la souris sortira du carr, on animera son opacit vers sa valeur initiale de 1
(pleinement opaque) :
1
2

// Anime l ' opacit vers 100 %


TweenMax . to ( carre , 1 , { alpha : 1 } ) ;

Il ne nous reste plus qu placer ces lignes dans les couteurs correspondants :
1
2
3
4

function onOver ( e : MouseEvent ) : void


{
TweenMax . to ( carre , 1 , { alpha : 0 . 5 } ) ;
}

5
6
7
8
9

function onOut ( e : MouseEvent ) : void


{
TweenMax . to ( carre , 1 , { alpha : 1 } ) ;
}

Ainsi, notre carr va devenir demi transparent au passage de la souris !


Animer plusieurs objets en mme temps
Il est possible danimer plusieurs objets en mme temps en passant un tableau
dobjet dans le paramtre cible. Ces objets seront anims de la mme faon sur les
mmes attributs de manire synchronise.
Il faut bien faire attention ce que les attributs que lon veut animer soient
prsents et accessibles sur tous les objets anims.
Par exemple, si nous disposions dun deuxime carr, nous pourrions les animer de la
mme manire laide dun tableau :
487

CHAPITRE 23. ANIMER DES OBJETS


1
2
3
4

var cibles : Array = new Array () ;


// On ajoute les carr s animer
cibles . push ( carre ) ;
cibles . push ( carre2 ) ;

5
6
7

// Anime l ' opacit des objets contenus dans le tableau vers 50 %


TweenMax . to ( cibles , 1 , { alpha : 0 . 5 } ) ;

On peut, bien entendu, utiliser la forme abrge des tableaux pour rendre le code plus
facile crire et lire :
1
2

// Anime l ' opacit des deux objets vers 50 %


TweenMax . to ([ carre , carre2 ] , 1 , { alpha : 0 . 5 } ) ;

Animation avec initialisation


La deuxime mthode statique trs utile est TweenMax.fromTo, elle permet dinitialiser
les valeurs dattributs avant lanimation. Voici sa signature :
TweenMax . fromTo ( cible : Object , duree : Number , initialisation :
Object , parametres : Object ) : TweenMax

Un nouveau paramtre est demand aprs la dure de lanimation : il sagit dun autre
objet anonyme contenant les attributs initialiser sur lobjet cible au dbut de lanimation. Par exemple, on peut initialiser les attributs scaleX et scaleY 0 pour que
lobjet soit minuscule, puis animer ces mmes attributs vers 1 (taille normale) :
1
2

// Les attribus scaleX et scaleY vont varier de 0 1 en une


seconde
TweenMax . fromTo ( carre , 1 , { scaleX :0 , scaleY : 0 } , { scaleX :1 ,
scaleY : 1 } ) ;

Avec cette instruction, notre carr apparatra en grossissant progressivement.

Utilisation avance de TweenMax


Les proprits des animations
En plus des attributs de lobjet cible (ou des objets cibles), on peut ajouter quelques
proprits relatives lanimation dans lobjet de paramtrage. Par exemple, on peut
dfinir un nombre de rptition de lanimation laide de lattribut repeat (en mettant
-1, on rpte lanimation infiniment) :
1
2

// L ' animation se r p tera infiniment


TweenMax . to ( carre , 1 , { alpha : 0 .5 , repeat : - 1 }) ;

On peut galement retarder le dbut de lanimation avec delay (dure exprime en


secondes) :
488

LES INTERPOLATIONS AVEC TWEENMAX


1
2

// L ' animation se lancera dans 3 secondes


TweenMax . to ( carre , 1 , { alpha : 0 .5 , delay : 3 }) ;

Bien sr, il est possible de combiner plusieurs de ces paramtres :


1
2

// L ' animation se r p tera infiniment avec 3 secondes de d lai


entre chaque r p tition
TweenMax . to ( carre , 1 , { alpha : 0 .5 , repeat : -1 , delay : 3 }) ;

Il existe dautres paramtres disponibles comme la documentation de la librairie le


dcrit (en anglais).
Utiliser les vnements
Certaines proprits pouvant tre spcifies dans lobjet de configuration de lanimation
sont des fonctions qui peuvent tre appelles automatiquement par lanimation lors
de certains vnements. Nous allons voir les deux plus importantes. Tout dabord, la
proprit onStart qui est une fonction appelle lorsque lanimation commence :
1
2
3
4
5

TweenMax . to ( carre , 1 , { x : 0 , y : 0 , onStart : debutAnimation }) ;


function debutAnimation () : void
{
trace ( " D but de l ' animation " ) ;
}

La fonction debutAnimation sera appelle ds que lanimation commencera ou sera


relance, hors rptitions.
Lautre proprit est onComplete, reprsentant une fonction appelle une fois lanimation termine (aprs rptitions) :
1
2
3
4
5

TweenMax . to ( carre , 1 , { x : 0 , y : 0 , onComplete : finAnimation }) ;


function finAnimation () : void
{
trace ( " Fin de l ' animation " ) ;
}

Valeurs relatives
Il est possible danimer des attributs numriques de manire relative en passant
lopration dincrmentation ou de dcrmentation entre guillemets. Par exemple, si
lon veut animer la position horizontale du carr pour quil avance de 100 pixels, nous
pouvons crire ceci :
1

TweenMax . to ( carre , 1 , { x : " += 100 " } ) ;

Ainsi, nous navons pas besoin de savoir quelle est la valeur initiale de sa position pour
calculer la nouvelle, TweenMax se charge de le faire notre place. Nous pouvons
galement rduire la position horizontale comme ceci :
1

TweenMax . to ( carre , 1 , { x : " -= 100 " } ) ;

489

CHAPITRE 23. ANIMER DES OBJETS


Easing
On peut faire varier la vitesse de lanimation laide de fonctions mathmatiques,
appeles fonctions de easing. Lanimation suit alors cette fonction pour modifier les
diffrentes valeurs successives. Ces fonctions peuvent intervenir en entre danimation,
en sortie ou les deux. Par exemple, avec la fonction x2 en dbut danimation, la vitesse
sera au dpart nulle puis va augmenter petit petit (suivant la fonction mathmatique
de la puissance deux).
Pour illustrer cette notion de fonction de easing, voici quatre exemples o lon a
dessin les diffrentes positions dun point anim. Dans le premier, nous utilison la
fonction x, galement appele fonction linaire (figure 23.9).

Figure 23.9 Fontion de easing linaire : vitesse constante


Les diffrentes positions sont calcules avec la fonction linaire, donc lanimation est
linaire.
Maintenant, nous utilisons la fonction x3 (ou fonction cubique) en dbut danimation
(voir figure 23.10).

Figure 23.10 Fonction de easing Cubique en entre


Les diffrentes position sont calcules avec la fonction cubique en entre ce qui donne
un effet dacclration.
Cette fois-ci, nous utilisons la fonction cubique en sortie, comme la figure 23.11.

Figure 23.11 Fonction de easing Cubique en sortie


Cela nous donne alors un effet de dclration.
Enfin, nous utilisons la fonction cubique en entre et en sortie (voir figure 23.12).

Figure 23.12 Fonction de easing Cubique en entre et en sortie


On a alors un effet dacclration puis de dclration.
Pour utiliser ces diffrentes fonctions easing, nous devons spcifier la proprit ease
dans la configuration de lanimation, en utilisant comme valeur les attributs statiques
490

LES INTERPOLATIONS AVEC TWEENMAX


des classes contenues dans le package com.greensock.easing que nous avons ajout
en haut de notre classe :
1
2
3

import com . greensock .*;


// On inclut les diff rentes fonctions de easing gr ce l '
toile
import com . greensock . easing .*;

Dans ce package, une classe par fonction de easing est dfinie, avec une mthode
statique correspondant lentre, la sortie ou les deux, passer dans la proprit
ease :
1

var choixEasing : Function ;

2
3
4

// Animation lin aire


choixEasing = Linear . easeNone ;

5
6
7
8
9
10
11

// Animation cubique en entr e


choixEasing = Cubic . easeIn ;
// Animation cubique en sortie
choixEasing = Cubic . easeOut ;
// Animation cubique en entr e et en sortie
choixEasing = Cubic . easeInOut ;

12
13
14

// Animation avec le param tre ease


TweenMax . to ( carre , 1 , { x : " += 100 " , ease : choixEasing } ) ;

Nous pouvons, bien sr, abrger ce code en se passant de variable intermdiaire :


1
2

// Animation lin aire


TweenMax . to ( carre , 1 , { x : " += 100 " , ease : Linear . easeNone } ) ;

Par dfaut, la fonction de easing utilise pour toutes les animations est la
fonction x^2 (ou fonction Carr) en sortie, cest--dire Quad.easeOut. Il y
a donc une lgre dclration par dfaut.
Il est possible dutiliser des fonctions de easing plus exotiques comme la fonction
Bounce qui fait rebondir les valeurs des attributs anims. Essayons cette fonction en
sortie :
1

TweenMax . fromTo ( carre , 1 , { scaleX :5 , scaleY : 5 } , { scaleX :1 ,


scaleY :1 , ease : Bounce . easeOut } ) ;

Ici, on anime la taille relative de notre carr de cinq fois plus grand sa taille normale
avec un effet de rebondissement intressant.
Vous pouvez consulter la liste de toutes les fonctions de easing disponibles sur la
documentation de la librairie.
491

CHAPITRE 23. ANIMER DES OBJETS


Contrle dune animation
Lorsque nous utilisons les mthodes statiques de la classe TweenMax pour animer des objets, nous pouvons rcuprer une instance de cette classe reprsentant lanimation. En
effet, les mthodes TweenMax.to et TweenMax.fromTo que nous avons vues retournent
un objet de classe TweenMax :
1
2

// Animation de rotation de notre carr , affect e une


variable
var animation : TweenMax = TweenMax . to ( carre , 5 , { rotation : 360 ,
repeat : -1 , ease : Linear . easeNone }) ;

A partir de l, nous pouvons accder aux proprits des instances de la classe TweenMax
pour contrler lanimation. Nous pouvons ainsi la mettre en pause laide de sa mthode pause comme ceci :
animation . pause () ;

Il est possible de reprendre la lecture de lanimation laide de la mthode resume :


animation . resume () ;

La mthode restart, quant elle, permet de recommencer lanimation depuis le dbut :


animation . restart () ;

Enfin, la mthode kill permet darrter compltement lanimation qui est alors supprime :
animation . kill () ;

Animer une animation


Vous souvenez-vous que les animations prenaient en paramtre nimporte quel objet ?
Y compris dautres animations ? En effet, il est tout fait possible danimer des
proprits dune animation laide dune nouvelle animation. Lattribut qui nous
intresse alors est le nombre flottant timeScale, qui permet dacclrer ou de ralentir
une animation de manire arbitraire. A zro, lanimation est en pause, un, lanimation
avance la vitesse normale, deux, elle se droule deux fois plus vite, etc.
animation . timeScale = 0 . 5 ; // On ralentit l ' animation de moiti

Ainsi, il nous est possible danimer cet attribut laide dune nouvelle animation :
1
2

// On anime l ' attribut timeScale de notre animation de rotation


TweenMax . fromTo ( animation , 5 , { timeScale : 0 } , { timeScale : 1 }) ;

Grce cette instruction, lanimation de rotation de notre cube sera initialement en


pause puis va sacclrer jusqu atteindre la vitesse normale. Cela signifie que le carr
va progressivement se mettre tourner sur lui-mme !
492

LES INTERPOLATIONS AVEC TWEENMAX

En rsum
Animer un objet consiste modifier au moins lune de ses proprits intervalles
rguliers.
Lvnement Event.ENTER_FRAME est gnr avant que chaque image ne soit rendue.
La proprit frameRate de lobjet Stage permet de grer le cadencement des images
au sein de lanimation.
La classe Timer offre un moyen de contrler le temps de manire prcise, contrairement lvnement Event.ENTER_FRAME.
TweenMax est une clbre librairie dinterpolation qui permet de simplifier au
maximum lanimation de vos objets.

493

CHAPITRE 23. ANIMER DES OBJETS

494

Chapitre

24

Les collisions
Difficult :
Un jour, si tes amen programmer des jeux vido, vous allez devoir vous intresser
la notion de collisions. Vous souhaiterez alors savoir si votre voiture quitte la route, si un
objet sort du cadre de la scne, si deux billes se touchent ou encore si votre personnage a
les pieds sur terre. . .
Au cours de ce chapitre, nous dcouvrirons ensemble les prmices de la thorie des collisions. Ainsi, nous serons capables de dtecter une collision entre des objets de diffrentes
tailles et diffrentes formes. Nous verrons galement comment affiner, plus ou moins, cette
dtection de collisions, en fonction de la forme des objets, afin doptimiser au maximum
les performances du programme.
la fin de ce chapitre, vous serez enfin en mesure de raliser vos propres jeux vido !

495

CHAPITRE 24. LES COLLISIONS

Prambule
Dfinition dune collision
Comme cela a t annonc en introduction, nous parlerons de collisions tout au long
de ce chapitre. Aussi, pour mieux comprendre tout ce qui va suivre, nous allons dabord
dfinir le terme collision .
Dans la vie de tous les jours, nous attribuons ce terme toutes sortes dimpact ou de
choc entre deux objets. Nous pouvons citer lexemple dun verre qui se brise au contact
du sol, dune balle qui atteint sa cible ou encore dune voiture qui percute un mur.
Dans un programme, nous pourrons parler de collision lorsque deux objets se touchent
ou se chevauchent. De la mme manire, nous pourrons savoir si un objet verre est en
contact avec un autre objet sol ou si notre objet voiture percute lobjet mur.
En principe, rien nempche votre objet voiture de continuer sa course travers lobjet
mur. Cela ne posera absolument aucun problme votre application pour continuer
sexcuter. Il faut avouer que cest tout de mme fcheux ! Il nous incombe donc de
grer les collisions lintrieur de notre programme afin de pouvoir excuter des tches
appropries.
la figure 24.1, vous pouvez voir que les objets voiture et mur se chevauchent lgrement, et sont, par consquent, en collision.

Figure 24.1 Collision entre les objets voiture et mur

Dtecter des collisions


Des fonctions boolennes
Le principal objectif pour un programmeur sera donc de dtecter lexistence dune
collision entre deux objets.
Mais alors, comment savoir sil y a collision entre deux objets ?

Cest justement toute la difficult de la chose, mais galement la raison dtre de ce


chapitre. Nous verrons quil existe diffrents moyens dy arriver, qui dpendent princi496

PRAMBULE
palement de la forme des objets et de la prcision souhaite.
Quoi quil en soit, nous dtecterons les collisions toujours de la mme manire : nous
utiliserons diverses fonctions ou mthodes, prenant en paramtres les objets tester,
et renvoyant un boolen, qui sera vrai si il y a collision entre les objets transmis ou
faux dans le cas inverse.

Effets produits par une collision


Les effets engendrs par une ventuelle collision ne sont pas pris en compte dans ces
fonctions de dtection de collisions. Ce nest quune fois la collision confirme
quil est possible de grer limpact gnr par celle-ci.
Prenons lexemple dun choc entre deux boules quelconques, comme sur la figure 25.21.

Figure 24.2 Choc lastique entre deux boules


Dans lexemple prcdent, nous voyons que nos boules sont en collision la troisime
position. la suite de ce choc, les boules sont alors dvies et leur vitesse modifie.
Dans ce cas prcis, nous pourrions nous appuyer sur la thorie des chocs lastiques
pour mettre jour le mouvement de chacune des boules. Nanmoins, leffet produit
par la collision aurait t trait diffremment sil sagissait dun choc entre un objet
voiture et un objet mur ou encore entre les objets verre et sol.
Les instructions qui dcoulent dune collision sont donc directement lis aux types
dobjets que vous manipulez, ou plutt ce quils reprsentent. Par ailleurs, cela dpend
galement de ce que vous, en tant que programmeur, souhaitez faire. Par exemple,
limpact de lobjet voiture sur le mur pourrait stopper net cette dernire en dformant
son capot, mais pourrait tout aussi bien la faire rebondir et laisser celle-ci intacte.
De plus, suivant la vue utilise (vue de face, de dessus, de ct, etc.) et la manire dont
vos classes sont construites, les instructions ne seront pas tout les mmes.
Les manipulations post-collision sont spcifiques chaque programme et ne
sont pas forcment transposables tous vos projets. Dans ce chapitre, nous
nous donc concentrerons uniquement sur les mthodes de dtection de
collisions entre objets.

497

CHAPITRE 24. LES COLLISIONS

La thorie des collisions


Collisions rectangulaires
La mthode hitTestObject()
Par dfaut, tout objet hritant de DisplayObject dispose de deux mthodes servant dtecter des collisions entre objets daffichage. La premire, nomme
hitTestObject() est celle dont nous allons parler maintenant. Pour cela, nous aurons
besoin de deux objets. Traons deux rectangles qui se superposent, au moins partiellement :
1
2
3
4
5
6
7
8

var obj1 : Shape = new Shape () ;


obj1 . graphics . beginFill ( 0x000000 ) ;
obj1 . graphics . drawRect (0 , 0 , 100 , 100 ) ;
var obj2 : Shape = new Shape () ;
obj2 . graphics . beginFill ( 0x880088 ) ;
obj2 . graphics . drawRect ( 50 , 50 , 100 , 100 ) ;
addChild ( obj1 ) ;
addChild ( obj2 ) ;

La figure 24.3 nous confirme que les objets obj1 et obj2 se chevauchent bien.

Figure 24.3 Collision entre deux rectangles


prsent, testons la collision entre ces deux objets.
Pour cela, nous allons donc nous servir de la mthode hitTestObject() qui prend en
paramtre simplement lobjet daffichage avec lequel tester la collision. Sachant que la
mthode hitTestObject() appartient la classe DisplayObject, nous pouvons aussi
bien lutiliser partir de lobjet daffichage obj1 comme obj2.
Pour sassurer de son bon fonctionnement, affichons le rsultat de cette fonction dans
la console, comme ceci :
trace ( obj1 . hitTestObject ( obj2 ) ) ; // Affiche : true

Comme vous ntes pas dupes, confirmons le bon fonctionnement de la mthode


hitTestObject() en dplaant un de des rectangles et en r-affichant le rsultat :
1
2

obj2 . y = 100 ;
trace ( obj1 . hitTestObject ( obj2 ) ) ; // Affiche : false

498

LA THORIE DES COLLISIONS


La mthode hitTestObject() possde nanmoins un norme dfaut lorsquil sagit
dtudier une collision entre deux objets non rectangulaires. En effet, la dtection de
collision ralise lintrieur de cette mthode est effectue non pas sur les objets
daffichages eux-mmes, mais sur leur cadre de slection que nous allons prsent
voquer.
Les cadres de slection
Un cadre de slection (ou bounding box en anglais) peut tre dfini comma la plus
petite zone rectangulaire incluant intgralement un objet daffichage.
tant donn quun dessin est toujours plus parlant, reprenons lexemple de la collision
entre nos objets daffichage voiture et mur. La figure 24.4 nous montre alors ces deux
objets dlimits par leur cadre de slection respectif.

Figure 24.4 Les objets daffichage et leur cadre de slection


La classe DisplayObject dispose des deux mthodes getBounds() et
getRect() pour rcuprer les coordonnes du cadre de slection dun objet daffichage. La diffrence entre celles-ci est que la mthode getRect()
dfinit le cadre de slection sans tenir compte des lignes contenues dans lobjet
daffichage. Pour plus dinformations, je vous invite aller voir la documentation.


Documentation getBounds()
B et getRect()
Code web : 719404


Pour revenir aux collisions rectangulaires, la mthode hitTestObject() ralise donc
un test de collision entre les cadres de slection de deux objets daffichage et non sur
leurs formes relles.
Ce type de collisions peut tre donc tre utile pour tout objet de forme rectangulaire, bien entendu, mais pas seulement ! La mthode hitTestObject()
peut aussi vous servir lorsque vous navez pas besoin dune prcision extrme.
Et enfin, les dtections de collisions rectangulaires peuvent galement
tre suffisantes lorsque vos objets non rectangulaires sont de tailles minimes.
En effet, pour des objets trs petits, le cadre de slection est quasiment
confondu avec lobjet lui-mme.

499

CHAPITRE 24. LES COLLISIONS


Collisions avec la scne principale
Jusqu prsent, nous avons vu uniquement comment dtecter des collisions rectangulaires correspondant, plus ou moins, deux objets qui se percutent. Toutefois,
dans dautres cas, il peut tre utile de dtecter si un objet sort dune certaine
zone dlimite.
Par exemple, ce type de collisions peut tre utilis pour dtecter si un objet sort de la
scne principale. Nous allons donc voir maintenant comment grer ce genre de cas.
Sur la figure 24.5, jai rappel les coordonnes limites de la scne principale de votre
animation.

Figure 24.5 Limites de la scne principale


Pour apprendre grer les collisions avec la scne principale, je vous propose
un petit exemple. Nous allons ainsi raliser une animation o un rectangle suivra les
mouvements de souris, mais sans sortir du cadre de la scne principale.
Commenons par dessiner un rectangle et faisons-le suivre la souris. Vous devriez maintenant savoir coder tout a, mais je vais quand mme vous donner un petit coup de
pouce pour ceux qui auraient oubli comment procder :
1
2
3
4
5
6
7

var rectangle : Shape = new Shape () ;


rectangle . graphics . beginFill ( 0x00BB00 ) ;
rectangle . graphics . drawRect ( - 50 , -50 , 100 , 100 ) ;
addChild ( rectangle ) ;
stage . addEventListener ( MouseEvent . MOUSE_MOVE , deplacer ) ;
function deplacer ( event : MouseEvent ) : void
{

500

LA THORIE DES COLLISIONS


8
9
10

rectangle . x = event . stageX ;


rectangle . y = event . stageY ;

Pour tester si notre objet sort de la scne principale, nous devons tester les limites
de notre rectangle par rapport aux dimensions de lanimation. tant donn que notre
rectangle est centr sur son origine locale, nous pouvons dtecter les dpassements de
cette manire :
1
2
3
4

function deplacer ( event : MouseEvent ) : void


{
rectangle . x = event . stageX ;
rectangle . y = event . stageY ;

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

// Bord gauche
if ( rectangle . x
{
trace ( " Trop
}
// Bord droit
if ( rectangle . x
{
trace ( " Trop
}
// Bord haut
if ( rectangle . y
{
trace ( " Trop
}
// Bord bas
if ( rectangle . y
{
trace ( " Trop
}

- rectangle . width / 2 < 0 )


gauche " ) ;
+ rectangle . width / 2 > stage . stageWidth )
droite " ) ;
- rectangle . height / 2 < 0 )
haut " ) ;
+ rectangle . height / 2 > stage . stageHeight )
bas " ) ;

Certains dentre vous pourraient se dire que dans le cas prsent, nous navons
pas de fonction boolenne pour la dtection de collisions. Toutefois, doisje vous rappeler quune condition renvoie une valeur boolenne ? Nous
pouvons ainsi considrer chaque condition comme un dtecteur de collision avec une bordure. Dans cet exemple, nous avons donc quatre tests de
collisions diffrents ; videmment, un rectangle compte quatre cts !
Enfin, pour empcher le rectangle de sortir de la scne principale, il suffit de rinitialiser
sa position pour que celui-ci reste adjacent la bordure ventuellement franchie.
Voil comment nous pourrions faire :
1
2

function deplacer ( event : MouseEvent ) : void


{

501

CHAPITRE 24. LES COLLISIONS


3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

rectangle . x = event . stageX ;


rectangle . y = event . stageY ;
if ( rectangle . x - rectangle . width / 2 < 0 )
{
rectangle . x = rectangle . width / 2 ;
}
if ( rectangle . y - rectangle . height / 2 < 0 )
{
rectangle . y = rectangle . height / 2 ;
}
if ( rectangle . x + rectangle . width / 2 > stage . stageWidth )
{
rectangle . x = stage . stageWidth - rectangle . width / 2 ;
}
if ( rectangle . y + rectangle . height / 2 > stage . stageHeight )
{
rectangle . y = stage . stageHeight - rectangle . height / 2 ;
}

Ici, nous avons travaill avec la scne principale, nanmoins, il est tout fait
possible de travailler avec un conteneur enfant de type Sprite. Il faudrait
alors utiliser lespace de coordonnes local ce conteneur, ainsi que ses dimensions dcrites par les attributs width et height. Pour gnraliser ceci,
quelque soit la position du rectangle par rapport sa propre origine, il est
possible dutiliser la mthode getBounds() de lobjet en question.

Collisions circulaires
Le thorme de Pythagore
Pour dtecter des collisions entre deux objets de forme circulaire, nous aurons besoin de calculer la distance qui spare leurs centres. Pour cela, nous utiliserons
le thorme de Pythagore ! Certains dentre vous auront peut-tre limpression de retourner sur les bancs de lcole, mais il est important de faire un petit rappel de ce
thorme. Je passerai nanmoins relativement vite sur ce point, ne vous inquitez pas !
Pour rappel, le thorme de Pythagore dfinit une relation entre les trois cts dun
triangle rectangle, tel que celui sur la figure 24.6.
En utilisant la notation de limage prcdente, le thorme de Pythagore dfinit la
relation suivante :
a2 = b2 + c2
Dun point de vue littraire, ce thorme est dfini de la manire suivante :
Si un triangle est rectangle, alors le carr de lhypotnuse est gale la
somme des carrs des deux autres cts.
502

LA THORIE DES COLLISIONS

Figure 24.6 Un triangle rectangle


Calcul des distances
Maintenant, nous allons voir comment calculer la distance entre deux objets. Dans
le cas prsent, nous nous focaliserons sur les cercles. Nanmoins, ceci peut facilement
tre transposable dautres types dobjets.
Lorsque nous utilisons le terme distance entre deux objets, nous parlons de celle
qui spare les centres de nos objets. Ainsi, la figure 24.7, nous pouvons voir comment
elle est dfinie dans le cas des cercles.

Figure 24.7 Distance entre deux cercles


Daprs le thorme de Pythagore, nous avons donc la relation suivante :
d2 = ( x)2 + ( y)2
Dans lexpression prcdente, x reprsente la diffrence dabscisse entre les deux
objets, cest--dire
x2 x1
. Bien entendu, cest la mme chose pour y.
Nous supposerons ici que les objets daffichage correspondant aux cercles possdent
leur origine daffichage au centre des cercles. Nous pouvons alors calculer la distance
entre deux cercles de cette manire :
1

var d : Number = Math . sqrt ( Math . pow ( objet2 . x - objet1 .x , 2 ) +


Math . pow ( objet2 . y - objet1 .y , 2 ) ) ;

503

CHAPITRE 24. LES COLLISIONS


Toutefois, en considrant le temps ncessaire pour raliser cette opration, il serait
prfrable dutiliser quelque chose de plus optimis. En effet, lutilisation de la multiplication est plus rapide que le passage par la mthode pow() de la classe Math. En
fait, il serait plus intressant, du point de vue des performances, de ne pas utiliser cette
classe. Cest pourquoi, il est prfrable de travailler avec des distances au carr, ce qui
nous vite davoir recours la mthode sqrt().
Voici donc comment redfinir cette mme instruction sans utiliser la classe Math et en
restant en distance au carr :
1

var d : Number = ( objet2 . x - objet1 . x ) *( objet2 . x - objet1 . x ) + (


objet2 . y - objet1 . y ) *( objet2 . y - objet1 . y ) ;

Je rappelle quun carr est une valeur toujours positive. Quel que soit les
objets et le sens avec lesquels vous les utilisez, le rsultat sera toujours le
mme.

Dtecter une collision


prsent, vous savez calculer la distance entre deux cercles. Cela tombe bien,
nous allons justement en avoir besoin pour dtecter les collisions entre objets de forme
circulaire. Quelle que soit la position et lorientation de chacun des deux cercles, ceux-ci
seront en collision si la distance entre leurs centres est infrieure une certaine valeur.
Voyez plutt la figure 24.8.

Figure 24.8 Distance maximale de collision


En regardant limage prcdente de plus prs, nous pouvons en dduire que la distance
maximale de collision entre deux cercles est r1 + r2 , soit 2r dans le cas de deux
cercles de rayons identiques. Par ailleurs, nous pouvons galement utiliser le fait que le
rayon dun objet correspond exactement la moiti de sa largeur ou de sa hauteur.
Pour dtecter une collision entre deux objets daffichage obj1 et obj2 de forme circulaire, nous pouvons dfinir une fonction de ce style :
1
2

function testerCollision ( obj1 : DisplayObject , obj2 : DisplayObject


) : Boolean
{

504

LA THORIE DES COLLISIONS


3
4
5
6
7
8
9
10

var collision : Boolean = false ;


var d : Number = ( obj2 . x - obj1 . x ) *( obj2 . x - obj1 . x ) + ( obj2 .
y - obj1 . y ) *( obj2 . y - obj1 . y ) ;
if ( d < ( obj1 . width / 2 + obj2 . height / 2 ) *( obj1 . width / 2 + obj2 .
height / 2 ) )
{
collision = true ;
}
return collision ;

Encore une fois, ce code se base sur le fait que les objets daffichage sont
centrs sur leur origine. Si ce nest pas le cas, il sera ncessaire de ladapter
lgrement.

Collisions ponctuelles
La mthode hitTestPoint()
Nous allons maintenant nous pencher sur le cas des collisions ponctuelles, cest-dire entre un objet daffichage et un point. Ce dernier sera alors uniquement caractris
par ses coordonnes x et y.
Nous nallons pas entrer dans la thorie, je vais plutt vous prsenter une mthode
faisant le travail votre place. Il sagit de la mthode hitTestPoint() prsente dans
toute classe hritant de DisplayObject. En voici sa signature :
1

hitTestPoint ( x : Number , y : Number , shapeFlag : Boolean = false ) :


Boolean

Comme vous le voyez, lutilisation de cette mthode ncessite de renseigner les coordonnes du point avec lequel tester la collision ainsi quun troisime paramtre facultatif
nomme shapeFlag. Ce dernier paramtre, de type Boolean, sert spcifier si la dtection de collision doit tre faite sur lobjet lui-mme en tant que forme complexe (true)
ou uniquement daprs son cadre de slection (false).
Ce type de dtection de collisions peut tre extrmement utile dans certains cas.
Par exemple, vous pourriez raliser un jeu de tir et dtecter la collision entre la position
de votre curseur et un ennemi quelconque comme lillustre bien la figure 24.9.
Pour vous donner un exemple de code, voici comment il serait possible de raliser cette
dtection partir de la mthode hitTestPoint() :
1
2
3
4
5

stage . addEventListener ( MouseEvent . MOUSE_DOWN , tir ) ;


function tir ( event : MouseEvent ) : void
{
if ( maCible . hitTestPoint ( event . stageX , event . stageY , true ) )
{
trace ( " Cible atteinte " ) ;

505

CHAPITRE 24. LES COLLISIONS

Figure 24.9 Un jeu de tir utilisant les collisions ponctuelles


6
7

Si vous souhaitez tester ce code, il vous suffit dinstancier un objet daffichage maCible
et de lajouter la liste daffichage. Le code prcdent vous servira alors dtecter les
collisions entre votre curseur et cet objet lors dun clic avec votre souris.
Exercice : Un mini-jeu de tir
Le principe du jeu va tre relativement simple. Nous allons tout dabord dessiner une
balle qui se baladera lintrieur de la scne principale. Puis, lorsque vous cliquerez
dessus, votre score de points augmentera.
Dmarrons tout de suite en dessinant un disque reprsentant notre balle que nous
placerons initialement au centre de lcran :
1
2
3
4
5
6
7

var cible : Shape = new Shape () ;


cible . graphics . beginFill ( 0x880088 ) ;
cible . graphics . drawCircle (0 , 0 , 50 ) ;
cible . x = stage . stageWidth / 2 ;
cible . y = stage . stageHeight / 2 ;
addChild ( cible ) ;
var score : int = 0 ;

Pour grer les mouvements de notre balle, nous allons avoir besoin dutiliser deux variables vitesseX et vitesseY qui reprsenteront donc sa vitesse de dplacement horizontale et verticale. Pour dtecter les collisions avec la scne principale, nous utiliserons
le principe des collisions rectangulaires, qui, dans ce cas, sera plus que suffisant.
la suite dune collision, nous pourrons mettre jour la position de lobjet ainsi que sa
vitesse, qui sera inverse suivant le ct de la scne que la balle aura percut.
Tout ceci peut sans doute vous paratre compliqu, pourtant, regardez le code correspondant qui nest pas si terrible :
1

// On initialise des vitesses horizontales et verticales al


atoirement

506

LA THORIE DES COLLISIONS


2
3

var vitesseX : int = 1 + Math . random () * 10 ;


var vitesseY : int = 1 + Math . random () * 10 ;

4
5
6
7
8
9
10
11

// Pour chaque frame


addEventListener ( Event . ENTER_FRAME , deplacer ) ;
function deplacer ( event : Event ) : void
{
// On d place la balle
cible . x += vitesseX ;
cible . y += vitesseY ;

12

// On d tecte les collisions de la balle avec la sc ne

13
14

// Bord gauche
if ( cible . x - cible . width / 2 < 0 )
{
cible . x = cible . width / 2 ;
vitesseX = - vitesseX ;
}
// Bord droit
else if ( cible . x + cible . width / 2 > stage . stageWidth )
{
cible . x = stage . stageWidth - cible . width / 2 ;
vitesseX = - vitesseX ;
}

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

// Bord haut
if ( cible . y - cible . height / 2 < 0 )
{
cible . y = cible . height / 2 ;
vitesseY = - vitesseY ;
}
// Bord bas
else if ( cible . y + cible . height / 2 > stage . stageHeight )
{
cible . y = stage . stageHeight - cible . height / 2 ;
vitesseY = - vitesseY ;
}

Utiliser le mot-cl else nous permet ici dconomiser des tests. En effet, si
lobjet entre en collision avec le bord gauche, il est inutile de tester le bord
droit ; de mme avec le bord haut et bas.
Enfin, la gestion des tirs peut se faire laide la mthode hitTestpoint() comme cela
a t dcrit prcdemment :
1
2

stage . addEventListener ( MouseEvent . CLICK , tir ) ;


function tir ( event : MouseEvent ) : void

507

CHAPITRE 24. LES COLLISIONS


3

4
5
6
7
8
9

if ( cible . hitTestPoint ( event . stageX , event . stageY , true ) )


{
score += 10 ;
trace ( " Score : " + score ) ;
}

Lexercice que nous venons de raliser est un prambule un jeu de tir plus complexe.
Pour vous exercer, je vous invite donc grandement essayer de raliser un vrai jeu de
tir suivant vos envies.

Les collisions de pixels


Utiliser lopacit
Les masques
Une autre manire dapprhender les collisions est dutiliser les objets daffichage sous
forme dimages bitmap. Comme vous le savez maintenant, ces images sont dcrites
par une srie de pixels. Et rappelez-vous, les pixels sont caractriss par des nombres
de la forme 0xAARRVVBB, o AA reprsentent lopacit du pixel.
Lopacit dun objet daffichage permet justement de dcrire les contours de la partie
visible de celui-ci. Cest pourquoi, lopacit est grandement utile pour effectuer des
tests de collisions. Mais nous reviendrons l-dessus plus tard.
En attendant, la figure 24.10 vous montre quoi peut ressembler le canal alpha de
limage voiture, appel gnralement masque de limage.

Figure 24.10 Masque (ou opacit) de lobjet voiture

Bien entendu, il serait tout fait possible de raliser des tests de collisions
en utilisant les canaux rouge, vert ou bleu. Cependant, cela nest pas trs
courant, aussi, nous nen parlerons pas.

508

LES COLLISIONS DE PIXELS


Une manire de dtecter des collisions

Ici, nous allons voir comment nous pourrions procder pour dtecter une collision
entre deux images bitmap. Toutefois, nous verrons que la classe BitmapData intgre
une mthode hitTest(). Malheureusement, je ne suis pas certain de son fonctionnement interne. Mais, quoi quil en soit, cela ne nous empche pas dimaginer la manire
dont cela pourrait tre fait.
La technique dont je vais vous parler est simplement tire de mon imagination. Il est
donc fort probable quil y ait dautres faons dy parvenir et de manire plus optimise.
Nanmoins, je cherche ici simplement vous faire dcouvrir une mthode que vous
pourriez vous-mmes transcrire en code. Vous pourrez ensuite trs facilement adapter
celle-ci ou une autre vos projets pour des applications diverses.
La technique que je vais vous prsenter maintenant tire parti du fait quune transparence totale est reprsente par une valeur correspondante nulle. Je ferais galement
lhypothse que lopacit est reprsente par une valeur dcimale comprise entre 0 et
1. Ainsi, en multipliant simplement les valeurs des opacits des deux pixels devant se
superposer, nous obtenons un nouveau masque contenant simplement lintersection des
deux images.
Je vous propose un exemple utilisant des matrices pour illustrer ceci. Pour cela, nous
utiliserons le produit dHadamard ou produit composante par composante.
Nayez pas peur, cela nest pas aussi compliqu que a en a lair.
Voyez plutt :

1
1

1
1

1
1
1
1

0
0
0
0

0
0

1
1
0
0

1
1
0
0

1
1
0
0

1
1
1
1
=
0
0
0
0

1
1
0
0

0
0
0
0

0
0

0
0

Grce ce calcul, toute valeur non-nulle correspond donc un pixel tant en collision
entre les deux objets. Il pourrait mme tre envisageable dutiliser un seuil pour les
valeurs intermdiaires entre 0 et 1 pour considrer sil y a collision ou non.
Dans lencadr rouge de la figure 24.11, je vous laisse apprcier ce que cette mthode
pourrait donner localement pour notre problme de collision entre les objets voiture
et mur.
Une fois cette multiplication faite, nous nallons plus qu parcourir lensemble des
pixels pour dtecter si les pixels dpassent le seuil dopacit dfinit (ou son carr si
vous souhaitez prendre en compte la multiplication applique aux valeurs de base). Un
seul pixel dpassant le seuil dopacit est alors synonyme de collision.
509

CHAPITRE 24. LES COLLISIONS

Figure 24.11 Rsultat dune multiplication entre les masques de deux images

Application en code
Une mthode prte lemploi
Vous ayant dj dtaill le principe, je vais simplement ici vous exposer le code dune
classe intgrant une mthode statique ralisant ce travail partir dobjets daffichage
quelconques.
1
2
3
4
5
6
7

package
{
import
import
import
import
import

flash . display . DisplayObject ;


flash . display . BitmapData ;
flash . geom . Matrix ;
flash . geom . Point ;
flash . geom . Rectangle ;

8
9
10

public class Collision


{

11
12
13
14
15

public function Collision ()


{
throw new Error ( ' Classe abstraite ') ;
}

16
17
18
19
20
21
22

510

static public function tester ( obj1 : DisplayObject , obj2 :


DisplayObject , seuil : uint ) : Boolean
{
var collision : Boolean = false ;
if ( obj1 . hitTestObject ( obj2 ) == true )
{
var img1 : BitmapData = creerBitmapData ( obj1 ) ;

LES COLLISIONS DE PIXELS


var
var
var
var

img2 : BitmapData = creerBitmapData ( obj2 ) ;


rect1 : Rectangle = obj1 . getBounds ( obj1 ) ;
rect2 : Rectangle = obj2 . getBounds ( obj2 ) ;
pos1 : Point = new Point ( obj1 . x + rect1 .x ,
obj1 . y + rect1 . y ) ;
var pos2 : Point = new Point ( obj2 . x + rect2 .x ,
obj2 . y + rect2 . y ) ;
collision = img1 . hitTest ( pos1 , seuil , img2 ,
pos2 , seuil ) ;

23
24
25
26
27
28
29
30

31

}
return collision ;

32

static private function creerBitmapData ( objet :


DisplayObject ) : BitmapData
{
var image : BitmapData = new BitmapData ( objet . width ,
objet . height , true , 0x00000000 ) ;
var rect : Rectangle = objet . getBounds ( objet ) ;
var transformation : Matrix = new Matrix () ;
transformation . translate ( - rect .x , - rect . y ) ;
image . draw ( objet , transformation ) ;
return image ;
}

33
34
35
36
37
38
39
40
41
42

43
44
45

Comme je lai dit plus haut, tout repose sur la mthode hitTest() de la classe
BitmapData. Le reste est uniquement la mise en place des lments transmettre
cette mthode.
La mthode propose ci-dessus possde nanmoins un petit dfaut. En effet,
les diverses transformations appliques lobjet ne sont pas prises en compte
et gnreront des bugs. Les objets daffichage utiliss doivent ne doivent donc
subir aucune transformation. Nanmoins, ceci peut tre corrig en les prenant
en compte lors du trac des BitmapData.

Un exemple dutilisation
Pour tous ceux qui souhaiteraient voir lefficacit de la mthode statique donne prcdemment, je vous propose ci-dessous un petit code dexemple. Regardez alors la
simplicit dutilisation de cette mthode. Encore une fois, un grand merci la POO.
1
2
3

var obj1 : Shape = new Shape () ;


obj1 . graphics . lineStyle ( 20 , 0x000000 ) ;
obj1 . graphics . drawCircle ( 200 , 200 , 100 ) ;

511

CHAPITRE 24. LES COLLISIONS


4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

var obj2 : Shape = new Shape () ;


obj2 . graphics . beginFill ( 0x880088 ) ;
obj2 . graphics . drawCircle (0 , 0 , 15 ) ;
obj2
addChild ( obj1 ) ;
addChild ( obj2 ) ;
addEventListener ( Event . ENTER_FRAME , maFonction ) ;
function maFonction () : void
{
obj2 . x = mouseX ;
obj2 . y = mouseY ;
if ( Collision . tester ( obj1 , obj2 , 0x11 ) ) {
obj1 . filters = new Array ( new GlowFilter () ) ;
} else {
obj1 . filters = new Array () ;
}
}

Ce chapitre ntait quune introduction la thorie des collisions. Mme si vous


savez dsormais rpondre la plupart de vos besoins en termes de collisions, nhsitez
pas vous perfectionner, notamment grce au tutoriel sur la thorie des collisions de
Fvirtman.

En rsum
La dtection dune collision entre deux objets daffichage se fait laide dune
fonction boolenne.
Suivants la forme des objets daffichage et la prcision de dtection souhaite, ces
fonctions de tests de collisions doivent tre diffrentes.
Pour tout DisplayObject, la mthode hitTestObject() permet de dtecter des
collisions entre deux objets partir de leur cadre de slection.
La mthode hitTestPoint() de la classe DisplayObject sert tester une ventuelle collision entre un objet quelconque et un point.
Pour affiner au mieux les collisions entre deux objets aux formes complexes, la
mthode hitTest() de la classe BitmapData effectue des tests au niveau des pixels.
Les effets engendres par une collision doivent tre traits en dehors des fonctions
boolennes de dtection des collisions.

512

Chapitre

25

TP : Jeu de billard
Difficult :
La fin du cours approche grand pas et, aprs tous ces chapitres thoriques, il est temps
de passer de nouveau la pratique ! Cette partie consiste en un gros TP : en effet, nous
allons crer un jeu de billard amricain ! Une grande partie des notions que nous avons vues
jusquici seront utiles pour crire votre jeu de billard, alors nhsitez pas revenir sur les
passages sur lesquels vous ne vous sentez pas laide avant dentamer le TP.
Cest parti pour le grand TP final !

513

CHAPITRE 25. TP : JEU DE BILLARD

Objectifs
Les rgles de notre billard
Lobjectif de ce TP est de crer un jeu video reprenant le jeu du billard amricain.
Le billard est un jeu en deux quipes se droulant sur une table de billard, avec plusieurs
billes numrotes et de diffrentes couleurs. Chaque joueur manipule une sorte de bton
appel la queue et a le droit de taper seulement dans la bille blanche. La table de
billard (avec ou sans bandes) dispose de six trous dans lesquels il faut envoyer les billes
de notre quipe.
Nous nallons pas implmenter toutes les autres rgles du billard amricain
pour simplifier le TP, nous laisserons le soin au joueur de dcider comment il
veut jouer. Toutefois, rien ne vous empche de les implmenter vous-mme
par la suite pour vous entraner !
Vous verrez la figure 25.1 ce quoi devrait ressembler notre jeu, peu de choses prs.

Figure 25.1 En pleine partie de billard !

514

OBJECTIFS

Le droulement dune partie


Phase 1 : Prparation de la partie
Cette phase est lance lorsquune nouvelle partie dmarre. Dans un premier temps, il
faut placer le triangle des billes droite de la table comme la figure 25.2.

Figure 25.2 Disposition initiale des billes


La bille 8 est toujours au centre de la troisime range, tandis que les autres billes
peuvent tre places dans lordre que vous voulez.
La bille blanche peut tre place nimporte o (en gnral, soit sur le premier
point blanc de la table, soit sur le deuxime au dbut de la partie). Nous
pouvons alors laisser le choix de lemplacement de cette bille au joueur lors
de la phase suivante.

Phase 2 : Placement de la bille blanche


La bille blanche suit le curseur de la souris tout en ne pouvant sortir de la zone de jeu
(en vert clair sur la table). Lorsque le joueur clique sur le bouton gauche de la souris,
il faut placer la bille (voir figure 25.3) et passer la phase suivante (phase 3).

Figure 25.3 On placera la bille blanche la souris

515

CHAPITRE 25. TP : JEU DE BILLARD


Phase 3 : Vise avec la queue
La queue est aligne sur la bille blanche et le joueur peut viser la bille blanche en
faisant bouger la souris (voir figure 25.4). La distance entre le bout de la queue et la
bille blanche dtermine la puissance du coup port. Au clic de la souris, on tape dans
la bille blanche et cest au tour de la phase 4.

Figure 25.4 On visera avec la queue de billard


Il serait prfrable de limiter la distance maximum de la queue avec la bille
blanche afin dviter que la puissance du coup soit trop leve. On peut
galement envisager de poser une limite de distance minimum pour que le
joueur ne puisse pas faire de coup sans puissance du tout.

Phase 4 : Simulation des billes


Durant cette phase, il faut calculer le dplacement des billes chaque avance dimage.
Si deux billes entrent en collision, un calcul de choc lastique permet de dterminer leur
nouvelle direction et vitesse de dplacement. Si une bille entre en collision de bordure
avec un trou, la bille est retire du jeu jusqu la prochaine partie. Sil sagit de la bille
blanche, il faut la replacer : nous retournons donc la phase 2. Une fois les billes toutes
rentres (hors bille blanche), nous pouvons recommencer une partie et donc retourner
la phase 1.
Pendant quelle se dplace, chaque bille doit tourner sur elle-mme en fonction de sa
vitesse de dplacement, afin de donner un minimum dimpression de mouvement.
516

PRPARATION ET CONSEILS
Comme le calcul des chocs lastiques est un peu mathmatique et technique
et que cela nest pas lobjet du cours, le code correspondant vous sera fourni,
je vous rassure.

Consigne supplmentaire
Afin que notre jeu soit utilisable sur un petit cran, il serait prfrable de pouvoir
dplacer le billard laide du bouton droit de la souris.

Prparation et conseils
Prparation du projet
Dossier et ressources
Avant de commencer le TP, il nous faut prparer un peu le terrain. Commencez par crer
un nouveau dossier (ou projet Flashdevelop) appell Billard. Copiez le dossier com
de la librairie GSAP (que nous avons dcouverte dans le chapitre sur lanimation)
dans le dossier src o se trouve votre classe principale Main.
Nous allons galement utiliser une image et des polices de caractres placer dans un
dossier lib qui seront embarques dans notre application. Pour cela, je vous ai prpar
une archive extraire directement dans le dossier de votre projet.


Tlchargez les ressources
B
Code web : 166391


Ces ressources comprennent un dossier img contenant la texture de fond de notre
application et un dossier fonts contenant les fichiers de police de caractres inclure
laide dune classe EmbedFonts crer sur le modle de celle que nous avons vue dans
le chapitre sur le texte.
Premires classes utiles
Vous pouvez dj crer ces deux classes contenant des valeurs utiles pour notre projet.
Tout dabord, les constantes des units de mesure dans un fichier Unite.as :
1
2

package
{

3
4
5
6
7
8

public class Unite


{
public static const METRE : Number = 400 ;
public static const GRAMME : Number = 1 ;
}

517

CHAPITRE 25. TP : JEU DE BILLARD


Puis, les constantes mathmatiques dont nous aurons besoin pour certains calculs dans
un fichier Constantes.as :
1
2
3
4
5
6
7
8

package
{
public class Constantes
{
public static var restitution : Number = 0 . 85 ;
public static var frottement : Number = 0 . 007 ;
}
}

Il pourrait tre utile de pouvoir modifier ces constantes mathmatique


pendant le jeu (par exemple, dans un cran doptions), afin de permettre
au joueur daffiner ses prfrences au niveau du comportement des billes.
Nous ne le ferons pas dans le cadre de ce TP, mais cela peut tre une ide
damlioration.
Enfin, voici quelques fonctions mathmatiques rassembles au sien de cette classe qui
pourront vous tre utiles :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

package
{
import flash . display . DisplayObject ;
/* *
* Quelques fonctions utiles .
* @author Guillaume CHAU
*/
public class Outils
{
/* *
* Calcule et renvoie la distance ( en pixels ) entre
deux objets .
* @param
obj1
* @param
obj2
* @return
Distance en pixels
*/
static public function distance ( obj1 : DisplayObject ,
obj2 : DisplayObject ) : Number
{
return distanceNombres ( obj1 .x , obj1 .y , obj2 .x , obj2
.y);
}

20
21
22

23
24

518

/* *
* Calcule et renvoie la distance ( en pixels ) entre les
deux points form s par les coordonn es parss es en
param tre .
* @param
x1
* @param
y1

PRPARATION ET CONSEILS
* @param
x2
* @param
y2
* @return
Distance en pixels
*/
static public function distanceNombres ( x1 : Number , y1 :
Number , x2 : Number , y2 : Number ) : Number
{
var X : Number = x2 - x1 ;
var Y : Number = y2 - y1 ;
return Math . sqrt ( X * X + Y * Y ) ;
}

25
26
27
28
29
30
31
32
33
34
35

/* *
* Calcule et renvoie l ' angle ( en radians ) entre les
deux objets .
* @param
obj1
* @param
obj2
* @return
Angle en radians
*/
static public function angle ( obj1 : DisplayObject , obj2 :
DisplayObject ) : Number
{
return angleNombres ( obj1 .x , obj1 .y , obj2 .x , obj2 . y )
;
}

36
37
38
39
40
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
56
57
58

59

/* *
* Calcule et renvoie l ' angle ( en radians ) entre les
deux points form s par les coordonn es pass es en
param tre .
* @param
x1
* @param
y1
* @param
x2
* @param
y2
* @return
Angle en radians
*/
static public function angleNombres ( x1 : Number , y1 :
Number , x2 : Number , y2 : Number ) : Number
{
return Math . atan2 ( y2 - y1 , x2 - x1 ) ;
}

60
61

A quoi servent ces commentaires un peu tranges devant les proprits publiques ?

519

CHAPITRE 25. TP : JEU DE BILLARD


1
2
3
4
5
6

/* *
* Calcule et renvoie la distance ( en pixels ) entre deux objets
.
* @param
obj1
* @param
obj2
* @return
Distance en pixels
*/

Ces commentaires sont des commentaires de documentation. Il permettent de


dcrire, dans un format standardis, le fonctionnement de la proprit. Si vous voulez
en savoir plus, je vous invite consulter le chapitre correspondant dans les annexes.

Les diffrents lments du jeu


Voici les diffrents lments qui composerons notre jeu du billard. Il peut tre judicieux
de dfinir nos classes partir de ces lments.

La table
La table peut tre reprsente par un rectangle arrondi marron contenant un autre
rectangle arrondi vert avec quelques marques blanches transparentes pour aider placer
la bille blanche. La zone jouable en vert clair mesure 2,34 m de largeur et 1,17 m de
hauteur ; la marge de la partie vert fonce fait 0,08 m (8 cm). Nous pouvons par exemple
dfinir les diffrentes tailles ainsi en utilisant notre classe Unite :
1
2
3

var tableLargeur : Number = 2 . 34 * Unite . METRE ;


var tableHauteur : Number = 1 . 17 * Unite . METRE ;
var margeFond : Number = 0 . 08 * Unite . METRE ;

Vous verrez ce quoi la table doit ressembler la figure 25.9.


Pour obtenir ce rsultat, il faut dessiner en plusieurs tapes.
Tout dabord, dessinons un rectangle de couleur 0x0c351e (vert fonc) avec une bordure
de taille 5, de couleur 0x432e0e (marron) et arrondie de 32 pixels (figure 25.6).
Ajoutons un dessin (par exemple avec la classe Shape) dans notre table qui reprsentera
la zone de jeu, avec un rectangle de couleur 0x006029 (vert clair) avec bords arrondis
de 10 pixels, sans bordure (figure 25.7).
Nous pouvons ajouter un filtre dombre porte interne de couleur noire la zone
de jeu pour donner un peu de relief.
Ensuite, ajoutons trois lignes blanches transparentes (alpha 15%) avec un petit disque
au centre (alpha 30%), voir la figure 25.8.
Enfin, nous pouvons ajouter un filtre dombre porte pour simuler le volume de la table,
comme la figure 25.9.
520

PRPARATION ET CONSEILS

Figure 25.5 Le rendu final de la table

Figure 25.6 Premire tape : le fond

521

CHAPITRE 25. TP : JEU DE BILLARD

Figure 25.7 Etape 2 : zone de jeu

Figure 25.8 Etape 3 : marquage blanc

522

PRPARATION ET CONSEILS

Figure 25.9 Le rendu final de la table


Les trous
Chaque trou fait 0.069 m (ou 6,9 cm) de diamtre. Il sera constitu dun simple disque
de couleur noire (voir figure 25.10).

Figure 25.10 Un trou de billard


Il y en a six disposer autour de la zone de jeu de cette manire, comme la figure
25.11.
Les billes
Chaque bille sera reprsente par un disque de couleur, avec un numro au centre.
Une bille sur deux aura des bandes blanches (sauf la bille blanche et la bille 8) pour
diffrencier les deux quipes. Leur diamtre est de 0.07 m (ou 7 cm), et leur masse vaut
172 g :
1
2

var diametre : Number = 0 . 05 * Unite . METRE ;


var masse : Number = 172 * Unite . GRAMME ;

Voici les 16 couleurs rglementaires des billes dans lordre (la bille numro zro est la
bille blanche) :
1

var couleurs : Array = [

523

CHAPITRE 25. TP : JEU DE BILLARD

Figure 25.11 La position de chaque trou

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

];

0xffffff , // Bille blanche


0xfac92e ,
0x1744c1 ,
0xee372e ,
0x271d53 ,
0xff8d59 ,
0x189e66 ,
0x931422 ,
0x000000 , // Bille 8
0xf7af1d ,
0x2059e8 ,
0xde291d ,
0x2f2665 ,
0xfb8351 ,
0x0d955c ,
0x92121d

Il est temps de mettre en forme ces billes ! Prenons le cas de la bille 13 et commenons
par dessiner un disque (centr sur lorigine) de la couleur de la bille (figure 25.12).
Si le numro de la bille est suprieur ou gal 9, il faut ajouter des bandes blanches
comme la figure 25.13.
Pensez utiliser un masque circulaire pour faire prendre aux deux bandes la
forme circulaire de la bille.
524

PRPARATION ET CONSEILS

Figure 25.12 Etape 1 : disque de couleur

Figure 25.13 Etape 2 : ventuelles bandes blanches

Ensuite, si le numro est suprieur zro (donc si ce nest pas la bille blanche), on
ajoute un champ de texte noir contenant le numro avec un disque planc dessin en
dessous (figure 25.14).

Figure 25.14 Etape 3 : tiquette du numro

Souvenez-vous : il faut utiliser des polices de caractres embarques dans


notre application, sinon on ne pourra pas faire tourner les billes sans que le
texte ne disparaisse !
Enfin, pour donner un peu de volume nos billes, nous pouvons ajouter quelques filtres
sur chacune :
1
2
3
4
5
6

filters = [
// Ombre
new DropShadowFilter (3 , 45 , 0 , 0 .3 , 6 , 6 , 1 , 2 ) ,
// Volume ( ombre int rieure )
new DropShadowFilter ( -10 , 45 , 0 , 0 .3 , 6 , 6 , 1 , 2 , true )
];

Ce qui nous donne la figure 25.15.


525

CHAPITRE 25. TP : JEU DE BILLARD

Figure 25.15 Etape 4 : filtres dombrage

La queue
La queue est un bton de bois quip dun manche plus confortable pour bien la tenir.
Elle mesure 1,5 m de long et 0,025 m (ou 2,5 cm) de large.
Encore une fois, on peut utiliser les dessins pour parvenir nos fins : un rectangle
de couleur noire pour le manche et un autre rectangle lgrement plus fin de couleur
0x3e2317 (marron) pour le bton (figure 25.16).

Figure 25.16 Queue de billard

Je vous recommande de dessiner la queue de telle sorte que son origine soit
au bout, comme sur la figure ci-dessus.
Ce dessin doit tre plac dans un objet de dessin (Shape) dans notre classe qui reprsentera la queue afin de pouvoir la centrer sur la bille blanche et bouger le dessin
uniquement comme la figure 25.17.

Figure 25.17 On place la queue sur la bille blanche et on ne bouge que le dessin
Nous pouvons ventuellement ajouter un trait blanc semi-transparent comme viseur,
un texte prcisant la puissance du coup qui sera port en fonction de la distance par
rapport la bille blanche et quelques effets dombre (figure 25.18).
526

PRPARATION ET CONSEILS

Figure 25.18 Quelques ajouts sur la queue de billard


Encore une fois, il faut utiliser des polices de caractres embarques pour
viter que le texte ne disparaisse la rotation de la queue de billard.

Le fond
Le fond de notre scne sera un dessin couvrant la taille de la fentre rempli avec cette
texture (figure 25.19).

Figure 25.19 Texture de fond


Il faut donc ajouter un couteur sur lvnement Event.RESIZE sur la scne principale
pour dtecter le changement de taille. Pour remplir avec une image, nous utiliserons la
mthode beginBitmapFill() de la classe Graphics.

Un peu de Maths
Voici quelques portions de code permettant deffectuer les calculs sortants un peu du
cadre du cours.
Vecteur gomtrique
En premier lieu, nous aurons besoin de vecteurs gomtriques deux dimensions, dots
de quatre attributs pour nos calculs : x, y, module et angle (figure 25.20).
Voici la classe Vecteur2D reprsentant un vecteur gomtrique deux dimensions :
1
2

package
{

527

CHAPITRE 25. TP : JEU DE BILLARD

Figure 25.20 Un vecteur gomtrique deux dimensions

3
4
5
6
7
8
9
10

/* *
* Un vecteur x ;y , pour les calculs
* @author Guillaume CHAU
*/
public class Vecteur2D
{
private var _x : Number ;
private var _y : Number ;

11
12
13

private var _module : Number = 0 ;


private var _angle : Number = 0 ;

14
15
16
17
18

public function Vecteur2D ( x : Number = 0 , y : Number = 0 )


{
_x = x ;
_y = y ;

19
20
21

_calculAngleModule () ;

22
23
24
25
26

public function toString () : String


{
return " [ Vecteur2D x = " + x + " y = " + y + " module = "
+ module + " angle = " + angle + " ] " ;
}

27
28
29
30
31
32
33
34
35

528

/* *
* Revoie une copie du vecteur .
* @return
*/
public function clone () : Vecteur2D
{
var c : Vecteur2D = new Vecteur2D () ;
c . x = _x ;

PRPARATION ET CONSEILS
36
37
38

c . y = _y ;
return c ;

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

/* *
* Ajoute le vecteur pass en param tre au vecteur
courant .
* @param vecteur
Vecteur ajouter .
* @param apply
Si vrai , modifie directement le
vecteur courant . Sinon , renvoie un nouveau vecteur .
* @return
Le vecteur repr sentant la somme
des deux premiers vecteurs .
*/
public function ajouter ( vecteur : Vecteur2D , apply :
Boolean = false ) : Vecteur2D
{
var cible : Vecteur2D ;
if ( apply )
{
cible = this ;
}
else
{
cible = clone () ;
}
cible . x += vecteur . x ;
cible . y += vecteur . y ;
return cible ;
}

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

/* *
* Soustrait le vecteur pass en param tre au vecteur
courant .
* @param vecteur
Vecteur soustraire .
* @param apply
Si vrai , modifie directement le
vecteur courant . Sinon , renvoie un nouveau vecteur .
* @return
Le vecteur repr sentant la
soustraction des deux premiers vecteurs .
*/
public function soustraire ( vecteur : Vecteur2D , apply :
Boolean = false ) : Vecteur2D
{
var cible : Vecteur2D ;
if ( apply )
{
cible = this ;
}
else
{
cible = clone () ;

529

CHAPITRE 25. TP : JEU DE BILLARD


78
79
80
81
82

}
cible . x -= vecteur . x ;
cible . y -= vecteur . y ;
return cible ;

83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

/* *
* Multiplie le vecteur par un coefficient num rique .
* @param coef
Coefficient num rique .
* @param apply
Si vrai , modifie directement le
vecteur courant . Sinon , renvoie un nouveau vecteur .
* @return
Le vecteur ayant re u la
multiplication .
*/
public function multiplier ( coef : Number , apply : Boolean =
false ) : Vecteur2D
{
var cible : Vecteur2D ;
if ( apply )
{
cible = this ;
}
else
{
cible = clone () ;
}
cible . x *= coef ;
cible . y *= coef ;
return cible ;
}

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121

530

/* *
* Normalise le vecteur ( c 'est - - dire modifie ses
coordonn es x et y telles que son module vaille 1 ) .
* @param apply
Si vrai , modifie directement le
vecteur courant . Sinon , renvoie un nouveau vecteur .
* @return
Le vecteur normalis .
*/
public function normaliser ( apply : Boolean = false ) :
Vecteur2D
{
var cible : Vecteur2D ;
if ( apply )
{
cible = this ;
}
else
{
cible = clone () ;
}

PRPARATION ET CONSEILS
122
123
124
125
126
127
128
129
130
131
132
133
134

var m : Number = cible . module ;


if ( m != 0 )
{
cible . x /= m ;
cible . y /= m ;
}
else
{
cible . x = 0 ;
cible . y = 0 ;
}
return cible ;

135
136
137
138
139
140
141
142
143
144

/* *
* Calcule le produit du vecteur courant avec le
vecteur pass en param tre .
* @param vecteur
Le vecteur multiplier avec le
vecteur courant .
* @return
Nombre r sultant de la
multiplication des deux vecteurs .
*/
public function produit ( vecteur : Vecteur2D ) : Number
{
return this . x * vecteur . x + this . y + vecteur . y ;
}

145
146

/* PRIVE */

147
148
149
150
151
152
153
154
155
156
157
158
159
160

private function _calculCoord () : void


{
if ( _module == 0 )
{
_x = 0 ;
_y = 0 ;
}
else
{
_x = Math . cos ( angle ) * _module ;
_y = Math . sin ( angle ) * _module ;
}
}

161
162
163
164
165
166
167
168

private function _calculAngleModule () : void


{
if ( _x == 0 && _y == 0 )
{
_angle = 0 ;
_module = 0 ;
}

531

CHAPITRE 25. TP : JEU DE BILLARD


else
{

169
170
171
172
173
174

_module = Outils . distanceNombres (0 , 0 , _x , _y ) ;


_angle = Outils . angleNombres (0 , 0 , _x , _y ) ;

175
176

/* GETTERS */

177
178
179
180
181
182
183
184

/* *
* Coordonn e horizontale .
*/
public function get x () : Number
{
return _x ;
}

185
186
187
188

public function set x ( value : Number ) : void


{
_x = value ;

189
190
191

_calculAngleModule () ;

192
193
194
195
196
197
198
199

/* *
* Coordonn e verticale .
*/
public function get y () : Number
{
return _y ;
}

200
201
202
203

public function set y ( value : Number ) : void


{
_y = value ;

204
205
206

_calculAngleModule () ;

207
208
209
210
211
212
213
214

/* *
* Module ( longeur du vecteur ) .
*/
public function get module () : Number
{
return _module ;
}

215
216
217
218

532

public function set module ( value : Number ) : void


{
_module = value ;

PRPARATION ET CONSEILS
219
220

221

_calculCoord () ;

222

/* *
* Angle du vecteur par rapport l ' horizontale .
*/
public function get angle () : Number
{
return _angle ;
}

223
224
225
226
227
228
229
230

public function set angle ( value : Number ) : void


{
_angle = value ;

231
232
233
234
235

236

_calculCoord () ;

237

238
239
240

Vous
pouvez lafficher pour la copier
 en utilisant le code web ci-dessous.
Classe Vecteur2D
B
Code
web : 933976


Cette classe sera notamment utile pour calculer les changements de trajectoires entre
les billes ou, pourquoi pas, reprsenter le dplacement de chaque bille.
Il peut souvent tre intressant de reprsenter des concepts abstraits (comme
les vecteurs gomtriques) en classes par entire afin de faciliter les calculs
par la suite et de rendre le tout plus clair et lisible.

Choc lastique
Lorsque deux billes de billard se rencontrent, il se produit un choc lastique : la trajectoire et la vitesse des deux billes est alors modifie comme on peut le remarquer dans
la figure 25.21.
Pour le projet, partons du principe que chaque bille possde un attribut velocite de
classe Vecteur2D qui reprsente son dplacement (horizontal et vertical) dans la zone
de jeu. Pour la phase de simulation du jeu de billard, il faut alors dplacer chaque bille
en fonction de la valeur des coordonnes du vecteur (velocite.x pour le dplacement
horizontal et velocite.y pour le dplacement vertical), et ceci rgulirement pour
donner lillusion du dplacement (par exemple, chaque changement de frame grce
lvnement Event.ENTER_FRAME).
On peut calculer les nouvelles trajectoires de deux billes entrant en collision laide de
533

CHAPITRE 25. TP : JEU DE BILLARD

Figure 25.21 Choc lastique entre deux billes


ce calcul un peu complexe que je vous ai prpar :
1

var taille : Number = ( this . taille + bille . taille ) / 2 ;

2
3
4
5
6
7
8
9
10
11
12
13

// Repositionnement au point de contact


// Vecteur distance entre les boules
var delta : Vecteur2D = new Vecteur2D ( this . x - bille .x , this . y bille . y ) ;
var d : Number = delta . module ;
// Distance de translation minimum pour pousser les boules
if ( d == 0 )
{
d = ( this . taille + bille . taille ) * 0 . 5 - 1 ;
delta = new Vecteur2D (( this . taille + bille . taille ) * 0 .5 , 0
);
}
var mtd : Vecteur2D = delta . multiplier ((( this . taille + bille .
taille ) * 0 . 5 - d ) / d ) ;

14
15
16
17

// Masse inverse
var im1 : Number = 1 / this . masse ;
var im2 : Number = 1 / bille . masse ;

18
19
20
21
22
23
24

// Repousser les balles pour viter qu ' elles se chevauchent


var correction : Vecteur2D = mtd . multiplier ( im1 / ( im1 + im2 ) ) ;
this . x += correction . x ;
this . y += correction . y ;
bille . x -= correction . x ;
bille . y -= correction . y ;

25
26
27
28
29
30
31

// Calcul de la base orthonorm e (n , g )


// n est perpendiculaire au plan de collision , g est tangent
var nx : Number = ( bille . x - this . x ) / taille ;
var ny : Number = ( bille . y - this . y ) / taille ;
var gx : Number = - ny ;
var gy : Number = nx ;

32
33

// Calcul des vitesses dans cette base

534

ORGANISATION DE LAPPLICATION
34
35
36
37

var
var
var
var

v1n : Number
v1g : Number
v2n : Number
v2g : Number

=
=
=
=

nx
gx
nx
gx

*
*
*
*

this . velocite . x + ny * this . velocite . y ;


this . velocite . x + gy * this . velocite . y ;
bille . velocite . x + ny * bille . velocite . y ;
bille . velocite . x + gy * bille . velocite . y ;

38
39
40
41
42
43
44

// Permute les coordonn es n et conserve la vitesse


tangentielle
// Ex cute la transformation inverse ( base orthonorm e = >
matrice transpos e )
this . velocite . x = nx * v2n + gx * v1g ;
this . velocite . y = ny * v2n + gy * v1g ;
bille . velocite . x = nx * v1n + gx * v2g ;
bille . velocite . y = ny * v1n + gy * v2g ;

Lobjet courant de ce calcul (cest--dire lobjet point par le mot-cl this)


est la bille qui est entre en collision avec la deuxime bille, contenue dans la
variable bille.
Aprs ce calcul, lobjet velocite de chaque bille contient le nouveau dplacement
horizontal (velocite.x) et le nouveau dplacement vertical (velocite.y) de la bille.

Organiser son projet


Maintenant que vous avez toutes les cls en mains, il faut organiser votre projet. Posezvous plusieurs questions avant de commencer coder quoi que ce soit ! Commencez par
dessiner sur une feuille les classes que vous allez crer, rflchissez la faon dont elles
vont interagir entre elles, si il y aura des classes mres, etc. Pour vous donner un ordre
dide, mon projet compte au total 12 classes (hors librairie GSAP), mais vous pouvez
tout fait en crer plus ou moins que moi. Ensuite, reprsentez le droulement dune
partie de billard pour lavoir bien en tte lorsque vous implmenterez la logique de
ce jeu de billard. Et surtout, nhsitez par parcourir nouveau certaines sections du
cours. Essayez de produire quelque chose, mme si cela na pas autant de fonctionnalits
que vous lespriez, avant de regarder la correction : on apprend le mieux en pratiquant
soi-mme !
A vos stylos et claviers !

Organisation de lapplication
La structure de lapplication
Avant de commencer programmer tte baisse, il faut rflchir la structure du
projet. Avec quelques feuilles et un crayon, vous pouvez commencer organiser votre
application, ce travail est trs important pour que votre projet soit clair et lisible (y
compris pour vous-mme). Je vais vous prsenter la structure que jai choisie, qui peut
535

CHAPITRE 25. TP : JEU DE BILLARD


tout fait diffrer de la vtre, il ny a pas une seule solution ce problme, ne loubliez
pas !
Jai donc articul mon application autour dune classe nomme Billard qui reprsente
le jeu de billard que nous concevons. Cette classe utilise dautres classes pour composer
les diffrents lments du jeu : la table, les trous, les billes et la queue, qui sont les
diffrents objets visuels. La logique du jeu de billard est galement contenue dans la
classe Billard. A ct de cette classe, nous retrouvons la classe Vecteur2D servant
faire plusieurs calculs (comme les dplacements des billes et les chocs lastiques). Enfin,
la classe Main reprsente le programme principal qui va crer un jeu de billard laide
de la classe Billard.
Vous verre la figure 25.22 le diagramme des classes principales de lapplication.

Figure 25.22 Diagramme des classes


Les autres classes annexes (comme les classes Unite et Constantes) ne sont
pas reprsentes sur ce diagramme pour des raisons de lisibilit.
536

CRATION DES CLASSES

Description des diffrents classes


Nous avons donc huit classes principales :
Classe Main : programme principal, charg de grer la cration du jeu du Billard et
la texture de fond de lapplication.
Classe Billard : reprsente le jeu du billard, cest--dire sa logique (avec les quatre
phases de jeu) et ses diffrents lments.
Classe Visuel : classe mre des lments composants le jeu.
Classe Table : consiste principalement en un dessin de la table de billard et gestion
des collisions entre les billes et les bords de la zone de jeu.
Classe Trou : dessin dun trou de la table de billard avec la gestion des collisions des
billes avec ce trou .
Classe Bille : dessin dune bille de billard (avec un numro), ainsi que la gestion du
dplacement de la bille et des collisions entre deux billes.
Classe Queue : dessin de la queue de billard (avec les indicateurs visuels).
Classe Vecteur2D : reprsente un vecteur gomtrique deux dimensions pour les
calculs.

Cration des classes


Dans cette partie, nous allons dtailler les diffrentes classes du projet, une une.
Toutefois, essayez quand mme daboutir un rsultat par vos propres moyens avant
de vous jeter sur cette correction, cela vous aidera progresser !

Visuel
Commenons par crer la classe de base de nos objets graphiques, la classe Visuel.
Cette classe va grer la taille des objets visuels et va faire en sorte de les dessiner
chaque modification de taille en partant de la classe daffichage Sprite. Grce au
polymorphisme, nous pouvons redfinir les accesseurs width et height de la classe
Sprite de telle sorte que la mthode protge _dessiner soit appelle automatiquement ds quun changement de taille intervient : ainsi, nos objets graphiques seront
redessins ds quil sera ncessaire !
1
2
3

package
{
import flash . display . Sprite ;

4
5
6
7
8
9
10
11

/* *
* Classe de base des objets graphiques .
* @author Guillaume CHAU
*/
public class Visuel extends Sprite
{
// Taille " virtuelle "

537

CHAPITRE 25. TP : JEU DE BILLARD


12
13

private var _width : Number = 0 ;


private var _height : Number = 0 ;

14
15

private var _taille : Number = 0 ;

16
17
18

public function Visuel ()


{

19
20

21
22

/* PRIVE */

23
24
25
26
27

protected function _dessiner () : void


{
// A impl menter dans les sous - classes
}

28
29

/* GETTERS */

30
31
32
33
34

override public function get width () : Number


{
return _width ;
}

35
36
37
38

override public function set width ( value : Number ) : void


{
_width = value ;

39
40
41

_dessiner () ;

42
43
44
45
46

override public function get height () : Number


{
return _height ;
}

47
48
49
50

override public function set height ( value : Number ) : void


{
_height = value ;

51
52
53

_dessiner () ;

54
55
56
57
58
59
60

538

/* *
* Taille de l ' objet visuel au cas o il n 'a besoin que
d ' un nombre ( exemple : diam tre ) .
*/
public function get taille () : Number
{
return _taille ;

CRATION DES CLASSES


}

61
62

public function set taille ( value : Number ) : void


{
_taille = value ;

63
64
65
66
67
68

69

_dessiner () ;

70
71

Vous
pouvez lafficher pour la copier
 en utilisant le code web ci-dessous.
Classe Visuel
B
Code
web : 930063


Jai ajout un attribut taille pour les objets nayant besoin que dun nombre
pour leur taille (comme les billes et les trous de la table).
Au lieu de laisser la classe Sprite redimensionner (tirer) lobjet comme dhabitude,
nous stockons les nouvelles informations de taille (que jai appelles les informations
de taille virtuelle), puis nous utiliserons ses informations dans la mthode _dessiner
(redfinie dans les sous-classes) afin de redessiner les objets graphiques la bonne taille.

Bille
La classe Bille (et les autres objets graphiques du jeu de billard) est une sous-classe
de la classe Visuel. Commenons donc par lui faire hriter la classe Visuel :
1
2
3
4
5
6
7
8

package
{
/* *
* Bille de billard .
* @author Guillaume CHAU
*/
public class Bille extends Visuel
{

9
10
11

Si vous utilisez Flashdevelop, il est possible de spcifier la classe mre lorsque vous
crez une classe pour que lIDE crive le code correspondant automatiquement (avec
les imports). Il suffit de la renseigner dans le champ Base Class de la fentre de cration
de classe. Cliquez dabord sur le bouton Browse en face du champ Base Class, comme
la figure 25.23.
Puis tapez le nom de la classe mre et slectionnez-la (voir figure 25.24).
539

CHAPITRE 25. TP : JEU DE BILLARD

Figure 25.23 Fentre de cration de classe

Figure 25.24 Slection de la classe mre

540

CRATION DES CLASSES


Une fois la classe cre, ajoutons-lui les attributs des billes :
1
2
3
4

// Infos de
private var
private var
private var

bases
_couleur : uint ;
_numero : int ;
_masse : Number ;

5
6
7

// Vraie si la bille est tomb e dans un trou


private var _horsJeu : Boolean = false ;

8
9
10
11

// El ments visuels
private var _masque : Shape ;
private var _etiquette : TextField ;

12
13
14

// Vecteur de d placement
private var _velocite : Vecteur2D ;

Sans oublier les accesseurs correspondants :


1
2
3
4
5
6
7

/* *
* Couleur de la bille ( exemple : 0xFF0055 ) .
*/
public function get couleur () : uint
{
return _couleur ;
}

8
9
10

11
12
13
14
15

/* *
* Num ro de la bille . Si le num ro est 0 , la bille n 'a pas d '
tiquette . Si le num ro est sup rieur ou gal 9 , la bille
a des bandes blanches .
*/
public function get numero () : int
{
return _numero ;
}

16
17
18
19
20
21
22
23

/* *
* Masse de la bille . Utiliser Unite . GRAMME .
*/
public function get masse () : Number
{
return _masse ;
}

24
25
26
27
28

public function set masse ( value : Number ) : void


{
_masse = value ;
}

29
30

/* *

541

CHAPITRE 25. TP : JEU DE BILLARD


31
32
33
34
35
36

* Vecteur g om trique repr sentant le d placement de la bille


par frame .
*/
public function get velocite () : Vecteur2D
{
return _velocite ;
}

37
38
39
40
41

public function set velocite ( value : Vecteur2D ) : void


{
_velocite = value ;
}

42
43
44
45
46
47
48
49

/* *
* Indique si la bille est hors - jeu ( ex : tomb e dans un trou ) .
*/
public function get horsJeu () : Boolean
{
return _horsJeu ;
}

50
51
52
53
54

public function set horsJeu ( value : Boolean ) : void


{
_horsJeu = value ;
}

Constructeur
Le constructeur de la bille cr les diffrents objets contenus dans la bille : ltiquette du
numro et le vecteur de dplacement. De plus, il reoit en paramtre les informations
de bases sur la bille (couleur, numro, taille et masse).
1
2
3
4
5
6
7
8
9

public function Bille ( couleur : uint , numero : int , taille : Number ,


masse : Number )
{
// Etiquette affichant le num ro de la bille
_etiquette = new TextField () ;
_etiquette . selectable = false ;
_etiquette . autoSize = TextFieldAutoSize . LEFT ;
_etiquette . defaultTextFormat = new TextFormat ( ' arial ' , 10 ,
0x000000 ) ;
_etiquette . embedFonts = true ;
addChild ( _etiquette ) ;

10
11
12
13
14
15

542

// Effets sp ciaux
filters = [
// Ombre
new DropShadowFilter (3 , 45 , 0 , 0 .3 , 6 , 6 , 1 , 2 ) ,
// Volume ( ombre int rieure )

CRATION DES CLASSES


16

];

17

new DropShadowFilter ( -10 , 45 , 0 , 0 .3 , 6 , 6 , 1 , 2 , true


)

18

// Vecteur g om trique deux dimensions repr sentant le d


placement de la bille pour chaque frame
_velocite = new Vecteur2D () ;

19
20
21
22
23
24
25
26
27

// Autres attributs
_couleur = couleur ;
_numero = numero ;
this . taille = taille ;
_masse = masse ;

Dessin de la bille
Nous avons notre disposition une mthode _dessiner hrite de la classe mre Visuel
qui, pour rappel, sera appele ds quil faudra redessiner lobjet graphique. Nous allons
donc redfinir cette mthode pour dessiner notre bille :
1
2
3

override protected function _dessiner () : void


{
super . _dessiner () ;

4
5
6
7
8
9

// Bille
graphics . clear () ;
graphics . lineStyle (1 , _couleur ) ;
graphics . beginFill ( _couleur ) ;
graphics . drawCircle (0 , 0 , taille * 0 . 5 - 1 ) ;

10
11
12
13
14
15
16
17
18
19

// Bandes
if ( _numero >= 9 )
{
// Rectangles blancs
graphics . lineStyle () ;
graphics . beginFill ( 0xffffff ) ;
graphics . drawRect ( - taille / 2 , - taille / 2 , taille , 3
);
graphics . drawRect ( - taille / 2 , taille / 2 - 3 , taille ,
3);
graphics . endFill () ;

20
21
22
23
24
25
26

// Masque circulaire
_masque = new Shape () ;
_masque . graphics . beginFill ( 0 ) ;
_masque . graphics . drawCircle (0 , 0 , taille * 0 . 5 - 1 ) ;
addChild ( _masque ) ;
mask = _masque ;

543

CHAPITRE 25. TP : JEU DE BILLARD


}

27
28

// Num ro
_etiquette . visible = ( _numero > 0 ) ;

29
30
31

if ( _etiquette . visible )
{
_etiquette . text = _numero . toString () ;
_etiquette . x = - _etiquette . width * 0 . 5 ;
_etiquette . y = - _etiquette . height * 0 . 5 ;

32
33
34
35
36
37
38
39
40
41

graphics . beginFill ( 0xffffff ) ;


graphics . drawCircle (0 , 0 , _etiquette . height * 0 . 4 ) ;

Les bandes ne sont dessines que si le numro de la bille est suprieur ou gal 9 :
on utilise alors un masque circulaire et deux rectangles blancs. Puis, nous cachons
ltiquette si le numro vaut zro (correspondant alors la bille blanche). Dans le cas
contraire, nous mettons jour ltiquette, la centrons au milieu de la bille et dessinons
un disque blanc supplmentaire.
Collision avec une autre bille
La gestion des collisions avec les autres billes seffectue en deux tapes :
On teste dabord la collision entre les deux billes.
Si les deux billes sont entres en collision, on calcule leur nouveau vecteur de dplacement suite au choc lastique.
Commenons donc par crer une mthode testant la collision de la bille avec une autre :
1
2
3
4

private function _dectecterCollision ( bille : Bille ) : Boolean


{
var dX : Number = this . x - bille . x ;
var dY : Number = this . y - bille . y ;

var racineRayons : Number = ( this . taille + bille . taille ) * 0 .


5;
racineRayons = racineRayons * racineRayons ;

6
7
8

var racineDistance : Number = ( dX * dX ) + ( dY * dY ) ;

9
10
11
12

return racineDistance <= racineRayons ;

Pour savoir si deux billes sont entres en collision, nous calculons la distance entre les
deux au carr, puis nous la comparons au carr de la somme de leur rayon, comme nous
lavons vu dans le chapitre sur la thorie des collisions (et plus prcisment la partie
sur les collisions circulaires).
544

CRATION DES CLASSES


Ensuite, il faut crer une mthode qui va calculer les changements des vecteurs de
dplacement lors dun choc lastique entre deux billes :
1
2
3

private function _ca lcu le rCh oc Ela sti qu e ( bille : Bille ) : void
{
var taille : Number = ( this . taille + bille . taille ) / 2 ;

4
5
6
7
8
9
10
11
12
13
14
15

// Repositionnement au point de contact


// Vecteur distance entre les boules
var delta : Vecteur2D = new Vecteur2D ( this . x - bille .x , this .
y - bille . y ) ;
var d : Number = delta . module ;
// Distance de translation minimum pour pousser les boules
if ( d == 0 )
{
d = ( this . taille + bille . taille ) * 0 . 5 - 1 ;
delta = new Vecteur2D (( this . taille + bille . taille ) * 0 .
5, 0);
}
var mtd : Vecteur2D = delta . multiplier ((( this . taille + bille .
taille ) * 0 . 5 - d ) / d ) ;

16
17
18
19

// Masse inverse
var im1 : Number = 1 / this . masse ;
var im2 : Number = 1 / bille . masse ;

20
21
22
23
24
25
26

// Repousser les balles pour viter qu ' elles se chevauchent


var correction : Vecteur2D = mtd . multiplier ( im1 / ( im1 + im2 )
);
this . x += correction . x ;
this . y += correction . y ;
bille . x -= correction . x ;
bille . y -= correction . y ;

27
28
29
30
31
32
33

// Calcul de la base orthonorm e (n , g )


// n est perpendiculaire au plan de collision , g est
tangent
var nx : Number = ( bille . x - this . x ) / taille ;
var ny : Number = ( bille . y - this . y ) / taille ;
var gx : Number = - ny ;
var gy : Number = nx ;

34
35
36
37
38
39

// Calcul des vitesses dans cette base


var v1n : Number = nx * this . velocite . x + ny * this . velocite .
y;
var v1g : Number = gx * this . velocite . x + gy * this . velocite .
y;
var v2n : Number = nx * bille . velocite . x + ny * bille .
velocite . y ;
var v2g : Number = gx * bille . velocite . x + gy * bille .
velocite . y ;

545

CHAPITRE 25. TP : JEU DE BILLARD


40
41
42
43
44
45
46
47

// Permute les coordonn es n et conserve la vitesse


tangentielle
// Ex cute la transformation inverse ( base orthonorm e = >
matrice transpos e )
this . velocite . x = nx * v2n + gx * v1g ;
this . velocite . y = ny * v2n + gy * v1g ;
bille . velocite . x = nx * v1n + gx * v2g ;
bille . velocite . y = ny * v1n + gy * v2g ;

Il sagit du calcul que je vous avais donn la prparation du TP qui permet de dfinir
de nouveaux vecteurs gomtriques de dplacement pour la bille courante et la bille
teste laide de la thorie des chocs lastiques.
Maintenant que nous avons ces deux mthodes de prtes, nous pouvons crer la mthode
publique grant la collision de la bille avec une autre bille :
1
2
3
4
5
6
7
8
9
10
11

/* *
* Teste la collision avec une autre bille , et applique le choc
lastique le cas ch ant .
* @param bille
*/
public function testerCollision ( bille : Bille ) : void
{
if ( _ dectecterCollision ( bille ) )
{
_ c al cul erC ho cEl as tiq ue ( bille ) ;
}
}

Il est important de bien sparer chaque fonctionnalit dans des fonctions


diffrentes : ici, nous avons cr deux mthodes prives qui serons utilises
dans la mthode principale au lieu de tout mlanger dans une seule mthode :
le test de collision puis le calcul du choc lastique. Cela permet de rendre
le code plus clair, mais cela permet aussi au dveloppeur de tester chaque
fonctionnalit plus finement et donc de cerner les problmes plus facilement.

Dplacement
Enfin, il nous faut une mthode pour dplacer la bille dune frame. Jai ajout un
paramtre multiplicateur qui permet de faire varier la vitesse de la simulation : il nous
est alors possible de faire un magnifique ralenti ou au contraire, dacclrer le jeu !
1
2
3

/* *
* D place la bille d ' une frame avec application de la d c l
ration .
* @param multiplieur

546

CRATION DES CLASSES


4
5
6
7
8

*/
public function deplacer ( multiplicateur : Number = 1 ) : void
{
x += _velocite . x * multiplicateur ;
y += _velocite . y * multiplicateur ;

rotation += _velocite . module * 3 * multiplicateur ;

10
11
12
13
14
15
16
17
18
19
20

if ( _velocite . module
{
_velocite . module
frottement +
}
else
{
_velocite . module
}

> 0 . 03 )
-= ( _velocite . module * Constantes .
0 . 03 ) * multiplicateur ;

= 0;

Nous commenons par dplacer la bille en fonction de son vecteur de dplacement


velocite, puis nous la faisons tourner sur elle-mme plus ou moins rapidement en
fonction de sa vitesse de dplacement (cest--dire le module du vecteur de dplacement). Ensuite, nous diminuons la vitesse de la bille dau moins 0.03 pixels par frame
(fois le multiplicateur) en fonction de la constante de frottement que nous avons dfini
au dbut. Ceci nous permet de simuler la dclration de la bille sur la table.
Le minimum de 0.03 permet dviter des comportements bizarres de la bille
lors de la dclration en imposant une diminution minimale et un arrt si la
vitesse est trop petite (infrieure 0.03).

Table
La table contient deux dessins (table et zone de jeu) et gre la collision des billes avec
les bords de la zone de jeu. Ajoutons dabord les deux attributs de la table (limage de
fond et le dessin de la zone de jeu) :
1
2
3

// El ments visuels
private var _fond : Shape ;
private var _dessin : Shape ;

Constructeur
Le constructeur sert une fois de plus crer les objets daffichages qui composent
notre objet. Il sagit ici du dessin de la table et du dessin de la zone de jeu :
1
2

public function Table ()


{

547

CHAPITRE 25. TP : JEU DE BILLARD


_fond = new Shape () ;
// Ombre port e
_fond . filters = [ new DropShadowFilter ( 10 , 45 , 0 , 0 .6 , 10 ,
10 , 1 , 2 ) ];
addChild ( _fond ) ;

3
4
5
6
7
8
9
10
11
12

_dessin = new Shape () ;


// Ombre int rieure
_dessin . filters = [ new DropShadowFilter (4 , 45 , 0 , 0 .3 , 20 ,
20 , 1 , 2 , true ) ];
addChild ( _dessin ) ;

Dessin de la table
Comme pour la classe Bille, nous redfinissions la mthode _dessiner de la classe
mre Visuel pour dessiner la table :
1
2
3

override protected function _dessiner () : void


{
super . _dessiner () ;

4
5
6
7
8
9
10

// Fond
var margeFond : Number = 0 . 08 * Unite . METRE ;
_fond . graphics . clear () ;
_fond . graphics . lineStyle (5 , 0x432e0e , 1 , true ) ;
_fond . graphics . beginFill ( 0x0c351e ) ;
_fond . graphics . drawRoundRect ( - margeFond , - margeFond , width
+ 2 * margeFond , height + 2 * margeFond , 32 ) ;

11
12
13
14
15
16

// Zone de jeu
_dessin . graphics . clear () ;
_dessin . graphics . beginFill ( 0x006029 ) ;
_dessin . graphics . drawRoundRect (0 , 0 , width , height , 10 ) ;
_dessin . graphics . endFill () ;

17
18
19
20
21
22
23
24

// Lignes et points centraux


for ( var i : int = 1 ; i <= 3 ; i ++)
{
// Ligne
_dessin . graphics . lineStyle (4 , 0xffffff , 0 . 15 ) ;
_dessin . graphics . moveTo ( width * 0 . 25 * i , 0 ) ;
_dessin . graphics . lineTo ( width * 0 . 25 * i , height ) ;

25
26
27
28
29

548

// Point
_dessin . graphics . lineStyle () ;
_dessin . graphics . beginFill ( 0xffffff , 0 . 3 ) ;
_dessin . graphics . drawCircle ( width * 0 . 25 * i , height *
0 .5 , 3 ) ;

CRATION DES CLASSES


30
31

La taille dfinie grce width et height correspond la taille de la zone de


jeu pour faciliter lcriture du code. La taille totale de la table (en comptant
les bordures) est donc plus grande.

Collision avec les billes


Intressons nous maintenant la collision des billes avec les bords de la table. Il sagit
dun cas dont nous avons parl dans le chapitre sur la thorie des collisions travers
de lexemple de la collision avec la scne principale. Cette-fois, il sagit dune zone plus
rduite reprsente par la zone de jeu.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

/* *
* Teste la collision de la bille avec les bords de la zone de
jeu et applique la collision le cas ch ant .
* @param bille
*/
public function testerCollision ( bille : Bille ) : void
{
var taille : Number = bille . taille * 0 . 5 ;
// Bord gauche
if ( bille . x - taille <= 0 )
{
bille . x = taille ;
bille . velocite . x *= -1 ;
}
// Bord droit
else if ( bille . x + taille >= width )
{
bille . x = width - taille ;
bille . velocite . x *= -1 ;
}

20
21
22
23
24
25
26
27
28
29
30
31
32
33

// Bord haut
if ( bille . y - taille <= 0 )
{
bille . y = taille ;
bille . velocite . y *= -1 ;
}
// Bord bas
else if ( bille . y + taille >= height )
{
bille . y = height - taille ;
bille . velocite . y *= -1 ;
}

549

CHAPITRE 25. TP : JEU DE BILLARD

Trous
Chaque trou contient un dessin trs simple et permet de grer la collision avec les billes.
Ce ntait pas demand, mais jai ajout en plus une poche pour afficher les billes qui
sont tombes dans chaque trou (voir figure 25.25).

Figure 25.25 Poche contenant les billes tombes dans le trou


Cest quand-mme plus agrable, non ? Mais ne vous inquitez pas si vous navez pas
fait quelque chose de similaire, il sagit dun bonus.
Attributs
Au niveau des attributs, nous avons le numro du trou, la liste des billes tombes
dans le trou, le dessin du trou et enfin le dessin de la poche :
1
2

// Infos de base
private var _numero : int ;

3
4
5

// Billes tomb es dans le trou


private var _billes : Vector . < Bille >;

6
7
8
9

// El ments visuels
private var _dessin : Shape ;
private var _poche : Shape ;

la figure 25.26, les numros de nos trous.


Les trous dont le numro est infrieur ou gal 3 sont en haut et les autres sont en
bas. Cette information sera utile pour dessiner les poches des billes.
Vous pouvez ajouter des accesseurs pour chaque attribut si vous jugez cela ncessaire.
Constructeur
Le constructeur sert encore initialiser les objets de la classe. Ici, nous crons la liste
des billes, puis ajoutons les diffrents objets daffichage (dessin du trou et de la poche),
et enfin affectons le paramtre numero :
1

550

public function Trou ( numero : int )

CRATION DES CLASSES

Figure 25.26 Numro des trous


2

super () ;

_billes = new Vector . < Bille >() ;

5
6

_dessin = new Shape () ;


addChild ( _dessin ) ;

7
8
9

_poche = new Shape () ;


_poche . alpha = 0 ;
// Ombre int rieure de la poche
_poche . filters = [ new GlowFilter ( 0x000000 , 0 .5 , 6 , 6 , 2 , 2 ,
true ) ];
addChild ( _poche ) ;

10
11
12
13
14
15
16
17

_numero = numero ;

Dessin du trou
Encore une fois, nous redfinissons la mthode _dessiner :
1
2
3

override protected function _dessiner () : void


{
super . _dessiner () ;

4
5
6

// Trou
_dessin . graphics . clear () ;

551

CHAPITRE 25. TP : JEU DE BILLARD


7
8
9

_dessin . graphics . beginFill ( 0 ) ;


_dessin . graphics . drawCircle (0 , 0 , taille * 0 . 5 ) ;

Test de la collision des billes avec le trou


Pour la gestion des collisions avec les billes, nous avons besoin que dune mthode
testant la collision dune bille avec le trou :
1
2
3
4
5
6
7
8
9

/* *
* Teste la collision de la bille avec le trou courant .
* @param bille
* @return
Vrai si la bille est entr e en collision avec
le trou .
*/
public function testerCollision ( bille : Bille ) : Boolean
{
return _dessin . hitTestObject ( bille ) ;
}

Cette mthode permettra au billard de savoir si une bille est tombe dans un trou.
Ajout dune bille tombe dans le trou
Dans le cas dune collision, la bille sera ajout au trou par le jeu de billard pour tre
affiche dans la poche. Il nous faut alors cette mthode qui ajoute une bille :
1
2
3
4
5
6
7
8

/* *
* Ajoute une bille dans le trou . Elle sera affich e dans une
poche .
* @param bille
*/
public function ajouterBille ( bille : Bille ) : void
{
// Index de la bille dans la liste des billes tomb es dans
le trou
var index : int = _billes . length ;

9
10
11
12
13
14
15

// Bille
bille . alpha = 1 ;
bille . rotation = 0 ;
bille . x = x + (( index % 5 ) - 2 ) * bille . taille ;
bille . y = y + Math . floor ( index / 5 ) * bille . taille ;
_billes . push ( bille ) ;

16
17
18
19

552

// Ajustement de la position de la bille en fonction de l '


enplacement de la poche
if ( numero <= 3 )
{

CRATION DES CLASSES


20
21

}
else
{

22
23
24
25
26

27

// Poche au dessus du trou


bille . y -= bille . taille * 6 ;

// Poche en dessous du trou


bille . y += bille . taille * 4 ;

28

// Animation bille
TweenMax . fromTo ( bille , 0 .8 , { scaleX :0 , scaleY : 0 } , {
scaleX :1 , scaleY :1 , ease : Bounce . easeOut , delay : 0 . 3 } ) ;

29
30
31

// Poche
_poche . graphics . clear () ;
_poche . graphics . beginFill ( 0x888888 , 1 ) ;
_poche . graphics . drawRoundRect (0 , 0 , 5 * bille . taille + 20 ,
3 * bille . taille + 20 , 20 ) ;
_poche . x = - _poche . width * 0 . 5 ;
_poche . y = - _poche . height ;

32
33
34
35
36
37
38

// Dessin du triangle de la poche ( fa on bulle de BD )


if ( numero <= 3 )
{
// Triangle en bas de la bulle
_poche . y -= bille . taille * 3 ;
_poche . graphics . moveTo ( _poche . width * 0 . 5 - bille .
taille , _poche . height ) ;
_poche . graphics . lineTo ( _poche . width * 0 . 5 + bille .
taille , _poche . height ) ;
_poche . graphics . lineTo ( _poche . width * 0 .5 , _poche .
height + bille . taille ) ;
_poche . graphics . endFill () ;
}
else
{
// Tirangle en haut de la bulle
_poche . y += bille . taille * 3 + _poche . height ;
_poche . graphics . moveTo ( _poche . width * 0 . 5 - bille .
taille , 0 ) ;
_poche . graphics . lineTo ( _poche . width * 0 . 5 + bille .
taille , 0 ) ;
_poche . graphics . lineTo ( _poche . width * 0 .5 , - bille .
taille ) ;
_poche . graphics . endFill () ;
}

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

// Animation poche
TweenMax . to ( _poche , 0 . 25 , { alpha : 1 } ) ;

553

CHAPITRE 25. TP : JEU DE BILLARD


Vous remarquerez que je dessine la poche ici au lieu de la dessiner dans la
mthode _dessiner : en effet, nous avons besoin de la taille des billes pour
faire une bulle pouvant contenir au moins 15 billes. La poche doit faire donc
une taille suprieure 5 billes en largeur et 3 billes en hauteur.

Retrait des billes tombes dans le trou


Lorsque lon recommence la partie, il nous faut enlever les billes dans chaque trou,
grce cette mthode :
1
2
3
4
5
6

/* *
* Retire les billes du trou .
*/
public function enleverBilles () : void
{
_billes = new Vector . < Bille >() ;

7
8
9
10

// On cache la poche
TweenMax . to ( _poche , 0 . 25 , { alpha :0 , onComplete : _poche .
graphics . clear } ) ;

Queue
La classe de la queue de billard est plustt simple a crer par rapport aux autres classes,
on na pas de collision grer. Ici, il ne sagit que daffichage.
Commenons par les attributs de la classe :
1
2
3

// Infos de base
private var _distance : Number ;
private var _puissance : Number ;

4
5
6

// Indique si les indicateurs visuels sont actifs


private var _indicateursActifs : Boolean = true ;

7
8
9
10

// El ments visuels
private var _etiquette : TextField ;
private var _dessin : Shape ;

Constructeur
Cette fois encore, le constructeur cr les objets daffichage contenus dans lobjet courant :
1
2

public function Queue ()


{

554

CRATION DES CLASSES


super () ;

3
4

// Dessin de la queue de billard


_dessin = new Shape () ;
_dessin . filters = [ new DropShadowFilter ( 12 , 45 , 0 , 0 .3 , 6 ,
6 , 1 , 2 ) ];
addChild ( _dessin ) ;

5
6
7
8
9
10
11
12
13
14
15
16
17
18

// Etiquette indiquant la puissance du coup


_etiquette = new TextField () ;
_etiquette . autoSize = TextFieldAutoSize . LEFT ;
_etiquette . embedFonts = true ;
_etiquette . selectable = false ;
_etiquette . defaultTextFormat = new TextFormat ( ' arial ' , 22 ,
0xffffff , true ) ;
_etiquette . filters = [ new GlowFilter ( 0x000000 , 0 .5 , 2 , 2 , 2
, 1 ) , new DropShadowFilter ( 12 , 45 , 0 , 0 .3 , 6 , 6 , 1 , 2 ) ];
addChild ( _etiquette ) ;

Dessin de la queue de billard


Surprise ! Nous redfinissons encore la mthode _dessiner pour le dessin de notre
queue de billard ! Ltiquette indiquant la puissance du coup ne sera pas modifie ici,
mais plutt dans une autre mthode. En effet, il est inutile (voire non-recommand)
de lier les deux oprations : la queue serait alors redessine chaque fois que le joueur
bougera la souris pour modifier la puissance du coup. Nous nous contenterons ici de
cacher ltiquette si les indicateurs visuels sont dsactivs.
1
2
3

override protected function _dessiner () : void


{
super . _dessiner () ;

4
5
6
7
8
9
10

// Queue
_dessin . graphics . clear () ;
_dessin . graphics . beginFill ( 0x000000 ) ;
_dessin . graphics . drawRect ( - width , - height * 0 .5 , width * 0 .
4 , height ) ;
_dessin . graphics . beginFill ( 0x3e2317 ) ;
_dessin . graphics . drawRect ( - width * 0 .6 , - height * 0 . 6 * 0 .
5 , width * 0 .6 , height * 0 . 6 ) ;

11
12
13
14
15
16
17
18

// Viseur
if ( _ ind icateursActifs )
{
graphics . clear () ;
graphics . lineStyle (3 , 0xffffff , 0 . 5 ) ;
graphics . moveTo ( 25 , 0 ) ;
graphics . lineTo ( 45 , 0 ) ;

555

CHAPITRE 25. TP : JEU DE BILLARD


}

19
20
21
22
23

// Etiquette de puissance
_etiquette . visible = _indicateursActifs ;

Crons donc une autre mthode pour mettre jour ltiquette indiquant la puissance
du coup :
1
2
3

private function _majEtiquette () : void


{
_etiquette . text = Math . round ( _puissance * 100 ) + '% ';

4
5
6
7
8
9
10
11
12
13
14
15
16
17

if ( rotation < - 90 || rotation > 90 )


{
_etiquette . rotation = 180 ;
_etiquette . x = - _distance ;
_etiquette . y = _etiquette . height ;
}
else
{
_etiquette . rotation = 0 ;
_etiquette . x = - _distance - _etiquette . width ;
_etiquette . y = - _etiquette . height ;
}

Pourquoi distinger ici deux cas de rotation ?

Cela permet dviter que ltiquette soit retourne si lon tourne la queue dans lautre
sens. Lorsque la queue est gauche de la bille de tir, tout va bien. Ltiquette est affich
dans le bon sens pour lutilisateur (figure 25.27).
Mais si on tourne la queue du ct droit vis--vis de la bille, notre tiquette vas ce
retrouver lenvers ! Et ce nest pas trs confortable lire, comme la figure 25.28.
Il faut alors inverser ltiquette si la queue est droite de la bille de tir, cest--dire
si la rotation de la queue est infrieure -90 degrs ou suprieure 90 degrs, comme
aux figures 25.29 et 25.30.
Nous avons alors un rsultat satisfaisant (voir figure 25.31) !
Accesseurs
Enfin, ajoutons quelques accesseurs pour permettre la modification des donnes de la
queue de billard :
1

/* *

556

CRATION DES CLASSES

Figure 25.27 Queue gauche de la bille de tir

Figure 25.28 A droite, ltiquette est lenvers.

557

CHAPITRE 25. TP : JEU DE BILLARD

Figure 25.29 Rotation 0 de la queue

Figure 25.30 Rotation 135 de la queue

558

CRATION DES CLASSES

Figure 25.31 Ltiquette est dans le bon sens !

2
3
4
5
6
7

* Distance du bout de la queue par rapport la bille de tir .


*/
public function get distance () : Number
{
return _distance ;
}

8
9
10
11

public function set distance ( value : Number ) : void


{
_distance = value ;

12
13
14
15

// On d place le dessin de la queue en fonction de la


distance par rapport la bille de tir
_dessin . x = - _distance ;

16
17
18
19
20
21
22
23

/* *
* Puissance du tir d livr par la queue .
*/
public function get puissance () : Number
{
return _puissance ;
}

24
25
26
27

public function set puissance ( value : Number ) : void


{
_puissance = value ;

28
29
30

_majEtiquette () ;

31
32
33
34

/* *
* Indique si les indicateurs visuels sont visibles ou non .
*/

559

CHAPITRE 25. TP : JEU DE BILLARD


35
36
37
38

public function get indicateursActifs () : Boolean


{
return _indicateursActifs ;
}

39
40
41
42

public function set indicateursActifs ( value : Boolean ) : void


{
_i nd icateursActifs = value ;

43
44
45

_dessiner () ;

Billard
Cette classe est la plus complexe de lanimation : cest le coeur de notre jeu de billard.
Commenons par crire les diffrents attributs de la classe :
1
2
3
4
5
6

// El ments
private var
private var
private var
private var
private var

visuels
_table : Table ;
_billes : Vector . < Bille >;
_billeDeTir : Bille ;
_queue : Queue ;
_trous : Vector . < Trou >;

7
8
9
10
11
12
13
14

// Configuration de la queue de billard


private var _distanceMinimum : Number = 25 ;
private var _distanceMaximum : Number = 250 ;
private var _puissanceMinimum : Number = 1 ;
private var _puissanceMaximum : Number = 35 ;
// Distance de la souris par rapport la pointe de la queue
private var _distanceSouris : Number = 200 ;

15
16
17

// Vitesse actuelle de l ' animation ( 1 = vitesse normale )


private var _vitesseAnimation : Number = 1 ;

18
19
20
21

// Indicateurs
private var _simulationEnCours : Boolean = false ;
private var _phaseDeTir : Boolean = false ;

22
23
24

// Indique si le billard est en train d ' tre d plac


private var _tableDrag : Boolean = false ;

Constructeur
Le constructeur de la classe va une fois de plus nous servir crer les objets ncessaires au bon fonctionnement de lobjet courant (ici, le jeu de billard).
Commenons par ajouter la table de billard :
560

CRATION DES CLASSES


1
2
3
4
5
6

// Table
_table = new Table () ;
// Taille standard
_table . width = 2 . 34 * Unite . METRE ;
_table . height = 1 . 17 * Unite . METRE ;
addChild ( _table ) ;

Puis, continuons sur les six trous de la table :


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

// Trous
_trous = new Vector . < Trou >() ;
// Marge entre les trous et les bords de la table
var margeTrou : Number = 0 . 015 * Unite . METRE ;
var i : int ;
for ( i = 0 ; i < 6 ; i ++)
{
var trou : Trou = new Trou ( i + 1 ) ;
trou . taille = 0 . 069 * Unite . METRE ;
// Lignes de trois colonnes de trous
trou . x = ( i % 3 ) * ( _table . width + 2 * margeTrou ) / 2 margeTrou ;
trou . y = Math . floor ( i / 3 ) * ( _table . height + 2 * margeTrou
) - margeTrou ;
_table . addChild ( trou ) ;
_trous . push ( trou ) ;
}

Attaquons-nous maintenant aux billes. Dabord, spcifions les diffrents couleurs possibles :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

// Billes
// Couleurs r glementaires
var couleurs : Array = [
0xffffff , // Bille blanche
0xfac92e ,
0x1744c1 ,
0xee372e ,
0x271d53 ,
0xff8d59 ,
0x189e66 ,
0x931422 ,
0x000000 , // Bille 8
0xf7af1d ,
0x2059e8 ,
0xde291d ,
0x2f2665 ,
0xfb8351 ,
0x0d955c ,
0x92121d
];

Puis, crons les 16 billes dont nous avons besoin pour notre billard :
561

CHAPITRE 25. TP : JEU DE BILLARD


1
2
3
4
5
6
7
8

// Liste des billes


_billes = new Vector . < Bille >() ;
// Cr ation des 15 billes
for ( i = 0 ; i <= 15 ; i ++)
{
var bille : Bille = new Bille ( couleurs [ i ] , i , 0 . 05 * Unite .
METRE , 172 * Unite . GRAMME ) ;
_table . addChild ( bille ) ;
_billes . push ( bille ) ;

9
10
11
12
13
14

if ( i == 0 )
{
_billeDeTir = bille ;
}

Etant donn que nous allons dplacer la premire bille (bille de tir) lors de la phase
1 du droulement du jeu, il est bon de la remettre au premier plan afin quelle ne se
retrouve pas affiche derrire les autres billes :
1
2

// On remet la bille de tir au premier plan


_table . setChildIndex ( _billeDeTir , _table . numChildren - 1 ) ;

Occupons-nous maintenant de la queue de billard :


1
2
3
4
5

// Queue
_queue = new Queue () ;
_queue . width = 1 . 5 * Unite . METRE ;
_queue . height = 0 . 025 * Unite . METRE ;
_table . addChild ( _queue ) ;

Puis, ajoutons un couteur dvnement qui nous permet dattendre que lobjet soit
ajout la scne principale afin davoir accs la proprit stage :
1
2

// Lorsque le billard est ajout la sc ne , nous ajoutons les


autres couteurs d ' v nements
addEventListener ( Event . ADDED_TO_STAGE , onAddedToStage ) ;

Lcouteur de cet vnement ajoute des couteurs pour grer la souris :


1
2
3
4
5

private function onAddedToStage ( event : Event ) : void


{
// D placement de la table de billard
stage . addEventListener ( MouseEvent . RIGHT_MOUSE_DOWN ,
onMouseRightDown ) ;
stage . addEventListener ( MouseEvent . RIGHT_MOUSE_UP ,
onMouseRightUp ) ;

6
7
8
9

562

// Ralenti
stage . addEventListener ( MouseEvent . MIDDLE_CLICK ,
onMiddleClick ) ;

CRATION DES CLASSES


Ainsi, lorsque le bouton droit de la souris est enfonc, il faut dplacer le billard. Par
contre, il faut le faire uniquement si lon nest pas en train de placer la bille de tir,
cest--dire si on est en phase de tir ou que la simulation est en cours.
1

/* D placement de la table de billard */

2
3
4
5
6
7
8
9
10

private function onMouseRightDown ( event : MouseEvent ) : void


{
if ( _phaseDeTir || _simulationEnCours )
{
_table . startDrag () ;
_tableDrag = true ;
}
}

Une fois relach, on arrte le dplacement de la table de billard si elle est en cours de
dplacement :
1
2
3
4
5
6
7

private function onMouseRightUp ( event : MouseEvent ) : void


{
if ( _tableDrag )
{
_table . stopDrag () ;
}
}

Enfin, si on appuie sur la molette de la souris, on active ou dsactive le ralenti (qui


ntait pas demand) :
1

/* Ralenti */

2
3
4
5
6

private function onMiddleClick ( event : MouseEvent ) : void


{
ralenti () ;
}

Avec une mthode publique permettant dactiver ou dsactiver le ralenti en modifiant


lattribut _vitesseAnimation :
1
2
3
4
5
6
7
8
9
10
11
12
13

/* *
* Active ou d sactive le ralenti .
*/
public function ralenti () : void
{
if ( _vitesseAnimation != 0 . 15 )
{
_vite sseAnimation = 0 . 15 ; // Ralenti 15 % !
}
else
{
_vite sseAnimation = 1 ;
}

563

CHAPITRE 25. TP : JEU DE BILLARD


14

Phase 1 : Prparation
Il est tant dimplmenter les quatres phases du droulement dune partie. Commenons
par la premire : la prparation de la partie. Dans un premier temps, il faut vider les
trous au cas o des billes seraient tombes dedans. Ensuite, nous plaons les billes pour
former le triangle initial :
1
2
3
4
5
6
7

private function _placerBilles () : void


{
// Vider les trous
for each ( var trou : Trou in _trous )
{
trou . enleverBilles () ;
}

8
9
10
11
12
13
14
15
16
17
18

// Triangle
var bille : Bille ;
var l : int = _billes . length ;
var triangleLignes : int = 1 ;
var triangleLigne : int = 0 ;
var triangleX : Number = _table . width * 0 . 75 - _billeDeTir .
taille * 2 . 5 ;
var order : Array = [0 , 9 , 7 , 12 , 15 , 8 , 1 , 6 , 10 , 3 , 14 , 11 ,
2 , 13 , 4 , 5 ];
for ( var i : int = 0 ; i < l ; i ++)
{
bille = _billes [ order [ i ]];

19
20
21
22
23
24
25

// Initialisation des billes


bille . alpha = 1 ;
bille . scaleX = 1 ;
bille . scaleY = 1 ;
bille . velocite . x = 0 ;
bille . velocite . y = 0 ;

26
27
28
29
30
31

bille . horsJeu = false ;


if ( i > 0 )
{
bille . x = triangleX ;
bille . y = _table . height * 0 . 5 + ( triangleLigne triangleLignes * 0 . 5 ) * _billeDeTir . taille +
_billeDeTir . taille * 0 . 5 ;

32
33
34
35
36

564

triangleLigne ++;
if ( triangleLigne == triangleLignes )
{
triangleLigne = 0 ;

CRATION DES CLASSES


37
38
39
40
41
42

triangleLignes ++;
triangleX += _billeDeTir . taille ;

Phase 2 : Placement de la bille de tir


Pour la phase suivante, il faut laisser au choix du joueur le placement de la bille de tir,
mais uniquement dans la zone de jeu. Pour cela, nous utilisons la mthode startDrag
qui nous permet de coller la bille de tir la souris tout en la restreignant une zone
bien prcise :
1
2
3
4

private function _la nce rP has eB ill eDe Ti r () : void


{
_a rr et erP haseDeTir () ;
_ a r r e t e r P h as e Si mu la t io n () ;

_table . stopDrag () ;
_tableDrag = false ;

6
7
8

// On annule d ' ventuelles animations sur les propri t s de


la bille de tir pour viter les conflits avec le " drag "
TweenMax . killTweensOf ( _billeDeTir ) ;

9
10
11

// R initialisation de la bille
_billeDeTir . horsJeu = false ;
_billeDeTir . scaleX = 1 ;
_billeDeTir . scaleY = 1 ;
_billeDeTir . velocite . x = 0 ;
_billeDeTir . velocite . y = 0 ;

12
13
14
15
16
17
18

// On fait r appara tre la bille de tir


TweenMax . to ( _billeDeTir , 0 .2 , { alpha : 1 } ) ;

19
20
21

// On active le " drag " :


// Lorsque la souris du joueur va se d placer , la bille de
tir se positionnera en dessous , dans les limites de la
zone de jeu .
_billeDeTir . startDrag ( true , new Rectangle ( _billeDeTir .
taille * 0 .5 , _billeDeTir . taille * 0 .5 , _table . width _billeDeTir . taille , _table . height - _billeDeTir . taille ) )
;

22
23

24

25
26
27

addEventListener ( MouseEvent . MOUSE_UP ,


o n P h a se Bil le DeT ir Cli ck ) ;

565

CHAPITRE 25. TP : JEU DE BILLARD

La zone de jeu est dfinie par la taille de la table.

Lorsque lutilisateur effectue un clic de souris, nous passons la phase suivante (phase
de tir) dans un couteur dvnement de souris :
1
2
3
4

private function onP ha seB ill eD eTi rC lic k ( event : MouseEvent ) : void
{
// On emp che la propagation de l ' v nement pour viter que
le tir ne se d clenche tout de suite
event . s t op I m me d i at e P ro p a ga t i on () ;

5
6
7

_lanc erPhaseDeTir () ;

Il faut empcher lvnement du clic de se propager dans les lments graphiques parents (voir le flux dvnement dans le chapitre sur les vnements) : car effectivement, la mthode _lancerPhaseDeTir va ajouter un
couteur sur le mme vnement MouseEvent.MOUSE_UP, ce qui va le dclencher galement et tirer sur la bille blanche tout de suite. A laide de la
mthode stopImmediatePropagation de lobjet event, nous nous assurons
que dautres couteurs ne seront pas appells par la suite.
Enfin, il nous faut une mthode pour terminer la phase de placement de la bille blanche,
qui se charge de lcher la bille et de supprimer lcouteur de souris que nous avons cr
pour cette phase :
1
2
3

private function _a r re te rP h as eB il l eD eT ir () : void


{
_billeDeTir . stopDrag () ;

4
5
6

r em o v eEventListener ( MouseEvent . MOUSE_UP ,


o n Ph ase Bi lle DeT ir Cli ck ) ;

Phase 3 : Tir avec la queue de billard


Nous arrivons cette phase de jeu aprs la phase deux ou si les billes ne bougent plus.
Crons une mthode pour lancer la phase :
1
2
3
4

private function _lancerPhaseDeTir () : void


{
_ a r r e te r Ph as eB i ll eD e Ti r () ;
_ a r r e te r Ph as eS i mu la t io n () ;

5
6

566

// Gestion de la souris

CRATION DES CLASSES


stage . addEventListener ( MouseEvent . MOUSE_MOVE ,
o n P h a seDe TirMo useMov e ) ;
stage . addEventListener ( MouseEvent . MOUSE_UP ,
onPh aseDeTirClick ) ;

7
8
9

_phaseDeTir = true ;
_queue . indicateursActifs = true ;
_queue . visible = true ;

10
11
12
13
14
15

_deplacerQueue () ;

Dans un premier temps, nous arrtons les autres phases, puis nous ajoutons les couteurs dont nous avons besoin. Enfin, nous prparons la queue de billard tre affiche.
Voici les fonctions couteurs que nous allons utiliser pour cette phase de jeu :
1
2
3
4

private function on Phase DeTirM ouseM ove ( event : MouseEvent ) : void


{
_deplacerQueue () ;
}

5
6
7
8
9

private function onPhaseDeTirClick ( event : MouseEvent ) : void


{
_tirer () ;
}

Lorsque lutilisateur dplace la souris, il faut mettre jour la queue de billard, et,
lorsque quil clique, il faut tirer sur la bille blanche.
Comme pour la deuxime phase, il nous faut une mthode pour arrter la phase de tir
qui se charge de supprimer les couteurs dvnements :
1
2
3
4
5

private function _arreterPhaseDeTir () : void


{
// Fin de la gestion de la souris
stage . r em oveEventListener ( MouseEvent . MOUSE_MOVE ,
o n P h a seDe TirMo useMov e ) ;
stage . r em oveEventListener ( MouseEvent . MOUSE_UP ,
onPh aseDeTirClick ) ;

6
7
8
9

_phaseDeTir = false ;
_queue . visible = false ;

Lorsque nous bougeons la souris, la queue doit tourner autour de la bille blanche et
changer la puissance du tir en fonction de la distance entre la souris et la bille. Pour
cela, nous crons cette mthode :
1
2
3

private function _deplacerQueue () : void


{
// On centre la queue sur la bille de tir

567

CHAPITRE 25. TP : JEU DE BILLARD


_queue . x = _billeDeTir . x ;
_queue . y = _billeDeTir . y ;

4
5
6

// Distance entre la souris et la bille de tir


var distance : Number = Outils . distanceNombres ( _table . mouseX ,
_table . mouseY , _billeDeTir .x , _billeDeTir . y ) _distanceSouris ;
if ( distance > _distanceMaximum )
{
distance = _distanceMaximum ;
}
else if ( distance < _distanceMinimum )
{
distance = _distanceMinimum ;
}

7
8

9
10
11
12
13
14
15
16
17

// Angle entre la souris et la bille de tir ( radians )


var angle : Number = Outils . angleNombres ( _table . mouseX ,
_table . mouseY , _billeDeTir .x , _billeDeTir . y ) ;

18
19
20
21
22
23
24
25

// Aplication des modifications sur la queue de billard


_queue . rotation = angle / Math . PI * 180 ;
_queue . distance = distance - 10 ;
_queue . puissance = ( distance - _distanceMinimum ) / (
_distanceMaximum - _distanceMinimum ) ;

Il est intressant de limiter la puissance du coup pour viter que le tir soit
trop fort, en limitant la distance entre la queue et la bille de tir laide des
attributs _distanceMinimum et _distanceMaximum.
Dcortiquons un peu la mthode : nous commenons par placer la queue sur la bille
de tir, puis nous calculons la distance entre la pointe de la queue et la bille (distance
dtermine par la position de la souris de lutilisateur). Nous vrifions que cette distance
est bien dans les limites autorises, puis nous calculons langle entre la souris et la bille
de tir pour faire tourner la queue de billard dans la direction approprie. Enfin, nous
mettons jour les attributs de la queue de billard avec les rsultats de nos calculs.
Enfin, la dernire mthode de cette phase de jeu sert tirer dans la bille blanche :
1
2
3
4
5
6

private function _tirer () : void


{
// On arr te la phase de tir
_a rr eterPhaseDeTir () ;
_queue . indicateursActifs = false ;
_queue . visible = true ;

7
8
9

568

// Distance entre la souris et la bille de tir


var distance : Number = Outils . distanceNombres ( _table . mouseX ,
_table . mouseY , _billeDeTir .x , _billeDeTir . y ) -

CRATION DES CLASSES


_distanceSouris ;
if ( distance > _distanceMaximum )
{
distance = _distanceMaximum ;
}
else if ( distance < _distanceMinimum )
{
distance = _distanceMinimum ;
}

10
11
12
13
14
15
16
17
18

// Angle entre la souris et la bille de tir ( radians )


var angle : Number = Outils . angleNombres ( _table . mouseX ,
_table . mouseY , _billeDeTir .x , _billeDeTir . y ) ;
var module : Number = ( distance - _distanceMinimum ) / (
_distanceMaximum - _distanceMinimum ) * (
_pui ssanceMaximum - _puissanceMinimum ) +
_pui ssanceMinimum ;

19
20
21

22

// Coup sur la bille


_billeDeTir . velocite . angle = angle ;
_billeDeTir . velocite . module = module ;

23
24
25
26
27
28
29

// Animation de la queue
TweenMax . to ( _queue , 0 .1 , { distance : 10 , onComplete :
_ l a n c er Pha se Sim ul ati on } ) ;

On arrte dabord la phase actuelle (phase de tir), puis on calcule la puissance et langle
du coup qui est port. Ensuite, on modifie le vecteur de dplacement de la bille blanche
pour la faire partir dans la direction et la vitesse souhaites. Enfin, on anime rapidement
la queue de billard pour donner la sensation quelle tape dans la bille blanche (ne pas
oublier de la rendre visible, car la mthode _arreterPhaseDeTir la cache).
Phase 4 : Simulation des billes
La dernire phase de jeu est la simulation des billes, o lon doit les dplacer tout en
grant les diffrentes collisions des billes avec les autres billes, les trous et les bords de
la zone de jeu.
Encore une fois, crons une mthode pour dmarrer la phase de jeu :
1
2
3
4
5

private function _la nce rP has eS imu lat io n () : void


{
_table . stopDrag () ;
_ a r r e t e r P h as e Bi ll eD e Ti r () ;
_a rr et erP haseDeTir () ;

6
7

addEventListener ( Event . ENTER_FRAME ,


onPhaseSimulationEnterFrame );

569

CHAPITRE 25. TP : JEU DE BILLARD


9
10

_s im ulationEnCours = true ;

On ajoute un couteur qui va se dclencher pour chaque nouvelle image (par exemple,
30 fois par seconde) et appeler cette mthode :
1
2
3
4

private function o n P h a s e S i m u l a t i o n E n t e r F r a m e ( event : Event ) : void


{
_deplacerBilles () ;
}

Ajoutons tout de suite la mthode pour stopper cette phase de jeu (qui supprime
lcouteur dvnement) :
1
2
3

private function _a r re te rP h as eS im u la ti on () : void


{
r em o v eEventListener ( Event . ENTER_FRAME ,
onPhaseSimulationEnterFrame );

4
5
6

_s im ulationEnCours = false ;

A chaque nouvelle image, il faut donc dplacer toutes les billes encore en jeu en fonction
de leur vecteur vitesse et tester toutes les collisions possibles avec les autres billes, les
trous et les bords de la table. Crons une mthode pour grer tout cela :
1
2
3

private function _deplacerBilles () : void


{
var t o u t e s L e s B i l l e s S o n t I m m o b i l e s : Boolean = true ;

4
5
6
7
8
9
10

// D tection des collisions entre les billes


var l : int = _billes . length ;
var bille1 : Bille , bille2 : Bille ;
for ( var i : int = 0 ; i < l ; i ++)
{
bille1 = _billes [ i ];

11
12
13
14
15
16

// Si la bille courante est hors - jeu , on passe la


suivante
if ( bille1 . horsJeu )
{
continue ;
}

17
18
19
20
21
22

// Si la bille courante se d place


if ( bille1 . velocite . module > 0 )
{
t o u t e s L e s B i l l e s S o n t I m m o b i l e s = false ;
}

23
24

570

// Tests des collisions de la bille courante avec les


autres billes

CRATION DES CLASSES


for ( var j : int = i + 1 ; j < l ; j ++)
{
bille2 = _billes [ j ];

25
26
27
28

// Bille hors - jeu : on passe la suivante


if ( bille2 . horsJeu )
{
continue ;
}

29
30
31
32
33
34
35
36

37

// Test de collition
bille1 . testerCollision ( bille2 ) ;

38
39
40

41

// D placement de la bille courante


_deplacerBille ( bille1 ) ;

42
43
44
45
46
47
48

49
50
51
52
53
54
55

// Toutes les billes sont immobiles et la bille de tir n '


est pas dans un trou , il faut relancer la phase de tir
if ( t o u t e s L e s B i l l e s S o n t I m m o b i l e s )
{
if ( _billeDeTir . horsJeu )
{
setTimeout ( _lancerPhaseBilleDeTir , 400 ) ; // Laisse
du temps pour l ' animation de chute de la bille
dans le trou
}
else
{
_lancerPhaseDeTir () ;
}
}

A laide du boolen toutesLesBillesSontImmobiles, nous dterminons si les billes ne


bougent plus : il faut alors soit retourner la phase 2 (placement de la bille blanche)
si la bille blanche est tombe dans un trou, soit retourner la phase 3 (phase de tir)
pour taper nouveau dans la bille blanche.
Pour dplacer chaque bille, jai cr une autre mthode pour sparer un petit peu le
code :
1
2
3
4

private function _deplacerBille ( bille : Bille ) : void


{
// Mouvement de la bille ( avec multiplicateur pour le
ralenti )
bille . deplacer ( _vitesseAnimation ) ;

5
6

// D tection des collisions de la bille avec les trous de


la table de billard

571

CHAPITRE 25. TP : JEU DE BILLARD


_ d e t e ct erC ol lis io nTr ou ( bille ) ;

7
8
9
10
11
12
13
14

// D textion des collisions de la bille avec les bords de


la table
if (! bille . horsJeu )
{
_table . testerCollision ( bille ) ;
}

Comme nous pouvons le voir, elle se charge de dplacer la bille dun cran, puis teste les
collisions entre la bille et les trous. Si la bille nest pas tombe dans un trou, on teste
alors les collisions entre la bille et les bords de la table.
La gestion des collisions avec les trous est implmente dans une autre mthode (encore
dans une optique de sparation du code) :
1
2
3
4
5
6
7
8
9

private function _de te cte rCo ll isi on Tro u ( bille : Bille ) : void
{
// On teste la collision de la bille avec chaque trou
for each ( var trou : Trou in _trous )
{
if ( trou . testerCollision ( bille ) )
{
// La bille est sortie -> hors - jeu
bille . horsJeu = true ;

10

// Param tres de l ' animation


var params : Object = { x : trou .x , y : trou .y , scaleX :
0 .7 , scaleY : 0 .7 , alpha : 0 };

11
12
13

if ( bille != _billeDeTir )
{
// Si la bille n ' est pas la bille de tir , on l '
ajoute la r serve du trou la fin de l '
animation
params . onComplete = trou . ajouterBille ;
params . onCompleteParams = [ bille ];
}

14
15
16

17
18
19
20
21
22
23
24
25

// Animation de chute dans le trou


TweenMax . to ( bille , 0 .4 , params ) ;

Pour chaque trou, on teste sil y a collision avec la bille. Le cas chant, la bille est
mise hors jeu et est anime pour donner limpression quelle chute dans le trou.
572

CRATION DES CLASSES


Nouvelle partie
Pour lancer une nouvelle partie, crons une mthode publique nouvellePartie qui se
charge darrter les diffrentes phases de jeu et relance le jeu de billard :
1
2
3
4
5
6
7
8
9

/* *
* Remet le billard z ro et lance une nouvelle partie .
*/
public function nouvellePartie () : void
{
// Arr t de l ' ventuelle partie ne cours
_ a r r e t e r P h as e Bi ll eD e Ti r () ;
_ a r r e t e r P h as e Si mu la t io n () ;
_a rr et erP haseDeTir () ;

10

// Triangle des billes


_placerBilles () ;

11
12
13
14
15
16

// Bille de tir
_ l a n c e r P h a se Bil le DeT ir () ;

Accesseurs
Enfin, ajoutons deux dfinitions des accesseurs de taille du billard afin de ne prendre
en compte que la taille de la table (sans la queue de billard). Cela sera notamment
utile pour centrer le billard au milieu de lcran.
1

/* On remplace le fonctionnement habituel des accesseurs de la


taille du billard pour ne prendre en compte que la taille de
la table . */

2
3
4
5
6

override public function get width () : Number


{
return _table . width ;
}

7
8
9
10
11

override public function get height () : Number


{
return _table . height ;
}

Main
Dans notre classe principale, nous allons grer la cration du jeu de billard et laffichage
de la texture de fond de notre application.
573

CHAPITRE 25. TP : JEU DE BILLARD


Prparatifs
Commenons par configurer la scne pour quelle soit aligne en haut gauche, sans
zoom automatique, tout en initialisant nos polices de caractres embarques :
1
2
3

// Configuration de la sc ne
stage . align = StageAlign . TOP_LEFT ;
stage . scaleMode = StageScaleMode . NO_SCALE ;

4
5
6

// Polices embarqu es
EmbedFonts . init () ;

Voici alors le code minimal notre classe Main :


1
2
3
4
5
6
7
8

package
{
import
import
import
import
import
import

flash . display . Sprite ;


flash . display . StageAlign ;
flash . display . StageDisplayState ;
flash . display . StageQuality ;
flash . display . StageScaleMode ;
flash . events . Event ;

9
10
11
12
13
14
15
16
17
18
19
20

/* *
* Classe principale
* @author Guillaume CHAU
*/
public class Main extends Sprite
{
public function Main () : void
{
if ( stage ) init () ;
else addEventListener ( Event . ADDED_TO_STAGE , init ) ;
}

21

private function init ( e : Event = null ) : void


{
removeEventListener ( Event . ADDED_TO_STAGE , init ) ;
// entry point

22
23
24
25
26

// Configuration de la sc ne
stage . align = StageAlign . TOP_LEFT ;
stage . scaleMode = StageScaleMode . NO_SCALE ;
stage . quality = StageQuality . BEST ;

27
28
29
30
31

// Polices embarqu es
EmbedFonts . init () ;

32
33
34
35
36
37

574

// Commencer coder ici

CRATION DES CLASSES


38
39

Cration de la texture de fond


Attaquons avec la texture tapissant le fond de lapplication. Tout dabord, embarquons
limage dont nous avons besoin et dclarons les attributs ncessaires dans la classe (en
dehors de la mthode init) :
1
2

[ Embed ( source = " ../ lib / img / fond . png " ) ]


private var Fond : Class ;

3
4
5

private var _fond : Sprite ;


private var _texture : BitmapData ;

Puis, crons le dessin de fond et la texture :


1
2
3

// Fond
_fond = new Sprite () ;
addChild ( _fond ) ;

4
5
6
7

// Texture du fond
var bmp : Bitmap = new Fond () ;
_texture = bmp . bitmapData ;

Jutilise un objet de classe Sprite et non de classe Shape pour quil puisse
recevoir les clics de souris afin que nous puissions couter les vnements de
souris partout sur la scne principale (par exemple, pour dplacer la table
avec le clic droit).

Cration du billard
Puis, occupons-nous du billard, avec en premier lajout dun attribut dans la classe :
1

private var _billard : Billard ;

Ensuite, crons le billard, ajoutons-le la scne et lanons une nouvelle partie automatiquement :
1
2
3
4

// Billard
_billard = new Billard () ;
addChild ( _billard ) ;
_billard . nouvellePartie () ;

575

CHAPITRE 25. TP : JEU DE BILLARD


Position du billard et dessin de la texture de fond
Une fois nos objets crs, il faut soccuper de leur position et taille sur la scne. Pour
cela, ajoutons cette mthode :
1
2
3
4
5
6

private function _rafraichir () : void


{
// Fond
_fond . graphics . clear () ;
_fond . graphics . beginBitmapFill ( _texture ) ;
_fond . graphics . drawRect (0 , 0 , stage . stageWidth , stage .
stageHeight ) ;

7
8
9
10
11

// Billard
_billard . x = ( stage . stageWidth - _billard . width ) * 0 . 5 ;
_billard . y = ( stage . stageHeight - _billard . height ) * 0 . 5 ;

La mthode se charge de dessiner le fond de lapplication avec un remplissage de limage


de la texture grce la mthode beginBitmapFill de la classe Graphics (voir le
chapitre sur le dessin avec lActionscript 3). Elle centre galement le billard au milieu
de la scne pour des raisons de confort de lutilisateur.
Cette mthode rafraichir doit tre appele une fois au lancement de notre application
afin de mettre le fond et le billard en place, puis chaque fois que la fentre de
lapplication est redimensionne.
Ainsi, dans le code principal (mthode init), ajoutons un premier appel cette fonction :
1
2

// On met jour la position du billard et la texture de fond


pour la premi re fois
_rafraichir () ;

Gestion du redimensionnement de lapplication


Comme nous lavons vu, il faut couter le changement de taille de la scne de lapplication, afin de redessiner le fond textur et de recentrer le billard. Crons la fonction
qui coutera lvnement de redimensionnement :
1
2
3
4

private function onStageResize ( event : Event ) : void


{
_rafraichir () ;
}

Puis, ajoutons dans le code principal lcouteur la scne principale pour se dclencher
au redimensionnement (vnement Event.RESIZE) :
1
2

// Lorsque la sc ne est redimensionn e


stage . addEventListener ( Event . RESIZE , onStageResize ) ;

576

CONCLUSION ET AMLIORATIONS POSSIBLES


Maintenant, si lutilisateur met lapplication en plein cran par exemple, la texture de
fond recouvrera correctement la surface de lcran et le billard sera bien centr.
Raccourci clavier
Enfin, ajoutons un raccourci clavier pour lancer une nouvelle partie tout moment avec
la touche espace. Ajoutons un couteur dvnement clavier sur la scne principale :
1
2

// Gestion du clavier
stage . addEventListener ( KeyboardEvent . KEY_UP , onKeyUp ) ;

Puis, crivons cette fonction couteur qui lance une nouvelle partie si le code de la
touche relche par lutilisateur correspond au code de la touche espace :
1
2
3
4
5
6
7

private function onKeyUp ( event : KeyboardEvent ) : void


{
if ( event . keyCode == Keyboard . SPACE )
{
_billard . nouvellePartie () ;
}
}

Et voil ! Nous avons fait le tour de toutes les classes du projet : vous avez pu comparer
votre code avec le mien, si vous avez des diffrences, ne vous inquitez pas, cest tout
fait normal ! Il nexiste pas une seule solution pour implmenter notre billard.

Conclusion et amliorations possibles


Sources du Billard
Jai prpar une archive contenant lensemble du dossier du projet de Billard afin que
vous puissiez le tlcharger, lexplorer et le compiler par vous-mme. Vous aurez alors
une bonne vision globale de larchitecture de lapplication.


Tlcharger le dossier du proB jet
Code web : 865950


Ides damlioration
Notre billard amricain fonctionne, mais il lui manque srement quelques fonctionnalits pour constituer un jeu complet.
Afficher un menu : la plupart des jeux disposent dun menu pour effectuer diverses
oprations. Ici, nous pourrions imaginer un menu permettant de lancer une nouvelle
partie, afficher les rgles du jeu de billard amricain, une liste des raccourcis clavier
et souris, etc.
577

CHAPITRE 25. TP : JEU DE BILLARD


Appliquer plus de rgles : le billard amricain comporte davantage de rgles que
nous navons pas implmentes dans notre jeu. Par exemple, ds quun joueur met
la bille 8 dans un trou, il perd et la partie sarrte !
Amliorer linterface : il serait intressant dafficher plus dinterface pour les
joueurs comme des compteurs de score, un indicateur de tour, un message indiquant
quel joueur doit jouer, etc.
Afficher le dbut de la trajectoire potentielle : pour aider le joueur viser
sur la table de billard, ce qui nest pas forcment vident sur un ordinateur, nous
pourrions afficher des points blancs reprsentant la trajectoire possible de la bille
blanche aprs le coup.
Afficher diffrentes options : les joueurs aiment bien personnaliser leur jeu en
choisissant parmi plusieurs thmes visuels par exemple ou en jouant en un temps
limit.
Proposer du billard franais : le billard franais dispose de ses propres rgles car
il ny a pas de trou dans la table et on ne dispose que de trois billes ! On pourrait
alors crer une autre classe BillardFrancais et proposer le choix du type de billard
au joueur.
Nhsitez pas amliorer votre billard car comme je lai dj rpt : pratiquer, cest
progresser !

578

Chapitre

26

La gestion des erreurs


Difficult :
Avant de clturer cette partie, nous allons aborder un des sujets les plus fcheux pour un
programmeur : la gestion des erreurs. Vous verrez que cela pourra savrer extrmement
utile lorsque vous travaillerez avec des donnes externes lapplication. Ce sera notamment
le cas si vous tes amens charger du contenu multimdia lintrieur de lapplication
ou si vous souhaitez changer des donnes en rseau. Aussi, essayez dtre particulirement
attentif ce qui va suivre, ce chapitre est important.

579

CHAPITRE 26. LA GESTION DES ERREURS

Les principes de base


Introduction la gestion des erreurs
Lorsque nous prononons le mot erreurs , il est frquent de voir des sourcils se froncer.
Il sagit en effet dun sujet dlicat, souvent synonyme de complications. Nanmoins,
nous devons en passer par l pour sassurer quun code sexcute correctement. En
ce qui nous concerne, nous pouvons distinguer deux principaux types derreurs : les
erreurs de compilation et les erreurs dexcution.
Sans grande surprise, les erreurs de compilation sont des erreurs qui se produisent
lors de la compilation. Elles sont gnralement facile dceler puisque que le compilateur nous informe de leur existence. Par ailleurs, lors de lapparition dune erreur
de ce genre, la compilation est stoppe et la gnration du fichier SWF nest pas
acheve. Il nous est alors ncessaire de corriger cette erreur afin de pouvoir finaliser
la compilation. Ce ne sont pas ces erreurs qui nous intressent dans ce chapitre, nous
allons plutt nous concentrer sur les erreurs dexcution.
Les erreurs dexcution surviennent, comme leur nom lindique, durant lexcution
du code. Contrairement aux erreurs de compilation, les erreurs dexcution ne
bloquent pas la compilation dun programme, mais se produisent lors de lexcution
dune instruction ou dun code erron. Suivant la complexit du programme, ces erreurs
peuvent tre difficiles dtecter, et donc corriger.
La gestion des erreurs consiste alors ajouter ou modifier du code dans un programme spcialement conu pour traiter une ou plusieurs erreurs. Cela revient dtecter les ventuelles erreurs dexcution et les contourner afin de pouvoir reprendre,
si possible, une excution normale du programme. Le cas chant, il peut tre
intressant den informer tout simplement lutilisateur.

Les diffrents types derreurs dexcution


Les erreurs synchrones
Les erreurs dexcution dites synchrones se produisent lors de lexcution dune
instruction renvoyant un rsultat immdiat. Nous pouvons galement parler dexceptions.
Pour vous donner un exemple, voici un code qui ajoute un objet de type Sprite la
liste daffichage sans lavoir instancier au pralable :
1
2

var objet : Sprite ;


addChild ( objet ) ;

Comme vous pouvez le voir, la compilation du code ne pose absolument aucun problme : le fichier SWF est donc bien gnr. Toutefois, lors de lexcution du code,
vous allez voir apparatre ceci dans la console de sortie :
[ Fault ] exception , information = TypeError : Error #2007: Le param
tre child ne doit pas tre nul .

580

LES ERREURS SYNCHRONES


Un tel message saffichera chaque fois quune erreur naura pas t traite ; on dit
alors que lexception na pas t intercepte. Ce message permet au dveloppeur de
cibler lerreur afin de la rparer ou de la corriger. Comme vous avez peut-tre pu le
constater, lexcution du code sest stoppe lors de lapparition de lerreur. En revanche,
ceci nest valable que dans la version de dbogage du Flash Player. En effet, dans la
version commerciale, le Flash Player va tenter de passer outre lerreur et de continuer
lexcution du code si possible.
Pour en revenir la gestion des exceptions, rappelez-vous que celles-ci sont gnres
ds lors que linstruction en question est excute. Il est alors possible de traiter lerreur
immdiatement dans le mme bloc que linstruction incrimine. Pour cela, nous verrons
comment isoler le code erron lintrieur dune instruction try...catch afin de ragir
tout de suite et de pouvoir reprendre lexcution de la suite du programme.
Les erreurs asynchrones
Lors dune opration quelconque, il peut arriver quune erreur ne puisse pas tre retourne immdiatement. Ceci pourrait tre le cas, par exemple, lors de la lecture ou de
lcriture de donnes. En effet, laccs des donnes externes lapplication ne se fait
pas de faon immdiate. Dans cette situation, une instruction try...catch serait alors
inutile. La rponse aux erreurs lies ces oprations est donc gre par vnements.
Lorsque la gnration dune erreur nest pas directe mais diffre, lerreur dexcution
est dite asynchrone . Celle-ci est reprsente par la classe ErrorEvent ou lune de
ses sous-classes. La rponse cette dernire se fait grce une fonction dcouteur
comme dordinaire.

Les erreurs synchrones


Lintruction throw
Prsentation
Avant dentamer la gestion (ou interception) des exceptions en elle-mme, nous
allons parler de linstruction throw. Ce mot-cl, que nous avons dj vaguement voqu,
sert en ralit renvoyer une exception. Cette exception se prsente alors sous la
forme dune instance de la classe Error ou de lune de ses sous-classes.
Pour vous donner un exemple, voici comment renvoyer une exception :
1
2

var monErreur : Error = new Error () ;


throw monErreur ;

En excutant ce code, la console de sortie laisse alors apparatre ceci :


[ Fault ] exception , information = Error

581

CHAPITRE 26. LA GESTION DES ERREURS


Il faut avouer que dans le cas prcdent, les informations concernant lerreur taient
relativement minces. Pour remdier ce problme, il est possible de renseigner des
informations sur lerreur dans le constructeur de la classe Error. Vous pouvez donc
renseigner un message qui saffichera dans la console de sortie ou qui pourra tre utilis
lors de linterception de lerreur. Un second paramtre id peut galement servir
identifier lerreur avec prcision.
Cet identificateur sert gnralement rechercher les causes de lerreur, principalement si vous ntes pas lauteur de la classe layant gnre. Vous pouvez
notamment trouver des informations prcieuses par une recherche sur Internet.
Une erreur bien renseigne serait par exemple :
1

var monErreur : Error = new Error ( " Le param tre child ne doit pas
tre nul . " , 2007 ) ;

Exemple
prsent, nous allons raliser une petite fonction renvoyant diverses erreurs que nous
utiliserons dans la suite avec le bloc try...catch.
Voil donc la fonction que je vous propose :
1
2
3
4
5
6
7

function testerErreur ( objet : Object ) : void


{
if ( objet == null )
throw new TypeError ( " Le param tre objet ne doit pas
tre nul . " , 4000 ) ;
if ( objet == stage )
throw new Error ( " Le param tre objet ne doit pas tre la
sc ne principale . " , 4001 ) ;
}

En lanalysant, vous constaterez que celle-ci renvoie des exceptions diffrentes suivant
la nature de lobjet pass en paramtre. Cela pourrait correspondre par exemple aux
vrifications ncessaires en dbut dune mthode quelconque. Vrifions tout de mme
le bon fonctionnement de cette fonction. En premier lieu, passons la scne principale
en paramtre et voyons comment la version de dbogage du Flash Player ragit.
Linstruction correspondante est la suivante :
testerErreur ( stage ) ;

Aucun souci, lexception non intercepte est bien affiche dans la console :
[ Fault ] exception , information = Error : Le param tre objet ne doit
pas tre la sc ne principale .

582

LES ERREURS SYNCHRONES


La seconde erreur renvoye par la fonction dfinie plus haut, correspond au passage en
paramtre dun objet quelconque non instanci :
1
2

var monObjet : Object ;


testerErreur ( monObjet ) ;

Lerreur est galement bien renvoye et affiche dans la console de sortie :


[ Fault ] exception , information = TypeError : Le param tre objet ne
doit pas tre nul .

Linstruction try...catch
Utilisation basique
Entrons maintenant dans le vif du sujet et dcouvrons le fonctionnement de linstruction try...catch. Cette instruction permet disoler le code pouvant renvoyer une
exception : cela se fait alors lintrieur du bloc try. Ce bloc ne peut tre utilis
indpendamment du bloc catch qui sert intercepter les exceptions renvoyes.
1
2
3
4
5
6
7
8

try
{

// Instructions isol es
}
catch ( e : Error )
{
// Gestion de l ' exception
}

Par exemple, utilisons notre fonction testerErreur() pour comprendre comment lensemble try...catch fonctionne. En labsence derreur, seul le bloc try est excut.
Voyons cependant ce que cela donne lorsquune erreur apparat. Tentons de renvoyer
une exception de type Error :
1
2
3
4
5
6
7
8
9

try
{

testerErreur ( stage ) ;
trace ( " Aucune exception renvoy e " ) ;

}
catch ( e : Error )
{
trace ( " Exception intercept e : # " + e . errorID ) ;
}

Le rsultat dans la console de sortie est le suivant :


Exception intercept e : #4001

583

CHAPITRE 26. LA GESTION DES ERREURS


Grce cet exemple, nous pouvons constater un certain nombre de choses. Tout
dabord, nous voyons que lexception a bien t intercepte puisque quaucun message derreur nest apparu dans la console de sortie. Ensuite, vous remarquerez que
lexcution du bloc try sest stoppe lors de lapparition de lerreur. Enfin, le bloc
catch a t excut intgralement et il possible de rcuprer des informations

Utilisation avance
Prcdemment, nous avons vu comment mettre en place un bloc try...catch, permettant de grer de faon basique les erreurs synchrones. Toutefois, il est possible
de grer de manire plus pousse les exceptions renvoyes lintrieur du bloc try.
Dune part, nous pouvons ajouter plusieurs blocs catch permettant didentifier plus
spcifiquement diffrents types derreurs. Chaque instruction catch est alors vrifie
dans lordre et est associe un type dexception. Seul le premier bloc catch, correspondant au type dexception renvoye, est excut. Dautre part, le mot-cl facultatif
finally permet dinstroduire des instructions supplmentaires, excutes au terme de
la gestion de lerreur, quel que soit le chemin parcouru travers les diffrents blocs try
ou catch.
Pour illustrer tout ce qui vient dtre dit, voici un exemple de code contenant un certain
nombre de blocs :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

try
{

testerErreur ( null ) ;
}
catch ( e : TypeError )
{
trace ( " Exception intercept e de type TypeError " ) ;
}
catch ( e : Error )
{
trace ( " Exception intercept e de type Error " ) ;
}
finally
{
trace ( " Gestion termin e " ) ;
}

Aprs excution du code, la console laisse apparatre ceci :


Exception intercept e de type TypeError
Gestion termin e

Comme prvu, les blocs try et finally ont t excuts et le seul bloc catch associ
au type TypeError a t excut.
584

LES ERREURS ASYNCHRONES


Dans le cas de blocs catch associs plusieurs types dexceptions, ceux-ci
doivent tre ordonns du type le plus spcifique au moins spcifique. Ainsi,
la classe Error, super-classe de toutes les autres, doit tre traite en dernier.
Dans lexemple prcdent, une exception de type ArgumentError aurait t
intercepte par le dernier bloc catch.

Les erreurs asynchrones


Distribuer un objet ErrorEvent
Nous allons maintenant nous intresser aux erreurs asynchrones et leur gestion.
Comme je vous lai introduit plus tt, ce type derreurs est reprsent par des vnements hritant de la classe ErrorEvent. Pour gnrer une erreur asynchrone, nous
pouvons donc nous servir de la mthode dispatchEvent() de la classe EventDispatcher.
Pour la suite, je vous propose donc de renvoyer des erreurs via la fonction suivante :
1
2
3
4
5

function testerErreur ( objet : Object ) : void


{
if ( objet == null )
dispatchEvent ( new ErrorEvent ( ErrorEvent . ERROR ) ) ;
}

Ensuite, voici comment gnrer ladite erreur :


1

testerErreur ( null ) ;

Sans gestion directe de lerreur, la version de dbogage du Flash Player arrte lexcution du code et renvoie lerreur lintrieur de la console de sortie. Voil le message
affich :
Error #2044: error non pris en charge : text =

Bien videmment, il est prfrable dtendre la classe ErrorEvent afin de


personnaliser lerreur son utilisation. Par exemple, la classe IOErrorEvent
est spcifique aux erreurs gnres par linteraction avec des donnes externes
au programme.

Grer des vnements derreurs


Aussi surprenant que cela puisse paratre, vous nallez rien apprendre ici. Effectivement, la gestion des vnements est strictement identique quel que soit le type
dvnements. Seul la classe dvnement devra tre ajuste pour pouvoir rpondre
aux erreurs asynchrones.
585

CHAPITRE 26. LA GESTION DES ERREURS


Nous pouvons donc trs facilement dfinir une fonction de rappel pour un objet de
type ErrorEvent et enregistrer lcouteur auprs de lobjet courant. Dailleurs en voici
lcriture :
1
2
3
4
5

function traiterErreur ( error : ErrorEvent ) : void


{
trace ( " Erreur trait e " ) ;
}
addEventListener ( ErrorEvent . ERROR , traiterErreur ) ;

Testons la gestion de lerreur comme tout lheure :


testerErreur ( null ) ;

Aucune surprise, la fonction dcouteur est excute lors de lapparition de lvnement :


Erreur trait e

Bien comprendre les deux approches


Une classe utilisant les deux approches
Prcdemment, nous avons vu comment grer des erreurs dexcution, quelles
soient synchrones ou asynchrones. Cependant, il est fort probable que certains
dentre vous narrivent pas encore bien distinguer les diffrences dutilisation qui
existent entre les deux types derreurs. Je vous propose ici une classe permettant dillustrer ceci.
Prsentation
Dans un premier temps, je vous laisse dcouvrir et vous familiariser avec le code de
cette classe donn ci-dessous :
1
2
3
4
5

package
{
import flash . display . DisplayObject ;
import flash . events . ErrorEvent ;
import flash . events . Event ;

6
7
8
9
10

public class Animation


{
private var _objet : DisplayObject ;
private var _vars : Object ;

11
12
13
14

586

public function Animation ( objet : DisplayObject = null )


{
_objet = objet ;

BIEN COMPRENDRE LES DEUX APPROCHES


15

16

_vars = null ;

17

public function incrementer ( vars : Object ) : void


{
if ( _objet == null ) {
throw new TypeError ( " Objet nul " ) ;
} else {
_vars = vars ;
_objet . addEventListener ( Event . ENTER_FRAME ,
animer ) ;
}
}

18
19
20
21
22
23
24
25
26
27

private function animer ( event : Event ) : void


{
for ( var p : String in _vars ) {
try {
_objet [ p ]++;
if ( _objet [ p ] >= _vars [ p ]) {
_objet . removeEventListener ( Event .
ENTER_FRAME , animer ) ;
}
} catch ( e : Error ) {
_objet . dispatchEvent ( new ErrorEvent ( "
AnimErrorEvent " ) ) ;
}
}
}

28
29
30
31
32
33
34
35
36
37
38
39
40
41

42
43
44

Fonctionnement
Rassurez-vous, si vous navez pas entirement cern le fonctionnement de la classe
Animation, cest normal ! Cest pourquoi, je vous propose maintenant quelques explications. Tout dabord, et jespre que vous laurez compris, cette classe va nous
permettre danimer un objet de type DisplayObject. Pour tre plus prcis, la mthode incrementer() va servir lancer une animation visant augmenter la valeur de
certaines des proprits de lobjet daffichage jusqu une certaine valeur. Les proprits
prendre en compte doivent tre renseignes travers le paramtre vars.
Revenons sur la dfinition de la mthode incrementer() :
1
2
3

public function incrementer ( vars : Object ) : void


{
if ( _objet == null ) {

587

CHAPITRE 26. LA GESTION DES ERREURS


4
5
6
7
8
9
10

// R sultat imm diat permettant de g n rer une erreur


synchrone
throw new TypeError ( " Objet nul " ) ;
} else {
_vars = vars ;
_objet . addEventListener ( Event . ENTER_FRAME , animer ) ;
}

Nous pouvons constater quun test est ralis afin de vrifier que llment _objet
est bien instanci, et donc diffrent de la valeur null. Si ce nest pas le cas, nous
ne pouvons pas dmarrer lanimation et choisissons de renvoyer une exception. Dans
cette situation, lerreur est dtecte immdiatement et est bien de type synchrone.
Dans la classe parente, une instruction try...catch permettra de grer lerreur. Si
aucune erreur nest dtecte, lanimation peut tre lance en enregistrant un couteur
sur lvnement Event.ENTER_FRAME.
Je vous invite prsent tester le bon fonctionnement de la classe Animation. Essayons
par exemple danimer la position dun objet jusqu la position (100,100) :
1
2

var animation : Animation = new Animation ( unObjet ) ;


animation . incrementer ( { x : 100 , y : 100 } ) ;

Nous voyons ici que le programme ne pose aucun problme lors de lexcution.
Vous remarquerez le passage de la valeur null en paramtre de la mthode
incrementer() gnre bien une exception.
Penchons-nous maintenant sur lanimation en elle-mme, traite lintrieur de la
fonction de rappel animer(). Voici le contenu de cette mthode :
1
2
3
4
5
6
7
8
9
10
11
12
13

private function animer ( event : Event ) : void


{
for ( var p : String in _vars ) {
try {
_objet [ p ]++;
if ( _objet [ p ] >= _vars [ p ]) {
_objet . removeEventListener ( Event . ENTER_FRAME ,
animer ) ;
}
} catch ( e : Error ) {
_objet . dispatchEvent ( new ErrorEvent ( " AnimErrorEvent
"));
}
}
}

Concernant le fonctionnement, la boucle for...in permet de rcuprer chacune des


proprits de lobjet _vars sous forme de chanes de caractres. laide de ces
588

BIEN COMPRENDRE LES DEUX APPROCHES


dernires, nous avons alors accs aux proprits correspondantes de lobjet daffichage
afin de pouvoir les incrmenter. Toutefois, il pourrait arriver que les proprits renseignes ne soient pas de type numrique ou nexistent tout simplement pas. Il serait
alors avis de renvoyer une erreur informant lutilisateur quil tente daccder une
proprit inexistante ou ne pouvant tre incrmente.
Pour raliser ceci, commenons par isoler le code daccs la proprit en question.
En effet, cest cette instruction qui pourrait renvoyer une erreur et qui permettra de
dterminer si une erreur doit tre renvoye. Si lerreur est avre, celle-ci doit tre
renvoye lutilisateur sous forme derreur asynchrone.
Il sagit bien dune exception qui est renvoye en tant querreur asynchrone
la classe de niveau suprieur. En effet, si cette erreur est synchrone
lintrieur de la mthode animer(), celle-ci est nanmoins asynchrone par
rapport lappel de la mthode incrementer() ralise par lutilisateur.
Dites-vous bien quentre lappel de cette dernire et lapparition de lerreur, il
sest coul un certain temps puisque nous sommes dans la fonction dcouteur de lvnement Event.ENTER_FRAME.
Prenons lexemple suivant afin de provoquer lapparition dune erreur :
1
2

var animation : Animation = new Animation ( objet ) ;


animation . incrementer ( { a : 100 , b : 100 } ) ;

Lapparition de lerreur asynchrone a bien lieu :


Error #2044: AnimErrorEvent non pris en charge : text =

Vous remarquerez quen diminuant la cadence danimation du projet, il est


possible de percevoir trs nettement le retard de gnration de lerreur asynchrone. Essayez par exemple de donner la valeur 1 la proprit frameRate
de lobjet stage. Vous verrez alors lerreur apparatre au bout dune seconde
seulement dans la console de sortie.

Intrts des erreurs


Les erreurs dexcution ont principalement deux utilits. Dune part, une erreur peut
servir informer le programmeur ou utilisateur dune classe quil en fait un usage
erron. Cest notamment le cas lors de la conception de classes abstraites, comme
nous lavons vu, ou encore lorsque lon souhaite avertir que lun des paramtres dune
mthode nest pas valide. Dans ce cas, le programmeur va revoir presque systmatiquement son code afin de rparer lerreur en question. Dautre part, lerreur peut tre
persistante et non rparable par le programmeur. Ce dernier peut alors contourner
le problme afin de pouvoir poursuivre au mieux lexcution du programme. Cest le
genre de situation que vous pourrez rencontrer lorsque vous tenterez daccder des
donnes externes lapplication.
589

CHAPITRE 26. LA GESTION DES ERREURS


Dans tous les cas, la meilleure chose faire est de ne pas traiter lerreur vous-mmes,
mais de laisser la possibilit lutilisateur de la classe de grer les erreurs comme il
lentend.

En rsum
La gestion des erreurs consiste ajouter du code spcifique au traitement des
erreurs dexcution.
Les erreurs synchrones sont renvoyes immdiatement lors de lexcution de linstruction errone.
Les erreurs asynchrones correspondent aux erreurs ne pouvant pas tre gnres
dans limmdiat.
Linstruction try...catch permet disoler un code erron renvoyant une erreur
synchrone ou exception.
Une erreur asynchrone est reprsente par la classe ErrorEvent ou une de ses
sous-classes et peut tre gre comme nimporte quel type dvnements.

590

Cinquime partie

Annexes

591

Chapitre

27

Bonnes pratiques
Difficult :
Pour clturer ce cours, je vous propose un petit chapitre dannexe o nous allons parler de
bonnes pratiques . Grce ce chapitre, vous pourrez prendre de bonnes habitudes ds
maintenant. Ce nest pas aprs cinq ans de programmation quil faudra commencer se
proccuper de coder et documenter proprement vos projets. Dans un premier temps, nous
traiterons donc de la gestion de la mmoire dans Flash, puis nous enchanerons sur les
commentaires de documentation et la documentation avec ASDoc.

593

CHAPITRE 27. BONNES PRATIQUES

La mmoire dans Flash


Flash et la mmoire vive
Tout dabord, vous devez savoir que tout programme qui se lance doit dabord se
charger en mmoire, et ventuellement charger dautres fichiers (comme des images).
Je parle bien entendu de la mmoire vive de votre ordinateur o sont chargs tous
les fichiers ncessaires au fonctionnement de votre systme dexploitation et de tous les
logiciels qui fonctionnent sur votre machine.
Le lecteur Flash dispose dune machine virtuelle qui excute un langage interprt
de haut niveau, ce qui implique que lActionScript ne vous permet pas de grer
directement la mmoire mise la disposition de vos programmes et animations. En
effet, cest le lecteur Flash qui va soccuper dallouer de la mmoire et de la vider
votre place (sauf pour quelques exceptions). Bien sr, il faut respecter certaines rgles
que nous allons voir plus bas, pour que la mmoire soit libre correctement, rgles qui
sont quelquefois bafoues par certains dveloppeurs (do certains problmes rcurrents
de consommation de mmoire).

Le ramasse-miettes
Flash utilise donc une technique propre aux plateformes dexcution (comme Java)
pour vider le plus efficacement possible la mmoire de lordinateur qui nest plus utilise
par votre animation : le ramasse-miettes (ou garbage collector). Cest un petit programme qui va se charger de trouver tout ce qui est devenu inutile dans le programme
puis deffacer la mmoire correspondante et ceci rgulirement lors de lexcution. Il
nest pas possible de lappeler manuellement car lopration peut tre complexe et donc
relativement lente : ainsi, seul le lecteur a le droit de lancer le ramasse-miettes quand
il juge que cela est ncessaire.
Il sera nanmoins possible de lappeler pendant que vous ferez des tests
de dbogage lors de lcriture de vos programmes : il suffit dentrer cette
ligne : System.gc(); Cette commande sera tout simplement ignore lors de
lexcution relle du programme (par exemple sur une page web).

Prparer un objet pour la suppression


Un objet doit remplir un certains nombre de conditions avant de pouvoir tre supprim
de la mmoire par le ramasse-miette. On dit alors quil est ligible au nettoyage.
Cet objet doit donc :
Ne pas tre prsent dans larbre daffichage de la scne principale.
Ne pas avoir de rfrences (variables) pointant sur lui dans dautres objets.
Ne pas avoir dcouteurs dvnement enregistrs auprs de lobjet en question.
594

LA MMOIRE DANS FLASH

Exemple
Pour illustrer tout ceci, je vous propose prsent un petit exemple. Nous allons raliser un bouton qui pourrait servir daccueil pour un site web ou pour un jeu. Une
fois le bouton cliqu, celui-ci disparat pour laisser place lapplication en elle-mme.
Lobjectif est donc de prparer lobjet a sa suppression de la mmoire vive.
Dans un premier temps, crez une classe Button pour dfinir le graphisme de notre
bouton. Celui-ci sera alors compos dun fond en dgrad, avec un texte par dessus.
Voici le code de cette classe :
1
2
3
4
5
6
7
8
9

package
{
import
import
import
import
import
import
import

flash . display . Sprite ;


flash . geom . Matrix ;
flash . display . Shape ;
flash . display . GradientType ;
flash . text . TextField ;
flash . text . TextFieldAutoSize ;
flash . text . TextFormat ;

10
11
12
13
14

public class Button extends Sprite


{
private static const LARGEUR_SCENE : int = 320 ;
private static const HAUTEUR_SCENE : int = 240 ;

15
16
17
18

public function Button ()


{
super () ;

19
20
21
22
23

// D grad de base
var couleurs : Array = [ 0xEEBBBB , 0xDD0000 ];
var alphas : Array = [1 , 1 ];
var ratios : Array = [0 , 255 ];

24
25
26
27
28
29
30
31
32

// Matrice de description
var matrix : Matrix = new Matrix () ;
var largeur : Number = 100 ;
var hauteur : Number = 15 ;
var rotation : Number = Math . PI / 2 ;
var tx : Number = 0 ;
var ty : Number = 0 ;
matrix . createGradientBox ( largeur , hauteur , rotation
, tx , ty ) ;

33
34
35
36
37
38

// Trac du bouton
var fond : Shape = new Shape ;
fond . graphics . lineStyle (1 , 0x880000 ) ;
fond . graphics . beginGradientFill ( GradientType . LINEAR
, couleurs , alphas , ratios , matrix ) ;
fond . graphics . drawRoundRect (0 , 0 , 100 , 25 , 10 ) ;

595

CHAPITRE 27. BONNES PRATIQUES


fond . x = ( LARGEUR_SCENE - fond . width ) / 2 ;
fond . y = ( HAUTEUR_SCENE - fond . height ) / 2 ;
addChild ( fond ) ;

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

55

// Cr ation du Texte
var texte : TextField = new TextField () ;
texte . autoSize = TextFieldAutoSize . LEFT ;
var format : TextFormat = new TextFormat () ;
format . font = " Calibri " ;
format . color = 0xFFFFFF ;
texte . defaultTextFormat = format ;
texte . text = " ENTRER " ;
texte . selectable = false ;
texte . x = ( LARGEUR_SCENE - texte . width ) / 2 ;
texte . y = ( HAUTEUR_SCENE - texte . height ) / 2 ;
addChild ( texte ) ;

56

57
58
59

Vous
pouvez lafficher pour la copier
 en utilisant le code web ci-dessous.
Classe Button
B
Code web : 988840


Aucun problme pour la mise en place du bouton ! Nanmoins, pour illustrer les trois
points vus plus haut, nous allons dclarer notre bouton en tant quattribut de la classe
principale :
private var _monBouton : Button ;

Nous linstancions donc, lui ajoutons un couteur pour lvnement MouseEvent.CLICK,


et enfin lajoutons la liste daffichage, comme ceci :
_monBouton = new Button () ;
_monBouton . addEventListener ( MouseEvent . CLICK , maFonction ) ;
addChild ( _monBouton ) ;

1
2
3

Une fois lapplication lance dans le Flash Player, cela donne la figure 27.1.
Une fois le bouton cliqu, nous devons le prparer sa suppression de la mmoire vive.
Dans le cas prsent, nous aurons besoin de supprimer lcouteur enregistr auprs de
lobjet, de supprimer celui-ci de la liste daffichage, mais aussi de supprimer la rfrence
lobjet dfinit pour lattribut. Tout cela sera fait lintrieur de la fonction dcouteur
maFonction(). Voil comment raliser tout ceci :
1
2
3
4

function maFonction ( e : MouseEvent ) : void


{
_monBouton . removeEventListener ( MouseEvent . CLICK , maFonction
);
removeChild ( _monBouton ) ;

596

LES COMMENTAIRES DE DOCUMENTATION

Figure 27.1 Lobjet monBouton devant tre supprim

5
6
7

_monBouton = null ;
// L ' objet " monBouton " est pr sent ligible au nettoyage

Voil ! Ce nest pas bien compliqu, mais il est vraiment essentiel de raliser ces oprations pour librer la mmoire au fil de lexcution de votre programme. Beaucoup trop
de dveloppeurs ont un gros problme de formation la gestion de la mmoire, ce qui
conduit aprs des internautes qui pestent parce que Flash Player prend toute la
RAM .

Les commentaires de documentation


Ecrire un commentaire de documentation
Nous avons rencontr dans le TP ce commentaire devant certaines proprits dans la
classe Vecteur2D :
1
2
3
4
5
6

/* *
* Ajoute le vecteur pass en param tre au vecteur courant .
* @param vecteur
Vecteur ajouter .
* @param apply
Si vrai , modifie directement le vecteur
courant . Sinon , renvoie un nouveau vecteur .
* @return
Le vecteur repr sentant la somme des deux
premiers vecteurs .
*/

Ces commentaires sont des commentaires de documentation. Il permettent votre


IDE dafficher des informations propos de ces proprits lors de lautocompltion ou
si vous passez la souris dessus. Il sert galement gnrer une documentation de
votre classe laide de loutil asdoc (voir figure 27.2).
597

CHAPITRE 27. BONNES PRATIQUES

Figure 27.2 Une infobulle de Flashdevelop tirant des informations du commentaire


de documentation
Pour crer un commentaire de documentation, placez votre curseur de saisie sur
la ligne prcdent une proprit publique et entrez /** avec deux toiles. Si vous
tes sur un IDE comme Flashdevelop, il vous sera propos de gnrer automatiquement le squelette du commentaire de documentation associ votre proprit. Par
exemple :
1
2
3
4
5
6
7
8
9
10

/* *
*
* @param vecteur
* @param apply
* @return
*/
public function ajouter ( vecteur : Vecteur2D , apply : Boolean =
false ) : Vecteur2D
{
// ...
}

A vous ensuite de remplir le commentaire partir de la deuxime ligne en dcrivant


lutilit de la proprit de manire ce que quelquun dautre que vous puisse comprendre quoi elle sert.
Voici quelques uns des tags utiliser pour concevoir un commentaire de documentation :

@auteur : permet de spcifier lauteur du code source.


@param : permet de faire la description du paramtre spcifi.
@return : permet de spcifier la valeur de retour pour la mthode.
@default : permet de spcifier la valeur par dfaut.
@private : permet dexclure llment de la documentation.
@see : permet de crer un lien interne ou externe la documentation.

Bien videmment, il en existe dautres, je vous laisserai les dcouvrir par vous-mmes !

Gnrer la documentation de vos classes


prsent, je vais vous montrer comment gnrer une belle documentation. Pour cela,
nous allons avoir besoin dun projet contenant des classes documentes. Nous pourrions
par exemple imaginer une collection de classes permettant de manipuler des lments
mathmatiques, tels que des points, des matrices, des vecteurs, . . .
Voici, la figure 27.3, un exemple de projet contenant un certain nombre de classes.
598

LES COMMENTAIRES DE DOCUMENTATION

Figure 27.3 Un exemple de projet contenant diverses classes


Pour lexemple, vous remarquerez que jai repris les deux classes Outils et
Vecteur2D conues spcialement pour le jeu de billard. Cela nous vitera
de perdre du temps dans lcriture de nouvelles classes, et puis les les commentaires de documentation y sont dj tout prts. Je vous invite en faire
autant !
Pour gnrer la documentation, nous allons utiliser loutil inclus dans FlashDevelop,
tout prt tre utilis. Pour le lancer, allez dans le menu Tools, puis cliquez sur
Documentation Generator..., comme illustrer sur limage 27.4.

Figure 27.4 Menu Outils


Une fois la fentre ActionScript Documentation Generator ouverte, vous devez alors
renseigner un certain nombre de champs. Au minimum, vous devez remplir les champs
suivants :
599

CHAPITRE 27. BONNES PRATIQUES


Page title : il sagit du titre de la documentation. En gnral, vous renseignerez
simplement le nom de votre projet ou de votre bibliothque de classes.
Output directory : ceci correspond au rpertoire qui contiendra lensemble des
fichiers de votre documentation.
Classpaths : vous devez renseigner ici lensemble des rpertoires o se situe le code
source de vos classes.
Compiler : tant donn que nous travaillons depuis le dpart en Actionscript 3,
utilisez plutt loption ASDOC (AS3) que celle donne par dfaut.
Voici les donnes spcifies pour lexemple en cours, la figure 27.5.

Figure 27.5 Interface pour le gnrateur de documentation


Lorsque tout est prt, lancer le gnrateur simplement en appuyant sur le bouton
Generate!. Si des erreurs se produisent durant la gnration des fichiers, on vous le
fera savoir via la console de sortie spcifique loutil, prsent sous longlet Output de
la fentre. Si tout sest bien droul, vous devriez trouver dans le rpertoire de sortie,
toute une panoplie de fichiers gnrs automatiquement. Pour visualiser le rendu, vous
devez utilisez le fichier index.hmtl, prsent la racine du rpertoire.
Voil ce que cela donne pour le projet ASDocExample, et plus particulirement pour la
classe Vecteur2D : voir la figure 27.6.
Les documents gnrs avec ASDoc sont trs populaires au sein de la communaut des dveloppeurs Actionscript. Elles accompagnent trs gnralement
les bibliothque de classes, telle que lAPI Documentation pour la librairie
dinterpolation TweenMax, librairie dinterpolation cre par Greensock et
que nous avons dcouvert lors de la dernire partie.
600

LES COMMENTAIRES DE DOCUMENTATION

Figure 27.6 La documentation du projet ASDocExample

601

CHAPITRE 27. BONNES PRATIQUES



LAPI Documentation
B
Code web : 353359

En rsum
Afin de ne pas saturer la mmoire vive de lutilisateur de votre application, il est
ncessaire de librer la mmoire au fur et mesure de lexcution de celle-ci.
Pour tre ligible au nettoyage, un objet doit rpondre un certain nombre de
critres.
Les commentaires de documentation permettent votre IDE dafficher des
informations concernant les proprits lors de lautocompltion ou lors dun survol
avec la souris.
Les commentaires de documentation dbutent par la srie de caractres /** et
utilisent un certain nombre de tags commenant par @.
LASDoc est un outil permettant de gnrer automatiquement une documentation,
et il est disponible via la fentre Documentation Generator dans FlashDevelop.

602

Index

A
accesseur . . . . . . . . . . . . . . . . . . . 133, 142, 159
affectation. . . . . . . . . . . . . . . . . . . . . . . .53, 149
affichage . . . . . . . . . . . . . . . 221, 225, 233, 359
animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 473
Flash . . . . . . . . . . . . . . . . . . . . . . . . . . 4, 13
Apache Flex . . . . . . . . . . . . . . . . . . . . . . . 14, 15
Array . . . . . . . . . . . . . . . . . . . . . . . 98, 331, 373
ASDoc . . . . . . . . . . . . . . . . . . . . . . . . . . 593, 600
attribut . . . . . . . . . . . . . . . . . . . . 126, 128, 141
statique . . . . . . . . . . . . . . . . . . . . . . . . . 146

D
dclaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
dessin . . . . . . . . . . . . . . . . . . . . . . . . . . . 303, 351
DisplayObject . . . . . . . . . . . . . . . . . . . . . . 238
do...while . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
droit daccs . . . . . . . . . . . . . . . . . . . . . . . . . 185

E
couteur . . . . . . . . . . . . . . . . . . . . . . . . 423, 424
else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
encapsulation . . . . . . . . . . . . . . . . . . . 115, 132
erreur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 579
Error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581
B
vnement . . . . . . . . . . . . . . . . . . . . . . 421, 585
binaire . . . . . . . . . . . . . . . . . . . . . . . . . . . 12, 219
Event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 435
Bitmap . . . . . . . . . . . . . . . . . . . . . . . . . . 226, 344
EventDispatcher . . . . . . . . . . . . . . . . . . . . 425
BitmapData . . . . . . . . . . . . . . . . 349, 359, 509
exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581
Boolean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
extends . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
boucle . . . . . . . . . . . . . . . . . . . . . . . 79, 105, 107
C
chane de caractres . . . . . . . . . . . . . . . 60, 69
Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
abstraite . . . . . . . . . . . . . . . . . . . . . . . . 200
dynamique . . . . . . . . . . . . . . . . . . . . . . 190
clavier . . . . . . . . . . . . . . . . . . . . . . . 31, 455, 577
collision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495
commentaire . . . . . . . . . . . . . . . . . . 30, 54, 519
de documentation . . . . . . . . . . . . . . . 597
condition. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .67
const . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
constructeur . . . . . . . . . . . . . . . . . . . . . .29, 129
curseur . . . . . . . . . . . . . . . . 256, 308, 444, 449

F
filtre . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362, 364
final . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
Flash Player . . . . . . . . . . . . . . . . . . . . . . . . 8, 13
FlashDevelop . . . . . . . . . . . . . . . . 36, 137, 259
fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84, 105
function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
G
get . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308
H
hritage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175

603

INDEX
I
if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
if...else . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
image . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
implements . . . . . . . . . . . . . . . . . . . . . . . . . . 196
import . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
instance. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .123
int . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
internal . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
interpolation . . . . . . . . . . . . . . . . . . . . . . . . . 482

pointeur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
police de caractres . . . . . . . . . . . . . 269, 287
polymorphisme . . . . . . . . . . . . . . . . . . . . . . 183
private . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
protected . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
public . . . . . . . . . . . . . . . . . . . . . . . . . . 133, 185
R
ramasse-miettes . . . . . . . . . . . . . . . . . . . . . . 594
return . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

S
scne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
Shape . . . . . . . . . . . . . . . . . . . . . . . . . . . 226, 304
M
souris . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440
masque . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387 Sprite . . . . . . . . . . . . . . . . . . . . . . . . . . 227, 229
Math . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Stage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
matrice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327 static . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
Matrix . . . . . . . . . . . . . . . . . . . . . . . . . . 328 String . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
mmoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 594
super . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
mthode . . . . . . . . . . . . . . . . . . . . . . . . 128, 130
switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
mode de fusion . . . . . . . . . . . . . . . . . . 376, 378
Mouse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447
T
MouseEvent . . . . . . . . . . . . . . . . . . . . . . . . . . 440
tableau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
mutateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
TextField . . . . . . . . . . . . . . . . . . . . . . 250
N
this
. . . . . . . . . . . . . . . . . . . . . . . . . . . . 142, 231
new . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
throw
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581
null . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
Timer
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477
Number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
trace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
transparence . . . . . . . . . . . . . . . . . . . . 244, 390
O
objet. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .112 try...catch. . . . . . . . . . . . . . . . . . . . . . . . .583
Object . . . . . . . . . . . . . . . . . . . . . . . . . . 209 TweenMax . . . . . . . . . . . . . . . . . . . . . . . . . . . . 482
opacit. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .244 typage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
oprateur
U
arithmtique. . . . . . . . . . . . . . . . . . . . . .56
uint
.
.
.
.
.
.
.
.
. . . . . . . . . . . . . . . . . . . . . . . . . . 55
logique . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
undefined
.
.
.
. . . . . . . . . . . . . . . . . . . . . . . . . 53
relationnel . . . . . . . . . . . . . . . . . . . . . . . . 68
origine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
V
override . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
var . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
P
statique . . . . . . . . . . . . . . . . . . . . . . . . . 146
package . . . . . . . . . . . . . . . . . . . . . . . . . . 25, 127
paramtre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 Vector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
facultatif . . . . . . . . . . . . . . . . . . . . . . . . 130 void . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
K
KeyboardEvent . . . . . . . . . . . . . . . . . . . . . . 455

604

INDEX
W
While . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

605

Vous aimerez peut-être aussi