Académique Documents
Professionnel Documents
Culture Documents
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. . .
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.
REMERCIEMENTS
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
Avant-propos
ii
ii
ii
iii
Remerciements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
iii
Guillaume Chau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
iii
Guillaume Lapayre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
iv
Adobe Flash
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Prsentation de Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Un peu dhistoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
LActionscript 3
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
v
De haut niveau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
vnementiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
12
Le compilateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12
Le lecteur Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13
14
Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
Flex SDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
19
21
21
23
23
30
30
Place au test ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
32
FlashDevelop la rescousse ! . . . . . . . . . . . . . . . . . . . . . . . . . . .
36
Tlchargement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
36
Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
36
Un peu de paramtrage . . . . . . . . . . . . . . . . . . . . . . . . . . .
40
43
43
47
3 Les variables
vi
11
51
52
Dclaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
52
53
Les nombres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
54
54
56
La classe Math . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
58
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
60
60
61
Concatnation de chanes . . . . . . . . . . . . . . . . . . . . . . . . . .
62
62
4 Les conditions
67
68
68
68
. . . . . . . . . . . . . . . . . . . . . . . . . . .
70
71
72
La structure de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
72
Le type boolen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
74
75
Linstruction switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
76
Lutilisation conventionnelle . . . . . . . . . . . . . . . . . . . . . . . . .
76
77
5 Les boucles
79
La boucle while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
80
Le principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
80
criture en Actionscript . . . . . . . . . . . . . . . . . . . . . . . . . . .
80
82
La boucle for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
84
Prsentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
84
6 Les fonctions
87
Concept de fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Le principe de fonctionnement
88
. . . . . . . . . . . . . . . . . . . . . . .
88
Prsentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
89
90
Instructions de fonction . . . . . . . . . . . . . . . . . . . . . . . . . . .
90
Expressions de fonction . . . . . . . . . . . . . . . . . . . . . . . . . . .
92
vii
92
Message de bienvenue . . . . . . . . . . . . . . . . . . . . . . . . . . . .
93
Calcul de PGCD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
93
93
7 Les tableaux
97
Le type Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
98
Cration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
98
98
99
II
109
111
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
. . . . . . . . . . . . . . . . . . . . . . . . . . . 150
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
ix
175
189
. . . . . . . . . . . . . . . . . . . . . . 204
III
Laffichage
215
217
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
x
. . . . . . . . . . . . . . . . . . . . 234
249
303
327
341
361
387
403
IV
Interaction et animation
21 Les vnements
419
421
439
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440
473
495
Prambule . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 496
Dfinition dune collision . . . . . . . . . . . . . . . . . . . . . . . . . . . 496
xv
513
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 514
579
Annexes
591
27 Bonnes pratiques
593
xvii
xviii
Premire partie
Chapitre
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.
ADOBE FLASH
LACTIONSCRIPT 3
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
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
11
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)
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.
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.
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
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
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.
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).
17
18
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
20
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
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 !
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
package ET . telephoner {
2
3
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
package {
3
4
5
package {
3
4
5
27
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
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
4
5
28
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
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
4
5
6
7
8
9
10
11
// Constructeur de la classe
public function Hello () {
12
13
14
15
16
17
18
19
20
29
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
/* Ceci
est un commentaire
sur quatre
lignes . */
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
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
3
4
5
6
7
8
9
10
11
12
13
// Constructeur de la classe
public function Hello () {
14
15
16
17
18
31
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 "
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
33
./ fdb
Sur Mac :
./ fdb
continue
Miracle ! Notre trace("Hello world !"); a fonctionn et le message est apparu dans
la console ! (voir figure 2.24)
Vous pouvez galement lister lintgralit des commandes du dbogueur avec cette
commande :
help
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 !
37
FLASHDEVELOP LA RESCOUSSE !
39
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 !
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 !
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.
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 !
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
17
47
18
19
20
21
22
23
24
25
26
27
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.
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
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
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 !
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
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
maVariable = nouveauContenu ;
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
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
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
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
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
55
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
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
2;
= 3 . 14 ;
= unEntier + unNombre ;
// Affiche : 5
Ainsi lcriture de cette instruction peut tre simplifie et rduite sous la forme :
1
monResultat /= 100 ;
57
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
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
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
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
59
Pour gnrer un nombre alatoire entre deux valeurs a et b (voir figure 3.1), il faut
utiliser la formule suivante :
1
Mais vous pouvez aussi mettre des apostrophes la place des guillemets :
1
Attention toutefois ne pas mlanger les deux, cela ne marcherait pas. Ainsi,
le code trace("Hello world !); est incorrect.
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 !" ') ;
trace ( ' Hello . swf m \ ' a dit : \" Hello world !\" ') ;
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
Ainsi, si lon voulait afficher notre texte en deux parties, nous cririons ceci :
1
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
7
8
9
Le point est important : il signifie que cest la longueur de cette chane particulire que
lon veut.
maVariable . replace ( " Cha ne recherch e " , " Cha ne ins rer la
place " ) ;
Le texte nest remplac quune seule fois : ds que le texte recherch est
rencontr, il est remplac et la fonction sarrte.
1
2
Pour pouvoir remplacer tous les world en Jrme , il faut faire autant de
replace()que ncessaire :
1
2
3
4
5
6
7
64
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
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
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.
1
2
3
4
5
6
<
>
est suprieur
<=
>=
==
!=
===
!==
est
est
est
est
gal
diffrent de
strictement gal
strictement diffrent de
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.
Signification
NON logique
ET logique
OU logique
Ainsi, nous allons comparer notre nombre par rapport un intervalle laide de loprateur && :
1
2
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
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
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
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
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
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
if ( true )
trace ( " Ma condition est vraie . " ) ;
else
trace ( " Ma condition est fausse . " ) ;
5
6
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
2
3
4
5
6
7
8
9
10
if ( estEnVie )
{
trace ( " Vous tes toujours en vie . " ) ;
}
else
{
trace ( " Vous tes mort . " ) ;
}
11
12
tant donn que le rsultat dune condition est un boolen, il est tout fait possible
de le stocker dans une variable :
1
2
3
2
3
4
5
if ( monNombre < 0 )
{
trace ( " Ce nombre est n gatif . " ) ;
75
}
else if ( monNombre == 0 )
{
trace ( " Ce nombre est nul . " ) ;
}
else
{
trace ( " Ce nombre est positif . " ) ;
}
15
16
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
= 1;
Notez quaprs chaque argument vous devez crire un double point et non
un point-virgule.
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
77
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
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
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
}
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
81
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.
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.
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
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
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
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
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
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
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
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.
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.
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
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
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.
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
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
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
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
91
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
Nous ne nous attarderons pas trop sur ces expressions de fonction, voici tout de
mme un exemple dutilisation :
1
2
3
4
5
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
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
% 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 !
93
}
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
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
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
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
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
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
LE TYPE ARRAY
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
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 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 ) ;
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
101
Enfin, vous noterez que les mthodes push(), pop(), shift, unshift() et splice()
fonctionnent galement avec les tableaux de type Vector.
Sachant que les lments du tableau principal sont des tableaux, vous obtiendrez donc
un tableau en utilisant la notation avec indice vue prcdemment :
1
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
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
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
103
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.
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 ]) ;
}
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
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 ]) ;
}
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
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 !
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
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
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
111
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
114
LES NOTIONS-CLS
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
LES NOTIONS-CLS
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
Crer un objet
Tout dabord, il nous faut apprendre crer des objets. Il y a une syntaxe particulire
respecter :
1
118
Figure 8.10 Les trois classes sont des sous-classes de la classe Vhicule
119
revient crire :
1
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
3
4
5
6
7
8
120
var monNom : String = new String ( " Bryan " ) ; // Je sens que je
connais cette phrase ...
var ouSuisJe : String = " In the kitchen ! " ; // Argh !
121
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
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
Figure 8.11 Les variables-pointeurs sont toutes les deux lies lobjet.
Modifions sa marque :
1
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
124
Chapitre
125
package
{
4
5
6
7
// M thodes
8
9
10
11
12
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
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
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
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
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
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
package
{
4
5
6
7
8
// Constructeurs
public function MaClasse ()
{
_unAttribut = 0 ;
}
9
10
11
12
13
14
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
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
131
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 !
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
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
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
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
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
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.
package
{
134
ENCAPSULATION
/* *
* Une classe d ' exemple
*/
public class Voiture
{
private var _largeur : int ;
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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
Grce aux accesseurs, il est possible de lappeler automatiquement ds que lon modifie
la largeur de lobjet :
1
2
3
4
5
135
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
13
14
15
16
17
18
19
20
21
22
23
24
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
4
5
6
136
ENCAPSULATION
{
_largeur = 100 ;
}
else if ( _largeur > 200 )
{
_largeur = 200 ;
}
8
9
10
11
12
13
14
15
16
mettreAJour () ;
5
6
7
Avouez que cest extrmement pratique ! Je vous conseille dappliquer cette faon de
faire le plus souvent possible, cela vous rendra service.
5
6
7
8
9
137
Figure 9.2 1. Placer le curseur sur la ligne de lattribut dont il faut gnrer les
accesseurs
138
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
package
{
public class Voiture
{
6
7
8
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
141
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
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
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
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
143
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
145
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.
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 ++;
146
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
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
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.
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
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
19
20
21
22
23
24
25
26
150
27
28
29
return _couleur ;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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
151
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
152
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
Notre classe commence devenir complique, il vaudrait mieux crer une nouvelle
classe pour partager les proprits.
package
153
3
4
5
6
7
8
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
154
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
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
155
40
41
42
return _immatriculation ;
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
68
69
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
156
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
{
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
3
4
5
// D g ts de base
private var _degats : int ;
6
7
8
Les accesseurs
Noublions pas daccompagner les attributs de leurs accesseurs :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Le contructeur
Ensuite, initialisons nos attributs au sein du constructeur :
1
2
3
// Constructeur
public function Personnage ()
{
159
sante = 100 ;
degats = 0 ;
chanceCritique = 0 ;
La mthode
Enfin, ajoutons une mthode, afin que nos personnages puissent attaquer un autre
personnage :
1
2
3
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
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
package
{
3
4
5
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
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
161
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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
package {
import flash . display . Sprite ;
import flash . events . Event ;
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
moi . degats = 80 ;
moi . chanceCritique = 80 ;
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
1
2
3
4
5
package
{
3
4
5
6
7
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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 ) ;
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 !
package
{
4
5
6
// D g ts de l ' arme
private var _degats : int ;
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
La classe Personnage
Noublions pas dadapter la classe Personnage, comme nous lavons fait dans le chapitre
prcdent :
1
2
package
{
3
4
166
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
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
167
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
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
4
5
6
7
8
9
10
11
12
13
14
15
16
168
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 .
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
4
5
6
7
8
9
10
11
12
13
// On applique les d g ts
169
14
15
10
11
12
13
14
15
16
17
18
19
20
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
6
7
8
9
170
// Sant du personnage
private var _sante : int ;
10
11
// Amre quip e
private var _armeEquipee : Arme ;
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
171
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
1
2
package
{
3
4
5
6
7
8
// D g ts de l ' arme
private var _degats : int ;
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
172
34
35
36
37
38
39
40
41
42
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
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
173
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
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 :
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
package
{
public class Vehicule
{
protected var _marque : String ;
protected var _vitesse : int ;
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
177
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.
package
{
public class Voiture extends Vehicule
{
5
6
7
178
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
179
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
5
6
7
8
9
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
Il peut mme tre simplifi (vu que vous avez compris le principe) :
1
2
3
4
181
8
9
10
11
12
13
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
182
LE POLYMORPHISME
15
16
17
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
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
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
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.
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
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 ;
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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
4
5
6
7
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
188
Chapitre
12
189
package
{
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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
Nous allons maintenant voir comment tendre les fonctionnalits de notre classe durant
190
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
Nous pouvons ainsi appeler cette mthode comme nimporte quelle autre de la classe
de base :
1
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
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.
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
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
6
7
8
194
LES INTERFACES
Figure 12.1 Les classes et les interfaces que nous allons raliser
public function Personnage ()
{
sante = 100 ;
}
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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
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
6
7
8
9
10
11
12
196
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
{
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
197
package
{
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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.
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.
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
200
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
3
4
5
6
7
8
9
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
package
{
/* *
* Une sous - classe concr te .
*/
public class MaClasseConcrete extends MaClasseAbstraite
{
9
10
11
12
13
14
15
16
17
18
2
3
var
var
var
var
entier : int = - 23 ;
entierPositif : uint = 42 ;
nombre : Number = 3 . 14 ;
chaine : String = ' Hello world ! ';
5
6
7
8
9
10
203
11
12
13
14
15
16
17
18
19
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
5
6
7
8
9
10
11
12
13
14
Il existe un raccourci pour spcifier que le type dun paramtre est inconnu : le caractre
* ! Reprenons lexemple prcdent en utilisant ce raccourci :
204
5
6
7
8
9
10
11
12
13
14
15
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
5
6
7
8
9
10
11
12
13
14
15
16
17
205
package
{
public class Voiture
{
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Ou plus simplement :
1
2
206
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
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
19
20
21
22
23
24
207
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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
3
4
5
6
7
8
9
10
208
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
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 !
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 ,
...
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 ,
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
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
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
211
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
212
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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
}) ;
213
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
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
6
7
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
217
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).
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
Base seize
C
5
1F
20
10
A0
42
La variable ainsi cre peut tre manipule comme nimporte quelle autre variable :
1
2
3
4
220
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.
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
222
Figure 13.10 Nous disposons les diffrents objets dans le conteneur Voiture
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.
.
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
5
6
7
8
229
1
2
3
4
/* *
* ...
* @author Guillaume
*/
public class Main extends Sprite {
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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
230
addChild ( rue ) ;
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
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
231
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).
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.
// On cr e la rue
var rue : Sprite = new Sprite () ;
3
4
5
6
7
8
233
10
11
12
13
trace ( " La
) ) ; //
trace ( " La
) ) ; //
trace ( " La
) ) ; //
14
15
16
voiture1
Affiche
voiture2
Affiche
voiture3
Affiche
// 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
10
11
12
13
14
15
16
trace ( " La
) ) ; //
trace ( " La
) ) ; //
trace ( " La
) ) ; //
voiture1
Affiche
voiture2
Affiche
voiture3
Affiche
234
1
2
// On cr e une rue
var rue : Sprite = new Sprite () ;
3
4
5
6
7
8
9
10
11
12
trace ( " Il y a " + rue . numChildren + " voitures dans la rue . " ) ;
// Affiche 3 .
2
3
4
235
trace ( " La
) ) ; //
trace ( " La
) ) ; //
trace ( " La
) ) ; //
6
7
8
voiture1
Affiche
voiture2
Affiche
voiture3
Affiche
doit
tre
situe
entre
et
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
var
var
var
var
236
sprite1 : Sprite
sprite2 : Sprite
sprite3 : Sprite
sprite4 : Sprite
=
=
=
=
new
new
new
new
Sprite () ;
Sprite () ;
Sprite () ;
Sprite () ;
8
9
10
11
12
//
//
//
//
Affiche :
Affiche :
Affiche :
Affiche :
true
true
true
false
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
10
11
12
13
14
15
16
trace ( " La
) ) ; //
trace ( " La
) ) ; //
trace ( " La
) ) ; //
voiture1
Affiche
voiture2
Affiche
voiture3
Affiche
17
18
19
20
21
237
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
238
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.
239
241
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
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
5
6
7
8
9
10
11
12
242
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
5
6
7
8
9
10
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
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
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
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
4
5
6
7
8
9
10
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.
245
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 ;
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Cest trs simple : il suffit daffecter la variable en question avec le mot-cl null :
1
2
3
4
5
6
246
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
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
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
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
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
3
4
5
6
7
8
9
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
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
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
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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 ;
// Taille x3 !
monSuperTexte . scaleX = 3 ;
monSuperTexte . scaleY = 3 ;
254
255
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 ) ;
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
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
3
4
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
Cela signifie que lon peut accder la scne principale depuis notre classe Main
comme ceci :
1
2
3
4
5
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
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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
[ SWF ( width = " 640 " , height = " 480 " , backgroundColor = " # ffffff " ) ]
261
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
Sans oublier dimporter la classe TextFieldAutoSize (qui contient les valeurs autorises
pour lattribut autoSize) :
1
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.
263
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
266
5
6
7
8
9
10
11
// Activons la bordure
monSuperTexte . border = true ;
12
13
14
15
16
17
18
19
20
21
22
Nous pouvons compacter la dernire partie de notre code qui permet de centrer le
champ de texte :
1
2
3
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
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
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
3
4
5
6
7
8
9
10
// Mise en forme
format . size = 42 ;
format . font = " Arial " ;
format . color = 0x0000ff ;
11
12
13
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
27
28
29
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 )
3
4
5
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 ;
3
4
5
3
4
5
6
7
8
9
10
11
// Mise en forme
format . size = 42 ;
format . font = " Arial " ;
format . color = 0x0000ff ;
format . bold = true ;
271
12
13
14
15
16
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
30
31
32
33
34
// ...
35
36
37
38
39
40
41
42
43
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
3
4
format . size = 72 ;
5
6
7
3
4
5
format . size = 72 ;
format . letterSpacing = 3 ;
6
7
8
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
273
9
10
11
12
13
// Je cr le format
format = new TextFormat () ;
format . color = 0x0000ff ;
format . italic = false ;
14
15
16
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
2
3
4
274
LA MISE EN FORME
5
6
7
8
9
10
11
addChild ( monSuperTexte ) ;
12
13
14
15
// Centre
monSuperTexte . x = ( stage . stageWidth - monSuperTexte . width ) / 2 ;
monSuperTexte . y = ( stage . stageHeight - monSuperTexte . height ) /
2;
275
Le champ de texte est peut-tre un peu trop troit, augmentons sa largeur (avant le
code qui le centre) :
1
2
3
4
5
6
// Centre
monSuperTexte . x = ( stage . stageWidth - monSuperTexte . width ) / 2 ;
monSuperTexte . y = ( stage . stageHeight - monSuperTexte . height ) /
2;
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
LA MISE EN FORME
1
3
4
5
// Texte justifi
format . align = TextFormatAlign . JUSTIFY ;
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 . " ;
278
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 >
Reprenons lexemple des balises imbriques pour voir ce que cela donnerait :
1
2
3
4
5
6
< balise > Quel temps fera -t - il demain ? </ balise >
< 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
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 . ';
Balises principales
Retour la ligne
Pour effectuer un retour la ligne dans un texte HTML, nous utiliserons la balise
<br/> comme ceci :
1
280
monSuperTexte . htmlText = ' <p align =" right " > Lorem ipsum dolor
sit amet , consectetur adipiscing elit . In pharetra magna
imperdiet elit pretium a malesuada nisl pellentesque . </p > ';
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 > ';
281
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
monSuperTexte . htmlText = ' Voici Zozor ! < img src =" zozor . png "
width =" 150 " height =" 150 " align =" right "/ > ';
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
' <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 > ';
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 > ';
284
Italique
Pour mettre le texte en italique, cest tout aussi simple : seule la balise change. Cette
fois, il sagit de <i>...</i> :
1
Souligner
Il est possible de souligner du texte grce la balise <u>...</u> comme ceci :
1
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
Nom du fichier
Walkway_SemiBold.ttf
Walkway_UltraBold.ttf
Walkway_Oblique_SemiBold.ttf
Walkway_Oblique_UltraBold.ttf
289
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 ;
10
11
12
13
14
15
16
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
45
46
47
48
291
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 ) ]
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
Lattribut fontName spcifie le nom de la police de caractre, nom qui nous servira
lutiliser ensuite.
1
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
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
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
293
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
/* *
* Notre application embarque des polices de caract res
embarqu es !
*/
[ SWF ( width = " 640 " , height = " 480 " , backgroundColor = " # ffffff " ) ]
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// Polices embarqu es
EmbedFonts . init () ;
36
37
294
4
5
6
Voici le code complet pour afficher un champ de texte avec une police de caractres
embarque :
1
2
3
4
5
6
7
8
9
10
11
12
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;
296
// Polices embarqu es
EmbedFonts . init () ;
3
4
5
6
7
8
9
10
11
12
13
14
15
// Alignement au centre
monSuperTexte . x = ( stage . stageWidth - monSuperTexte . width ) / 2 ;
monSuperTexte . y = ( stage . stageHeight - monSuperTexte . height ) /
2;
4
5
6
7
8
9
297
298
299
10
11
12
13
14
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).
// 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
300
301
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
303
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) !
304
LOBJET GRAPHICS
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.
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
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
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
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
307
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.
Si vous lancez votre projet, vous verrez apparatre la belle ligne visible la figure 15.6.
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
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
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
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
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
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
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 ) ;
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
Vous verrez alors deux disques de couleur bleu dont lintersection est non remplie
comme sur la figure 15.8.
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.
package
{
import flash . display . Sprite ;
import flash . events . Event ;
import flash . display . Shape ;
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
314
27
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
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
// 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.
1
2
3
4
5
6
7
Voici donc notre mouton qui commence doucement prendre forme comme le montre
la figure 15.14.
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
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).
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
// 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) !
320
// 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.
Code final
Pour terminer ce chapitre, je vous ai rcrit lintgralit du code afin que vous puissiez
effectuer vos propres tests.
1
package
321
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 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 ) ;
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
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
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
326
Chapitre
16
327
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
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
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
Dclaration et initialisation
Comme toute classe, un objet Matrix sinitiale grce au constructeur de la classe
dans une variable. Voici donc comment procder :
1
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
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.
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
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
332
CRATION DE DGRADS
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
333
// 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.
334
Pour que vous puissiez mieux comparer les effets des diffrentes transformations, voici,
la figure 16.4, loriginal que nous venons de crer.
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
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 ) ;
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 ) ;
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
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.
Les oprations sont donc insres en une seule fois lintrieur de la matrice et produisent la figure 16.7.
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
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
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
341
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
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.
package
{
/* *
* Librairie contenant nos images embarqu es .
* @author Guillaume CHAU
*/
public class ImageLibrary
{
9
10
343
11
12
13
14
15
// 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
4
5
6
7
// Alignement au centre
zozor . x = ( stage . stageWidth - zozor . width ) / 2 ;
zozor . y = ( stage . stageHeight - zozor . height ) / 2 ;
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
345
346
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
4
5
6
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 ;
348
4
5
6
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 ;
Figure 17.10 Tout objet de la classe Bitmap dispose dun attribut bitmapData de
la classe BitmapData
350
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 ) ;
Ne nous arrtons pas l et crons notre premire image grce la classe BitmapData :
1
2
352
Il existe une deuxime pipette qui nous renvoie la couleur dun pixel avec son opacit :
getPixel32(x, y).
1
2
3
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
354
4
5
6
7
8
9
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
18
19
20
// Couleur al atoire
couleur = Math . random () * 0xffffff ;
21
22
23
24
25
// /// Barbouillage v 2 . 0
// On d finit d ' abord les couleurs possibles
var couleurs : Array = [ 0xff0000 , 0x00ff00 , 0x0000ff ];
4
5
6
7
8
356
9
10
11
12
13
14
// Couleur choisie
couleur = couleurs [ choix ];
15
16
17
18
19
20
21
// /// Barbouillage v 3 . 0
// On d finit d ' abord les couleurs possibles
var couleur : uint ;
var couleurs : Array = [ 0xff0000 , 0x00ff00 , 0x0000ff ];
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Couleur choisie
couleur = couleurs [ choix ];
21
22
23
358
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
360
Chapitre
18
361
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.
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.
362
LES FILTRES
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
Correction colorimtrique
1
2
3
4
5
6
Rouge
Vert
Bleu
= new ColorMatrixFilter
363
Nous obtenons ainsi notre image avec une correction de couleur et un flou comme le
montre la figure 18.3.
Ombres portes
Les ombres portes sont dfinies grce la classe DropShadowFilter :
1
2
3
4
365
Nous retrouvons ici des proprits semblables celles que nous avons dj vu prcdemment, auxquelles vous pouvez en ajouter de nouvelles :
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
366
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
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
367
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.
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
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]
salpha
A[3]
A[8]
A[13]
A[18]
A[4]
A[9]
A[14]
A[19]
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
Rouge
Vert
Bleu
= new ColorMatrixFilter
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
370
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
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
372
new Array () ;
0);
-1 ) ,
0);
373
new Array () ;
0);
-1 ) ,
0);
374
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.
375
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.
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.
Une autre manire de grer lopacit de certaines zones dun lment est
lutilisation de masques, comme nous le verrons dans le chapitre suivant.
377
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 ;
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.
constante ADD :
1
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
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
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
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
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.
5
6
7
8
9
10
11
12
Nous avons ici plac lobjet masque au premier plan, ce qui donne la figure 19.2.
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).
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.
391
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
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
394
395
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.
// 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.
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
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
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 ') ]
399
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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
52
53
54
55
56
57
58
59
60
61
62
63
400
// Animation de la lampe
lampe . startDrag ( true ) ;
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
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
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
Dans linstruction prcdente, maMethode reprsente une mthode, donc de type Function,
et intervalle correspond au temps espaant deux excutions conscutives de la fonction prcdente.
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 .
406
LA CORRECTION
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
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 ;
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
Sachant que nos flocons ne tomberont pas tous la mme vitesse, nous allons donc
crer un attribut _vitesse pour retenir celle-ci :
1
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
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
409
// Tableau de Flocon
private var mesFlocons : 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
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
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
410
LA CORRECTION
5
6
7
8
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
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
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
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
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
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.
413
// 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
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
// 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.
package
{
import flash . display . Shape ;
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
La classe Neige
Neige.as
1
2
3
4
5
6
package
{
import
import
import
import
7
8
9
10
11
12
13
14
15
415
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
416
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
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
417
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
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 :
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
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
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.
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
Nanmoins, dans un premier temps, nous allons laisser de ct les paramtres facultatifs. Ce qui nous donne donc :
1
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
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
426
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
427
Si vous souhaitez tester cet exemple, vous pouvez alors excuter linstruction suivante
aprs avoir dfini les deux fonctions prcdentes :
uneFonction ( true , fonctionDeRappel ) ;
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
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
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
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
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
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 !
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
431
LE FLUX DVNEMENTS
tous les mcanismes du flux dvnements, nous allons maintenant raliser quelques
manipulations.
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
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
433
Appliquons alors cette fonction dcouteur nos deux objets voiture et roue2, pour
les vnements de type MouseEvent.CLICK :
1
2
3
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
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
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
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
Ce qui donne :
v nement de type click
Cible de l v nement [ object Stage ]
436
LOBJET EVENT
Maintenant, enregistrons un couteur pour chacune des phases du flux dvnements :
1
2
3
4
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
437
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
439
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).
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
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.
// 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
36
37
38
39
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 ?
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
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 ) ;
445
souris
bouton
bouton
bouton
bouton
bouton
souris
souris
souris
souris
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
446
LA SOURIS
10
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 () ;
447
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
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
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
Un curseur natif ne peut pas dpasser une taille de 32 pixels sur 32 pixels.
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
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
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
Comme un curseur natif ne peut dpasser une taille de 32 pixels de ct, nous allons
rduire la taille du 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
apercu . scaleX = 4 ;
apercu . scaleY = apercu . scaleX ;
451
Ensuite, il nous faut un vecteur contenant une ou plusieurs images (ici nous lui insrons
la capture du viseur) :
1
2
3
4
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
Enfin, il faut enregistrer notre curseur natif en lui donnant un nom, grce la
mthode statique registerCursor de la classe Mouse :
1
2
Et voil que notre curseur de souris sest transform en viseur, comme le montre la
figure 22.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
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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
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.
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.
457
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
27
28
29
458
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
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
3
4
5
6
// Formatage du texte
var format : TextFormat = new TextFormat ( " Arial " , 14 , 0x000000 ) ;
monSuperTexte . defaultTextFormat = format ;
7
8
9
10
11
12
13
// Taille
monSuperTexte . width = 200 ;
monSuperTexte . height = 20 ;
14
459
// Centrage
monSuperTexte . x = ( stage . stageWidth - monSuperTexte . width ) / 2 ;
monSuperTexte . y = ( stage . stageHeight - monSuperTexte . height ) /
2;
18
19
20
21
22
23
24
25
26
Je peux maintenant crire ce que je veux dans le champ de texte ditable, comme le
montre la figure 22.9.
CHAMPS DE SAISIE
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.
Si vous entrez des caractres alphabtiques, ceux-ci sont alors automatiquement saisis
en majuscule comme vous voir sur la figure 22.13.
prsent, si vous saisissez du texte, le contenu du champ de texte sera remplac par
une srie de * , comme sur la figure 22.14.
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 :
Si vous entrez du texte dans notre champ de saisie, vous obtiendrez une sortie similaire
dans la console :
C
Ce
Cec
Ceci
463
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.
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
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
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
C
e
c
i
e
s
t
m
a
s
a
i
s
i
e
!
466
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.
Nom.
Prnom.
Date de naissance.
Lieu de naissance.
package
{
import
import
import
import
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
468
CHAMPS DE SAISIE
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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
472
Chapitre
23
473
[ 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 ;
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
Au final, nous obtenu un objet en perptuelle rotation comme illustr sur limage 23.2.
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
En lanant lanimation, vous verrez alors notre carr se flouter progressivement puis se
figer au bout dun certain temps, comme sur limage 23.3.
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
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
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.
LUTILISATION DE TIMER
package
{
import flash . display . Sprite ;
import flash . display . Shape ;
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package
{
import flash . display . Shape ;
4
5
6
479
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
480
LUTILISATION DE TIMER
6
7
8
9
10
11
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
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
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
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
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
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
1
2
3
4
5
484
485
8
9
10
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
Nous pouvons aussi crire lobjet sous forme abrge avec des accolades :
486
Lorsque la souris sortira du carr, on animera son opacit vers sa valeur initiale de 1
(pleinement opaque) :
1
2
Il ne nous reste plus qu placer ces lignes dans les couteurs correspondants :
1
2
3
4
5
6
7
8
9
5
6
7
On peut, bien entendu, utiliser la forme abrge des tableaux pour rendre le code plus
facile crire et lire :
1
2
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
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
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
489
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
2
3
4
5
6
7
8
9
10
11
12
13
14
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
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
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 () ;
Enfin, la mthode kill permet darrter compltement lanimation qui est alors supprime :
animation . kill () ;
Ainsi, il nous est possible danimer cet attribut laide dune nouvelle animation :
1
2
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
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
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.
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.
497
La figure 24.3 nous confirme que les objets obj1 et obj2 se chevauchent bien.
obj2 . y = 100 ;
trace ( obj1 . hitTestObject ( obj2 ) ) ; // Affiche : false
498
499
500
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
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
}
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
501
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
503
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.
504
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
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
505
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
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
506
4
5
6
7
8
9
10
11
12
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
507
4
5
6
7
8
9
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.
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
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
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
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
510
23
24
25
26
27
28
29
30
31
}
return collision ;
32
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
511
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
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.
514
OBJECTIFS
515
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
517
package
{
public class Constantes
{
public static var restitution : Number = 0 . 85 ;
public static var frottement : Number = 0 . 007 ;
}
}
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
/* *
* Calcule et renvoie la distance ( en pixels ) entre deux objets
.
* @param
obj1
* @param
obj2
* @return
Distance en pixels
*/
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
PRPARATION ET CONSEILS
521
522
PRPARATION ET CONSEILS
Voici les 16 couleurs rglementaires des billes dans lordre (la bille numro zro est la
bille blanche) :
1
523
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
];
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
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).
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 )
];
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).
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
Le fond
Le fond de notre scne sera un dessin couvrant la taille de la fentre rempli avec cette
texture (figure 25.19).
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
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
14
15
16
17
18
19
20
21
_calculAngleModule () ;
22
23
24
25
26
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
}
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
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
161
162
163
164
165
166
167
168
531
169
170
171
172
173
174
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
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
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
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
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
2
3
4
5
6
7
8
9
10
11
12
13
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
25
26
27
28
29
30
31
32
33
534
ORGANISATION DE LAPPLICATION
34
35
36
37
var
var
var
var
v1n : Number
v1g : Number
v2n : Number
v2g : Number
=
=
=
=
nx
gx
nx
gx
*
*
*
*
38
39
40
41
42
43
44
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
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
14
15
16
17
18
19
20
21
22
/* PRIVE */
23
24
25
26
27
28
29
/* GETTERS */
30
31
32
33
34
35
36
37
38
39
40
41
_dessiner () ;
42
43
44
45
46
47
48
49
50
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 ;
61
62
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
540
// Infos de
private var
private var
private var
bases
_couleur : uint ;
_numero : int ;
_masse : Number ;
5
6
7
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 ;
/* *
* 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
29
30
/* *
541
37
38
39
40
41
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
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
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 )
];
17
18
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
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
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
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
6
7
8
9
10
11
12
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
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
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
27
28
29
30
31
32
33
34
35
36
37
38
39
545
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 ) ;
}
}
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
*/
public function deplacer ( multiplicateur : Number = 1 ) : void
{
x += _velocite . x * multiplicateur ;
y += _velocite . y * 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;
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
547
3
4
5
6
7
8
9
10
11
12
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
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
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 ) ;
/* *
* 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
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).
// Infos de base
private var _numero : int ;
3
4
5
6
7
8
9
// El ments visuels
private var _dessin : Shape ;
private var _poche : Shape ;
550
super () ;
5
6
7
8
9
10
11
12
13
14
15
16
17
_numero = numero ;
Dessin du trou
Encore une fois, nous redfinissons la mthode _dessiner :
1
2
3
4
5
6
// Trou
_dessin . graphics . clear () ;
551
/* *
* 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
}
else
{
22
23
24
25
26
27
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
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
/* *
* 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
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
554
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
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
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
557
558
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
28
29
30
_majEtiquette () ;
31
32
33
34
/* *
* Indique si les indicateurs visuels sont visibles ou non .
*/
559
39
40
41
42
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
15
16
17
18
19
20
21
// Indicateurs
private var _simulationEnCours : Boolean = false ;
private var _phaseDeTir : Boolean = false ;
22
23
24
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
// Table
_table = new Table () ;
// Taille standard
_table . width = 2 . 34 * Unite . METRE ;
_table . height = 1 . 17 * Unite . METRE ;
addChild ( _table ) ;
// 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
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
// 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
6
7
8
9
562
// Ralenti
stage . addEventListener ( MouseEvent . MIDDLE_CLICK ,
onMiddleClick ) ;
2
3
4
5
6
7
8
9
10
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
/* Ralenti */
2
3
4
5
6
/* *
* 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
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
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
26
27
28
29
30
31
32
33
34
35
36
564
triangleLigne ++;
if ( triangleLigne == triangleLignes )
{
triangleLigne = 0 ;
triangleLignes ++;
triangleX += _billeDeTir . taille ;
_table . stopDrag () ;
_tableDrag = false ;
6
7
8
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
19
20
21
22
23
24
25
26
27
565
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
4
5
6
5
6
566
// Gestion de la souris
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
5
6
7
8
9
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
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
567
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
7
8
9
568
10
11
12
13
14
15
16
17
18
19
20
21
22
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
6
7
569
_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
Ajoutons tout de suite la mthode pour stopper cette phase de jeu (qui supprime
lcouteur dvnement) :
1
2
3
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
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
570
25
26
27
28
29
30
31
32
33
34
35
36
37
// Test de collition
bille1 . testerCollision ( bille2 ) ;
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
5
6
571
7
8
9
10
11
12
13
14
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
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
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
/* *
* 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
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
2
3
4
5
6
7
8
9
10
11
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
// Configuration de la sc ne
stage . align = StageAlign . TOP_LEFT ;
stage . scaleMode = StageScaleMode . NO_SCALE ;
4
5
6
// Polices embarqu es
EmbedFonts . init () ;
package
{
import
import
import
import
import
import
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
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
3
4
5
// 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
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
7
8
9
10
11
// Billard
_billard . x = ( stage . stageWidth - _billard . width ) * 0 . 5 ;
_billard . y = ( stage . stageHeight - _billard . height ) * 0 . 5 ;
Puis, ajoutons dans le code principal lcouteur la scne principale pour se dclencher
au redimensionnement (vnement Event.RESIZE) :
1
2
576
// 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
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.
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
578
Chapitre
26
579
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
581
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
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
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 ) ;
}
583
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 " ) ;
}
Comme prvu, les blocs try et finally ont t excuts et le seul bloc catch associ
au type TypeError a t excut.
584
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 =
package
{
import flash . display . DisplayObject ;
import flash . events . ErrorEvent ;
import flash . events . Event ;
6
7
8
9
10
11
12
13
14
586
16
_vars = null ;
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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
587
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
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
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
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).
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
10
11
12
13
14
15
16
17
18
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
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 ;
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
596
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 .
/* *
* 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 .
*/
/* *
*
* @param vecteur
* @param apply
* @return
*/
public function ajouter ( vecteur : Vecteur2D , apply : Boolean =
false ) : Vecteur2D
{
// ...
}
Bien videmment, il en existe dautres, je vous laisserai les dcouvrir par vous-mmes !
601
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