programmez en actionscript 3

628

Upload: abdo-dz

Post on 18-Jul-2016

76 views

Category:

Documents


24 download

DESCRIPTION

Programmez en Actionscript 3

TRANSCRIPT

Page 1: Programmez en Actionscript 3
Page 2: Programmez en Actionscript 3
Page 3: Programmez en Actionscript 3
Page 4: Programmez en Actionscript 3
Page 5: Programmez en Actionscript 3

Sauf mention contraire, le contenu de cet ouvrage est publié sous la licence :Creative Commons BY-NC-SA 2.0

La copie de cet ouvrage est autorisée sous réserve du respect des conditions de la licence.Texte complet de la licence disponible sur : http : //creativecommons.org/licenses/by-nc-sa/2.0/fr/

Mentions légalesConception couverture : amalgam impression

Illustrations chapitres : Fan Jiyong et Alexandra PersilOpenClassrooms 2014 - ISBN : 979-10-90085-64-0

Page 6: Programmez en Actionscript 3

Avant-propos

S i vous lisez ces lignes, c’est que vous avez très certainement envie d’apprendreà programmer en Actionscript 3. Il s’agit du langage de programmation de pré-dilection pour concevoir des applications Adobe Flash, applications notamment

très répandues sur Internet, sous forme de jeux interactifs, de lecteurs de vidéos, debannières publicitaires. . .

Contrairement aux idées préconçues, l’Actionscript ne se cantonne pas uniquement àla réalisation de « vulgaires » animations. Il est possible de concevoir des applicationsen ligne visuellement très avancées ou de vrais logiciels de bureau à l’aide de Flash.L’arrivée de Adobe Air et Flex a également énormément contribué au déploiement de latechnologie Flash vers de nouvelles plateformes, telles que les terminaux mobiles iOS,Android ou BlackBerry. Initialement, Flash a été conçu pour réaliser des animationsvectorielles, au travers du logiciel Flash Professional édité par la société Adobe. Depuisla version 3, l’Actionscript est devenu un langage de programmation à part entière,et il est maintenant possible de concevoir des applications Flash sans avoir recours àce logiciel. Cet ouvrage s’intéresse justement à l’apprentissage de ce langage, en utili-sant essentiellement des outils gratuits et accessibles à tous. Certains d’entre vous sedemandent peut-être si l’Actionscript est un bon choix pour commencer la program-mation ? Grâce à sa documentation fournie et ses concepts haut niveau, ce langagede programmation est tout à fait accessible aux débutants. De plus, les possibilitésqu’offre ce langage sont vastes, et le rendu des applications intéresseront à coup sûr lesdéveloppeurs plus expérimentés. N’hésitez donc pas à vous lancer dès maintenant à ladécouverte de ce merveilleux langage qu’est l’Actionscript 3 !

Qu’allez-vous apprendre en lisant ce livre ?

Le plan de ce livre a été pensé en partant du principe que le lecteur est un parfaitnovice en programmation : ce cours se veut progressif et accessible à tous. Voici lesdifférentes parties qui vous attendent dans cet ouvrage.

1. Les bases de l’Actionscript : cette première partie est une introduction à laprogrammation et au langage Actionscript 3. Nous verrons ce qu’est réellementl’Actionscript 3 et quels sont les outils indispensables pour suivre ce cours. Unefois ces derniers en place, nous commencerons à étudier les fondamentaux de la

i

Page 7: Programmez en Actionscript 3

CHAPITRE 0. AVANT-PROPOS

programmation : les variables, les conditions, les boucles, les fonctions...

2. La programmation orientée objet : au cours de cette partie, nous aborderonsun concept incontournable en Actionscript 3, la programmation orientée objet.Il s’agit d’une manière de concevoir et de structurer le code au sein d’un projet.En organisant les programmes sous forme d’objets, le développement de logicielsdevient plus efficace et intuitif. Nous aborderons les notions de classes, d’héri-tage, de polymorphisme, d’interfaces... Un chapitre sur des notions avancées laprogrammation orientée objet en fin de partie vous permettra d’approfondir vosconnaissances.

3. L’affichage : tout au long de cette partie, nous découvrirons comment réaliserdu contenu visuel, qui a fait toute la réputation des applications Flash. Nousverrons notamment comment utiliser du texte et des images, mais surtout, nousapprendrons à dessiner des graphismes vectoriels directement à partir du langagede programmation. Un TP vous attend en fin de partie, et vous permettra devous exercer.

4. Interaction et animation : animer le contenu et le rendre interactif n’est paschose aisée. Néanmoins avec de précieux conseils et quelques astuces, vous par-viendrez à créer les applications dynamiques et attrayantes. Pour vous le prouver,nous réaliserons à travers un TP un véritable jeu de billard américain. Vous pren-drez alors conscience que vous avez déjà atteint un excellent niveau !

5. Annexes : avant de vous laissez explorer de nouveaux horizons par vous-mêmes,nous reviendrons dans cette partie sur quelques règles et astuces de bonnes pra-tiques à adopter.

Comment lire ce livre ?

Suivez l’ordre des chapitres

Lisez ce livre comme on lit un roman. Il a été conçu pour cela.

Contrairement à beaucoup de livres techniques où il est courant de lire en diagonale etde sauter certains chapitres, il est ici très fortement recommandé de suivre l’ordre ducours, à moins que vous ne soyez déjà un peu expérimentés.

Pratiquez en même temps

Pratiquez régulièrement l’Actionscript 3. N’attendez pas d’avoir fini la lecture de celivre pour allumer votre ordinateur et faire vos propres essais ; n’hésitez pas à mo-difier les codes donnés en exemples, afin de bien cerner le comportement de chaqueinstruction. Plus vous vous exercerez, et plus l’apprentissage sera rapide et efficace.

ii

Page 8: Programmez en Actionscript 3

REMERCIEMENTS

Utilisez les codes web !

Afin de tirer parti d’OpenClassrooms, dont ce livre est issu, celui-ci vous propose cequ’on appelle des « codes web ». Ce sont des codes à six chiffres à saisir sur une paged’OpenClassrooms pour être automatiquement redirigé vers un site web sans avoir àen recopier l’adresse.

Pour utiliser les codes web, rendez-vous sur la page suivante :

http://www.openclassrooms.com/codeweb

Un formulaire vous invite à rentrer votre code web. Faites un premier essai avec le codeci-dessous :

B

�Tester le code web

Code web : 123456Ces codes web ont deux intérêts :

– ils vous redirigent vers les sites web présentés tout au long du cours, vous permettantainsi d’obtenir les logiciels dans leur toute dernière version ;

– ils vous permettent d’afficher les codes sources inclus dans ce livre, ce qui vous éviterad’avoir à recopier certains programmes un peu longs.

Ce système de redirection nous permet de tenir à jour le livre que vous avez entre lesmains sans que vous ayez besoin d’acheter systématiquement chaque nouvelle édition.Si un site web change d’adresse, nous modifierons la redirection mais le code web àutiliser restera le même. Si un site web disparaît, nous vous redirigerons vers une paged’OpenClassrooms expliquant ce qui s’est passé et vous proposant une alternative.

En clair, c’est un moyen de nous assurer de la pérennité de cet ouvrage sans que vousayez à faire quoi que ce soit !

Remerciements

Nous tenons à remercier toutes les personnes qui nous ont aidées et soutenues dans laréalisation de ce livre.

Guillaume Chau

Je souhaite remercier :– Ma famille et mes proches pour leur soutien et leurs encouragements inestimables,– Guillaume Lapayre pour m’avoir soutenu dans le projet, aidé à rédiger le cours etmotivé à aller de l’avant,

– Jonathan Baudoin pour son suivi et sa relecture minutieuse, ainsi que son engagementauprès de nous dans le projet,

– Mathieu Nebra, Pierre Dubuc et toute l’équipe de Simple IT pour avoir créé laplate-forme OpenClassrooms nous ayant permis d’écrire cet ouvrage,

– Mais surtout, tous les lecteurs pour leurs questions et leurs encouragements !

iii

Page 9: Programmez en Actionscript 3

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 m’engage,

– Guillaume Chau pour m’avoir fait confiance et m’avoir permis de travailler à sescôtés et contribuer à la rédaction de cet ouvrage,

– Jonathan Baudoin pour avoir cru en ce projet, pour le temps passé à la relecture cecours, et pour avoir supporté nos nombreux coups de flemme,

– Mathieu Nebra et Pierre Dubuc, et toute l’équipe de Simple IT, sans lesquels cetouvrage n’aurait jamais vu le jour,

– Enfin, tous les lecteurs pour leurs encouragements et l’intérêt qu’ils portent à cecours.

iv

Page 10: Programmez en Actionscript 3

Table des matières

Avant-propos i

Qu’allez-vous apprendre en lisant ce livre ? . . . . . . . . . . . . . . . . . . . . i

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

Suivez l’ordre des chapitres . . . . . . . . . . . . . . . . . . . . . . . . . ii

Pratiquez en même temps . . . . . . . . . . . . . . . . . . . . . . . . . . ii

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

Remerciements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iii

Guillaume Chau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iii

Guillaume Lapayre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iv

I Les bases de l’Actionscript 1

1 Vous avez dit « Actionscript » ? 3

Adobe Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

Présentation de Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

Un peu d’histoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

Les dérivés de Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

Quelques exemples d’utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . 6

Le dynamisme apporté au web par l’Actionscript . . . . . . . . . . . . . 6

Création de sites web orientés vers le visuel . . . . . . . . . . . . . . . . 7

Introduction d’Adobe Air . . . . . . . . . . . . . . . . . . . . . . . . . . 8

L’Actionscript 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

v

Page 11: Programmez en Actionscript 3

TABLE DES MATIÈRES

Orienté objet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

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

Évènementiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

2 Votre premier programme avec Flex SDK 11

Préambule . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

Le compilateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

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

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

Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

Flex SDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

Version de débogage du lecteur Flash . . . . . . . . . . . . . . . . . . . . 19

Créer les sources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

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

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

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

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

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

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

FlashDevelop à la rescousse ! . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

Téléchargement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

Un peu de paramétrage . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

Créons un projet Actionscript . . . . . . . . . . . . . . . . . . . . . . . . 43

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

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

3 Les variables 51

Déclarer et utiliser des variables . . . . . . . . . . . . . . . . . . . . . . . . . . 52

Déclaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

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

Les nombres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

Les différents types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

Opérations sur les nombres . . . . . . . . . . . . . . . . . . . . . . . . . 56

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

vi

Page 12: Programmez en Actionscript 3

TABLE DES MATIÈRES

Les chaînes de caractères . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

Échappement des caractères spéciaux . . . . . . . . . . . . . . . . . . . . 60

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

Concaténation de chaînes . . . . . . . . . . . . . . . . . . . . . . . . . . 62

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

4 Les conditions 67

Écriture d’une condition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68

Qu’est-ce qu’une condition ? . . . . . . . . . . . . . . . . . . . . . . . . . 68

Les opérateurs relationnels . . . . . . . . . . . . . . . . . . . . . . . . . . 68

Les opérateurs logiques . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

La priorité des opérateurs . . . . . . . . . . . . . . . . . . . . . . . . . . 71

L’instruction if. . .else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

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

Le type booléen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

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

L’instruction switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

L’utilisation conventionnelle . . . . . . . . . . . . . . . . . . . . . . . . . 76

Une utilisation spécifique à l’Actionscript . . . . . . . . . . . . . . . . . 77

5 Les boucles 79

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

Le principe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

Écriture en Actionscript . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

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

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

Présentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

6 Les fonctions 87

Concept de fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88

Le principe de fonctionnement . . . . . . . . . . . . . . . . . . . . . . . 88

Présentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

Création et appel de fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

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

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

vii

Page 13: Programmez en Actionscript 3

TABLE DES MATIÈRES

Quelques exemples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92

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

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

Calcul d’un maximum . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93

7 Les tableaux 97

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

Création . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98

Les éléments du tableau . . . . . . . . . . . . . . . . . . . . . . . . . . . 98

Propriétés du type Array . . . . . . . . . . . . . . . . . . . . . . . . . . 99

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

Déclaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100

Gestion des éléments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

Les tableaux multidimensionnels . . . . . . . . . . . . . . . . . . . . . . . . . 102

Le concept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102

Un peu de pratique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

Parcourir un tableau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105

La boucle for classique . . . . . . . . . . . . . . . . . . . . . . . . . . . 105

La boucle for...in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105

La boucle for each . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

II La Programmation Orientée Objet 109

8 La POO dans tous ses états 111

Les notions-clés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

Il était une fois. . . un objet . . . . . . . . . . . . . . . . . . . . . . . . . 112

L’Objet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

La Classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

Un autre exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

L’encapsulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

L’héritage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

Manipuler des objets : les chaînes de caractères . . . . . . . . . . . . . . . . . 118

L’horrible secret du type String . . . . . . . . . . . . . . . . . . . . . . 118

Créer un objet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118

viii

Page 14: Programmez en Actionscript 3

TABLE DES MATIÈRES

Accéder aux propriétés d’un objet . . . . . . . . . . . . . . . . . . . . . 121

Des pointeurs sous le capot . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121

Plantons le décor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121

Explications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

9 Les classes (1ère partie) 125

Créer une classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126

La Classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126

Construire la classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127

Des paramètres facultatifs pour nos méthodes . . . . . . . . . . . . . . . . . . 130

La surcharge de méthodes . . . . . . . . . . . . . . . . . . . . . . . . . . 130

Les paramètres facultatifs . . . . . . . . . . . . . . . . . . . . . . . . . . 131

Encapsulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132

Les différents droits d’accès . . . . . . . . . . . . . . . . . . . . . . . . . 132

Les accesseurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133

Exercice : Créons notre première classe . . . . . . . . . . . . . . . . . . . . . . 139

Présentation de la classe . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

Écriture du code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140

La classe complète . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142

10 Les classes (2nde partie) 145

Les éléments statiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146

Les variables statiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146

Les méthodes statiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147

Une nouvelle sorte de « variable » : la constante ! . . . . . . . . . . . . . . . . 148

Présentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148

Intérêt des constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

Un objet dans un objet (dans un objet. . .) . . . . . . . . . . . . . . . . . . . . 150

Le problème du pétrole . . . . . . . . . . . . . . . . . . . . . . . . . . . 150

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

Exercice : Jeu de rôle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157

Présentation de l’exercice . . . . . . . . . . . . . . . . . . . . . . . . . . 157

Solution initiale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158

Une nouvelle classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

La bonne solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169

ix

Page 15: Programmez en Actionscript 3

TABLE DES MATIÈRES

11 L’héritage 175

La notion d’héritage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176

Construction d’un héritage . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177

La portée protected . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178

Construction des sous-classes . . . . . . . . . . . . . . . . . . . . . . . . 178

La substitution d’une sous-classe à une superclasse . . . . . . . . . . . . 182

Le polymorphisme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183

Les attributs de classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184

Les différents droits d’accès . . . . . . . . . . . . . . . . . . . . . . . . . 185

Exemple d’utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185

12 Notions avancées de la POO 189

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

Définition de la classe de base . . . . . . . . . . . . . . . . . . . . . . . . 190

Définition de propriétés hors de la classe . . . . . . . . . . . . . . . . . . 191

Les interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192

Problème . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192

Utilisation des interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . 193

Plus loin avec les interfaces . . . . . . . . . . . . . . . . . . . . . . . . . 198

Les classes abstraites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200

Le concept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200

Application à l’ActionScript 3 . . . . . . . . . . . . . . . . . . . . . . . . 201

Les types inconnus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203

Déterminer si un objet est une occurrence d’une certaine classe . . . . . 203

Des paramètres de type inconnu . . . . . . . . . . . . . . . . . . . . . . 204

Accéder dynamiquement aux propriétés . . . . . . . . . . . . . . . . . . . . . 206

Les objets anonymes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209

Créer un objet anonyme . . . . . . . . . . . . . . . . . . . . . . . . . . . 209

Les fonctions anonymes . . . . . . . . . . . . . . . . . . . . . . . . . . . 214

III L’affichage 215

13 Les objets d’affichage 217

Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218

x

Page 16: Programmez en Actionscript 3

TABLE DES MATIÈRES

Les couleurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218

L’affichage sur un écran . . . . . . . . . . . . . . . . . . . . . . . . . . . 221

L’arbre des objets d’affichage . . . . . . . . . . . . . . . . . . . . . . . . . . . 223

L’arbre d’affichage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223

Les classes d’affichage . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225

Manipuler les conteneurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228

Buvez du Sprite ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229

Ajouter des enfants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229

Afficher un objet sur la scène principale . . . . . . . . . . . . . . . . . . 230

L’index d’affichage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233

Ajouter un enfant à un index précis . . . . . . . . . . . . . . . . . . . . 234

Opérations sur les enfants . . . . . . . . . . . . . . . . . . . . . . . . . . 235

Retirer des enfants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237

Propriétés utiles des objets d’affichage . . . . . . . . . . . . . . . . . . . . . . 238

Position . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238

Un mot sur l’origine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239

Taille . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242

Rotation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243

Transparence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244

Supprimer un objet d’affichage de la mémoire . . . . . . . . . . . . . . . . . . 245

14 Afficher du texte 249

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

La classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250

Utilisation de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251

Sélection du texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256

Centrer le champ de texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258

Un mot sur la scène principale . . . . . . . . . . . . . . . . . . . . . . . 258

Adapter la taille du champ de texte au texte . . . . . . . . . . . . . . . 262

Modifier la position du champ de texte . . . . . . . . . . . . . . . . . . . 264

La mise en forme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268

Formatons notre champ de texte . . . . . . . . . . . . . . . . . . . . . . 268

Gestion du multi-ligne . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274

En HTML dans le texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278

xi

Page 17: Programmez en Actionscript 3

TABLE DES MATIÈRES

Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278

Balises principales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280

Balises de mise en forme . . . . . . . . . . . . . . . . . . . . . . . . . . . 285

Les polices de caractères embarquées . . . . . . . . . . . . . . . . . . . . . . . 287

Embarquer des polices . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287

Rotation sur soi-même . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297

15 Dessiner avec l’Actionscript 303

L’objet Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304

Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304

Des contours et des remplissages . . . . . . . . . . . . . . . . . . . . . . 306

Dessinez, c’est gagné ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308

Les lignes et les courbes . . . . . . . . . . . . . . . . . . . . . . . . . . . 308

Les formes prédéfinies . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310

Techniques avancées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311

Exercice : Dessine-moi un mouton . . . . . . . . . . . . . . . . . . . . . . . . 314

Conception du dessin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314

Code final . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321

16 Utilisation des matrices 327

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

Introduction aux matrices . . . . . . . . . . . . . . . . . . . . . . . . . . 328

L’objet Matrix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330

Création de dégradés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330

Présentation des dégradés . . . . . . . . . . . . . . . . . . . . . . . . . . 331

Ajouter une matrice de description . . . . . . . . . . . . . . . . . . . . . 332

Exemple : création d’un bouton . . . . . . . . . . . . . . . . . . . . . . . 334

Les transformations matricielles . . . . . . . . . . . . . . . . . . . . . . . . . . 335

Un objet à transformer . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335

Création d’une matrice de transformation . . . . . . . . . . . . . . . . . 336

Pour finir avec les matrices . . . . . . . . . . . . . . . . . . . . . . . . . 338

17 Manipuler des images 341

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

Préparation de l’image . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342

xii

Page 18: Programmez en Actionscript 3

TABLE DES MATIÈRES

Librairie d’images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342

Afficher des images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344

La classe Bitmap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344

Redimensionnement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345

Opérations sur les images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349

La classe BitmapData . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349

Créer notre première image . . . . . . . . . . . . . . . . . . . . . . . . . 351

Dessiner sur des images . . . . . . . . . . . . . . . . . . . . . . . . . . . 351

18 Filtres et modes de fusion 361

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

Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362

Création d’un exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362

Ajout de filtres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363

Application des filtres . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364

Glossaire des filtres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364

Les filtres de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364

Correction de couleurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 368

Convolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372

Mappage de déplacement . . . . . . . . . . . . . . . . . . . . . . . . . . 375

Les modes de fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376

Définition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376

Mise en place . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378

Glossaire de modes de fusion . . . . . . . . . . . . . . . . . . . . . . . . . . . 378

Le mode de fusion par défaut . . . . . . . . . . . . . . . . . . . . . . . . 378

Les fusions de calques . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378

Les fusions de transparence . . . . . . . . . . . . . . . . . . . . . . . . . 384

19 Les masques 387

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

Le principe des masques . . . . . . . . . . . . . . . . . . . . . . . . . . . 388

Les masques en Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388

Niveaux de transparence multiples . . . . . . . . . . . . . . . . . . . . . . . . 390

Présentation du concept . . . . . . . . . . . . . . . . . . . . . . . . . . . 390

Place au code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391

xiii

Page 19: Programmez en Actionscript 3

TABLE DES MATIÈRES

Exercice : une lampe torche . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393

Préparation des images . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393

Mise en place du masque . . . . . . . . . . . . . . . . . . . . . . . . . . . 396

Projet final . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398

20 TP : Mauvais temps 403

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

L’objectif du chapitre . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404

Le travail à réaliser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405

Les images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406

La correction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407

La structure du programme . . . . . . . . . . . . . . . . . . . . . . . . . 407

La classe Flocon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408

La classe Neige . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409

La classe principale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412

Le code source complet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414

La classe Flocon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414

La classe Neige . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415

La classe principale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417

IV Interaction et animation 419

21 Les événements 421

Qu’est ce qu’un évènement ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422

Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422

Un jour au bureau. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422

Les écouteurs en POO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424

L’interface IEventDispatcher . . . . . . . . . . . . . . . . . . . . . . . 424

La classe EventDispatcher . . . . . . . . . . . . . . . . . . . . . . . . . 425

Mise en place d’un écouteur . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426

Introduction aux fonctions de rappel . . . . . . . . . . . . . . . . . . . . 426

Créer une fonction d’écouteur . . . . . . . . . . . . . . . . . . . . . . . . 428

Gérer les écouteurs d’un objet . . . . . . . . . . . . . . . . . . . . . . . . 429

Le flux d’événements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430

xiv

Page 20: Programmez en Actionscript 3

TABLE DES MATIÈRES

Présentation du concept de flux d’évènements . . . . . . . . . . . . . . . 430

Bien comprendre le fonctionnement . . . . . . . . . . . . . . . . . . . . . 433

L’objet Event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 435

Présentation de la classe Event . . . . . . . . . . . . . . . . . . . . . . . 435

Les propriétés liés au flux d’évènements . . . . . . . . . . . . . . . . . . 436

22 Interagir avec l’utilisateur 439

La souris . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440

L’objet MouseEvent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440

La technique du « glisser-déposer » . . . . . . . . . . . . . . . . . . . . . 446

Exercice : Créer et animer un viseur . . . . . . . . . . . . . . . . . . . . 447

Curseurs personnalisés . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449

Le clavier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455

L’objet KeyboardEvent . . . . . . . . . . . . . . . . . . . . . . . . . . . 455

Exercice : gérer l’affichage de l’animation . . . . . . . . . . . . . . . . . 457

Champs de saisie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459

Retour sur l’objet TextField . . . . . . . . . . . . . . . . . . . . . . . . 459

Évènements et TextField . . . . . . . . . . . . . . . . . . . . . . . . . . 463

Exercice : un mini formulaire . . . . . . . . . . . . . . . . . . . . . . . . 467

23 Animer des objets 473

L’animation par images-clés . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474

L’évènement Event.ENTER_FRAME . . . . . . . . . . . . . . . . . . . . . . 474

Créer une animation basique . . . . . . . . . . . . . . . . . . . . . . . . 474

L’utilisation de Timer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477

La classe Timer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477

Exercice : une horloge . . . . . . . . . . . . . . . . . . . . . . . . . . . . 478

Les interpolations avec TweenMax . . . . . . . . . . . . . . . . . . . . . . . . 482

La librairie TweenMax . . . . . . . . . . . . . . . . . . . . . . . . . . . . 482

Les bases de l’animation avec TweenMax . . . . . . . . . . . . . . . . . . 484

Utilisation avancée de TweenMax . . . . . . . . . . . . . . . . . . . . . . 488

24 Les collisions 495

Préambule . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 496

Définition d’une collision . . . . . . . . . . . . . . . . . . . . . . . . . . . 496

xv

Page 21: Programmez en Actionscript 3

TABLE DES MATIÈRES

Détecter des collisions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 496

La théorie des collisions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498

Collisions rectangulaires . . . . . . . . . . . . . . . . . . . . . . . . . . . 498

Collisions circulaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502

Collisions ponctuelles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 505

Les collisions de pixels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508

Utiliser l’opacité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508

Application en code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510

25 TP : Jeu de billard 513

Objectifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 514

Les règles de notre billard . . . . . . . . . . . . . . . . . . . . . . . . . . 514

Le déroulement d’une partie . . . . . . . . . . . . . . . . . . . . . . . . . 515

Consigne supplémentaire . . . . . . . . . . . . . . . . . . . . . . . . . . . 517

Préparation et conseils . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517

Préparation du projet . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517

Les différents éléments du jeu . . . . . . . . . . . . . . . . . . . . . . . . 520

Un peu de Maths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 527

Organiser son projet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535

Organisation de l’application . . . . . . . . . . . . . . . . . . . . . . . . . . . 535

La structure de l’application . . . . . . . . . . . . . . . . . . . . . . . . . 535

Description des différents classes . . . . . . . . . . . . . . . . . . . . . . 537

Création des classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537

Visuel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537

Bille . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539

Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 547

Trous . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 550

Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 554

Billard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 560

Main . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 573

Conclusion et améliorations possibles . . . . . . . . . . . . . . . . . . . . . . . 577

Sources du Billard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 577

Idées d’amélioration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 577

26 La gestion des erreurs 579

xvi

Page 22: Programmez en Actionscript 3

TABLE DES MATIÈRES

Les principes de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 580

Introduction à la gestion des erreurs . . . . . . . . . . . . . . . . . . . . 580

Les différents types d’erreurs d’exécution . . . . . . . . . . . . . . . . . . 580

Les erreurs synchrones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581

L’intruction throw . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581

L’instruction try...catch . . . . . . . . . . . . . . . . . . . . . . . . . . 583

Les erreurs asynchrones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585

Distribuer un objet ErrorEvent . . . . . . . . . . . . . . . . . . . . . . . 585

Gérer des événements d’erreurs . . . . . . . . . . . . . . . . . . . . . . . 585

Bien comprendre les deux approches . . . . . . . . . . . . . . . . . . . . . . . 586

Une classe utilisant les deux approches . . . . . . . . . . . . . . . . . . . 586

Intérêts des erreurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 589

V Annexes 591

27 Bonnes pratiques 593

La mémoire dans Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 594

Flash et la mémoire vive . . . . . . . . . . . . . . . . . . . . . . . . . . . 594

Le ramasse-miettes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 594

Préparer un objet pour la suppression . . . . . . . . . . . . . . . . . . . 594

Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 595

Les commentaires de documentation . . . . . . . . . . . . . . . . . . . . . . . 597

Ecrire un commentaire de documentation . . . . . . . . . . . . . . . . . 597

Générer la documentation de vos classes . . . . . . . . . . . . . . . . . . 598

xvii

Page 23: Programmez en Actionscript 3

TABLE DES MATIÈRES

xviii

Page 24: Programmez en Actionscript 3

Première partie

Les bases de l’Actionscript

1

Page 25: Programmez en Actionscript 3
Page 26: Programmez en Actionscript 3

Chapitre 1Vous avez dit « Actionscript » ?

Difficulté :

Pour commencer ce cours en douceur, voici une petite introduction pour vous présenter latechnologie Flash, ainsi que son langage de programmation principal, l’Actionscript 3 !

Pour ceux qui ne connaîtraient pas cette technologie, nous verrons ce qu’il est possible defaire en Flash ainsi que les différentes utilisations de celui-ci. Nous essaierons égalementde présenter les technologies Flex et Air qui peuvent servir à enrichir Flash. Quelquesexemples de projets Flash vous seront donnés afin que vous puissiez vous faire une idée despossibilités de l’Actionscript.

Ce chapitre d’introduction ne présente aucune difficulté, même si vous êtes un parfaitdébutant en programmation. Je vous rappelle que ce cours est rédigé avec une difficultéprogressive aussi, contentez-vous de lire celui-ci à votre rythme et tout ira bien !

3

Page 27: Programmez en Actionscript 3

CHAPITRE 1. VOUS AVEZ DIT « ACTIONSCRIPT » ?

Adobe Flash

Présentation de Flash

Flash est une technologie actuellement développée et soutenue par Adobe Systems(prononcez « adobi »).

Elle est principalement utilisée pour afficher des animations dynamiques et interactivesdans des pages web à travers le navigateur Internet. Elle permet, par exemple, d’ajouterune vidéo ou un jeu sur son site web, animer une galerie d’images, proposer une interfacedynamique pour un service ou un logiciel en ligne.

Un document Flash est un fichier sous le format swf (Shockwave Flash), et vous enavez sûrement ouvert plusieurs à chaque visite sur le web : en effet, ces animationsFlash, couramment utilisées sur Internet, sont un assemblage d’images, de textes, dedessins et de sons pouvant s’animer et même interagir avec vous.

Parmi ses concurrents, on peut citer Silverlight, de Microsoft ou encore Java, de Sun/O-racle. L’HTML5, couplé avec le CSS3 est une nouvelle alternative standardisée à cesanimations, ne nécessitant pas de plug-in dans le navigateur. Les spécifications del’HTML5 ne sont malheureusement pas encore finalisées à l’heure actuelle. Je vousencourage à lire le tutoriel de Mathieu Nebra sur l’HTML5 et le CSS3 sur OpenClass-rooms, si vous vous sentez l’âme d’un webdesigner !

Un peu d’histoire

Flash n’est pas aussi récent que l’on pourrait le croire, car son ancêtre direct a vule jour en 1995 et est sorti un an plus tard : il s’agit de FutureSplash Animator(voir figure 1.1), un concurrent de Macromedia Shockwave à cette époque (un autreformat multimédia orienté vers le web). FutureSplash a été développé par FutureWaveSoftware, une compagnie à l’origine de SmartSketch, un logiciel de dessin vectoriel dontil manquait la composante animation contrairement à Shockwave.

Figure 1.1 – FutureSplash Animator

Son succès amena Macromedia à racheter FutureSplash Animator en décembre 1996,pour le renommer en Macromedia Flash (voir figure 1.2), contraction de Future etSplash. En 2005, Adobe Systems acquiert Macromedia ; le développement de Flash sepoursuit et aboutit à une évolution majeure de la technologie avec la sortie en 2007 deCS3 (Creative Suite 3 ) : c’est la naissance de l’Actionscript 3 et de Flash 9.

Depuis, Adobe travaille à l’amélioration du lecteur Flash avec notamment la sortieen 2008 de la dixième version de Flash apportant quelques nouveautés et un début desupport de l’accélération matérielle pour obtenir de meilleures performances. En 2011,

4

Page 28: Programmez en Actionscript 3

ADOBE FLASH

Figure 1.2 – Macromedia Flash

une onzième version majeure apporte une nouveauté très attendue : le support inté-gral de l’accélération matérielle par la carte graphique, ouvrant la voie à de nouveauxcontenus en 3D complexe. Le fameux moteur de jeux vidéo d’Epic Games, l’UnrealEngine 3, a d’ailleurs été porté sur la plate-forme Flash !

Adobe cherche maintenant à faciliter l’utilisation de sa technologie sur les autres appa-reils multimédia, et on peut désormais développer en Flash sur un téléphone portablefonctionnant sous Android de Google, iOs d’Apple ou BlackBerry 10 de RIM, sur destablettes tactiles et même sur des télévisions !

Les dérivés de Flash

La plupart des professionnels se servent du logiciel Flash Professionnal d’Adobe,mais il existe d’autres façons d’utiliser cette technologie. Voici les deux principales :la première utilise un autre langage tandis que la deuxième est en quelque sorte uneextension de l’Actionscript 3.

Flex

Flex est un logiciel jumeau de Flash Professionnal, il est orienté développement etdesign d’applications (voir figure 1.3). Il permet principalement de combler les lacunes,si on peut dire, de Flash en termes de création d’interfaces utilisateur. C’est pourquoi,celui-ci propose une grande collection de composants préconçus faciles à manipuler telsque des boutons, des champs de texte, etc. Les développeurs peuvent ainsi concevoirtrès rapidement une interface utilisateur pour des programmes qui ne nécessitent pastoute la puissance de dessin de Flash.

Figure 1.3 – Adobe Flex

Flex utilise principalement un autre langage inventé par Macromédia : le MXML(Macromedia ExtensibleMarkup Language), une variante du langage très connu qu’estle XML. Le MXML est utilisé pour décrire la structure visuelle d’une application dela même façon que pour écrire une page web avec l’HTML (lui aussi basé sur le

5

Page 29: Programmez en Actionscript 3

CHAPITRE 1. VOUS AVEZ DIT « ACTIONSCRIPT » ?

XML) ; on place alors des balises représentant les composants du programme touten les mettant en forme. Ensuite, l’Actionscript s’ajoute au XML dans une ba-lise <mx:Script> et permet de manipuler et d’animer les balises MXML ainsi qued’interagir avec l’utilisateur par exemple.

Pour obtenir plus d’informations, vous pouvez jeter un coup d’œil au tutoriel Flex deMigs sur OpenClassrooms.

Air

Adobe Air est une variante de Flash permettant à n’importe quelle animation crééeavec Flash ou Flex de s’installer et de fonctionner comme une véritable application(figure 1.4). Grâce aux nombreuses nouvelles fonctionnalités et outils qui sont à votredisposition lorsque vous programmez une application Air, vous pouvez gérer le sys-tème de fichiers de l’ordinateur ou les disques amovibles, créer des bases de données,monter un serveur, etc. Ainsi, peut-on programmer un traitement de texte ou encoreun logiciel de messagerie instantanée, voire un navigateur Internet avec Flash.

Figure 1.4 – Adobe Air

Une autre particularité de cette plate-forme ressemblant à Flash est que, en plus duMXML et de l’Actionscript 3, on peut utiliser uniquement du simple HTML, CSSet Javascript pour créer de telles applications. Air utilise alors le moteur Webkit(utilisé par Chrome et Safari entre autres) pour afficher ces éléments de pages web dansles applications. Ceci représente un avantage non négligeable pour les développeursweb voulant programmer des applications de bureau sans toutefois avoir à apprendreet maîtriser un autre langage de programmation !

Enfin, c’est Air qui permet aux développeurs Flash de créer des applications à destina-tion de mobiles comme l’iPhone, sur les tablettes tactiles ou encore sur les téléviseurs,et cela depuis 2010 avec la sortie d’Air 2.5 (voir figure 1.5).

Quelques exemples d’utilisation

Pour bien cerner les possibilités de Flash et différencier les multiples variantes de cettetechnologie, voici, rien que pour vous, quelques exemples illustrés.

Le dynamisme apporté au web par l’Actionscript

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

6

Page 30: Programmez en Actionscript 3

QUELQUES EXEMPLES D’UTILISATION

Figure 1.5 – Présentation d’Adobe AIR 2.5, un dérivé de Flash.

Flash. Bien entendu, ceux-ci sont réalisés en Flash à l’aide du langage Actionscript.Pour vous donner un exemple concret, je vous ai sélectionné un jeu nommé KingdomRush, dont un aperçu est donné à la figure 1.6.

Figure 1.6 – Un jeu réalisé en Flash : Kingdom Rush.

Création de sites web orientés vers le visuel

La technologie Flash est aussi grandement utilisée dans la conception des sites webeux-mêmes. En général, les animations Flash sont plutôt réservées aux sites webstatiques ou sites-vitrines. Ceux-ci sont très appréciés pour leurs interactions et leursanimations qui dynamisent énormément la navigation : il est important, notamment

7

Page 31: Programmez en Actionscript 3

CHAPITRE 1. VOUS AVEZ DIT « ACTIONSCRIPT » ?

pour les sites commerciaux à destination du grand public, d’attirer le regard. Toutefois,il est tout à fait possible de créer des sites web dynamiques et interagir avec un serveurgrâce au langage PHP par exemple. Pour que vous puissiez mieux vous faire une idéede la chose, je vous propose d’aller visiter le site de la nouvelle série de Canal+ (voirfigure 1.7) :

B

�Carlos

Code web : 751006.

Figure 1.7 – Le site de la série Carlos est réalisé en Flash.

Introduction d’Adobe Air

Comme nous le verrons dans le prochain chapitre, l’utilisation de la technologie Flashnécessite un lecteur spécifique nommé Flash Player. Celui-ci est très répandu à l’inté-rieur des navigateurs Internet, et l’utilisation de Flash s’est ainsi longtemps limitée auweb. Heureusement, ceci n’est plus le cas avec l’arrivée d’Adobe Air. En effet, cettetechnologie vient ajouter de nouvelles fonctionnalités à Flash et permettre l’utilisationde Flash hors-ligne en tant que programme. Pour vous donner un exemple, l’appli-cation Flash du site de poker Winamax (voir figure 1.8), disponible initialement surnavigateur Internet, a pu être convertie en véritable logiciel grâce à Adobe Air.

Ainsi l’utilisation d’Adobe Air permet de porter les applications directement sur unsystème d’exploitation. Cette technologie est notamment utilisée aujourd’hui par denombreux systèmes d’exploitation mobiles tels que l’iOS, Android ou BlackBerry 10.

8

Page 32: Programmez en Actionscript 3

L’ACTIONSCRIPT 3

Figure 1.8 – Le logiciel Winamax utilise la technologie Air.

L’Actionscript 3

L’Actionscript est le langage de programmation servant à faire fonctionner les ani-mations Flash. C’est le plus utilisé parmi les langages de Flash. Il est basé sur l’EC-MAscript, à l’instar du Javascript utilisé sur Internet, directement dans les pagesweb. Sans lui, aucune animation ou interaction dans un fichier Flash ne serait possibleet celui-ci serait alors réduit à une simple image fixe.

L’Actionscript est un langage orienté objet, de haut niveau et événementiel.

Orienté objet

En effet, sa structure est basée sur le concept d’objet, c’est-à-dire que tous les élémentsde l’animation (y compris ceux qui ne relèvent pas de l’affichage, comme par exemple lesnombres) sont des objets, avec des attributs et des méthodes qui leur sont attachés.Chaque objet est décrit par une classe : un ensemble d’attributs et de méthodesqui représentent son comportement.

Prenons comme exemple une voiture de sport : c’est un objet qui a pour classe Voiture,c’est-à-dire qu’elle a par exemple un attribut vitesse qui nous permet de connaître savitesse de déplacement, ou encore une méthode tourner à gauche, qui la fait tourner.Tous ces attributs et ces méthodes sont décrits et expliqués dans la classe Voiture.

S’il nous prenait l’envie de programmer un jeu de course de voitures basique, il faudraitd’abord écrire une classe Voiture, puis, sur le fichier principal, créer un nouvel objetde la classe Voiture pour créer une voiture (et ensuite la déplacer par exemple).

Une partie toute entière sera consacrée à la programmation orientée objet, ne vousen faites pas si vous n’arrivez pas à tout bien saisir maintenant.

9

Page 33: Programmez en Actionscript 3

CHAPITRE 1. VOUS AVEZ DIT « ACTIONSCRIPT » ?

De haut niveau

L’Actionscript est un langage dit de haut niveau, c’est-à-dire que son fonctionne-ment est très éloigné du fonctionnement de l’ordinateur au niveau matériel, au contrairedes langages dit de bas niveau, proches de la machine (comme le langage C).

Généralement, cela signifie qu’il est plus facile de réaliser certaines choses ou qu’il fautmoins d’instructions, mais cela se traduit souvent par des performances plus faibles.

Le Java, le Python ou le Ruby sont d’autres exemples de langages de haut niveau.

Évènementiel

Enfin, c’est un langage évènementiel, c’est-à-dire que l’interactivité de vos programmessera basée sur des événements que nous allons écouter. Par exemple, pour utiliserun bouton, nous allons écouter (donc attendre) sur lui l’événement « cliqué » qui seradéclenché lorsque l’utilisateur appuiera sur ce bouton. Bien sûr, pendant ce temps,nous pouvons faire autre chose : c’est tout l’intérêt de ce système.

En résumé– L’Actionscript est un langage interprété, il a donc besoin d’un interpréteur

(le lecteur Flash) pour être exécuté.– La technologie Flash regroupe les programmes Flash classiques, les applicationsFlex que l’on peut trouver sur des pages web, ainsi que les applications AIR àdestination du bureau ou d’autres appareils comme les mobiles.

– Le principal langage utilisé dans ces programmes est l’Actionscript 3, mais on peutaussi utiliser leMXML (pour Flex et AIR), voire l’HTML et le Javascript (pourles applications AIR uniquement).

– L’Actionscript 3 est un langage de haut-niveau : son fonctionnement est éloigné dela machine et il est en général plus facile d’implémenter des fonctionnalités complexes.

– C’est aussi un langage orienté objet : son fonctionnement est basé sur des conceptsd’objets et de classes.

– Enfin, c’est un langage événementiel : on écoute des objets, et si des événementssurviennent, on peut exécuter du code.

10

Page 34: Programmez en Actionscript 3

Chapitre 2Votre premier programme avec FlexSDK

Difficulté :

Maintenant que vous en savez un peu plus sur Flash, il est grand temps de passer à lapratique et à l’essentiel de ce cours : l’Actionscript 3 ! Vous aurez besoin d’outils poursuivre ce cours et appliquer ce que vous apprendrez (c’est très important), mais ne vousinquiétez pas, tous sont gratuits.

Le compilateur, qui servira à transformer votre code en animation, est effectivement gratuitpour tout le monde et même open-source ! Il s’agit de Flex SDK, qui faisait partie du projetAdobe Open Source et qui est récemment passé sous l’aile de la Fondation Apache. Nousutiliserons également un logiciel facultatif pour nous aider à coder et à compiler nos projets,disponible hélas uniquement sous Windows.

11

Page 35: Programmez en Actionscript 3

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Cette partie est un peu difficile, surtout si vous n’avez jamais programmé :accrochez-vous, relisez les parties que vous n’avez pas comprises ! La suiteen sera plus facile à appréhender. La partie sur la compilation en ligne decommande est facultative si vous travaillez sur Windows et que vous êtesallergiques à la console. . .

Préambule

Le compilateur

Un compilateur est un programme très utile dans la plupart des langages de program-mation. Vous vous doutez bien que l’ordinateur ne sait pas interpréter directement lecode que nous lui écrivons : en effet, les langages de programmation ont été conçuspour être facilement utilisables par les êtres humains comme vous et moi. Or, les ordi-nateurs ne comprennent que les instructions en binaire de bas niveau (voir chapitreprécédent). Il faut donc traduire nos programmes grâce au compilateur ! (voir figure2.1)

Figure 2.1 – Le principe de la compilation

Certains langages de programmation sont interprétés par un logiciel faisantl’intermédiaire entre le code et l’ordinateur : on peut en général se passer dela compilation. C’est le cas de la plupart des langages utilisés sur Internet,comme le Javascript ou le PHP. Mais c’est aussi le cas de l’Actionscript !

Mais alors, pourquoi doit-on compiler nos programmes écrits en Actions-cript ?

En Actionscript 3, la compilation vous donne des informations sur vos erreursde syntaxe pour que vous les corrigiez plus facilement, mais elle permet surtout derassembler tout votre code et le contenu nécessaire au bon déroulement de votre pro-gramme (comme les librairies) dans un seul fichier. Ainsi, il est plus facile d’intégrerune animation Flash dans un site web et il devient possible d’importer directementdans l’animation des images, des sons, des polices de caractères ou d’autres médias

12

Page 36: Programmez en Actionscript 3

PRÉAMBULE

qui seront chargés en même temps que votre programme. En outre, le compilateurcompresse votre animation afin qu’elle 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 n’est qu’un demi-compilateur : il ne s’occupe seulement de lier plusieursfichiers en un seul (opération appelée Édition de liens), alors que les compilateursclassiques traduisent également le code.

Figure 2.2 – Le compilateur Flash

Le fichier qui est produit est en général au format swf (ShockWave Flash) ; c’est luiqui sera chargé par un navigateur Internet par exemple.

Le lecteur Flash

Donc il nous faut un logiciel pour que l’ordinateur comprenne notre code ?

Oui ! C’est là que le lecteur Flash (ou Flash Player en anglais) entre en scène (voirfigure 2.3). Ce logiciel contient un ensemble d’outils permettant d’exécuter votre pro-gramme : Flash Player est un interpréteur, et l’Actionscript est un langage inter-prété.

Figure 2.3 – Le lecteur Flash

Tout ce processus se déroule à l’intérieur d’une machine virtuelle. Concrètement, FlashPlayer cache le système sur lequel votre programme tourne et gère lui-même la mé-moire et les autres échanges nécessaires au bon déroulement de votre programme.Ainsi, ce dernier peut fonctionner correctement sur plusieurs systèmes d’exploitation(Windows, Mac, Linux, Android, etc.) totalement différents. Entre autres, il dispose

13

Page 37: Programmez en Actionscript 3

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

d’un compilateur à la volée, ou JIT (Just In Time) qui traduit en temps réel certainspassages de votre code en binaire afin d’améliorer les performances.

Installation des outils

Ainsi, pour programmer en Actionscript, il nous faut plusieurs outils, dont uncompilateur et un lecteur Flash. Nous allons dès à présent nous occuper de toutcela !

Java

Java est une technologie similaire à Flash, développée initialement par Sun Microsys-tems (racheté par Oracle), qui regroupe un ensemble d’outils permettant de créer desapplications (voir figure 2.4). Or, le compilateur de Flash est écrit en Java : il fautdonc que Java soit installé sur votre ordinateur. Si vous êtes certains que c’est déjà lecas, vous pouvez passer à l’étape suivante. Sinon, téléchargez et installez Java :

B

�Téléchargez Java

Code web : 741426.

Figure 2.4 – Le logo Java

Flex SDK

Le Flex SDK (Software Development Kit) est un ensemble d’outils de développementqui permettent, entre autres, de compiler des programmes écrits en Actionscript 1, 2ou 3, et des applications Flex ou Air.

Depuis 2011, Adobe a placé Flex sous licence Apache, par le biais de la FondationApache. Le Flex SDK est ainsi distribué maintenant sous l’appellationApache Flex,et est donc un projet open source (figure 2.5).

Nous verrons, dans la dernière partie de ce chapitre, comment utiliser unlogiciel nous permettant de développer en Actionscript sans utiliser la consolede lignes de commande : il s’agit de Flashdevelop (Windows uniquement).Si vous ne voulez pas essayer de compiler avec la console et que vous êtessous Windows, vous pourrez alors vous passer de la console pour compilervos applications.

14

Page 38: Programmez en Actionscript 3

INSTALLATION DES OUTILS

Figure 2.5 – Le logo Apache Flex

Tout d’abord, il vous faut disposer d’Adobe Air pour installer le SDK, et suivezensuite les instructions d’installation.

B

�Adobe Air

Code web : 815403.

Ensuite, il faut que vous récupériez le SDK sur le site d’Apache :

B

�Apache Flex SDK

Code web : 944481.

Cliquez sur le bouton Download, lancez le téléchargement (voir figure 2.6) et allezprendre un café.

Figure 2.6 – Page de téléchargement d’Apache Flex

Une fois le téléchargement terminé, installez et lancez l’applicationApache Flex SDKInstaller. Un écran de sélection de la version des différents composants du SDK s’af-fiche une fois l’application ouverte (voir figure 2.7).

15

Page 39: Programmez en Actionscript 3

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Figure 2.7 – Application d’installation

Laissez les valeurs telles qu’elles sont : les dernières versions sont en effet sélectionnéespar défaut.

Sur l’écran suivant, choisissez l’emplacement d’installation du SDK, de préférence unrépertoire facilement accessible (votre dossier personnel par exemple) et nommez-leFlex SDK 4.

Ensuite, vous devez accepter les licences d’utilisation des différents composants du SDKen cochant les cases de la liste des composants (voir figure 2.8).

Figure 2.8 – Liste des composants du SDK

Le téléchargement et l’installation des composants débute alors. Une fois l’installationterminée, vous pouvez fermer l’application.

16

Page 40: Programmez en Actionscript 3

INSTALLATION DES OUTILS

Pour les utilisateurs de linux, il faut installer Adobe AIR 2.6.0 pour pouvoirutiliser l’application d’installation de Flex SDK 4. Skype peut égalemententrer en conflit avec Adobe AIR, il faut alors le désinstaller.

Vous voilà armés d’un compilateur Flash ! Mais comment s’en sert-on ? Avec les lignesde commande pardi ! Pour les utilisateurs de Windows, il est grand temps de renouerune relation avec le terminal ! Pour Mac et Linux en revanche, cela ne devrait pas tropvous poser de problèmes. . .

Voici la marche à suivre pour lancer un terminal :

– Windows : dans le menu démarrer, allez dans Tous les programmes, Accessoires,Invite de commandes, ou appuyez sur

�� ��Windows +�� ��R et entrez cmd puis validez

(voir figure 2.9).– Linux : comment ça, vous ne savez pas ouvrir un terminal ? :-˚ Le gnome-terminal(Gnome) ou la Konsole (KDE) conviendront parfaitement (voir figure 2.10).

– Mac : dans le Finder, sélectionnez Applications, puis Utilitaires et enfin Terminal(voir figure 2.11).

Sur Windows, il existe une alternative au terminal classique, bien plus com-plète et confortable, car elle se rapproche de ceux des systèmes d’exploitationLinux ou Mac. Il s’agit de Powershell ; pour le lancer, appuyez sur Win-dows+R, entrez powershell et validez. Désormais, vous pouvez par exempleappuyer sur TAB pour compléter automatiquement une commande ou unchemin, comme sur Linux !

Maintenant, il va falloir se placer dans le dossier bin du SDK : utilisez la commandecd (Change Directory) pour vous déplacer dans l’arborescence de fichiers.

Figure 2.9 – Windows

17

Page 41: Programmez en Actionscript 3

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Figure 2.10 – Linux

Figure 2.11 – Mac

18

Page 42: Programmez en Actionscript 3

INSTALLATION DES OUTILS

Version de débogage du lecteur Flash

Un deuxième outil va nous être indispensable : il s’agit d’une version légèrement dif-férente du lecteur Flash habituel que l’on trouve dans les navigateurs Internet parexemple. En effet, ceFlash Player de débogage peut s’exécuter tout seul commeune quelconque application et dispose surtout de fonctions de débogage très utiles.Par exemple, si un problème survient pendant que l’on teste notre programme, unefenêtre nous affichera les détails de l’erreur, la ligne incriminée et les différents appelsde fonctions ayant conduit à cette erreur.

Vous pouvez dès à présent récupérer le lecteur sur le site web d’Adobe :

B

�Flash Player de débogage

Code web : 927850Un large choix de versions s’offre à vous : il faut prendre le lecteur appelé « Projectorcontent debugger », correspondant à votre système d’exploitation :

– si vous êtes sur Windows, il faut cliquer sur le lien Download the Windows FlashPlayer xx.x Projector content debugger,

– si vous êtes sur Max, il s’agit du lien Download the Macintosh Flash Player xx.xProjector content debugger

– enfin, si vous êtes sur Linux, le bon lien est Download the Linux Flash Player xx.xProjector content debugger.

Sur Windows

Lancez le fichier exécutable téléchargé une fois afin que les fichiers .swf soient auto-matiquement associés au Lecteur Flash (voir figure 2.12)

Sur Linux

Commencez par extraire l’archive téléchargée. Pour que son utilisation soit plus facile,et surtout parce que l’on en aura besoin un peu plus loin, vous pouvez déplacer l’exécu-table flashplayerdebugger vers le dossier /usr/bin et le renommer en flashplayergrâce à la commande suivante (n’oubliez pas de vous placer dans le dossier de l’archiveextraite) :

sudo mv flashplayerdebugger /usr/bin/flashplayer

Une fois le déplacement effectué, relancez votre console et replacez-vous dans le dossierFlex SDK 4/bin.

Sur Mac

Installez le lecteur Flash en double-cliquant sur l’installateur Install Adobe FlashPlayer Debugger 11.dmg (voir figure 2.13)

19

Page 43: Programmez en Actionscript 3

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Figure 2.12 – Lecteur Flash de débogage Windows

Figure 2.13 – Installation de Flash Player Debugger

20

Page 44: Programmez en Actionscript 3

INSTALLATION DES OUTILS

Créer les sources

Vu que nous n’avons pas encore attaqué l’écriture de programmes en Actionscript3, je vous ai concocté un petit code de test, qui va nous permettre de vérifier que votreinstallation fonctionne bien.

Pour les utilisateurs de Windows, il est nécessaire de pouvoir enregistrer vosfichier dans n’importe quelle extension : sinon, il y a de grandes chancespour que Windows vous trahisse en sauvegardant votre fichier Test.as enTest.as.txt par exemple, sans que vous ne en rendiez compte ! Pour évitercela, il faut désactiver une fonctionnalité de Windows qui masque la plupartdes extensions : dans une fenêtre de l’explorateur de fichiers, allez dans lemenu Options des dossiers, puis dans l’onglet Affichage et décochezMasquer les extensions des fichiers dont le type est connu.

Commencez par créer un répertoire Sources dans le dossier bin où l’on mettra lessources de nos futurs programmes. Dans le répertoire Sources, créez un nouveau fi-chier nommé Test.as et copiez-y le code en utilisant un éditeur de texte quelconque,tel que le Bloc-notes si vous êtes sous Windows. Utilisez le code web ci-dessous pourafficher le code et le copier/coller.

B

�Code pour test.as

Code web : 171910

Compiler le programme de test

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

Windows

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

Linux et Max

./mxmlc Sources/Test.as

Il est possible que vous ayez besoin des droits administrateurs sur Linux pourpouvoir compiler. Pour contourner le problème, essayez d’ajouter bash ousudo avant la commande ./mxmlc.

21

Page 45: Programmez en Actionscript 3

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Ensuite, appuyez sur�� ��Entrée pour lancer la compilation (voir figures 2.14, 2.15 et

2.16 pour les différents cas).

Figure 2.14 – Windows

Figure 2.15 – Linux

Après quelques instants, et si tout s’est bien passé, un fichier Test.swf a été créé dansle dossier Sources ; il vous suffit de l’ouvrir avec le lecteur de débogage que nous avonstéléchargé précédemment !

22

Page 46: Programmez en Actionscript 3

DIS BONJOUR AU MONSIEUR

Figure 2.16 – Mac

Sur Windows ou Mac

Double-cliquez sur le fichier Test.swf. Si jamais le lecteur Flash ne s’ouvre pas,choisissez-le avec la commande Ouvrir avec... ou dans la liste Sélectionner unprogramme installé (voir figures 2.17 et 2.18).

Sur Linux

Entrez dans votre terminal (voir figure 2.19) :

flashplayer Sources/Test.swf

Si votre curseur laisse une traînée blanche et brumeuse, cela signifie que la compilationa réussi et que vous êtes prêts pour passer à la suite !

Dis bonjour au monsieur

Nous allons maintenant écrire de A à Z notre premier programme Flash ! Commencezpar créer un nouveau fichier Actionscript dans le répertoire Source, et nommez-leHello.as.

Structure de notre programme

Un programme écrit intégralement en Actionscript, ce qui sera le cas durant ce cours,présente toujours la même structure : le code est obligatoirement mis dans des fonc-tions, elles-mêmes placées dans une classe, englobée par un paquet (on utilise alors

23

Page 47: Programmez en Actionscript 3

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Figure 2.17 – Windows

Figure 2.18 – Mac

24

Page 48: Programmez en Actionscript 3

DIS BONJOUR AU MONSIEUR

Figure 2.19 – Linux

le mot anglais package). Pour l’instant, il y a de grandes chances que les trois termesque je viens d’utiliser soient obscurs pour vous ; la seule chose importante à retenir estl’organisation de ces trois niveaux qui composent le code source de tout fichier Ac-tionscript. Pas de panique : nous explorerons plus en détails chacune de ces notionsplus tard dans le cours.

Vous trouverez un petit schéma récapitulatif à la figure 2.20.

Figure 2.20 – Structure d’un programme

Le package

Commençons par le plus simple : le package. Il est composé d’un nom facultatif etd’un bloc d’accolades. Nous utilisons le mot-clé package comme ceci :

1 package nom {23 }

25

Page 49: Programmez en Actionscript 3

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Un mot-clé (ou réservé) est une expression qui est utilisée par le langage etqui lui est donc réservée. Vous ne pourrez donc pas utiliser ce type de motsautrement que tels qu’ils ont été définis en Actionscript.

Le nom du package décrit la position de la classe dans l’arborescence des fichiers devotre projet. Effectivement, vous ne pouvez choisir vous-mêmes le nom du package :vous devez mettre le chemin relatif du fichier par rapport au fichier principal (celui quel’on compile avec la commande mxmlc vue plus haut), en séparant les dossiers par despoints (à la place des slashes ou antislashes).

Par exemple, si votre fichier principal Hello.as se trouve dans le dossier source etque vous créez un nouveau dossier ET dans lequel vous rajoutez un dossier telephoner,en y mettant un fichier Actionscript Maison.as qui est utilisé par votre programmeprincipal, vous devrez écrire son package ainsi :

1 package ET.telephoner {23 }

L’arborescence des fichiers est alors Sources/ET/telephoner/Maison.as.

Comment cela, on peut utiliser un autre fichier Actionscript depuis notreprogramme principal ?

Bien sûr ! C’est même très utile : il vaut mieux faire plusieurs fichiers bien triés (undossier pour les utilitaires, un dossier pour le chargement de son. . .), que mettre l’en-semble des données dans un seul et unique fichier. Imaginez que votre programme fasseplusieurs centaines de milliers de lignes de code : il vous sera impossible de vous yretrouver ! Nous allons voir cette notion appelée importation de fichiers dans trèspeu de temps.

Qu’en est-il de notre fichier Hello.as ?

Très bonne question : pour le programme principal contenu dans le fichier que vousallez compiler avec la commande mxmlc, il n’y a pas de nom de package ! Et oui, il estdéjà dans le dossier principal de votre projet, inutile donc de mettre un chemin.

Dans ce cas, le package s’écrit ainsi :

1 package {23 }

Vous pouvez écrire ce code dans votre fichier vide si vous ne l’avez pas déjà fait !

26

Page 50: Programmez en Actionscript 3

DIS BONJOUR AU MONSIEUR

Importer des fichiers Actionscript

Comme nous l’avons vu, importer des fichiers peut s’avérer très utile, voire vital dansla plupart des cas. L’importation est une instruction (ou une ligne de code si vouspréférez) qui permet de rendre tout le code du fichier importé utilisable dans notrecode. Il y a deux types de fichiers que vous pouvez importer : les fichiers contenus dansles packages de Flash (commençant par flash.) et vos propres fichiers. Dans lesdeux cas, on utilise le mot-clé import suivi du package du fichier à importer, son nomet un point-virgule :

1 import ET.telephone.Maison;

La plupart des instructions et lignes de code devraient être terminées par unpoint-virgule en fin de ligne. Je dis « devraient » car il est toléré d’omettrele point-virgule, mais c’est très fortement déconseillé : il est le symbole quiindique clairement la fin de votre ligne de code. Il est possible, dans de rarescas, que vous obteniez des erreurs à cause de cela. Votre ordinateur ne s’au-todétruira pas si vous ne mettez pas les points-virgules, mais ce serait unetrès, très, très mauvaise habitude : si jamais vous voulez apprendre et utiliserun autre langage, vous oublierez constamment les points-virgules et maudirezle jour où vous avez décidé de ne pas suivre mon conseil. . . :-˚ Vous remar-querez qu’il ne faut pas mettre de point-virgule quand il s’agit de blocs decode délimités par des accolades ({ et }), comme pour le package que l’onvient de voir.

Les importations s’écrivent juste après avoir ouvert la première accolade du package :

1 package {23 import ET.telephone.Maison;45 }

Pour notre programme, il va falloir importer un fichier standard de Flash : Sprite. Ilest nécessaire pour toute application : nous détaillerons son utilité bien plus tard dansle cours car il nous manque trop de notions actuellement. Je peux tout de même vousdire que cela nous permet d’afficher le programme et donc de le lancer : effectivement,tout programme Flash a besoin d’un affichage pour s’exécuter.

Je vous donne le code du fichier importé que vous devez avoir dans votre Hello.as :

1 package {23 import flash.display.Sprite;45 }

27

Page 51: Programmez en Actionscript 3

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Vous l’aurez sûrement compris, le package du fichier est flash.display(gestion de l’affichage).

La classe

Ensuite, vient la. . . Comment ça vous ne savez pas ? Retournez vite regarder le schéma !Effectivement, dans le package, on trouve une classe. Cette notion est un concept trèsimportant de la programmation orientée objet que j’ai mentionnée dans l’intro-duction. Il est trop tôt pour développer cette notion, mais rassurez-vous : une partieentière de ce cours sera consacrée à l’orienté objet.

L’essentiel est de retenir que la classe est obligatoire et que sa syntaxe est la suivante :les mots-clés public class suivis du nom de la classe et d’un bloc d’accolades, commepour le package.

1 public class NomDeMaClasse {23 }

Attention ! Le nom d’une classe ne doit contenir que des lettres, et doit êtreidentique au nom du fichier dans lequel elle se trouve (sans l’extension). Deplus, il doit impérativement commencer par une majuscule : cela expliquepourquoi tous nos fichiers Actionscript ont une majuscule depuis le débutdu cours !

Étant donné que le nom du fichier est le même que celui de la classe de ce fichier, nousparlerons désormais de classe dans les deux cas.

Il existe une notation appelée Camel (chameau) ou CamelCase (notationchameau), très utilisée dans le monde de l’informatique. Je l’ai utilisée pourécrire NomDeMaClasse : chaque mot débute par une majuscule, comme desbosses de chameau ! Son utilité est purement esthétique car cette notationaméliore la lisibilité du code lorsque l’on ne peut pas utiliser d’espaces oud’autres caractères spéciaux. C’est le cas ici avec le nom des classes. Je penseque c’est une bonne habitude à prendre, alors autant commencer tout desuite : avouez que si j’avais écrit Nomdemaclasse, ce serait beaucoup moinslisible !

La classe se dispose juste après les importations de fichiers, comme ceci pour notrefichier Hello.as :

1 package {23 import flash.display.Sprite;45 public class Hello extends Sprite {

28

Page 52: Programmez en Actionscript 3

DIS BONJOUR AU MONSIEUR

67 }8 }

Les plus observateurs d’entre vous auront remarqué que j’ai ajouté deux mots derrièrele nom de notre classe. Le mot-clé extends (étendre en anglais) permet d’utiliser laclasse Sprite d’une manière un peu spéciale, comme nous le verrons dans la partieconsacrée à l’orienté objet.

Les fonctions

Maintenant que notre classe est prête, il faut écrire une ou plusieurs fonctions pourpouvoir mettre du code dedans ! Une de ces fonctions est obligatoire et elle porte unnom : il s’agit du constructeur de la classe. Devinez quoi ? C’est encore lié à l’orientéobjet ! Pour faire simple, ce constructeur est automatiquement exécuté dans certainscas, lorsque l’on utilise une classe. Ici, le code à l’intérieur sera parcouru au lancementde notre programme. Pour écrire un constructeur, on utilisera les mots-clés publicfunction suivis du nom de la classe, de parenthèses et d’un nouveau bloc d’accolades.

Pour notre classe Hello contenue dans notre fichier Hello.as, le constructeur ressem-blera à ceci :

1 public function Hello (){23 }

Et voilà ! Notre fichier est fin prêt pour que nous commencions (enfin) à coder !

Voici le code complet de notre fichier Hello.as pour que vous puissiez vérifier :

1 // Premier niveau : le paquet2 package {34 // Les classes importées5 import flash.display.Sprite;67 // Deuxième niveau : la classe du fichier8 public class Hello extends Sprite {9

10 // Troisième niveau : la ou les fonctions1112 // Constructeur de la classe13 public function Hello () {1415 // Nous allons coder ici !1617 }1819 }20 }

29

Page 53: Programmez en Actionscript 3

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Commentez votre code !

Avez-vous remarqué que j’ai inséré du texte en français dans le code précédent qui n’aa priori rien à faire là ? On appelle cela des commentaires. Vous pouvez y écrire ab-solument n’importe quoi et pour cause, ils seront tout simplement ignorés lorsque vouslancerez votre programme. Vous vous demandez alors à quoi servent-ils ? La réponseest plutôt simple : commenter un code permet de s’y retrouver même si nous avonsnous-mêmes écrit le code en question. Imaginez que vous reveniez dessus quelques moisplus tard : s’il n’y a aucun commentaire, vous serez aussi perdu que si vous n’aviezpas été le programmeur ! Cela peut même arriver dans un intervalle de quelques joursseulement. Et ce serait encore pire si vous souhaitiez que votre code soit lu ou utilisépar d’autres personnes. . . Mais attention, il ne s’agit pas non plus d’inonder votre codede commentaires : vous ne réussiriez qu’à le rendre encore plus illisible et incompré-hensible ! Il faut trouver un juste milieu : commentez quand cela est nécessaire pourdécrire brièvement ce que fait un morceau de votre programme afin de vous en rappelerfacilement plus tard.

Il existe deux types de commentaires : les commentaires en ligne et les commen-taires multi-lignes.

Les commentaires en ligne

Ce sont des commentaires qui ne comportent qu’une seule ligne. On les débute pardeux slashs, comme ceci :

1 // Voici un commentaire en ligne

Tout le texte suivant les deux slashs sera considéré comme du commentaire.

Vous pouvez mettre un commentaire en fin de ligne, sans gêner personne :

1 import display.Sprite; // Pour l'affichage

Les commentaires multi-lignes

Cette fois-ci, il est possible d’étaler notre commentaire sur plusieurs lignes. Pourcela, il faut débuter notre commentaire par un slash et une astérisque et terminerexplicitement le commentaire par une astérisque et un slash :

1 /* Ceci2 est un commentaire3 sur quatre4 lignes. */

Afficher un message dans la console

Avant toute chose, il est important de souligner que la technologie Flash n’a jamaisété conçue pour être utilisée en lignes de commande : en effet, son objectif est de propo-

30

Page 54: Programmez en Actionscript 3

DIS BONJOUR AU MONSIEUR

ser des applications et des animations entièrement graphiques. Cela implique que l’onne puisse qu’afficher du texte à la console (avec quelques efforts) et qu’il est impossibled’entrer des données au clavier via la console, comme en langage C par exemple.

C’est une fonction qui nous permettra d’afficher des messages dans la console : ellerépond au doux nom de trace() et est quasiment exclusivement utilisée pour le dé-bogage des programmes Flash.

Cette fonction est accessible partout dans tout code Actioncript, il suffit de l’appeler.

L’appeler ? Comme mon chien pour partir en balade ?

Oui, on utilise le terme appeler lorsque l’on utilise une fonction : nous n’allons pasécrire du code entre les accolades de la fonction trace(), nous allons nous contenterde l’utiliser. En effet, son code est déjà prêt et fait partie du lecteur Flash lui-même !

Pour l’utiliser, nous allons prendre presque la même syntaxe que celle du constructeurHello (qui est lui aussi une fonction), sans le bloc d’accolades et sans oublier le point-virgule (car il s’agit d’une instruction) :

1 trace("texte à afficher");

Entre les deux parenthèses, vous devez spécifier à la fonction trace() ce qu’elle doitafficher. Ce peut être du texte (délimité 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 ca-pable d’afficher le grand classique « Hello world ! ». Souvenez-vous où il faut mettre lesinstructions dans le programme Hello que nous avons écrit jusqu’à présent !

1 // Premier niveau : le paquet2 package {34 // Les classes importées5 import flash.display.Sprite;67 // Deuxième niveau : la classe du fichier8 public class Hello extends Sprite {9

10 // Troisième niveau : la ou les fonctions1112 // Constructeur de la classe13 public function Hello () {1415 trace("Hello world !");1617 }18

31

Page 55: Programmez en Actionscript 3

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

19 }20 }

Place au test !

Compiler notre programme

Commençons tout d’abord par compiler Hello.as. Il y a une petite différence parrapport à tout à l’heure : cette fois-ci, il va falloir activer le mode débogage lors de lacompilation, pour que l’on puisse afficher le message « Hello world ! » dans la console.Pour ce faire, ajoutons un paramètre lors de la compilation : -debug=true.

Sur Windows :

.\mxmlc.exe -debug=true "Sources/Hello.as"

Sur Linux :

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

Et enfin, sur Mac :

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

Encore une fois, il est possible que vous ayez besoin des droits administra-teurs sur Linux pour pouvoir compiler. Pour contourner le problème, essayezd’ajouter bash ou sudo avant la commande ./mxmlc.

Si tout c’est bien passé, votre console devrait afficher quelque chose comme ce que vousvoyez à la figure 2.21.

Lancer le débogueur Flash

Pour pouvoir afficher les messages de la fonction trace(), il nous faut utiliser un autreoutil à notre disposition : le débogueur Flash. En effet, Flash Player, même enversion de débogage, ne peut pas afficher des messages en continu dans une console. Ilse contente de les envoyer : le débogueur va alors se charger de récupérer les messageset de nous les présenter dans la console. Il s’agit du programme fdb qui devrait êtredans le répertoire Flex SDK 4/bin (voir figure 2.22).

Lancez le programme dans votre console :

Sur Windows :

.\fdb.exe

Sur linux :

32

Page 56: Programmez en Actionscript 3

DIS BONJOUR AU MONSIEUR

Figure 2.21 – Résultat de la compilation

Figure 2.22 – Contenu du répertoire Flex SDK 4/bin

33

Page 57: Programmez en Actionscript 3

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

./fdb

Sur Mac :

./fdb

Un nouvel invité de commande, géré par fdb, devrait apparaître, comme à la figure2.23.

Figure 2.23 – Le nouvel invité de commande géré par fdb

Lancer notre programme

Tout d’abord il faut lancer une session de débogage pendant laquelle le débogueuressayera de récupérer les messages de débogage du lecteur Flash :

run

Le débogueur est ainsi en attente du lecteur Flash : lancez votre programme endouble-cliquant dessus, ou avec la commande que l’on a vu plus haut dans le cas deLinux. Le lecteur Flash n’est cependant pas encore démarré, il ne devrait donc pas sepasser grand-chose à l’écran.

Une fois que la session est correctement démarrée, entrez cette commande dans fdbpour réellement lancer le programme :

34

Page 58: Programmez en Actionscript 3

DIS BONJOUR AU MONSIEUR

continue

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

Figure 2.24 – Résultat de la fonction trace()

Une fenêtre blanche s’est ouverte : il s’agit de notre animation ! Pour l’instant, elle nefait presque rien, nous remédierons à cela dans la suite du cours.

Vous pouvez maintenant fermer votre programme. Si plus tard vous voulez quitter fdb,entrez cette commande :

quit

Vous pouvez également lister l’intégralité des commandes du débogueur avec cettecommande :

help

Lorsque vous programmez en lignes de commande, je vous conseille d’ouvrirdeux consoles : une pour la compilation à l’aide de mxmlc, et une autre pourle débogueur fdb. Cela vous évitera de quitter et relancer ce dernier à chaquecompilation ; il vous suffira d’utiliser la commande run à chaque fois que vousvoulez tester votre programme.

35

Page 59: Programmez en Actionscript 3

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Il en faut faire des efforts pour déboguer en lignes de commande, mais une foisque vous avez pris le coup de main, c’est plus facile. Pour se faciliter la vie, mieux vauts’équiper avec les meilleurs outils ! En effet, il existe des éditeurs de code très faciled’utilisation qui intègrent également des outils prêts à l’emploi pour compiler et testernos programmes !

FlashDevelop à la rescousse !

Pour Windows, il existe un très puissant éditeur pour programmer en Flash, deplus, il est gratuit et libre : j’ai nommé Flashdevelop ! Flashdevelop est ce quel’on appelle un IDE (Integrated Development Environment, environnement dedéveloppement intégré en anglais) : c’est un logiciel contenant tout le nécessaire pourprogrammer dans un ou plusieurs langages (ici l’Actionscript, mais pas seulement).Vous allez voir : compiler sera désormais aussi simple que d’appuyer sur un bouton !

Téléchargement

Flashdevelop est donc disponible au téléchargement gratuitement, malheureusement,la version officielle est réservée aux utilisateurs de Windows (voir figure 2.25). Com-mencez par télécharger Flashdevelop.

B

�Flashdevelop

Code web : 868865Il est possible, pour les utilisateurs d’un autre système d’exploitation, d’utiliser unemachine virtuelle, tant que les développeurs n’auront pas eu le temps d’adapter Fla-shdevelop à d’autres supports. Il existe également une version alternative, sous formed’un plugin pour le logiciel Eclipse. Rassurez-vous, le reste du cours ne porte pas surFlashdevelop, vous pourrez tout faire sans !

B

�Plugin

Code web : 649014

B

�Eclipse

Code web : 752289.

Installation

Une fois l’installateur de Flashdevelop téléchargé, lancez-le et appuyez sur Next (voirfigure 2.26).

Cet écran nous permet de choisir d’installer ou non des composants supplémentaires,comme le Flex SDK. Pour éviter tout problème, nous allons laisser les options pardéfaut, mais vous pouvez décocher Install Flex SDK si vous l’avez déjà téléchargé etque vous êtes sûr de vous. Je vous conseille toutefois de laisser le programme installerle compilateur lui-même pour éviter tout problème. Cliquez sur Next (voir figure 2.27).

36

Page 60: Programmez en Actionscript 3

FLASHDEVELOP À LA RESCOUSSE !

Figure 2.25 – Téléchargement de FlashDevelop

Figure 2.26 – Installation de FlashDevelop : étape 1

37

Page 61: Programmez en Actionscript 3

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Figure 2.27 – Installation de FlashDevelop : étape 2

Choisissez le dossier d’installation de Flashdevelop, puis cliquez une nouvelle fois surNext (voir figure 2.28).

Figure 2.28 – Installation de FlashDevelop : étape 3

Allez prendre un café pendant l’installation ! (voir figure 2.29)

Cliquez sur Finish pour terminer l’installation (voir figure 2.30).

Si Flashdevelop ne se lance pas tout seul, lancez-le. Vous arrivez sur l’écran d’accueil(voir figure 2.31).

38

Page 62: Programmez en Actionscript 3

FLASHDEVELOP À LA RESCOUSSE !

Figure 2.29 – Installation de FlashDevelop : étape 4

Figure 2.30 – Installation de FlashDevelop : étape 5

39

Page 63: Programmez en Actionscript 3

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Figure 2.31 – Page de démarrage de FlashDevelop

Vous pouvez fermer la page d’accueil en cliquant sur la croix correspondante (voir figure2.32).

Figure 2.32 – Fermeture de la page d’accueil

Un peu de paramétrage

Si vous avez décoché Install Flex SDK lors de l’installation du logiciel, il faut luidire où se trouve le Flex SDK que nous avions téléchargé au début avant de pouvoirl’utiliser : 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 SDKplus tard.

Commençons par nous rendre dans les paramètres du logiciel, à l’aide du menu Tools(voir figure 2.33).

40

Page 64: Programmez en Actionscript 3

FLASHDEVELOP À LA RESCOUSSE !

Figure 2.33 – Accès aux paramètres de FlashDevelop

La fenêtre des paramètres de Flashdevelop s’ouvre ; sélectionnez AS3Context dans laliste de gauche, puis Installed Flex SDKs dans le panneau de droite. Ensuite, cliquezsur le petit bouton avec trois points, comme à la figure 2.34.

Figure 2.34 – Paramètres de FlashDevelop

Le gestionnaire des SDK s’ouvre et est normalement vide. Nous allons ajouter notreSDK dans la liste : cliquez sur le bouton Ajouter en bas à gauche (voir figure 2.35).

Un nouveau SDK est apparu dans la liste ! Il faut maintenant spécifier le chemin (Path)

41

Page 65: Programmez en Actionscript 3

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Figure 2.35 – Éditeur de collections InstalledSDK

du SDK en le sélectionnant et en cliquant sur le petit bouton de droite à trois points(voir figure 2.36).

Figure 2.36 – Mise en place du SDK

Choisissez le dossier où vous avez placé le SDK au début du chapitre, par exempleD:\Flex SDK 4. Pour finir, validez en cliquant sur le bouton OK et fermez la fenêtredes paramètres à l’aide du bouton Close situé en bas à droite.

42

Page 66: Programmez en Actionscript 3

FLASHDEVELOP À LA RESCOUSSE !

Créons un projet Actionscript

Pour pouvoir programmer sereinement au même endroit durant le cours, il nous fautcréer un projet Actionscript 3. Pour cela, allez dans le menu Project de la barre demenus en haut, et cliquez sur New Project (voir figure 2.37).

Figure 2.37 – Création d’un nouveau projet

Une nouvelle fenêtre apparaît, proposant plusieurs types de projets. Sélectionnez AS3Project et donnez un nom à votre projet dans le champ Name. Vous pouvez demanderà Flashdevelop de vous créer automatiquement un dossier pour votre projet, en cochantla case Create directory for project (voir figure 2.38).

Validez et notre projet est prêt ! Flashdevelop a créé pour nous les dossiers et fichiers debase qu’il faut pour commencer à travailler sur notre programme Flash. Sélectionnezle panneau Project en bas à droite : il nous affiche l’arborescence de notre projet (voirfigure 2.39).

Le dossier bin doit contenir tous les médias qui seront chargés à l’exécution de notreprogramme (pour l’instant, nous allons le laisser tel qu’il est). C’est aussi le dossieroù notre fichier SWF sera créé à la compilation. Le dossier lib sert à regrouper tousles médias et librairies que vous pourriez importer dans votre programme, comme jel’ai expliqué au tout début du chapitre. Laissons-le vide également. Enfin, le dossiersrc contient tous les fichiers de code qui composent notre programme. Étendez-le,et vous verrez que Flashdevelop a créé pour nous un fichier Actionscript principal(reconnaissable à la petite flèche verte), qu’il a nommé Main.as. Double-cliquez dessuspour l’ouvrir dans l’éditeur.

Bien utiliser Flashdevelop

Avoir de bons outils ne suffit pas : il est primordial de bien savoir les utiliser ! Ainsi,avant de tester notre projet, il est préférable de faire un petit tour du propriétaire.

43

Page 67: Programmez en Actionscript 3

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

Figure 2.38 – Paramétrage du nouveau projet

Figure 2.39 – Arborescence du projet

44

Page 68: Programmez en Actionscript 3

FLASHDEVELOP À LA RESCOUSSE !

L’interface

L’interface de Flashdevelop, bien qu’écrite en anglais, est plutôt claire et surtout trèspratique (voir figure 2.40). Détaillons-la ensemble.

Figure 2.40 – L’interface de FlashDevelop

1. La barre de menu

Toutes les fonctionnalités de Flashdevelop sont accessibles dans ces menus.

– File (Fichier) : vous trouverez ici toutes les commandes en rapport avec les fichiers,comme la création de nouveaux documents, la sauvegarde, l’impression. . .

– Edit (Édition) : ce deuxième menu concerne le texte que vous tapez dans l’édi-teur. Vous pouvez ainsi facilement annuler des modifications, copier-coller du texte,commenter du code sélectionné. . .

– View (Affichage) : ici, vous pouvez modifier la présentation de Flashdevelop, et ré-ouvrir les panneaux que vous auriez malencontreusement fermé.

– Search (Recherche) : si vous voulez effectuer des recherches de texte dans votredocument ou dans le contenu des fichiers de votre projet, passez par ce menu !

– Debug (Débogage) : ce menu est un peu plus technique et concerne les sessionsde débogage que vous effectuerez dans Flashdevelop (comme avec fdb). Nous enreparlerons plus tard.

– Project (Project) : tout ce qui touche à la gestion de vos projets, comme la création,l’ouverture, mais aussi pour tester votre projet actuel.

– Insert (Insertion) : ici vous pouvez insérer du texte spécial dans votre document,comme l’heure actuelle (timestamp) ou une couleur entre autres.

– Refactor (Refactorisation) : derrière ce terme barbare se cachent les opérations au-tomatiques de maintenance et de mise en forme de votre code afin de le retravaillerpour qu’il soit plus clair (Code formatter). Dans Flashdevelop se trouvent égale-

45

Page 69: Programmez en Actionscript 3

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

ment des outils de génération de code pour travailler plus vite (Code generator).– Tools (Outils) : ici vous trouverez des outils pour le développement en Flash, etplusieurs fenêtres de paramétrage du logiciel.

– Macros : il s’agit de scripts à lancer dans le logiciel pour automatiser certaines tâches ;toutefois, nous n’aborderons pas les macros de Flashdevelop dans ce cours.

– Syntax (Syntaxe) : dans ce menu, vous pouvez spécifier à Flashdevelop dans quellangage vous êtes en train de coder, afin qu’il puisse colorier le code de manièreadéquate. En général, on n’utilise pas ce menu, car Flashdevelop détecte le type dechaque fichier à l’aide de son extension.

– Help (Aide) : ce menu regroupe toutes les aides disponibles pour Flashdevelop, etpermet également de vérifier les mises à jour du logiciel.

2. La barre de raccourcis

Les commandes les plus utilisées sont rassemblées ici pour pouvoir les utiliser directe-ment sans avoir à passer par les menus.

3. Les raccourcis de débogage

Cette zone de la barre des raccourcis est réservée aux boutons utiles pour compiler notreprojet (Build Project), le tester (Test Project) et changer le mode de débogage(choisir Debug revient à ajouter le paramètre -debug=true au compilateur du FlexSDK comme nous l’avons vu plus haut).

4. L’éditeur de texte

C’est ici que vous écrirez vos programmes. À gauche sont affichés les numéros des lignes,et en haut se trouvent les différents documents ouverts sous forme d’onglets.

5. Les panneaux de développement

Ce sont des outils qui vous faciliteront la vie lorsque vous programmerez.

6. La console de sortie

Dans ce panneau seront affichés tous les messages de Flashdevelop (comme l’état dela compilation par exemple) et les messages du lecteur Flash (par exemple, avec lafonction trace()).

L’auto-complétion

Cette fonctionnalité est très utile et vous l’utiliserez en permanence pendant que vousprogrammerez : en effet, elle peut terminer ce que vous êtes en train de taper à votreplace (toujours dans une optique de gain de temps) et peut également vous aider àchoisir quoi taper grâce aux informations qu’elle propose.

Commençons par compléter notre classe Main : placez-vous dans la fonction _initaprès le commentaire // entry point (point d’entrée) et commencez à taper trace.Surprise ! Un menu s’ouvre au bout du quatrième caractère, vous proposant d’ajouterla fonction trace(), avec en bonus sa description ! (voir figure 2.41)

Pour valider votre choix, appuyez sur�� ��Entrée et le mot trace est automatiquement

terminé ! Bien entendu, cela n’a pas une grande utilité dans notre cas car le nom de la

46

Page 70: Programmez en Actionscript 3

FLASHDEVELOP À LA RESCOUSSE !

Figure 2.41 – Auto-complétion de la fonction trace()

fonction est très court. Mais imaginez si vous aviez à retenir toutes les fonctions et sien plus leur nom fasait vingt caractères !

Il est également possible d’activer l’auto-complétion à tout moment, mêmesi l’on n’a rien encore tapé : il suffit d’appuyer simultanément sur les touchesCtrl et Espace.

Compiler et tester notre projet

Terminez votre ligne de code pour que votre programme affiche « Hello world ! » dansla console. Comment ça, vous ne vous souvenez plus comment faire ? ! Bon d’accord, jevous donne la ligne à ajouter, mais c’est bien parce que c’est vous :

1 trace("Hello world !");

Voici à quoi doit ressembler le fichier après modifications :

1 package {2 import flash.display.Sprite;3 import flash.events.Event;45 /**6 * ...7 * @author Guillaume8 */9 public class Main extends Sprite {

1011 public function Main():void {12 if (stage)13 init();14 else15 addEventListener(Event.ADDED_TO_STAGE , init);16 }17

47

Page 71: Programmez en Actionscript 3

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

18 private function init(e:Event = null):void {19 removeEventListener(Event.ADDED_TO_STAGE , init);20 // entry point2122 trace("Hello world !");23 }2425 }2627 }

Mais pourquoi le code est différent par rapport à tout à l’heure ?

Très bonne question ! Flashdevelop, en créant notre projet, a automatiquement rem-pli cette classe avec le code de base de telle sorte qu’il n’y ait aucun problème pournous. Les fonctions qu’il a rajouté sont utiles dans certains cas pour éviter des erreursd’affichage. Retenez qu’il faut commencer à programmer juste après le commentaire// entry point seulement dans notre classe Main. Dans les autres classes que vouscréerez, ce code supplémentaire ne sera pas nécessaire.

Une fois que votre classe Main est prête, lancez la compilation en cliquant sur lebouton en forme de flèche bleue (Test Project) dans la barre des raccourcis ou enappuyant simultanément sur les touches

�� ��Ctrl et�� ��Entrée . Vous remarquerez qu’il y

a un bouton Build Project immédiatement à gauche qui ne sert qu’à compiler notreprojet sans le lancer.

Si tout ce passe bien, une fenêtre du lecteur Flash s’ouvre avec votre programme et laconsole affiche notre message « Hello world ! », comme à la figure 2.42.

Figure 2.42 – Lancement du programme

48

Page 72: Programmez en Actionscript 3

FLASHDEVELOP À LA RESCOUSSE !

C’est aussi simple que cela !

En résumé– L’opération de vérification des erreurs, d’assemblage des différents fichiers et de com-

pression d’un projet s’appelle la compilation.– Le Flex SDK est un ensemble d’outils de développement, et notamment un compi-lateur permettant d’aboutir au fichier swf.

– FlashDevelop est un IDE, c’est-à-dire un outil qui permet d’écrire, de compiler etde tester du code Actionscript plus facilement.

– En Actionscript, le code s’écrit à l’intérieur de fonctions, elles-mêmes contenuesdans une classe, le tout placé dans un package.

– Il est possible d’insérer des commentaires au milieu du code grâce aux caractères« // », « /* » et « */ ».

– Il existe une fonction trace() qui permet d’écrire du texte dans la console, et estprincipalement utilisée pour les étapes de débogage.

49

Page 73: Programmez en Actionscript 3

CHAPITRE 2. VOTRE PREMIER PROGRAMME AVEC FLEX SDK

50

Page 74: Programmez en Actionscript 3

Chapitre 3Les variables

Difficulté :

Les variables sont un des éléments les plus importants dans tous les langages de program-mation : elles permettent de mémoriser des informations de toutes sortes. Sans elles, lesprogrammes seraient tous très basiques et moins puissants, le monde informatique seraitalors d’un ennui mortel.

Un petit exemple concret : vous voulez que votre programme vous dise bonjour, après luiavoir donné votre nom. Une variable (appelée monNom par exemple) se chargera alors demémoriser le mot que vous lui entrerez pour plus tard permettre au programme de vousappeler par votre nom : il lui suffira de regarder ce qu’il se trouve dans la variable monNom.

51

Page 75: Programmez en Actionscript 3

CHAPITRE 3. LES VARIABLES

Déclarer et utiliser des variables

Déclaration

Le mot-clé var

La première chose à faire avant d’utiliser des variables, c’est de les créer :

1 var maVariable;

Pour cela, nous avons à notre disposition un mot-clé (ou mot réservé) obligatoire : var.Cette instruction permet de déclarer une variable ; elle s’utilise de la façon suivante :var suivit d’un espace et du nom de la variable.

Petit rappel : un mot-clé (ou réservé) est une expression qui est utilisée parle langage et qui lui est donc réservée, c’est-à-dire que vous ne pouvez pasappeler une variable var ou utiliser ce mot réservé pour autre chose que sonutilité première.

Désormais, vous savez créer une variable, mais le code précédent n’est pas très utile.En effet, chaque variable possède un type, indispensable, qui décrit son comportementet son utilité (par exemple : nombre, entier, chaîne de caractères, etc.). Sans ce type,le langage ne saurait pas à qui il a affaire en lisant une variable et surtout commentl’utiliser.

N’oubliez pas de mettre le point-virgule en fin de ligne !

Comme pour les noms de classes, il est préférable d’utiliser la notationCamel pour le nom de nos variables : leNomDeMaVariable au lieu delenomdemavariable. Vous pouvez également utiliser l’underscore (_) poursimuler les espaces qui eux sont interdits.

Le typage

Il faut donc assigner un type à chaque nouvelle variable pour que le programme puissela reconnaître. Pour cela, on utilise les deux points ainsi :

1 var maVariable:sonType;

Ce type suivra la variable tout au long de l’exécution du programme.

Avant, en Actionscript 2, il était possible de déclarer des variables sans les typer, lelecteur Flash se chargeait de deviner le type de ces variables. Bien entendu, cettetechnique est à proscrire pour des raisons de performances et de rigueur (imaginez

52

Page 76: Programmez en Actionscript 3

DÉCLARER ET UTILISER DES VARIABLES

plusieurs centaines de variables à qui vous avez affaire, mais dont vous ne connaissezpas le type). Désormais, les variables doivent être typées à la création : on appelle celale typage strict. C’est une des principales raisons de l’amélioration des performancesdes animations depuis le passage à l’Actionscript 3.

Les différents types que vous pourrez utiliser seront détaillés un peu plus loin.

Initialiser la nouvelle variable

Après avoir créé une variable, il vous prendra peut-être l’envie d’y mettre quelquechose pour la réutiliser plus tard :

1 var maVariable:sonType = ceQueJeMetsDedans;

Vous remarquerez qu’on peut remplir une variable directement à sa création (ce qui estdrôlement pratique), en mettant un signe égal après le type ; on appelle cette opéra-tion l’initialisation. Ainsi, dès qu’elle sera créée, la variable maVariablesera du typesonTypeet contiendra ceQueJeMetsDedans.

Vous n’êtes évidemment pas obligés d’initialiser les variables, vous pourrez leur donnerune valeur (ou un contenu si vous préférez) plus tard à l’aide de l’affectation.

Les valeurs par défaut

Lorsque vous créez une variable et que vous ne l’initialisez pas, elle n’est pas tout à faitvide ; en effet, elle contient automatiquement une valeur par défaut qui sera souventnull, sauf quelques cas particuliers selon le type de la variable. Ainsi, si vous écrivezceci :

1 var maVariable:sonType;

maVariable contiendra sa valeur par défaut, donnée par son type.

Le mot-clé null est réservé à l’Actionscript, vous ne pouvez donc pas ap-peler une variable null. Cette valeur remplace l’ancien mot-clé équivalentundefined valable en Actionscript 2. Néanmoins, une variable que vous n’ini-tialisez pas contient undefined si elle n’a pas de type, et vous pourrez ren-contrer ce mot-clé avec les tableaux dans un des chapitres suivants.

Utiliser les variables

Affectation

Tout au long de l’exécution du programme, vous aurez sûrement besoin de modifier lecontenu d’une variable en fonction des besoins du moment. La méthode est presqueidentique à l’initialisation, car on utilise à nouveau le signe égal :

53

Page 77: Programmez en Actionscript 3

CHAPITRE 3. LES VARIABLES

1 maVariable = nouveauContenu;

Ainsi, la valeur nouveauContenu sera stockée dans la variable maVariable.

Il est absolument interdit d’affecter une valeur à une variable si cette dernièren’existe pas. Cela n’aurait aucun sens et le compilateur vous le fera savoir enrefusant de compiler votre programme. N’oubliez donc pas de déclarer vosvariables avant de les utiliser.

Lecture

Il est tout aussi intéressant de pouvoir lire une variable pour utiliser son contenu : parexemple, le programme aura besoin de regarder ce que contient la variable monNom pourpouvoir afficher « Bonjour Georges ! » si j’ai mis « Georges » dans la variable avant.Par exemple, pour copier le contenu de la variable a dans la variable b, il faut doncécrire :

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

Vous pouvez voir ainsi que la façon de procéder est très simple : il suffit de renseignerle nom de la variable.

Petite piqûre de rappel : // Je prends ce qu’il y a dans lavariable a, et je le mets dans b est un commentaire ; il per-met d’écrire des informations sur le programme à destination d’éventuelslecteurs ou pour vous-mêmes afin de vous rappeler à quoi sert ce que vousavez tapé là par exemple. Les commentaires n’influent en aucune façon surle fonctionnement du programme, ils sont tout simplement ignorés.

Avec les déclarations des variables, cela donnerait :

1 var a:typeDeA = contenuA;2 var b:typeDeB = contenuB;3 b = a; // Je prends ce qu'il y a dans la variable a, et je le

mets dans b4 // La variable b contient maintenant "contenuA"

Les nombres

Les différents types

Comme vous pouvez vous en douter, les nombres sont très utilisés dans le monde del’informatique, étant donné que le numérique est basé sur des suites de 0 et de 1. Ilexiste différents types de nombres en ActionScript 3, chacun ayant sa spécificité.

54

Page 78: Programmez en Actionscript 3

LES NOMBRES

Le type int

Le type int sert à manipuler des entiers relatifs. Voici un exemple de déclaration etd’initialisation de ce type de variables :

1 var monEntier:int = -100;

Ce type permet de manipuler des nombres codés sur 32 bits (c’est-à-dire 32 « 0 » ou« 1 »), donc compris entre -2 147 483 648 et 2 147 483 647. Si vous sortez de cetencadrement, vous obtiendrez une erreur. La valeur par défaut de ce type est 0.

Pour accéder rapidement à ces deux valeurs, utilisez respectivementint.MIN_VALUE et int.MAX_VALUE. Ce sont des variables un peu spécialescar elles sont utilisables partout dans votre code et on ne peut que les lire.On les appelle des constantes, notion que nous aborderons dans le chapitresur l’orienté objet.

Le type uint

Le type uint sert à manipuler des entiers naturels ou non-signés (c’est-à-dire positifs),voici un exemple de déclaration et d’initialisation :

1 var monEntier:uint = 42;

Le type uint permet d’utiliser des entiers naturels codés sur 32 bits également, donccompris entre 0 et 4 294 967 295. Comme le type int, la valeur par défaut est 0, etvous obtiendrez aussi une erreur si vous sortez de cet encadrement. Dans certainessituations, l’utilisation de ce type ralentit légèrement l’exécution de votre programme.Ainsi, je vous conseille d’utiliser le type int si les nombres que vous voulez manipulersont inférieurs à 2 147 483 647.

Pour accéder rapidement à ces deux valeurs, utilisez respectivementuint.MIN_VALUE et uint.MAX_VALUE. Elles sont également utilisables enlecture seule partout dans votre code.

Le type Number

Le type Number sert à manipuler tous les nombres (entiers comme flottants), dans unintervalle extrêmement grand. On peut presque considérer qu’on peut y mettre tousles nombres. Voici comment les utiliser :

1 var monNombre:Number = 3.1415;

55

Page 79: Programmez en Actionscript 3

CHAPITRE 3. LES VARIABLES

Comme dans la plupart des langages de programmation, et de façon généraleen informatique, on utilise la notation anglaise des nombres flottants (ou àvirgule). C’est-à-dire qu’à la place de la virgule, on met un point : 3,14 écriten français donne 3.14 en Actionscript.

La valeur par défaut de ce type est NaN.

Le mot-clé NaN signifie Not a Number (pas un nombre) : votre nombre prendcette valeur si vous ne l’initialisez pas à une certaine valeur ou si vous tentezd’y stocker autre chose qu’un nombre.

Ainsi, le code suivant ne ferait pas d’erreur, mais la variable nbr aurait pour valeurNaN :

1 var nbr:Number = Number("Je veux un nombre !"); // On force lavariable à contenir du texte ...

2 trace(nbr); // Affiche : NaN

Pour accéder rapidement à la valeur minimum ou à la valeur maximum au-torisée, utilisez respectivement Number.MIN_VALUE et Number.MAX_VALUE.Une nouvelle fois, elles sont utilisables en lecture seule partout dans votrecode.

Vous êtes curieux de savoir quels sont le minimum et le maximum autorisés ? Voici lecode pour les afficher :

1 trace(Number.MIN_VALUE + " à " + Number.MAX_VALUE);2 // Affiche : 4.9406564584124654e -324 à 1.79769313486231e+3083 // Le "e" signifie "fois dix puissance" ; par exemple , 1e+10 é

quivaut à 1x10^10 = 10 000 000 0004 // 1.79769313486231e+308 est donc un nombre à 309 chiffres

Si par mégarde vous essayez d’affecter un nombre flottant (c’est-à-dire àvirgule, comme 3.14) à une variable de type int ou uint, il sera automati-quement arrondi à l’entier inférieur avant d’être stocké dans la variable. Parexemple, 3.14 deviendra 3, et 45.9 deviendra 45.

Opérations sur les nombres

Les opérateurs de base

Pour effectuer une opération entre deux nombres, on procède comme sur les cahiersde Maths à l’école ! L’opération est effectuée lors de l’exécution du programme et lerésultat peut être stocké dans une variable monNombre par exemple. Voici un tableauqui regroupe les opérations de base :

56

Page 80: Programmez en Actionscript 3

LES NOMBRES

Nom de l’opération Symbole ExempleAddition + monNombre = 1 + 4; // monNombre = 5Soustraction - monNombre = 8 - 3; // monNombre = 5Multiplication * monNombre = 2 * 3; // monNombre = 6Division / monNombre = 8 / 4; // monNombre = 2Modulo % monNombre = 8 % 5; // monNombre = 3

Pour ceux qui ne le connaîtraient pas, le modulo est un opérateur moinscourant qui permet de renvoyer le reste de la division euclidienne entre deuxnombres.

Ces opérations peuvent être effectuées sur des variables des trois types de nombres quenous avons vu précédemment, même en les mélangeant. Voici quelques exemples decalculs :

1 var unEntier:uint = 3 + 42;2 var unAutreEntier:int = -25;3 var monResultat:Number = unEntier * unAutreEntier;4 monResultat = monResultat / 100;5 trace(monResultat); // Affiche : -11.25

Contrairement à beaucoup d’autres langages, diviser par zéro ne ferapas planter votre programme. . . Le résultat de l’opération sera en faitNumber.POSITIVE_INFINITY, autrement dit, le nombre infini ! Faites trèsattention à vérifier qu’une telle chose n’arrive pas, sinon vous pourriez avoirdes surprises lors de l’exécution de votre programme. . .

Notez également qu’il faut être prudent sur le type de variables utilisé pour les calculs.Je rappelle qu’un nombre à virgule sera automatiquement arrondi à l’entier inférieursi vous tentez de l’affecter à une variable de type int ou uint. Repérez donc ce qui sedéroule au fil de ces instructions :

1 var unEntier:uint = 2;2 var unNombre:Number = 3.14;3 var monResultat:int = unEntier + unNombre;4 trace(monResultat); // Affiche : 5

Simplifier les calculs

Comme dans beaucoup de langages, il est possible en Actionscript de simplifier descalculs de ce genre :

1 monResultat = monResultat / 100;

Ainsi l’écriture de cette instruction peut être simplifiée et réduite sous la forme :

1 monResultat /= 100;

57

Page 81: Programmez en Actionscript 3

CHAPITRE 3. LES VARIABLES

Ce code est donc plus rapide à écrire, et provoque le même résultat que précédemment.Bien évidemment, cette manipulation n’est pas réservée à la division, mais peut êtreeffectuée avec n’importe quel autre opérateur arithmétique : +=, -=, *=, /= et %=.

Nous avons à présent fait le tour des opérateurs disponibles en Actionscript.

Mais qu’en est-il des autres opérations mathématiques plus complexes,comme la racine carrée ?

En effet, il n’existe pas d’opérateurs arithmétiques en Actionscript 3 pour effectuerde telles opérations. Heureusement, une classe un peu spéciale appelée Math est fourniepar Flash.

La classe Math

Cette classe n’a pas besoin d’être importée, elle est accessible en permanence. Ellecontient une flopée d’outils mathématiques très utiles comme les puissances, les fonc-tions trigonométriques, les nombres aléatoires. . .

Les puissances

Ces fonctions de la classe Math vous permettent de manipuler les puissances sur desnombres :

1 var monNombre:Number = 42;2 // Elever à la puissance3 trace(Math.pow(monNombre , 5));4 // Racine carrée5 trace(Math.sqrt(monNombre));

Les arrondis

Il existe trois types d’arrondis : l’arrondi classique, l’arrondi à l’entier inférieur le plusproche et l’arrondi à l’entier supérieur le plus proche :

1 var monNombre:Number = 3.1415;2 // Arrondi3 trace(Math.round(monNombre)); // 34 // Entier inférieur5 trace(Math.floor(monNombre)); // 36 // Entier supérieur7 trace(Math.ceil(monNombre)); // 4

58

Page 82: Programmez en Actionscript 3

LES NOMBRES

Trigonométrie

Cosinus, sinus, tangente, arc-cosinus, arc-sinus et arc-tangente sont des fonctions tri-gonométriques que nous propose la classe Math :

La valeur de \pi est accessible à l’aide de Math.PI.

1 var angle1:Number = Math.PI / 2;2 var angle2:Number = Math.PI / 6;34 // Cosinus5 trace(Math.cos(angle1));6 // 6.123233995736766e -1778 // Sinus9 trace(Math.sin(angle1));

10 // 11112 // Tangente13 trace(Math.tan(angle1));14 // 163312393531953701516 // ArcCosinus17 trace(Math.acos(angle2 / angle1));18 // 1.23095941734077471920 // ArcSinus21 trace(Math.asin(angle2 / angle1));22 // 0.33983690945412192324 // ArcTangente25 trace(Math.atan(angle1));26 // 1.0038848218538872

Les angles sont toujours exprimés en radians.

Il existe une variante de la fonction arc-tangente en Actionscript 3 :Math.atan2(). Elle sert principalement à calculer sans erreur l’angle entredeux positions. Nous en aurons besoin plus loin dans le cours.

59

Page 83: Programmez en Actionscript 3

CHAPITRE 3. LES VARIABLES

Nombre aléatoire

Il serait très intéressant de fabriquer des nombres aléatoires, pour des jeux par exemple.Cela est possible avec la fonction Math.random() :

1 trace(Math.random ()); // Affiche un nombre flottant aléatoirecompris entre 0 et 1

Pour générer un nombre aléatoire entre deux valeurs a et b (voir figure 3.1), il faututiliser la formule suivante :

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

Figure 3.1 – Création d’un nombre aléatoire

Les chaînes de caractères

Les chaînes de caractères sont également très utilisées. Il s’agit d’une suite de carac-tères qui forme du texte. Par exemple, « Hello world ! » est une chaîne de caractères ;son premier caractère est le « H », et son dernier caractère est le « ! ».

Une chaîne de caractères est toujours entourée de guillemets, comme nous l’avonsvu dans le chapitre précédent :

1 trace("Hello world !");

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

1 trace('Hello world !');

Attention toutefois à ne pas mélanger les deux, cela ne marcherait pas. Ainsi,le code trace("Hello world !’); est incorrect.

Échappement des caractères spéciaux

Mais si je veux mettre des guillemets ou des apostrophes dans ma chaîne decaractères ?

60

Page 84: Programmez en Actionscript 3

LES CHAÎNES DE CARACTÈRES

Je vous voyais venir ! Effectivement, mettre des guillemets dans une chaîne de ca-ractères à guillemets ou des apostrophes dans une chaîne de caractères à apos-trophes serait problématique : en effet, le compilateur pensera que vous avez terminévotre chaîne au deuxième guillemet ou apostrophe rencontré, et se demandera pourquoidiable d’autres caractères se baladent derrière !

Dans cet exemple, vous pouvez voir que la coloration syntaxique nous montre le pro-blème :

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

En effet, le « Hello world ! » n’est dans ce cas plus considéré comme faisant partie dela chaîne de caractères. . .

Pour remédier à cela, il faut échapper le ou les caractères qui posent problème. Celaconsiste à mettre un autre caractère spécial, l’antislash (\), qui permettra de dire quele caractère suivant doit être pris pour un caractère tout à fait banal dans notre chaîne.

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 d’échapper, car ce n’est plus le caractère guillemet qui précise où débuteet où se termine la chaîne, mais l’apostrophe. Par contre, si vous voulez mettre uneapostrophe en plus, le problème 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 caractère apostrophe qui pose problème !

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

Vous pouvez systématiquement échapper les guillemets et apostrophes dansles chaînes de caractères si cela vous met à l’aise.

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

Utiliser les variables

Maintenant, si nous voulons mémoriser des chaînes de caractères, il va falloir lesranger dans des variables de type String. Par exemple, pour mémoriser notre phrase« Hello world ! » dans la variable coucou, il faut procéder ainsi :

61

Page 85: Programmez en Actionscript 3

CHAPITRE 3. LES VARIABLES

1 var coucou:String = "Hello world !";2 trace(coucou); // Affiche : Hello world !

La valeur par défaut d’une variable de type String est null.

Concaténation de chaînes

Concaténer deux chaînes de caractères consiste à les assembler pour ne for-mer qu’une seule chaîne. Par exemple, concaténer la chaîne « Hello » avec la chaîne« world ! » donnerait une nouvelle chaîne plus grande : « Hello world ! ». Pour cela, ilfaut utiliser l’opérateur + (qui sert aussi à additionner deux nombres), de cette façon :

1 "Hello" + " world !"

Ainsi, si l’on voulait afficher notre texte en deux parties, nous écririons ceci :

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

Il est alors possible de concaténer des chaînes avec des variables de tout type (y comprisavec des nombres) et de différentes manières :

1 var coucouDebut:String = "Hello ";2 var coucouFin:String = " !";3 var monNom:String = "Jérôme";4 var monAge:int = 42;5 trace(coucouDebut + monNom + coucouFin + " Tu as " + monAge + "

ans , n'est -ce pas ?");6 // Affiche : Hello Jérôme ! Tu as 42 ans , n'est -ce pas ?78 trace(Number.MIN_VALUE + " à " + Number.MAX_VALUE);9 // Affiche : 4.9406564584124654e -324 à 1.79769313486231e+308

Quelques variables et fonctions utiles

Ces variables ou fonctions sont obligatoirement attachées à une variable de type Stringà l’aide d’un point. Vous ne pouvez pas les utiliser sur une chaîne de caractères simplecomme "Hello world !".

Longueur d’une chaîne

Pour connaître la longueur d’une chaîne de caractères, c’est-à-dire, le nombre decaractères qu’elle contient, il faut utiliser la variable length disponible sur notre chaînede cette manière :

62

Page 86: Programmez en Actionscript 3

LES CHAÎNES DE CARACTÈRES

1 var coucou:String = "Hello world !";2 trace("Cette chaîne contient " + coucou.length + " caractères."

);3 // Affiche : Cette chaîne contient 13 caractères.

Le point est important : il signifie que c’est la longueur de cette chaîne particulière quel’on veut.

Changer la casse d’une chaîne

La casse est l’état d’une lettre, c’est-à-dire si elle est en minuscule ou en majuscule.Il est possible de modifier la casse de l’ensemble d’une chaîne de caractèresen utilisant les fonctions toLowerCase() (en casse minuscule) et toUpperCase() (encasse majuscule) :

1 var coucou:String = "Hello world !";2 // En minuscules3 trace(coucou.toLowerCase ()); // hello world !4 // En majuscules5 trace(coucou.toUpperCase ()); // HELLO WORLD !

Rechercher dans une chaîne

Il peut être utile de rechercher un ou plusieurs caractères dans une chaîne. Pour cela,on utilise la fonction indexOf() (position de) :

1 maVariable.indexOf("Chaîne recherchée");

La fonction renvoie la position du premier caractère de la chaîne recherché dans lavariable, ou -1 si elle ne l’a pas trouvé.

Vous pouvez aussi spécifier une variable de type String entre les parenthèses,au lieu d’une chaîne de caractères simple.

Cherchons la position de la première lettre « a » dans notre variable :

1 var coucou:String = "Hello world !";2 trace(coucou.indexOf("a")); // -1, on n'a rien trouvé

Effectivement, il n’y a pas de « a » dans notre chaîne. . . Retentons notre chance avecle mot « world » :

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

Bravo, nous avons trouvé le mot « world » à la septième lettre !

63

Page 87: Programmez en Actionscript 3

CHAPITRE 3. LES VARIABLES

Il se situe à la septième position, car le numéro des caractères commenceà zéro : le premier caractère a le numéro 0, le deuxième a le numéro 1 etainsi de suite. Du coup, pour avoir le numéro du dernier caractère dans lachaîne, il faut prendre sa longueur moins un : coucou.length - 1.

Remplacer dans une chaîne

Cette fonction replace() est similaire à la fonction de recherche, mais il faut en plusindiquer le texte qui va remplacer l’ancien.

1 maVariable.replace("Chaîne recherchée", "Chaîne à insérer à laplace");

Modifions dynamiquement notre chaîne pour remplacer « world » par « Jérôme » :

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

La variable de départ n’est pas modifiée : la fonction se contente de renvoyer la nouvellechaîne que l’on peut afficher ou mettre dans une variable :

1 var coucou:String = "Hello world !";2 var salut:String = coucou.replace("world", "Jérôme");3 trace(salut); // Hello Jérôme !4 trace(coucou); // Hello world !

Le texte n’est remplacé qu’une seule fois : dès que le texte recherché estrencontré, il est remplacé et la fonction s’arrête.

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

world !

Pour pouvoir remplacer tous les « world » en « Jérôme », il faut faire autant dereplace()que nécessaire :

1 var coucou:String = "Hello world world world !";2 coucou = coucou.replace("world", "Jérôme");3 trace(coucou); // Hello Jérôme world world !4 coucou = coucou.replace("world", "Jérôme");5 trace(coucou); // Hello Jérôme Jérôme world !6 coucou = coucou.replace("world", "Jérôme");7 trace(coucou); // Hello Jérôme Jérôme Jérôme !

64

Page 88: Programmez en Actionscript 3

LES CHAÎNES DE CARACTÈRES

Il existe une autre méthode bien plus efficace et puissante qui consiste à uti-liser les expressions régulières (ou RegExp) : ce sont des codes suivantdes règles précises, capables de rechercher et de remplacer du texte plu-sieurs fois dans une même chaîne, ceci parmi une foule d’autres choses fortutiles. Malheureusement, cette notion est plutôt complexe à appréhender, jene l’aborderais pas dans le cours.

En résumé– Une variable permet de mémoriser une valeur.– Le mot-clé var sert à déclarer une variable qui peut être affectée d’une valeur parun signe « = ».

– On utilise les trois types int, uint et Number pour des valeurs numériques.– Pour effectuer des calculs, il existe principalement les opérateurs de base : +, -,*, / et %.

– Grâce à la classe Math, il est possible de réaliser des opérations mathématiquescomplexes.

– Le type String est réservé à l’utilisation des chaînes de caractères.– Différentes fonctions permettent de manipuler les chaînes de caractères et il estpossible de les concaténer grâce à l’opérateur +.

65

Page 89: Programmez en Actionscript 3

CHAPITRE 3. LES VARIABLES

66

Page 90: Programmez en Actionscript 3

Chapitre 4Les conditions

Difficulté :

Nous avons vu dans le précédent chapitre comment manipuler les nombres à l’aide d’opérateurset de variables. Nous allons voir à présent comment tester le contenu de ces variables ;ainsi vous pourrez exécuter des instructions ou non pour les différentes valeurs que pourrontprendre vos variables. Comme vous pourrez le voir, les conditions sont très utiles dans lemonde de l’informatique, et sont la base de l’interactivité des machines, sans quoi ellesferaient toujours la même chose !

67

Page 91: Programmez en Actionscript 3

CHAPITRE 4. LES CONDITIONS

Écriture d’une condition

Qu’est-ce qu’une condition ?

Les conditions permettent de tester le contenu d’une ou plusieurs variables. Ainsi,vous pourrez exécuter des instructions différentes suivant le résultat du test. Grâce à cesstructures conditionnelles, le programme sera alors en mesure de prendre des décisions.Nos programmes seront donc moins monotones et pourront réagir différemment suivantles circonstances : imaginez si tous les programmes faisaient exactement la même chosequel que soit le contexte, cela serait bien ennuyeux ! Voici le genre d’instructions quenous serons capables de réaliser à l’aide des conditions :

1 SI ma condition est vraie2 ALORS effectuer mes instructions

Dans une condition, nous pourrons ainsi tester différentes choses. Par exemple, nouspourrions tester un nombre entier pour savoir s’il est positif ou non. Nous cherchonsdonc une relation entre deux valeurs pour pouvoir les comparer. Pour cela, nous utili-serons donc divers opérateurs présentés dans la suite de ce cours. Si la condition estvraie, alors les instructions qui la suivent sont exécutées. Dans le cas contraire, ellessont tout simplement ignorées.

Ne vous inquiétez pas si vous avez du mal à saisir le concept, vous comprendrez mieuxau fil du chapitre.

En Actionscript, comme dans beaucoup d’autres langages, les conditions ren-voient automatiquement une valeur de type Boolean comme nous le verronsplus loin dans le chapitre : true pour vraie et false pour fausse.

Les opérateurs relationnels

Les opérateurs relationnels permettent de comparer une variable à une valeur oudeux variables entre elles. Dans le tableau ci-dessous sont répertoriés les différentssymboles correspondants. Ces symboles seront utilisés en permanence, c’est pourquoiil serait judicieux de les retenir.

De manière générale, les opérateurs sont utilisés ainsi : une variable ou une valeur,l’opérateur et une autre variable ou valeur. Voici quelques exemples de conditions :

1 // Cette condition est vraie si monEntier contient un nombresupérieur à 2

2 monEntier > 23 // Cette deuxième condition est vraie si maVariable et

monAutreVariable contiennent la même valeur4 monVariable == monAutreVariable

Vous pouvez également comparer des chaînes de caractères :

68

Page 92: Programmez en Actionscript 3

ÉCRITURE D’UNE CONDITION

Opérateur Signification pour des va-leurs numériques

Signification pour des carac-tères

< est inférieur à est avant dans l’ordre alphabé-tique à

> est supérieur à est après dans l’ordre alphabé-tique à

<= est inférieur ou égal à est avant dans l’ordre alphabé-tique ou identique à

>= est supérieur ou égal à est après dans l’ordre alphabé-tique ou identique à

== est égal à est identique à!= est différent de est différent de=== est strictement égal à est strictement identique à!== est strictement différent de est strictement différent de

1 var t1:String = "Salut";2 var t2:String = "Salut";3 var t3:String = "Bonjour";4 trace(t1 == t2); // Affiche : true5 trace(t1 == t3); // Affiche : false6 trace(t1 > t3); // Affiche : true , car Salut est après Bonjour

dans l'ordre alphabétique

Vous remarquerez que le test d’égalité s’effectue à l’aide de deux signes «=».Les débutants omettent souvent le deuxième symbole « = », ce qui est sourced’erreurs dans votre code. En effet, le symbole « = » seul est un signe d’affec-tation pour les variables comme nous l’avons vu dans le précédent chapitre.

Comparer deux variables : une question de types

Un opérateur relationnel permet de comparer uniquement deux expressions du mêmetype. Il n’est pas possible de comparer deux variables dont l’une, par exemple, serait detype int et l’autre de type String. Si cela se produisait, le compilateur vous afficheraitun message d’erreur de ce type : « Error : Comparison between. . . ». Toutefois, il existeune exception : les nombres qui peuvent être comparés entre eux même si leur typevarie entre int, uint et Number. Par exemple, le code suivant fonctionnera sans erreur :

1 var nombre:Number = 0.4;2 var entier:int = 1;3 trace(nombre < entier); // Affiche : true

Mais alors, comment puis-je facilement comparer un nombre et une chaînede caractères ?

69

Page 93: Programmez en Actionscript 3

CHAPITRE 4. LES CONDITIONS

Et bien, il suffit de transformer l’une de nos deux variables pour que les deux aientexactement le même type ! Par exemple, transformons le nombre en chaîne de carac-tères :

1 var nombre:Number = 3.14;2 var texte:String = "3.14";3 trace(nombre.toString () == texte); // Affiche : true

En effet, taper .toString() derrière notre variable de type Number transforme sa valeuren chaîne de caractères afin que la comparaison fonctionne correctement !

La variable nombre n’est pas réellement transformée, elle reste de type Numberpar la suite.

Précisions sur les opérateurs stricts

Les opérateurs stricts (=== et !==) servent à comparer deux objets quelconques (parexemple, deux variables) en regardant non seulement leur valeur, mais aussi leur type.Ces opérateurs sont peu utilisés : en général, on connaît à l’avance le type des variablesque l’on manipule. Par exemple, je déclare et initialise trois variables de type Object,c’est-à-dire qu’elles n’ont pas de type bien défini et que l’on peut y mettre ce quel’on souhaite ; attention toutefois à ne pas abuser de ce type un peu spécial, il ralentitl’exécution de votre programme. Ensuite, je teste la valeur de ces variables avec ==,pour finalement tester leur valeur et leur type en même temps avec ===. De touteévidence, le caractère « 3 » n’est pas du même type que l’entier 3.

1 var nom:Object = "42";2 var prenom:Object = "42";3 var age:Object = 424 trace(nom === prenom); // Affiche : true5 trace(nom == age); // Affiche : true6 trace(nom === age); // Affiche : false

Dans ce cas très précis, votre programme Flash convertira automatiquement leformat des variables lorsqu’il est nécessaire, sauf si vous utilisez les opérateurs=== ou !==. Ainsi, la comparaison entre la chaîne de caractères et l’entier sedéroule sans accroc.

Les opérateurs logiques

Contrairement aux opérateurs précédents qui permettaient de comparer des valeurs, lesopérateurs logiques servent à combiner plusieurs conditions. Ceux-ci peuvent avoirleur utilité lorsque nous voulons tester par exemple, si un nombre est compris dans unintervalle. Les opérateurs relationnels ne permettent pas ce genre de comparaison.

70

Page 94: Programmez en Actionscript 3

ÉCRITURE D’UNE CONDITION

Nous pouvons donc contourner le problème en combinant plusieurs conditions. Prenonsun exemple : nous voulons savoir si une variable monNombre est comprise entre 0 et 10.Pour cela nous pourrions décomposer ce test en deux conditions :

– monNombre est supérieur à 0.– monNombre est inférieur à 10.

Les opérateurs logiques nous permettent alors d’associer ces deux conditions en uneseule : monNombre > 0 ET monNombre < 10.

Le tableau ci-dessous présente donc ces différents opérateurs, ainsi que les symbolesqui leur sont associés :

Opérateur Signification! NON logique&& ET logique|| OU logique

Ainsi, nous allons comparer notre nombre par rapport à un intervalle à l’aide de l’opé-rateur && :

1 // Test pour savoir si monNombre est compris entre 0 et 102 monNombre > 0 && monNombre < 10

La priorité des opérateurs

Pour décider dans quel ordre les différentes opérations seront effectuées, les opérateursrespectent les règles de priorité suivantes :

– Les opérateurs arithmétiques (+, -, *, /, %) sont prioritaires par rapport auxopérateurs relationnels (==, !=, <, >, etc. . .).

– Les opérateurs relationnels sont prioritaires par rapport aux opérateurs logiques(!, && et ||).

– Les opérations entourées de parenthèses sont toujours prioritaires.

Ainsi la condition 3 + 4 > 5 est vraie du fait que l’addition est effectuée avant lacomparaison.

Quelques exemples d’opérations imbriquées :

1 trace(1 == 2); // Affiche : false2 trace(1 + 1 == 2); // Affiche : true3 trace(1 == 2 || 2 == 2); // Affiche : true4 trace(1 != 2 && 1 + 1 == 2); // Affiche : true5 trace(1 != 2 && 1 + 2 == 2); // Affiche : false

Pour mieux comprendre l’utilisation de ces conditions, nous allons étudier différentesstructures qui les utilisent. Commençons tout de suite avec l’instruction if...else.

71

Page 95: Programmez en Actionscript 3

CHAPITRE 4. LES CONDITIONS

L’instruction if. . .else

La structure de base

La syntaxe

L’instruction if...else est la structure de base des conditions. Grâce à elle, nouspouvons exécuter des instructions différentes suivant si la condition est vraie ou fausse.Sans plus attendre, voyons la structure if...else écrite en Actionscript :1 if(/* Condition */)2 {3 // Instructions si la condition est vraie4 }5 else6 {7 // Instructions si la condition est fausse8 }

Vous remarquerez donc, dans cette structure, les deux blocs d’instructions définis par lespaires d’accolades. Si la condition est vérifiée, alors le premier bloc d’instructions seraexécuté, sinon (traduction du mot « else ») ce sera le second. Bien entendu, l’écrituredu bloc else n’est pas obligatoire. En revanche, il n’est pas possible d’écrire un blocelse seul. Vous pourriez donc vous contenter du code suivant :1 if(/* Condition */)2 {3 // Instructions si la condition est vraie4 }

Parce que rien ne vaut un bon exemple, nous allons tout de suite tester une premièrecondition dans notre IDE. Pour cela, nous prendrons une variable nommée maViereprésentant, par exemple, la vie restante dans un jeu quelconque. Nous pourrionsalors tester si vous êtes encore en vie ou si vous êtes mort. Voici donc le code à insérerjuste après le commentaire // entry point de votre classe Main :1 var maVie:uint = 1;23 if(maVie == 0)4 {5 trace("Vous êtes mort.");6 }7 else8 {9 trace("Vous êtes toujours en vie.");

10 }1112 // Affiche : Vous êtes toujours en vie.

Ici la variable maVie est égale à 1, et donc la condition maVie == 0 est fausse. Ainsi, lorsde l’exécution, seule l’instruction à l’intérieur des accolades du else sera exécutée. Vous

72

Page 96: Programmez en Actionscript 3

L’INSTRUCTION IF. . .ELSE

verrez donc apparaitre le message : « Vous êtes toujours en vie. » N’hésitez pas à testerce code avec différentes valeurs pour maVie afin de bien comprendre le fonctionnement.

Pour écrire une condition if seule ou if...else, il faut respecter un certainnombre de règles et de conventions que nous allons détailler.

Les règles et conventions d’écriture

Nous allons maintenant définir quelles sont les différentes règles d’écriture ainsi quedes conventions fortement recommandées. Tout d’abord, vous aurez sûrement remar-qué l’absence de point-virgule « ; » après les accolades. En effet, les conditions nese terminent jamais par un point-virgule. D’autre part, les parenthèses qui entourentvotre condition sont obligatoires. En revanche, les accolades peuvent être facultativesmais uniquement dans un cas ; il s’agit du cas où il n’y a qu’une seule instruction àl’intérieur du bloc d’instructions. Il est alors possible d’écrire votre condition suivantl’une des trois formes ci-dessous :

1 if(maVie == 0)2 trace("Vous êtes mort.");3 else4 trace("Vous êtes toujours en vie.");

ou bien :

1 if(maVie == 0)2 trace("Vous êtes mort.");3 else4 {5 trace("Vous êtes toujours en vie.");6 }

ou encore :

1 if(maVie == 0)2 {3 trace("Vous êtes mort.");4 }5 else6 trace("Vous êtes toujours en vie.");

Pour finir ce paragraphe, nous parlerons d’une chose très importante en termes deprésentation. Vous aurez certainement remarqué la mise en forme utilisée depuis ledébut pour écrire les conditions :

– L’accolade ouvrante sur une ligne.– Vos instructions décalées vers la droite à l’aide d’une tabulation.– L’accolade fermante sur une ligne.

73

Page 97: Programmez en Actionscript 3

CHAPITRE 4. LES CONDITIONS

Cette mise en forme est appelée l’indentation et n’est pas obligatoire cependant, ilest très fortement déconseillé de tout écrire sur une seule ligne ou de ne pas décalerles instructions à l’intérieur des accolades. En effet, respecter ces règles vous permettrade rendre vos codes beaucoup plus clairs et lisibles par vous mais aussi par d’autrespersonnes qui ne connaîtront pas la façon dont vous avez réalisé votre programme.

Les ternaires

Dans certains cas, il est possible de condenser des conditions : on appelle cela lesexpressions ternaires. Cette technique n’est pas applicable tout le temps et il nefaut pas en abuser. Pour introduire cette notion, nous allons partir du code suivant :

1 var monMessage:String;2 if(maVie == 0)3 monMessage = "Vous êtes mort.";4 else5 monMessage = "Vous êtes toujours en vie.";6 trace(monMessage);

Vous remarquerez qu’ici la condition sert uniquement à affecter une variable d’unevaleur qui dépend d’une condition. Les expressions ternaires ne peuvent être utiliséesque dans ce cas-là ! Il est alors possible de réécrire le code précédent sous une formecondensée :

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

2 trace(monMessage);

Le principe est alors d’écrire l’ensemble de la condition en une seule ligne et d’affecterdirectement la variable. C’est une forme d’écriture qui peut être pratique, mais sachezqu’en réalité elle est très peu utilisée car elle est difficile à lire. Utilisez donc les expres-sions ternaires pour diminuer le volume de votre code, mais tâchez de garder un codequi soit le plus facilement lisible !

L’écriture des expressions ternaires est assez spéciale et souvent trompeuse.Notez donc la présence du symbole « ? » qui permet de tester la conditionplacée juste avant, ainsi que le signe « : » permettant de remplacer le mot-clé else et de séparer les instructions.

Le type booléen

En Actionscript, il existe un type de variable de type booléen : Boolean. Ces va-riables ne peuvent prendre que deux valeurs : true ou false. Les booléens sont trèsutilisés avec les conditions car ils permettent facilement d’exprimer si une conditionest vraie ou fausse. D’ailleurs, une condition est elle-même exprimée sous la formed’un booléen. Pour s’en assurer, vous allez tester le code suivant :

74

Page 98: Programmez en Actionscript 3

L’INSTRUCTION IF. . .ELSE

1 if(true)2 trace("Ma condition est vraie.");3 else4 trace("Ma condition est fausse.");56 // Affiche : Ma condition est vraie.

Nous pouvons remarquer qu’en effet la condition true est vraie, c’est pourquoi l’utili-sation de variables de type booléen peut être préférable. Il n’est alors plus nécessaired’écrire le test « == true » pour une variable de type booléen. Ainsi, si vous utilisezdes noms judicieux pour vos variables, le code paraîtra plus clair :

1 var estEnVie:Boolean = true;23 if(estEnVie)4 {5 trace("Vous êtes toujours en vie.");6 }7 else8 {9 trace("Vous êtes mort.");

10 }1112 // Affiche : Vous êtes toujours en vie.

Étant donné que le résultat d’une condition est un booléen, il est tout à fait possiblede le stocker dans une variable :

1 var maVie:uint = 1;2 var estEnVie:Boolean = (maVie > 0);3 trace(estEnVie); // Affiche : true

L’utilisation des booléens sert principalement à alléger votre code et lerendre plus lisible. Encore une fois, choisissez des noms explicites pour vosvariables, cela permettra de faire plus facilement ressortir la logique de votreprogramme.

La structure avec else if

Avant de clore cette partie sur la structure if...else, nous allons voir comment réaliserdes tests supplémentaires avec else if. Ici, rien de bien compliqué, c’est pourquoi vouscomprendrez aisément le code ci-dessous :

1 var monNombre:int = 1;23 if(monNombre < 0)4 {5 trace("Ce nombre est négatif.");

75

Page 99: Programmez en Actionscript 3

CHAPITRE 4. LES CONDITIONS

6 }7 else if(monNombre == 0)8 {9 trace("Ce nombre est nul.");

10 }11 else12 {13 trace("Ce nombre est positif.");14 }1516 // Affiche : Ce nombre est positif.

Bien qu’il soit possible d’effectuer plusieurs tests à la suite à l’aide de cette méthode,cela peut s’avérer assez répétitif. C’est pourquoi, il existe une structure qui permetd’alléger l’écriture de telles conditions : il s’agit de l’instruction switch que nous allonsdétailler dans la suite.

L’instruction switch

L’utilisation conventionnelle

Face à la structure if...else, la condition switch permet de simplifier et d’allégerle code lorsque vous voulez tester différentes valeurs pour une même variable. Cettestructure n’offre pas plus de possibilités que celle en if...else, il s’agit simplementd’une manière différente d’écrire des conditions. Voici comment se présente l’instructionswitch :

1 switch(/* Variable */)2 {3 case /* Argument */ :4 // Instructions5 break;6 case /* Argument */ :7 // Instructions8 break;9 case /* Argument */ :

10 // Instructions11 break;12 default :13 // Instructions14 }

Pour utiliser cette structure, il suffit de renseigner la variable à tester puis d’étudierles différents arguments. Notez la présence de l’instruction « break; » qui permet desortir du switch. Cette instruction est obligatoire, en cas d’absence, les instructionssituées en dessous seraient exécutées. Enfin, le default correspond au cas par défaut,nous pouvons le comparer au else d’une instruction if...else. Voici un exemple decode que vous pouvez tester :

76

Page 100: Programmez en Actionscript 3

L’INSTRUCTION SWITCH

1 var monNombre:int = 1;2 switch(monNombre)3 {4 case 0 :5 trace("Ce nombre vaut 0.");6 break;7 case 1 :8 trace("Ce nombre vaut 1.");9 break;

10 case 2 :11 trace("Ce nombre vaut 2.");12 break;13 default :14 trace("Ce nombre ne vaut ni 0, ni 1, ni 2.");15 }

Notez qu’après chaque argument vous devez écrire un double point et nonun point-virgule.

Une utilisation spécifique à l’Actionscript

Contrairement à d’autres langages tels que le C ou encore le Java, l’instruction switchen Actionscript ne permet pas uniquement de faire des égalités. En plaçant la valeurtrue à la place de la variable, il est alors possible de la comparer avec un autre boo-léen, en particulier une condition. Voici la structure switch pouvant tester diversesconditions :

1 switch(true)2 {3 case (/* Condition */) :4 // Instructions5 break;6 case (/* Condition */) :7 // Instructions8 break;9 case (/* Condition */) :

10 // Instructions11 break;12 }

Voici un exemple concret qui permet de tester si une variable monNombre est un nombrenégatif, nul ou positif :

1 var monNombre:int = 1;2 switch(true)3 {4 case (monNombre < 0) :

77

Page 101: Programmez en Actionscript 3

CHAPITRE 4. LES CONDITIONS

5 trace("Ce nombre est négatif.");6 break;7 case (monNombre == 0) :8 trace("Ce nombre est nul.");9 break;

10 case (monNombre > 0) :11 trace("Ce nombre est positif.");12 break;13 }

En résumé– Grâce aux conditions, nous pouvons effectuer des choses différentes suivant l’étatd’une ou plusieurs variables.

– Les conditions sont réalisées à l’aide d’opérateurs relationnels et logiques, dontle résultat est un booléen.

– L’instruction if...else est la plus utilisée.– Les expressions ternaires permettent de condenser l’écriture d’une instructionif...else.

– Lorsque vous avez une multitude de valeurs à tester, l’instruction switch est plusappropriée.

78

Page 102: Programmez en Actionscript 3

Chapitre 5Les boucles

Difficulté :

Dans le chapitre précédent, nous avons vu comment réaliser des conditions et permettreainsi aux machines de faire des choix. C’est déjà un grand pas dans le monde informatique,mais ce n’est pas suffisant : à présent, nous allons introduire les boucles !

Les boucles sont liées à la notion de répétitivité : il s’agit en fait de réitérer une séried’instructions plusieurs fois. Les boucles sont indispensables dans tout un tas de situa-tions, par exemple lorsque nous demandons à l’utilisateur de jouer tant que la partie n’estpas terminée. Pour cela, nous disposons de trois boucles en Actionscript 3 que nousdétaillerons au fil du chapitre. Étant donné que nous avons déjà vu comment écrire unecondition, ce chapitre devrait être relativement simple à appréhender.

79

Page 103: Programmez en Actionscript 3

CHAPITRE 5. LES BOUCLES

La boucle while

Le principe

Comme nous l’avons dit précédemment, les boucles permettent de répéter des instruc-tions un certain nombre de fois. La difficulté est alors de savoir quand ces instructionsdoivent cesser d’être répétées. Pour cela, nous aurons besoin des conditions. Sans plusattendre, voici le genre d’instructions réalisables à l’aide des boucles :

1 TANT QUE ma condition est vraie2 ALORS effectuer mes instructions

Dans une boucle while, la condition s’utilise exactement de la même manière que pourune instruction if...else. Il faudra donc déclarer une variable avant la boucle puisla tester à l’intérieur de la condition. En revanche, dans ce cas, la variable devra êtremise à jour à l’intérieur de la boucle pour pouvoir en sortir. En effet, pour stopperla répétition des instructions, la condition doit obligatoirement devenir fausse à uncertain moment. Oublier de mettre à jour cette variable conduirait à une boucle infinie,les instructions se répèteraient alors à l’infini.

Dans le cas d’une boucle while, la condition est testée avant d’entrer dans laboucle. Ainsi, si la condition est déjà fausse avant la boucle, les instructionsà l’intérieur de celle-ci ne seront jamais exécutées.

Vous comprendrez mieux le fonctionnement des boucles au fur et à mesure de lalecture de ce chapitre.

Écriture en Actionscript

En Actionscript, la boucle while permet de gérer toutes les situations : celles quenous verrons plus tard sont légèrement différentes, mais n’offrent aucune fonctionnalitésupplémentaire. La structure d’une boucle est très similaire à celle des structuresconditionnelles vues précédemment. Voici donc comment écrire une boucle while enActionscript :

1 while(/* Condition */)2 {3 // Instructions si vraie4 }

Comme pour l’instruction if...else, les accolades deviennent facultatives s’il n’y aqu’une seule condition :

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

80

Page 104: Programmez en Actionscript 3

LA BOUCLE WHILE

Cette seconde syntaxe est correcte : en écrivant cela vous n’aurez pas demessage d’erreur. Cependant, dans une boucle digne de ce nom, vous n’aurezen réalité que très rarement une seule instruction. En effet, votre bouclecontiendra toujours au moins une instruction ainsi qu’une mise à jour devotre variable.

Afin de mieux comprendre le fonctionnement et la syntaxe d’une boucle while, nousallons voir différents exemples dans la suite de ce cours.

Exemples d’utilisation

Pour commencer, nous allons tester une boucle qui affiche la valeur de notre variabletestée dans la condition. Voici le code source de notre boucle à tester :

1 var i:uint = 0;2 while(i < 5)3 {4 trace(i);5 i = i + 1;6 }

Si vous lancez le projet, vous devriez obtenir ceci dans la console de sortie :

01234

Vous constaterez alors que la valeur 5 n’est pas affichée. Effectivement,lorsque notre variable i prend cette valeur, la condition i < 5 n’est plusvérifiée ; l’instruction trace(i) n’est donc plus exécutée. Il faudra ainsi êtrevigilant sur l’écriture de votre condition pour que votre boucle s’exécute biencomme vous le désirez.

L’intérêt d’utiliser une boucle while est que nous n’avons pas besoin de connaître àl’avance ou de nous soucier du nombre de répétitions. Pour illustrer cela, nous allonsprendre un exemple : imaginons que nous cherchions la puissance de 2 correspondant à1024. Nous devons alors calculer les puissances successives de 2 jusqu’à atteindre 1024.Cependant, dans notre cas, nous ne savons pas combien de fois nous allons devoirrépéter l’opération. Nous utiliserons donc une boucle while de la manière suivante :

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

81

Page 105: Programmez en Actionscript 3

CHAPITRE 5. LES BOUCLES

7 }8 trace(i); // Affiche : 10

En effet, pour ceux qui connaissaient déjà la réponse : 210 = 1024. Notre boucle s’estdonc exécutée 9 fois ce qui correspond à i = 10. Nous voyons bien ici que nous n’avionspas besoin de connaître à l’avance le nombre de répétitions de la boucle.

Quelques astuces

Vous savez déjà tout ce qu’il faut savoir sur la boucle while cependant, je vais vousdonner maintenant quelques astuces pour améliorer la lisibilité de votre code. Cesconseils ne sont en aucun cas une obligation, il s’agit principalement de pratiques trèscourantes chez les programmeurs. Elles permettront d’alléger votre code source maiségalement de le rendre plus lisible pour un autre programmeur. Voici donc ces astucesfortement recommandées :

– Traditionnellement, en Actionscript et dans beaucoup d’autres langages, on utiliseles noms de variables i, j et k pour compter à l’intérieur d’une boucle. En utilisant cesnoms, vous facilitez la lecture de votre code, surtout si celui-ci est assez conséquent.

– Lorsque vous utiliserez des boucles, vous serez très souvent amené à incrémenter oudécrémenter vos variables : i = i + 1 ou i = i- 1. Pour simplifier l’écriture, nouspouvons utiliser pour l’incrémentation i++ et pour la décrémentation i–.

Enfin, nous allons revenir sur la notion de boucle infinie. Comme nous l’avons dit, ils’agit d’une boucle dont la condition est toujours vérifiée. Les instructions à l’intérieursont alors répétées à l’infini. En voici un exemple :

1 var maCondition:Boolean = true;2 while(maCondition)3 {4 trace("Ceci est une boucle infinie");5 }

Vous vous en doutez certainement, cette boucle va afficher le message : « Ceci est uneboucle infinie » un nombre indéfini de fois, comme ceci :

Ceci est une boucle infinieCeci est une boucle infinieCeci est une boucle infinie...

En général, il faut à tout prix éviter d’écrire ce genre de choses. Cependant, ce type deboucles peut s’avérer utile dans certains cas.

La boucle do. . .while

Nous allons à présent parler de la boucle do...while qui est une voisine très prochede la boucle while. Toutefois, nous pouvons noter une différence dans la syntaxe par

82

Page 106: Programmez en Actionscript 3

LA BOUCLE DO. . .WHILE

l’apparition du mot do ainsi que du transfert de la condition en fin de boucle. Ceciapporte une légère différence dans l’interprétation du code, mais nous y reviendronsaprès. Voici la syntaxe de cette nouvelle boucle :

1 do2 {3 // Instructions si vraie4 } while(/* Condition */);

Notez cependant l’apparition d’un point-virgule « ; » après la condition. L’ou-bli de ce point-virgule est une erreur très courante chez les débutants. Veillezdonc à ne pas commettre cette erreur, cela vous évitera des problèmes decompilation.

Quelle est la différence avec la boucle précédente ?

Dans une boucle while classique, la condition est en début de boucle. C’est pourquoi laboucle peut ne jamais être exécutée si la condition est fausse dès le départ. En revanche,dans une boucle do...while, la condition est placée à la fin de la boucle. De ce fait,la boucle s’exécutera toujours au moins une fois. Il est donc possible d’utiliser cetteboucle pour s’assurer que le programme rentrera au moins une fois dans la boucle. Voiciun exemple de calcul de PGCD :

1 var nombre1:uint = 556;2 var nombre2:uint = 148;3 do4 {5 var reste:uint = nombre1 % nombre2;6 nombre1 = nombre2;7 nombre2 = reste;8 } while(nombre2 != 0);9 trace("PGCD = " + nombre1); // Affiche : PGCD = 4

Petit rappel : PGCD pour Plus Grand Commun Diviseur. Si vous ne voussouvenez plus de l’algorithme, il faut diviser le plus grand nombre par le pluspetit. Ensuite, on prend le reste de la division euclidienne pour diviser lenombre le plus petit. Puis on reprend le dernier reste pour diviser le reste dela division précédente. Et ainsi de suite jusqu’à ce qu’un reste soit nul. Vousavez ainsi votre PGCD qui correspond au dernier reste non nul !

Une fois encore, vous pouvez remarquer qu’il n’est pas nécessaire de connaître le nombred’exécutions de la boucle contrairement à une boucle for dont nous allons parler main-tenant.

83

Page 107: Programmez en Actionscript 3

CHAPITRE 5. LES BOUCLES

La boucle for

Présentation

La syntaxe

Comme nous l’avons déjà dit dans ce cours, la boucle while permet de réaliser toutesorte de boucle. Cependant, son écriture est quelque peu fastidieuse c’est pourquoi, ilexiste une écriture condensée utile dans certains cas : la boucle for. Celle-ci est utiliséelorsque nous connaissons à l’avance le nombre d’exécutions de la boucle directementou à travers une variable. Cette boucle permet de concentrer le traitement de la va-riable utilisée, rappelez-vous avec une boucle while, nous devions passer par les étapessuivantes :

– Déclaration et initialisation de la variable avant la boucle.– Condition sur la variable en entrée de boucle.– Incrémentation de la variable à l’intérieur de la boucle.

Grâce à la boucle for, nous pouvons maintenant condenser ces trois étapes au mêmeendroit :1 for(/* Initialisation */; /* Condition */; /* Incrémentation */

)2 {3 // Instructions4 }

Attention, là encore, à la présence des points-virgules « ; » pour séparerchaque champ. C’est également une source de problèmes pour la compila-tion.

Quelques exemples

La boucle for est très utilisée en programmation, elle permet d’éviter d’avoir à écriredes instructions répétitives et également de faire des recherches dans les tableaux,notion que nous aborderons très bientôt. En attendant, voici quelques exemples d’uti-lisation de la boucle for :1 for(var i:int = 0; i < 10; i++)2 {3 trace("La valeur de i est " + i);4 }

Ici également, les accolades deviennent facultatives s’il n’y a qu’une seule instruction.Aussi, il est possible d’utiliser la boucle for en décrémentation ou en encore par pasde 10 si vous le désirez :1 for(var i:int = 10; i > 0; i--)2 trace("La valeur de i est " + i);

84

Page 108: Programmez en Actionscript 3

LA BOUCLE FOR

La boucle for n’a rien de difficile, il s’agit simplement d’une boucle while condensée.En revanche, la syntaxe est assez spéciale, c’est pourquoi il est nécessaire de la retenircar cette boucle vous servira plus que vous ne l’imaginez !

En résumé– Les boucles permettent de répéter une série d’instructions tant qu’une condition estvérifiée.

– La boucle while permet de tout faire mais il est possible que les instructions àl’intérieur ne soient jamais exécutées.

– La boucle do...while est identique à la précédente, néanmoins la boucle est exécutéeau moins une fois.

– La boucle for est une forme condensée du while dans le cas où on connaît le nombrede répétitions de la boucle.

– L’incrémentation est utilisée en permanence dans les boucles et son écriture peutêtre simplifiée par les expressions « i++ » et « i– ».

85

Page 109: Programmez en Actionscript 3

CHAPITRE 5. LES BOUCLES

86

Page 110: Programmez en Actionscript 3

Chapitre 6Les fonctions

Difficulté :

Maintenant, nous allons introduire les fonctions ! Sachez que c’est un concept qui existedans tous les langages de programmation et que ces fonctions servent à structurer notreprogramme en petits bouts.

Nous verrons en quoi consistent réellement ces fonctions. Nous apprendrons commentutiliser des fonctions toutes prêtes, mais aussi comment en créer nous-mêmes. Afin quevous compreniez mieux toutes ces notions, je vous présenterais quelques exemples quiferont appel aux connaissances acquises jusqu’ici.

87

Page 111: Programmez en Actionscript 3

CHAPITRE 6. LES FONCTIONS

Concept de fonction

Le principe de fonctionnement

Depuis le début de ce cours, tout ce que nous faisons se trouve à l’intérieur d’une fonc-tion nommée Main (ou peut-être d’une fonction init si vous utilisez FlashDevelop).En effet, nous n’avons pas encore écrit à l’extérieur des accolades de celle-ci. En général,pour écrire un programme, il faut compter entre une centaine de lignes de code jusqu’àplusieurs milliers pour les plus conséquents. Il n’est donc pas envisageable d’insérer latotalité du code à l’intérieur de la fonction Main. En effet, il faut organiser le code, cequi permet de le rendre plus lisible mais également de faciliter le débogage. Pour cela,nous allons découper notre programme en morceaux. Nous regrouperons donc certainesinstructions ensemble pour créer des bouts de programme, puis nous les assembleronspour obtenir le programme complet. Chaque morceau est alors appelé : fonction !

Comment se présente une fonction ?

Une fonction est une série d’instructions qui ont été regroupées pour une tâche com-mune. Nous créons alors une fonction que nous appellerons à chaque fois que nous enavons besoin. Celle-ci se compose de la manière suivante :

– Une ou des entrées : il s’agit d’informations qui seront utiles au cours de l’exécutionde la fonction.

– Le traitement et les calculs : c’est le cœur de la fonction, les instructions internessont exécutées.

– Une unique sortie : une fois les instructions de la fonction terminées, celle-ci renvoieun résultat.

Pour résumer tout ceci, vous trouverez à la figure 6.1 un schéma reprenant le principede fonctionnement.

Figure 6.1 – Principe d’une fonction

Notez qu’une fonction ne possède pas obligatoirement une entrée et une sor-tie. Celle-ci peut très bien se satisfaire uniquement d’une entrée ou d’une sor-tie, et plus exceptionnellement aucune des deux. Nous reviendrons là-dessustrès rapidement dans ce cours.

88

Page 112: Programmez en Actionscript 3

CONCEPT DE FONCTION

En règle générale, on associe une fonction à une tâche bien précise. Par exemple,nous pourrions imaginer une fonction qui calcule et renvoie le carré d’un nombre placéen entrée. Vous trouverez à la figure 6.2 un schéma de ce que cela donnerait.

Figure 6.2 – Exemple d’une fonction

Bien évidemment, dans un programme, les fonctions sont généralement plus complexes.L’Actionscript possède déjà des centaines de fonctions qui permettent par exempled’afficher une image à l’écran ou encore de la transformer. Nous apprendrons à lesutiliser ainsi qu’à créer nos propres fonctions.

Présentation

Vous ne vous en doutez peut-être pas, mais vous avez déjà utilisé des fonctions depuisle début de ce cours ! Effectivement, nous avons déjà utilisé plusieurs fois la fonctiontrace() et également introduit la fonction toString(). Néanmoins, ces deux fonctionssont légèrement différentes dans leur utilisation. Nous présenterons donc brièvement icices différences entre les fonctions dites de base telle que la fonction trace() et lesméthodes comme la fonction toString(). Allons-y pour les fonctions de base !

Les fonctions de base

L’appel d’une fonction telle que la fonction trace() se fait de manière la plusbasique qui soit. Rappelez-vous la façon dont nous écrivions l’instruction faisant appelà cette fonction :

1 trace("Texte à afficher");

Vous remarquerez qu’il suffit simplement d’écrire le nom de la fonction, ainsi que letexte à afficher entre parenthèses. En revanche, ceci est différent pour les méthodes !

Les méthodes

Les méthodes sont liées à la notion de POO ou Programmation Orientée Ob-jet, je vous rappelle que nous y reviendrons dans une partie entièrement consacréeà ce concept. Contrairement aux fonctions de base, les méthodes sont associéesà un objet. Pour vous montrer ceci, reprenons l’exemple d’utilisation de la fonctiontoString() :

89

Page 113: Programmez en Actionscript 3

CHAPITRE 6. LES FONCTIONS

1 var nombre:Number = 3.14;2 trace(nombre.toString () == "3.14");

Ce qu’il faut noter par rapport à la fonction trace(), c’est que la méthode toString()est liée à l’objet nombre qui est de type Number. Notez le point « . » séparant l’objetnombre de la méthode toString() ; il signifie que la méthode est liée à l’objet et qu’ellene peut pas être utilisée indépendamment de l’objet auquel elle est associée. Quoi qu’ilen soit, vous aurez tout le temps de vous familiariser avec ceci au cours de la partie surla Programmation Orientée Objet.

Création et appel de fonctions

Nous allons maintenant apprendre à créer et appeler des fonctions. Nous verronsqu’il existe deux façons de déclarer une fonction : les instructions de fonction etles expressions de fonction. Commençons sans plus tarder par les instructions defonction.

Tout ce que nous allons voir ici concerne les fonctions de base. Néanmoins,les méthodes ne sont pas très différentes et reprendront tous les principes vustout au long du chapitre. Aussi, soyez attentifs à tout ce qui sera dit ici ! Parailleurs, pour l’instant, nous nous contenterons de tout écrire à l’intérieur dela fonction Main tel que nous le faisons depuis le début de ce cours.

Instructions de fonction

Déclaration

L’instruction de fonction est la première technique permettant de définir une fonc-tion. Il s’agit sans aucun doute de la manière que vous serez le plus amenés à utiliserà l’intérieur de vos programmes. Celle-ci débute par le mot-clé function suivi du nomdonné à cette fonction, d’ailleurs voici sa structure :

1 function nomDeLaFonction(sesParametres):sonType2 {3 // Instructions à exécuter lors de l'appel de la fonction4 }

Pour faciliter la compréhension de tous ces champs, nous allons reprendre le modèleutilisé plus haut pour décrire une fonction :

– Une ou des entrées : il s’agit des paramètres placés en entrées, par ex :(monParam1:int,monParam2:String). Vous pouvez également ne renseigner aucun paramètre, vouslaisserez alors les parenthèses vides, comme ceci ().

– Le traitement et les calculs : cela correspond aux instructions placées entre lesaccolades de la fonction, qui seront exécutées à l’appel de la fonction.

90

Page 114: Programmez en Actionscript 3

CRÉATION ET APPEL DE FONCTIONS

– Une unique sortie : il est possible que la fonction ne renvoie aucune valeur, auquel casutilisez le mot-clé void comme type de renvoi. Dans le cas contraire, celle-ci ne peutrenvoyer qu’une unique variable. Le type de cette variable doit être renseigné aprèsles paramètres et précédé de deux-points « : ». Le renvoi de cette valeur s’effectueen utilisant le mot-clé return suivi de la valeur ou variable à renvoyer.

Rien ne remplace un bon exemple, voici notre fonction qui élève un nombre au carré :

1 function carre(nombre:int):int2 {3 var resultat:int = 0;4 resultat = nombre*nombre;5 return resultat;6 }

Une variable déclarée à l’intérieur d’une fonction n’est définie que pour cettefonction. À la fin de celle-ci, la variable est supprimée de la mémoire et n’estdonc plus accessible ! Ne tentez donc pas de récupérer sa valeur en dehorsdes accolades de la fonction !

Sachez qu’il est possible d’effectuer des opérations après le mot-clé return, il est alorspréférable de placer des parenthèses autour du calcul. Veillez cependant à ne pas enfaire trop, le code doit toujours rester aéré et lisible. La fonction précédente aurait doncpu être écrite plus succinctement de la façon suivante :

1 function carre(nombre:int):int2 {3 return (nombre*nombre);4 }

Voilà notre fonction est définie, il ne reste plus qu’à l’appeler !

Appel

L’appel de la fonction n’est pas bien compliqué sachant que vous avez déjà réalisécette opération ! omme pour la fonction trace(), nous allons maintenant appeler notrefonction carre() en renseignant en paramètre le nombre que nous désirons élever aucarré. La fonction nous renvoie une variable de type int, nous allons ainsi la stockerdans une variable resultat déclarée et de type int également. Voici donc commentprocéder :

1 var resultat:int = carre(4);2 trace("le carré de 4 est " + resultat); // Affiche : le carré

de 4 est 16

91

Page 115: Programmez en Actionscript 3

CHAPITRE 6. LES FONCTIONS

Lorsque votre fonction ne renvoie rien, le mot-clé void peut être facultatif.Cependant, je vous conseille fortement de l’écrire quand même. D’ailleursle compilateur vous recommandera également de préciser son type de ren-voie : Warning: return value for function ’nomDeLaFonction’ hasno type declaration.

Ce n’est pas très flagrant dans ce cas, mais l’utilisation des fonctions permet d’organiserle code et de le rentre plus lisible. Ceci sera effectivement le cas lorsque vous aurez desfonctions complexes, et que vous n’aurez plus qu’à les utiliser en les appelant en uneseule instruction ! Nous verrons diverses fonctions pour mieux comprendre juste aprèsles expressions de fonction.

Expressions de fonction

Les expressions de fonction sont beaucoup moins utilisées que les instructions defonction et sont légèrement plus complexes. Les expressions de fonction utilisentune instruction d’affectation pour écrire une fonction. Pour cela, il nous faut dé-finir une fonction anonyme qui sera stockée dans une variable de type Function.Pour éviter de vous noyer dans des explications, voici la structure d’une déclarationd’expression de fonction :

1 var nomDeLaFonction:Function = function (sesParametres)2 {3 // Instructions à exécuter lors de l'appel de la fonction4 };

Nous ne nous attarderons pas trop sur ces expressions de fonction, voici tout demême un exemple d’utilisation :

1 var afficher:Function = function (texte:String):void2 {3 trace(texte);4 }5 afficher("Ceci est la fonction afficher.");

Pour l’instant, vous pouvez vous contenter uniquement des instructions defonction, ne vous compliquez pas la vie avec les expressions de fonctionqui sont moins utilisées. En revanche, retenez bien comment utiliser ces ins-tructions de fonction que nous utiliserons désormais tout le temps.

Quelques exemples

Pour clore ce chapitre sur les fonctions, nous verrons quelques exemples de fonctionsqui pourront vous être utile à l’avenir.

92

Page 116: Programmez en Actionscript 3

QUELQUES EXEMPLES

Message de bienvenue

Voici une fonction qui se contente d’afficher un message de bienvenue à la personneindiquée en paramètre. Cette fonction ne renvoie aucune valeur.

1 function bienvenue(nom:String):void2 {3 trace("Bonjour " + nom + " et bienvenue sur le Site du Zéro

!");4 }5 bienvenue("Marcel Dupont"); // Affiche : Bonjour Marcel Dupont

et bienvenue sur le Site du Zéro !

Pour que votre code soit encore plus lisible, n’hésitez pas à donner des nomsexplicites à vos fonctions !

Calcul de PGCD

Dans cet exemple, nous allons calculer le PGCD entre deux nombres comme nous avonsappris à le calculer dans le chapitre précédent :

1 function calculPGCD(nombre1:int , nombre2:int):int2 {3 do4 {5 var reste:uint = nombre1 % nombre2;6 nombre1 = nombre2;7 nombre2 = reste;8 } while(nombre2 != 0);9 return nombre1;

10 }11 trace("Le PGCD de 56 et 42 est : " + calculPGCD(56 ,42)); //

Affiche : Le PGCD de 56 et 42 est : 14

Pour ceux qui voudraient réellement utiliser cette fonction, sachez qu’ici lenombre1 est supposé plus grand que le nombre2. Si vous le désirez, n’hésitezpas à rajouter une condition pour tester si c’est effectivement le cas !

Calcul d’un maximum

Voici une fonction qui pourrait vous être utile, celle-ci vous renvoie le plus grand nombreentre ces deux paramètres. Il n’y a rien de très compliqué, voici comment procéder :

1 function max(nombre1:int , nombre2:int):int2 {

93

Page 117: Programmez en Actionscript 3

CHAPITRE 6. LES FONCTIONS

3 var resultat:int = 0;4 if(nombre1 > nombre2)5 {6 resultat = nombre1;7 }8 else9 {

10 resultat = nombre2;11 }12 return resultat;13 }14 var nombre1:int = 2;15 var nombre2:int = 3;16 trace("Le maximum entre " + nombre1 + " et " + nombre2 + " est

" + max(nombre1 ,nombre2)); // Affiche : Le maximum entre 2et 3 est 3

Lorsque vous réaliserez des programmes assez conséquents, vous devrez économiserau maximum les instructions dans vos programmes pour gagner en performance ousimplement pour le rendre plus lisible. Il peut alors devenir intéressant de regarder sivos fonctions ne peuvent pas s’écrire différemment, mais surtout en moins de lignes.Ceci peut être le cas pour cette fonction où nous pouvons aisément nous dispenser dubloc d’instructions else. Effectivement, testez le code suivant, vous verrez qu’il faitexactement la même chose :

1 function max(nombre1:int , nombre2:int):int2 {3 var resultat:int = nombre1;4 if(nombre2 > nombre1)5 {6 resultat = nombre2;7 }8 return resultat;9 }

10 var nombre1:int = 2;11 var nombre2:int = 3;12 trace("Le maximum entre " + nombre1 + " et " + nombre2 + " est

" + max(nombre1 ,nombre2)); // Affiche : Le maximum entre 2et 3 est 3

Vous verrez que la recherche d’un optimum (maximum ou minimum) est une pratiqueassez courante avec les tableaux, mais nous verrons ceci dans le prochain chapitre !

En résumé

– Les fonctions permettent d’organiser le code, de le rendre plus lisible mais égalementde se séparer de tâches répétitives.

– Pour déclarer une fonction, on utilise le mot-clé function.

94

Page 118: Programmez en Actionscript 3

QUELQUES EXEMPLES

– Une fonction peut recevoir plusieurs paramètres en entrée, mais ne peut retournerqu’une valeur au plus.

– On utilise le mot-clé return pour renvoyer une valeur.– On préfère généralement les instructions de fonction auxquelles on peut attribuerun nom.

95

Page 119: Programmez en Actionscript 3

CHAPITRE 6. LES FONCTIONS

96

Page 120: Programmez en Actionscript 3

Chapitre 7Les tableaux

Difficulté :

Pour clore cette première partie du cours, nous verrons les tableaux qui sont très utilisésen programmation !

Les variables de base, présentées dans un chapitre précédent, sont très utiles, mais pos-sèdent leurs limites lorsqu’il s’agit de gérer beaucoup de valeurs. Effectivement, à l’aide devariables nous pouvons associer une valeur à un nom. Ceci peut être handicapant lors dutraitement d’une quantité de valeurs importante. C’est ici qu’entrent en jeu les tableaux !Le principe des tableaux est de pouvoir stocker plusieurs valeurs sous un même nom. Cecifacilitera alors le traitement de ces données puisque celles-ci seront enregistrées sous lemême nom et seront simplement différenciées par un indice à l’intérieur du tableau.

En Actionscript, nous avons plusieurs manières de créer et d’utiliser des tableaux. Dansce chapitre, nous verrons les deux types de tableaux : Array et Vector.

97

Page 121: Programmez en Actionscript 3

CHAPITRE 7. LES TABLEAUX

Le type Array

Le premier type de tableau utilisé en Actionscript est Array. En Actionscript, lestableaux ne sont pas fixés en taille ce qui permet une programmation plus souple.De plus, en ce qui concerne le type Array, les tableaux ne sont pas typés, c’est-à-direqu’ils ne sont pas réservés à un seul type de variable. Il est alors possible d’insérer dansun tableau des variables de type int, uint, Number, String ou encore tout ce qui vouspasse par la tête.

Création

La création d’un tableau de type Array peut être réalisée de multiples façons. Ce-pendant, les tableaux sont soumis aux mêmes règles que les variables. C’est pourquoi,nous retrouverons donc la structure de base commune à toute variable :

1 var nomDuTableau:Array = ceQueJeMetsDedans;

En revanche, lorsqu’il s’agit d’initialiser un tableau, nous avons le choix entre di-verses méthodes. Voici quatre manières différentes d’initialiser une variable de typeArray :

1 var monTableau:Array = new Array(3); // Création d'un tableaude 3 valeurs non renseignées

2 var monTableau:Array = new Array(); // Création d'un tableauvide

3 var monTableau:Array = new Array("Site", "du", "Zéro"); // Création d'un tableau contenant les 3 valeurs indiquées

4 var monTableau:Array = ["Site", "du", "Zéro"]; // Création du même tableau contenant les 3 valeurs indiquées

Dans beaucoup de langages, la longueur d’un tableau doit être définie lors desa déclaration. Ce n’est pas le cas en Actionscript, il est tout à fait possiblede changer la longueur d’un tableau en cours de programme.

La fonction trace() permet également d’afficher le contenu d’un tableau. Vous pouvezainsi à tout moment connaître l’état de votre tableau :

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

Les éléments du tableau

Même si un tableau regroupe plusieurs valeurs, celles-ci doivent pouvoir être utiliséesséparément. C’est ici qu’entre en jeu la notion d’indice à l’intérieur d’un tableau. Cesindices sont utilisés entre crochets [] pour préciser la position de l’élément désiré dansle tableau. Les valeurs peuvent alors être traitées comme n’importe quelle variable :

98

Page 122: Programmez en Actionscript 3

LE TYPE ARRAY

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

Attention, en programmation les indices des tableaux commencent toujoursà 0. Ainsi, le troisième élément du tableau se trouve à l’indice2. Ce n’est pastrès compliqué à comprendre, mais on a souvent tendance à l’oublier lespremières fois.

Comme nous venons de le voir, les valeurs à l’intérieur d’un tableau se manipulent dela même manière que les variables. Toutefois, une valeur non initialisée dans le tableauaura une valeur par défaut, undefined :

1 var monTableau:Array = new Array();2 trace(monTableau[0]); // Affiche : undefined

Propriétés du type Array

Enfin, pour en finir avec le type Array, nous allons voir quelques méthodes et pro-priétés qui pourront vous être utiles. Tout d’abord, lorsque vous utiliserez des ta-bleaux, vous n’aurez pas besoin de connaître en permanence la taille de votre tableau.En revanche, vous pouvez à tout moment avoir besoin de connaître cette longueur detableau. Pour cela, vous pouvez utiliser la propriété length associée aux tableaux detype Array. Voici comment l’utiliser :

1 var monTableau:Array = new Array(5);2 var taille:int = monTableau.length;3 trace(taille); // Affiche : 5

Nous allons à présent voir différentes méthodes permettant d’insérer ou de supprimerdes éléments dans un tableau. D’abord, la méthode push() permet d’ajouter un ouplusieurs éléments à la fin du tableau. À l’opposé, la méthode unshift() insère un ouplusieurs éléments au début du tableau, c’est-à-dire à l’indice 0. Pour finir, la méthodesplice() est un compromis car elle permet d’insérer des éléments à un indice spécifié.Voici un exemple d’utilisation de ces méthodes :

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

99

Page 123: Programmez en Actionscript 3

CHAPITRE 7. LES TABLEAUX

La méthode splice() peut avoir des finalités différentes suivant les para-mètres renseignés. Voici donc la signification de chacun de ses paramètres :Indice de départ où on se place pour effectuer les opérations. Nombre d’élé-ments devant être supprimés à partir de l’indice de départ. Série d’élémentsqui doivent être insérés à la suite de l’indice de départ. Ainsi, la méthodesplice() permet à la fois d’insérer des éléments mais également de sup-primer ou remplacer des éléments. Dans le cas présent, la mise à zéro dudeuxième paramètre permet uniquement d’insérer des éléments sans en sup-primer.

Enfin, pour supprimer des éléments nous avons également trois méthodes : pop(),shift(), et splice(). Symétriquement à push() et unshift(), les méthodes pop()et shift() permettent de supprimer des éléments respectivement à la fin ou au débutd’un tableau. Pour supprimer des éléments au milieu du tableau, il faut utiliser laméthode splice() présentée juste avant. Encore une fois, voici un exemple pour biencomprendre :

1 var monTableau:Array = ["Bienvenue", "sur", "le", "Site", "du","Zéro", "!"];

2 monTableau.pop();3 monTableau.splice(1, 2);4 monTableau.shift ();5 trace(monTableau); // Affiche : Site ,du ,Zéro

Le type Vector

Le second type de tableaux utilisé en Actionscript est Vector. Vous verrez que cestableaux sont très proches de ceux de type Array, ils sont notamment également nonfixés en taille. La principale différence vient du fait que les tableaux de type Vectorsont typés. C’est-à-dire qu’une fois déclaré pour un certain type de variables, il n’estpas possible d’y mettre autre chose. Voyons tout ceci plus en détails !

Déclaration

Ici encore, la déclaration ressemble à celle d’une variable, mais à une nuance près.Étant donné que les tableaux de type Vector sont typés, il est nécessaire de préciser letype de variables qui sera utilisé à l’aide des chevrons « <> ». Voici donc commentdéclarer un tel tableau :

1 var nomDuTableau:Vector.<Type > = ceQueJeMetsDedans;

Pour initialiser un tableau de type Vector, voici les méthodes proposées :

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

"Zéro"]);

100

Page 124: Programmez en Actionscript 3

LE TYPE VECTOR

Étant donné que ces tableaux sont typés, vous ne pouvez pas insérer unevaleur dont le type ne correspondrait pas à celui déclaré. En effet, ceci en-trainerait des erreurs d’exécution ou de compilation.

Notez que la taille du tableau peut toutefois être fixée en utilisant un paramètre sup-plémentaire de type Boolean et valant true. Voici le code correspondant :

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

Gestion des éléments

Tout comme les tableaux Array, les valeurs internes peuvent être manipulées à l’aided’indices mis entre crochets « [] ». Voici encore quelques exemples de manipulationsde valeurs à l’intérieur d’un tableau :

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

Pour les plus perspicaces d’entre vous, vous aurez vu apparaître les premierstermes 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 termesde la suite que vous désirez !

Grâce à cet exemple nous commençons à cerner l’intérêt de l’utilisation des tableaux.Effectivement, lorsque nous utilisons des boucles par exemple, il devient relativementsimple de lier notre variable i de boucle avec les indices du tableau. Ceci avait déjàété dit précédemment, mais nous allons le rappeler, les boucles sont extrêmement utileset performantes pour parcourir des tableaux.

Pour allier tableaux et fonctions, nous allons transformer le code précédent pourcréer une fonction renvoyant le énième terme de la suite de Fibonacci. Découvronscette fonction :

1 function suiteFibonacci(terme:int):uint2 {3 var monTableau:Vector.<uint > = new Vector.<uint >(terme);4 monTableau[0] = 0;5 monTableau[1] = 1;6 for(var i:int = 2; i < monTableau.length; i++)7 {8 monTableau[i] = monTableau[i-1] + monTableau[i-2];9 }

101

Page 125: Programmez en Actionscript 3

CHAPITRE 7. LES TABLEAUX

10 return (monTableau[terme -1]);11 }12 trace(suiteFibonacci(10)); // Affiche : 3413 trace(suiteFibonacci(20)); // Affiche : 418114 trace(suiteFibonacci(30)); // Affiche : 514229

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

Les tableaux multidimensionnels

Le concept

Nous allons maintenant découvrir les tableaux multidimensionnels : un nom bar-bare pourtant, cette notion n’est pas si compliquée que ça ! Les tableaux multidi-mensionnels ne sont en réalité que des tableaux imbriqués dans d’autres tableaux.Certes, c’est une notion qui fait peur aux premiers abords cependant, il n’y a rien denouveau en matière de code. Pour mieux comprendre de quoi il s’agit, nous allons illus-trer cette notion par un exemple. Nous pourrions créer une liste regroupant l’ensembledes livres de la collection « Le Livre du Zéro », il serait alors possible de réaliser celaavec un tableau classique ou monodimensionnel. Imaginons maintenant qu’en plus destocker le nom des livres, nous souhaitions y ajouter le nom de l’auteur et l’année desortie. Dans ce cas, nous avons besoin d’utiliser un tableau bidimensionnel de lamanière suivante :

1 var livres:Array = new Array();2 livres[0] = ["Réalisez votre site web avec HTML5 et CSS3", "

Mathieu Nebra", 2011];3 livres[1] = ["Apprenez à programmer en Java", "Cyrille Herby",

2011];4 livres[2] = ["Débutez dans la 3D avec Blender", "Antoine Veyrat

", 2012];5 livres[3] = ["Rédigez des documents de qualité avec LaTeX", "No

ël-Arnaud Maguis", 2010];

Sachant que les éléments du tableau principal sont des tableaux, vous obtiendrez doncun tableau en utilisant la notation avec indice vue précédemment :

1 trace(livres[0]); // Affiche : Réalisez votre site web avecHTML5 et CSS3 ,Mathieu Nebra ,2011

Il est bien évidemment possible d’accéder à une valeur à l’intérieur du second tableau.Pour cela, nous devrons utiliser une notation à double indice, c’est ce qui rend cetableau multidimensionnel ! Regardez plutôt ce code :

1 trace(livres[0][0]); // Affiche : Réalisez votre site web avecHTML5 et CSS3

102

Page 126: Programmez en Actionscript 3

LES TABLEAUX MULTIDIMENSIONNELS

Pour bien comprendre, nous pouvons effectuer une analogie avec un tableauExcel par exemple où le premier indice correspondrait au numéro de la ligneet le second au numéro de la colonne. Si vous en avez besoin, sachez quevous pouvez réaliser des tableaux de la dimension que vous souhaitez.

Un peu de pratique

Dans cette section, nous allons réaliser plusieurs fonctions pour apprendre à bien ma-nipuler les tableaux. Pour les tests, nous reprendrons le tableau précédent :

1 var livres:Array = new Array ();2 livres[0] = ["Réalisez votre site web avec HTML5 et CSS3", "

Mathieu Nebra", 2011];3 livres[1] = ["Apprenez à programmer en Java", "Cyrille Herby",

2011];4 livres[2] = ["Débutez dans la 3D avec Blender", "Antoine Veyrat

", 2012];5 livres[3] = ["Rédigez des documents de qualité avec LaTeX", "No

ël-Arnaud Maguis", 2010];

Pour éviter de surcharger le code de ce cours, nous ne réécririons pas ces lignes avantchaque fonction. À vous de les copier si vous souhaitez réaliser des essais.

Qui est-ce ?

La fonction présentée ci-dessous permet de retrouver l’auteur d’un livre. Pour cela,nous réaliserons donc une boucle à l’intérieur de laquelle nous rechercherons le livrespécifié en paramètre. Une fois le livre trouvé, il ne reste plus qu’à retenir l’indicecorrespondant dans le tableau et de renvoyer le nom de l’auteur. Voici la fonction enquestion :

1 function auteur(monTableau:Array , monLivre:String):String2 {3 var i:int = 0;4 var continuer:Boolean = true;5 do6 {7 if(monTableau[i][0] == monLivre)8 continuer = false;9 i++;

10 } while(continuer);11 return monTableau[i-1][1]12 }13 trace(auteur(livres , "Apprenez à programmer en Java")); //

Affiche : Cyrille Herby14 trace(auteur(livres , "Réalisez votre site web avec HTML5 et

CSS3")); // Affiche : Mathieu Nebra

103

Page 127: Programmez en Actionscript 3

CHAPITRE 7. LES TABLEAUX

Vous remarquerez que dans cet exemple, nous combinons à la fois : condition, boucle,fonction et tableau. Si vous avez bien compris cet exemple c’est que vous êtes au pointsur la première partie et donc fin prêt pour entamer la deuxième !

Trions par chronologie

Comme cela est annoncé dans le titre, cette fonction va nous permettre de trier letableau en fonction de l’année de sortie des livres. Pour faire cela, nous allons devoircréer un nouveau tableau que nous allons remplir au fur et à mesure. Nous prendronsdonc chaque livre du premier tableau, puis nous chercherons où l’insérer dans le second.Pour réaliser ceci, nous devrons utiliser deux boucles, une pour chaque tableau. Cettefonction est plus complexe que la précédente :

1 function tri(monTableau:Array):Array2 {3 var nouveauTableau:Array = new Array();4 nouveauTableau[0] = monTableau[0];5 for(var i:int = 1; i < monTableau.length; i++)6 {7 var j:int = 0;8 var continuer:Boolean = true;9 while(continuer)

10 {11 if(j >= nouveauTableau.length || monTableau[i][2]

<= nouveauTableau[j][2])12 continuer = false;13 j++;14 }15 nouveauTableau.splice(j-1, 0, monTableau[i]);16 }17 return nouveauTableau18 }19 livres = tri(livres);20 trace(livres[0]); // Affiche : Rédigez des documents de qualité

avec LaTeX ,Noël-Arnaud Maguis ,201021 trace(livres[1]); // Affiche : Apprenez à programmer en Java ,

Cyrille Herby ,201122 trace(livres[2]); // Affiche : Réalisez votre site web avec

HTML5 et CSS3 ,Mathieu Nebra ,201123 trace(livres[3]); // Affiche : Débutez dans la 3D avec Blender ,

Antoine Veyrat ,2012

Prenez le temps de bien assimiler ces deux exemples qui reprennent la quasi-totalitédes concepts de la première partie.

104

Page 128: Programmez en Actionscript 3

PARCOURIR UN TABLEAU

Parcourir un tableau

Il existe plusieurs manières de parcourir un tableau, que ce soit un Array ou unVector. Il faut savoir que certaines sont plus rapides que d’autres, il faut savoir choisirlaquelle utiliser en fonction des possibilités. Nous utiliserons à chaque fois la bouclefor que nous avons déjà vue précédemment, néanmoins l’Actionscript en proposequelques « variantes » encore plus efficaces.

La boucle for classique

Comme nous l’avons vu, la boucle for est particulièrement bien adaptée au parcoursd’un tableau. Pour rappel, voici un exemple de manipulation de ce type de boucle :

1 var monTableau:Array = ["élément n˚1", "élément n˚2", "élémentn˚3", "élément n˚4"];

2 for(var i:int = 0; i < monTableau.length; i++)3 {4 trace(monTableau[i]);5 }

Ce qui affichera :

élément n˚1élément n˚2élément n˚3élément n˚4

Dans une boucle for classique, nous nous basons donc sur l’indice, ou la position,des différents éléments à l’intérieur du tableau. Pour cela, nous avons alors besoin deconnaître la longueur de celui-ci, que nous pouvons d’ailleurs stocker dans une variable :

1 var monTableau:Array = ["élément n˚1", "élément n˚2", "élémentn˚3", "élément n˚4"];

2 var longueur:int = monTableau.length;3 for(var i:int = 0; i < longueur; i++)4 {5 trace(monTableau[i]);6 }

Cependant, il est également possible d’utiliser d’autres boucles où la connaissance dela longueur d’un tableau devient superflue ; j’ai nommé les boucles for...in et foreach !

La boucle for...in

La boucle for...in est très proche de la boucle for classique, et s’utilise quasiment dela même manière. Toutefois, il n’est pas nécessaire de connaître le nombre d’éléments

105

Page 129: Programmez en Actionscript 3

CHAPITRE 7. LES TABLEAUX

contenus dans un tableau pour parcourir l’intégralité de ce dernier. Voici un exempled’utilisation de cette boucle :

1 var monTableau:Array = ["élément n˚1", "élément n˚2", "élémentn˚3", "élément n˚4"];

2 for(var i:String in monTableau)3 {4 trace(monTableau[i]);5 }

Ce qui nous affichera comme précédemment :

élément n˚1élément n˚2élément n˚3élément n˚4

Ainsi, vous pouvez considérer que dans une boucle for...in la variable se comportecomme un indice qui s’incrémente automatiquement et qui parcourt l’intégralité dutableau.

Il est fort probable que certains d’entre vous se demandent alors, pourquoidiable la variable i est-elle de type String et non de type int ?

Pour comprendre cela, nous allons devoir brièvement sortir du cadre de ce chapitre.En réalité, la boucle for...in n’est pas propre aux tableaux, mais peut être utiliséepour parcourir d’autres types d’éléments ou objets. Pour mieux cerner le problème,nous allons imaginer l’objet ou la variable suivante :

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

Nous avons donc ici une sorte de tableau contenant trois éléments. Néanmoins, ceséléments ne sont pas rangés à l’aide d’un indice, mais plutôt grâce à une étiquette oupropriété et ne sont donc pas disposés suivant un ordre particulier. La seule manièrede faire référence à un élément à l’intérieur de cette variable est donc d’utiliser lesétiquettes associées à chacun de ces éléments.

L’utilisation de la boucle for...in prend alors tout son sens :

1 for(var i:String in monObjet)2 {3 trace(i + ": " + monObjet[i]);4 }

Voici le résultat :

a: élément Ab: élément Bc: élément C

106

Page 130: Programmez en Actionscript 3

PARCOURIR UN TABLEAU

Pour utiliser correctement la boucle for...in, vous devez vous rappeler qu’àl’intérieur de celle-ci nous travaillons non pas à l’aide d’un indice numériquemais bien avec une étiquette sous forme de chaîne de caractères. Dansle cas d’un tableau de type Array ou Vector, la variable utilisée représentenéanmoins l’indice, mais toujours sous la forme d’une chaîne de caractères detype String !

La boucle for each

La dernière boucle permettant de parcourir un tableau est la boucle for each. Contrai-rement à ses congénères, la variable utilisée à l’intérieur de celle-ci ne fait pas référenceà l’indice, ou l’étiquette, associé aux éléments d’un tableau, mais aux éléments eux-mêmes.

La manipulation des éléments devient alors beaucoup plus simple :

1 var monTableau:Array = [12, 42 , 10 , 3];2 for each(var nombre:int in monTableau)3 {4 trace(nombre);5 }

Comme vous l’imaginez, dans ce cas, le type de la variable devra s’adapter suivant lanature des éléments contenus à l’intérieur du tableau :

1 var monTableau:Array = [2.3, 24567673 , 42, 3.14 , 276.54];2 for each(var nombre:Number in monTableau)3 {4 trace(nombre);5 }

Ou encore :

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

Notez toutefois qu’en utilisant cette boucle vous perdez la notion de repérageà l’intérieur du tableau et vous n’êtes alors plus en mesure de relier l’élémentau tableau.

Bien évidemment, ce qui est faisable avec un tableau de type Array, l’est aussi avec unautre tableau de type Vector :

1 var monVecteur:Vector.<String > = Vector.<String >(['Hello', 'world', '!']);

2 for each(var chaine:String in monVecteur)

107

Page 131: Programmez en Actionscript 3

CHAPITRE 7. LES TABLEAUX

3 {4 trace(chaine);5 }

En résumé– Grâce aux tableaux, nous pouvons stocker plusieurs valeurs sous un même nom devariable.

– Les éléments d’un tableau sont accessibles via un indice qui démarre à 0.– Les tableaux de type Array ne sont ni fixés, ni typés.– Les tableaux de type Vector ne sont pas fixés, mais en revanche ils sont typés.– Différentes méthodes permettent de manipuler des tableaux à la fois de Array et detype Vector.

– On utilise généralement les boucles for, for...in ou for each pour parcourir untableau.

– Il est possible de créer des tableaux multidimensionnels en utilisant une notationà double indice.

108

Page 132: Programmez en Actionscript 3

Deuxième partie

La Programmation OrientéeObjet

109

Page 133: Programmez en Actionscript 3
Page 134: Programmez en Actionscript 3

Chapitre 8La POO dans tous ses états

Difficulté :

Nous allons maintenant attaquer la deuxième partie du cours, traitant d’une notion très im-portante en Actionscript 3 : la Programmation Orientée Objet (ou POO). Appréhendercette notion sera peut-être difficile au début, mais vous finirez par tomber sous le charmede cette façon de programmer, je vous le promets !

Cette partie sera également l’occasion de faire (enfin !) un peu de pratique à l’occasion dequelques exercices que nous réaliserons ensemble.

Attachez vos ceintures, c’est parti ! La POO n’aura bientôt plus aucun secret pour vous !

111

Page 135: Programmez en Actionscript 3

CHAPITRE 8. LA POO DANS TOUS SES ÉTATS

Les notions-clés

Il était une fois. . . un objet

Vous avez sûrement une idée de ce qu’est un objet : dans la vie de tous les jours, nousen voyons, nous en touchons des centaines. Ils ont chacun une forme et remplissentune ou plusieurs tâches. On distingue rapidement plusieurs catégories d’objets quise ressemblent : quand vous mettez la table, vous manipulez des objets (fourchettes,couteaux, cuillères, . . .) appartenant à la catégorie « couvert ». Bien sûr, vous pouvezavoir plusieurs objets de cette catégorie, voire plusieurs fourchettes identiques. Lesobjets de la catégorie « fourchette » font également partie de la catégorie « couvert »car les fourchettes ne sont en fait que des couverts particuliers.

La programmation orientée objet part de ces différentes observations pour intro-duire de nouveaux concepts en programmation afin de rendre le développement delogiciels plus efficace et intuitif.

L’autre façon de programmer est appelée le procédural où il n’y a grosso-modo que des variables, des fonctions et des instructions effectuées lesunes à la suite des autres. La POO est différente par bien des aspects.

L’Objet

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

Figure 8.1 – Une fourchette (image de ArnoldReinhold, tirée du site Wikimedia Com-mons)

Il s’agit d’un objet ayant une forme particulière et une certaine utilité, caractéristiquesque l’on peut retrouver dans les autres fourchettes. Un objet en programmation

112

Page 136: Programmez en Actionscript 3

LES NOTIONS-CLÉS

est également une entité possédant des propriétés que l’on peut retrouver sur d’autresobjets de la même catégorie. Il ne s’agit ni d’une variable, ni d’une fonction, maisd’un mélange des deux : c’est un nouveau concept à part entière. Un objet peut donccontenir plusieurs variables (appelées attributs) et plusieurs fonctions (appelées mé-thodes). Ces variables et fonctions (appelées propriétés) sont profondément liées àl’objet qui les contient : les attributs stockent des informations sur cet objet. Parexemple, si mon objet « fourchette » possède un attribut « poids », cet attribut re-présente la masse de cette fourchette et non la masse d’une autre fourchette posée àcôté.

La Classe

Seulement, vous avez sur votre table non pas une mais dix fourchettes, quoique pasexactement identiques. En effet, cette fourchette ci et plus légère que cette fourchette là,donc son attribut « poids » est plus faible. Mais ces deux objets restent des fourchettes,malgré leur différence de poids. Fourchette est donc la catégorie de ces objets, appeléeclasse.

On dit que les objets d’une classe sont des instances (ou occurrences) decette classe.

Une classe décrit la nature de ses objets : c’est un schéma permettant de fabriquer etde manipuler plusieurs objets possédant les mêmes attributs et méthodes. Par exemple,la classe Fourchette pourrait décrire les attributs « poids », « taille », « nombre dedents », etc. (voir figure 8.2)

Nous pourrions aussi créer une classe Couteau pour les couteaux, et une classe Cuillèrepour les cuillères.

En Actionscript 3, les classes sont considérées comme des types, au mêmetitre que les int, Number ou String.

Un autre exemple

Une fois la table mise, vous tournez la tête et admirez à travers la fenêtre votre magni-fique 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 d’attributs etde méthodes que la classe Fourchette. . .

Voici quelques exemples d’attributs : « taille » (un grand classique), « marque », « cou-leur », « nombre de pneus », « nombre de sièges » ; et quelques exemples de méthodes :« verrouiller les portières », « démarrer le moteur », « accélérer », « freiner », « tournerà gauche », « tourner à droite ». . . (voir figure 8.4)

113

Page 137: Programmez en Actionscript 3

CHAPITRE 8. LA POO DANS TOUS SES ÉTATS

Figure 8.2 – La classe Fourchette et quelques instances

Figure 8.3 – Votre magnifique voiture

114

Page 138: Programmez en Actionscript 3

LES NOTIONS-CLÉS

Figure 8.4 – La classe Voiture et une instance

Vous apercevez un peu plus loin la voiture de votre voisin garée en face (figure 8.5).C’est également un objet de la classe Voiture, avec une marque, une couleur, unnombre de pneus et de sièges, la possibilité d’accélérer, de freiner, de tourner à gaucheou à droite. . . Seulement, elle n’a ni la même marque, ni la même couleur que la vôtre.

Ces deux objets sont des instances de la classe Voiture.

Figure 8.5 – La voiture de mon voisin est une autre instance

L’encapsulation

Vous vous souvenez avoir ouvert le capot de votre voiture après l’avoir garé : vous avezintensément regardé ce qu’il y a à l’intérieur (figure 8.6). Malgré votre immense effortde concentration, le fonctionnement du moteur, de tous ces câbles, circuits électriqueset autres tuyaux vous échappe encore. . .

Fort heureusement, lorsque vous refermez le capot et montez dans votre voiture, vous

115

Page 139: Programmez en Actionscript 3

CHAPITRE 8. LA POO DANS TOUS SES ÉTATS

Figure 8.6 – Sous le capot. . .

oubliez toute cette mécanique trop compliquée, et vous conduisez à l’aide d’un volant,de pédales et d’un levier de boîte de vitesse (figure 8.7). Grâce à eux, vous pouvezutiliser votre voiture sans être ingénieur en génie mécanique ou électronique !

Figure 8.7 – Votre volant vous facilite bien la tâche. . .

Imaginez maintenant que vous écriviez une classe très complexe, qui permet de faireplein de choses incroyables (figure 8.8) ! Malheureusement, personne ne voudra de votremagnifique classe : qui serait assez fou pour se plonger dans votre code et tentez de ledéchiffrer ?

En effet, votre code est un peu comme le bazar qui se trouve sous le capot de votre voi-ture. Mais vous êtes malins et vous fournissez aux autres développeurs des méthodes

116

Page 140: Programmez en Actionscript 3

LES NOTIONS-CLÉS

Figure 8.8 – Ce à quoi votre code pourrait ressembler. . .

très simples et faciles à comprendre, tout en cachant littéralement sous le capot cequ’elles font, à l’instar du volant, des pédales et du frein à main. Ainsi, les program-meurs qui utiliseront votre classe (y compris vous-mêmes) auront un volant à dispositionau lieu d’un moteur et vingt-et-un tuyaux. On appelle ce principe l’encapsulation.

L’héritage

Puis, votre regard se porte sur l’autoroute au loin (figure 8.9) : vous distinguez d’autresvoitures. Mais des formes différentes se déplacent parmi elles : ce ne sont de touteévidence pas des voitures, mais plutôt des camions et des motos. Vous remarquez queces objets comportent eux aussi des roues ; ils ont eux aussi une couleur et une marque ;ils peuvent eux aussi accélérer, freiner, tourner à gauche, tourner à droite. . . Ce seraientpresque des objets de la classe Voiture.

Figure 8.9 – Une autoroute belge (image de Purka, tirée du site Wikimedia Commons)

117

Page 141: Programmez en Actionscript 3

CHAPITRE 8. LA POO DANS TOUS SES ÉTATS

Mince alors ! Il va falloir refaire de nouvelles classes quasiment identiques. . . Pourquoine pas faire une classe Véhicule plus généraliste, qui décrirait les attributs et méthodescommuns aux classes Voiture, Camion et Moto ? C’est une excellente idée !

Notre nouvelle classe Véhicule décrit donc les attributs et les méthodes communs àtous les véhicules routiers, comme le nombre de roues et de sièges, la marque, la couleur,les méthodes « accélérer », « freiner », « tourner à gauche », « tourner à droite ». . . Onl’appelle la classe mère (ou superclasse), par opposition aux classes Voiture, Camionet Moto qui sont ses classes filles (ou sous-classes). On dit également que les classesVoiture, Camion et Moto héritent de la classe Véhicule.

Désormais, inutile de réécrire les attributs et méthodes de la classe Véhicule dans laclasse Voiture, car cette dernière hérite des attributs et des méthodes de la classeVéhicule (voir figure 8.10) ! Ainsi tous nos objets de la classe Voiture sont égalementdes objets de la classe Véhicule, mais leur description dans la classe Voiture est plusprécise (par exemple, les voitures ont un coffre, alors que les camions ont une remorque).

L’un des intérêts de l’héritage est donc de pouvoir créer plusieurs classes différentesdérivant d’une classe-mère sans avoir à recopier les attributs et les méthodes com-munes dans chaque classe. C’est aussi une façon de penser et concevoir le programmede manière logique et cohérente.

Si nous revenions sur le premier exemple, la classe Fourchette, ainsi que les classesCouteau et Cuillère, sont des sous-classes de la classe Couvert !

Manipuler des objets : les chaînes de caractères

L’horrible secret du type String

Vous souvenez-vous des chaînes de caractères que nous avons vues dans la premièrepartie ?

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

Regardez bien le type de la variable : String. . . Il cache un terrible secret : il s’agit enréalité d’une classe ! Et oui ! En écrivant la ligne au-dessus, nous avons sans le savoir,créé une instance de la classe String. Et nous avons également utilisé des propriétésde cette classe !

Créer un objet

Tout d’abord, il nous faut apprendre à créer des objets. Il y a une syntaxe particulièreà respecter :

1 new String (); // Je créé un objet de la classe String (je l'aid'ailleurs créé dans le vide , cette instruction ne servira àrien :D)

118

Page 142: Programmez en Actionscript 3

MANIPULER DES OBJETS : LES CHAÎNES DE CARACTÈRES

Figure 8.10 – Les trois classes sont des sous-classes de la classe Véhicule

119

Page 143: Programmez en Actionscript 3

CHAPITRE 8. LA POO DANS TOUS SES ÉTATS

Comme vous pouvez le voir, nous utilisons le mot-clé new, suivi du nom de la classede l’objet que nous voulons créer, et d’éventuels paramètres entre parenthèses (commepour les fonctions). Par exemple, si nous voulions créer un objet de la classe Stringcontenant la chaîne "Hello world!", nous procéderions ainsi :

1 var coucou:String = new String("Hello world!"); // Je créé unobjet String contenant la chaîne "Hello world !"

Mais, avant nous n’avions pas besoin de new pour faire ça !

Effectivement, la classe String possède une particularité : c’est un type de données.Cela signifie que les objets de cette classe sont un peu spéciaux : ils peuvent agir entant que simple donnée (nombre, chaîne de caractères, etc.). Ainsi, nous pouvons nouspasser de la syntaxe de création d’un objet :

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

revient à écrire :

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

Qu’en est-il de int, uint et Number ?

Et bien, figurez-vous que ce sont également des classes, qui fonctionnent de la mêmemanière que la classe String !

Il est impossible d’utiliser le mot-clé new pour créer des objets des classes intet uint ! C’est la raison pour laquelle elles commencent par une minuscule,cela permet de bien marquer la différence avec les autres classes.

En effet, ces deux classes sont encore plus spéciales et n’utilisent qu’une seule syntaxe :celle que vous avez apprise dans la première partie du cours. Par contre, la classeNumber fonctionne tout à fait normalement, comme la classe String :

1 var entier:int = new int(-47); // INTERDIT ! ! !2 var entier2:int = -42; // Autorisé34 var entierNonSigne:uint = new uint(47); // NOOON ! Tout sauf ça

!5 var entierNonSigne2:uint = 47; // Ouf !67 var nombre:Number = new Number(3.1415); // Pas de problème8 var nombre2:Number = 3.1415; // Pour les flemmards9

120

Page 144: Programmez en Actionscript 3

DES POINTEURS SOUS LE CAPOT

10 var monNom:String = new String("Bryan"); // Je sens que jeconnais cette phrase ...

11 var ouSuisJe:String = "In the kitchen!"; // Argh !

Accéder aux propriétés d’un objet

Reprenons un peu plus de code que nous avons écrit dans la première partie :

1 var coucou:String = new String("Hello world!");2 trace("Cette chaîne contient " + coucou.length + " caractères."

);3 // Affiche : Cette chaîne contient 13 caractères.

et observons plus particulièrement cette expression : coucou.length.

Nous avons utilisé la propriété length de la classe <minicode type="actionscript"String</minicode>qui renvoie la longueur de la chaîne ! Décortiquons cette instruction :

– Tout d’abord, nous renseignons le nom de la variable contenant notre objet. Ici, ils’agit de coucou, variable que nous avons déclaré plus haut avec cette ligne : varcoucou:String = "Hello world !"..

– Ensuite, nous utilisons le caractère point « . » pour signaler que nous allons utiliserun attribut ou une méthode de cet objet-là.

– Enfin, nous spécifions quelle propriété nous voulons utiliser : ici, nous tapons donclength, la propriété de la classe String qui nous intéresse.

Nous obtenons ainsi la longueur de l’objet « chaîne de caractères » contenu dans lavariable coucou ! En français, cela donnerait quelque chose comme : « Lis la propriétélongueur de l’objet contenu dans ma variable coucou. »

Des pointeurs sous le capot

Plantons le décor

Prenons notre classe Voiture, et supposons qu’elle ait une propriété marque de typeString qui contient le nom de la marque des voitures.

Créons un objet de la classe Voiture et spécifions sa marque :

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

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

Déclarons une deuxième variable :

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

121

Page 145: Programmez en Actionscript 3

CHAPITRE 8. LA POO DANS TOUS SES ÉTATS

La variable n’est pas initialisée, elle contient donc null.

Ensuite, procédons à une affectation :

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

Nous allons regarder de quelle marque sont les voitures (vous avez sûrement deviné) :

1 trace(lienVoiture.marque; // Affiche : Peugeot2 trace(lienVoiture2.marque); // Affiche : Peugeot

Bien ! Maintenant, modifions la marque de lienVoiture2 :

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

Enfin, regardons à nouveau la marque des voitures :

1 trace(lienVoiture.marque); // Affiche : Renault2 trace(lienVoiture2.marque); // Affiche : Renault

Horreur ! Les deux ont la même marque ! La réponse est simple : il s’agit du mêmeobjet ! Et oui, il n’y en a qu’un seul et unique !

Explications

Lorsque nous créons l’objet de classe Voiture, il est stocké dans la mémoire vive devotre système. Ensuite, quand nous l’affectons à une variable, un lien vers cet objet estcréé, puis stocké dans la variable. On dit alors que les variables sont des pointeurs :elles pointent du doigt l’objet qui leur est associé, afin que nous, programmeurs, puis-sions accéder à cet objet. D’ailleurs, vous aurez peut-être remarqué le nom précis quej’ai donné à mes variables : lienVoiture et lienVoiture2 ; n’est-ce pas évocateur ?(voir figure 8.11 )

Bien évidemment, j’ai nommé les variables ainsi dans un but pédagogique :évitez d’appeler vos variables de cette façon, cela ne servirait à rien (et tousvos collègues vous dévisageraient d’un air bizarre).

Donc, lorsque nous écrivons notre affectation, nous nous contentons en réalité de reco-pier le pointeur vers l’objet initialement créé :

1 lienVoiture2 = lienVoiture; // Recopions le pointeur delienVoiture dans lienVoiture2

Ainsi, en utilisant les propriétés de l’objet de lienVoiture2, nous utilisons égalementcelles de l’objet de lienVoiture. Logique : il s’agit du même objet !

122

Page 146: Programmez en Actionscript 3

DES POINTEURS SOUS LE CAPOT

Figure 8.11 – Les variables-pointeurs sont toutes les deux liées à l’objet.

Et si nous créions un autre objet de classe Voiture ?

Très bonne idée ! Créons un nouvel objet et affectons-le à la variable lienVoiture2 :

1 lienVoiture2 = new Voiture (); // Un deuxième objet Voitureentre en scène !

Modifions sa marque :

1 lienVoiture2.marque = "Citroën";

Et regardons la marque des deux voitures :

1 trace(lienVoiture.marque); // Affiche : Renault2 trace(lienVoiture2.marque); // Affiche : Citroën

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

En résumé– Les objets contiennent des propriétés : les variables sont appelées attributs et lesfonctions méthodes.

– Chaque objet est décrit par une classe : il s’agit d’une sorte de plan de constructiondes objets. On dit que les objets sont des instances (ou occurrences) de leur classe.

– L’encapsulation est un principe important en POO qui consiste à cacher le fonc-tionnement interne des classes, et à montrer seulement une interface simplifiée.

– L’héritage est un autre principe, tout aussi important, consistant à faire hériter desclasses (dites classes filles) d’une classe mère.

– En Actionscript 3, tout est objet : tout ce que vous manipulerez, ce sera des objets.– Le mot-clé new permet de créer des objets.– La plupart des variables sont en réalité des pointeurs (ou liens) vers des objetsstockés en mémoire.

123

Page 147: Programmez en Actionscript 3

CHAPITRE 8. LA POO DANS TOUS SES ÉTATS

124

Page 148: Programmez en Actionscript 3

Chapitre 9Les classes (1ère partie)

Difficulté :

Dans le chapitre précédent, nous avons introduit la notion de classe et nous avons mêmeappris à utiliser la classe String. C’est déjà un bon début dans la découverte de la Pro-grammation Orientée Objet, mais ce n’est pas suffisant. À partir de maintenant, nousallons apprendre à créer nos propres classes. En utilisant le concept d’objets ou de classes,la Programmation Orientée Objet permet d’organiser le code vraiment différemment dela programmation procédurale.

Étant donné qu’il y a beaucoup de choses à dire sur le sujet, la théorie sur les classess’étalera sur deux chapitres. Ce chapitre portera sur les principes fondamentaux, nous lecomplèterons avec quelques notions supplémentaires dans le prochain chapitre.

125

Page 149: Programmez en Actionscript 3

CHAPITRE 9. LES CLASSES (1ÈRE PARTIE)

Créer une classe

La Classe

Rappels

Comme nous l’avons déjà mentionné, une classe est l’ensemble du code permettant dereprésenter un objet dans un programme. Celle-ci est constituée de variables appeléesattributs et de fonctions appelées méthodes. On parle également de propriétéspour définir l’ensemble des attributs et des méthodes d’une classe. Ainsi, grâce àces propriétés, nous allons pouvoir structurer notre objet et définir l’intégralité de sescaractéristiques.

Une fois que la classe est définie, nous pouvons alors créer des instances ou occur-rences de cette classe. Pour vous faire une idée, on peut considérer une instancecomme un objet « physique », en opposition à la classe qui définit plutôt une descrip-tion générale de l’objet. Ainsi, nous pouvons créer plusieurs instances d’un même objet,mais dont les caractéristiques pourront varier légèrement.

Il est important de bien faire la différence entre la classe, qui est unique etqui décrit un certain objet, et ses instances qui peuvent être multiples etqui sont les objets « réels ». Ceux-ci peuvent être décrits à partir des mêmespropriétés dont les valeurs peuvent varier.

Pour rassurer tout le monde, nous allons prendre un petit exemple concret :

– Une classe Voiture permet de définir l’ensemble du parc automobile européen. Cetteclasse Voiture définit l’ensemble des caractéristiques que peut posséder une automo-bile. Il serait par exemple possible d’y retrouver la marque de celle-ci, mais égalementsa couleur ou encore son immatriculation que nous pourrions définir comme at-tributs.

– Maintenant nous savons ce qu’est une Voiture, nous aurions peut-être l’envie d’encréer quelques-unes. C’est une très bonne idée, et nous allons commencer par créerune Renault de couleur « grise » et immatriculée dans le « Rhône ». Voilà main-tenant que nous en avons besoin d’une seconde ; très bien, voici une Peugeot decouleur « noire » et immatriculée dans le « Cantal ».

Dans cet exemple, nous avons donc utilisé une classe Voiture pour en créer deuxinstances qui sont la Renault et la Peugeot.

Structure

Si vous avez bien suivi le deuxième chapitre de la première partie, vous devriez vousrappeler d’un schéma représentant la structure de la classe principale. Je vous pro-pose de généraliser ce schéma et de le compléter un peu plus avec ce que nous venons dedécouvrir. Nous pouvons y ajouter notamment les attributs et les méthodes. Vousverrez à la figure 9.1 comment sont structurées les classes.

126

Page 150: Programmez en Actionscript 3

CRÉER UNE CLASSE

Figure 9.1 – Schéma général de la structure d’une classe.

Vous ne devriez donc pas être surpris de la manière dont nous définissons une classe àl’intérieur du code :

1 package2 {34 public class NomDeLaClasse5 {6 // Attributs78 // Méthodes9

10 }1112 }

Nous allons à présent apprendre à définir chacune des propriétés de la classe !

Construire la classe

Package

Avant toute chose, nous allons brièvement reparler de la notion de package. Nousl’avions défini comme décrivant la position de la classe dans l’arborescence des fichiersde votre projet. Rassurez-vous, c’est toujours le cas ! Cependant, je voudrais présenterici la manière à adopter pour positionner ses propres classes dans différents dossiers.

Pour l’instant, il est vrai que nous ne disposons pas d’un projet conséquentet que le nombre de classes est assez faible. Cependant, lorsque nos projetsgrandiront et que les classes vont se multiplier, nous devrons faire le tri etranger nos classes dans différents dossiers afin d’y voir plus clair.

Voici donc un conseil qu’il serait prudent de suivre : organisez vos classes en fonctionde leur nature et de leur utilité !

Par exemple, nous pourrions imaginer un package nommé vehicules qui contien-drait les classes Voiture, Camion et Moto. Puis nous créons deux nouvelles classes

127

Page 151: Programmez en Actionscript 3

CHAPITRE 9. LES CLASSES (1ÈRE PARTIE)

Fourchette et Couteau, qui n’ont apparemment strictement rien à faire dans le packagevehicules. Il nous faut alors en insérer un nouveau que nous pourrions nommercouverts.

Attributs

Nous allons maintenant présenter le premier type de propriétés d’une classe : il s’agitdes attributs ! Les attributs ont en réalité des variables, nous pouvons donc lesdéclarer comme n’importe quelle variable :

1 var _unAttribut:String;

Lorsqu’on programme en POO, on a l’habitude de ne pas initialiser les variables lorsde la déclaration, mais plutôt à l’intérieur d’un constructeur que nous détailleronsun peu après dans ce cours.

Nous introduisons également le mot-clé private devant la déclaration de l’attribut,dont nous reparlerons aussi plus tard :

1 private var _unAttribut:String;

Ça y est, nous avons notre premier attribut !

Par convention, en Actionscript 3, nous ajouterons un caractère underscore« _ » devant le nom de tous nos attributs. Cela nous sera pratique lorsquenous écrirons des accesseurs et mutateurs.

Méthodes

Comme nous l’avons précisé plus haut, les méthodes sont des fonctions. Il peut doncs’agir aussi bien d’instructions de fonction que d’expressions de fonction (pourceux qui auraient tout oublié, allez faire discrètement un tour dans le chapitre sur lesfonctions !). Néanmoins, je vous avais dit que les instructions de fonction étaientpréférables, nous utiliserons donc ce type de fonctions :

1 function uneMéthode ():void2 {3 // Instructions4 }

Bien entendu, à l’intérieur de ces méthodes nous avons accès aux différents attributsafin de pouvoir modifier leur valeur ou simplement lire leur contenu. Au final, seuls lesattributs peuvent mémoriser des choses et ainsi se souvenir de l’état de l’objet enquestion. C’est la raison pour laquelle, en général, vos méthodes serviront à lire oumodifier le contenu d’un ou plusieurs attributs.

Voilà comment notre méthode pourrait modifier un attribut :

1 function uneMéthode(nouvelleValeur:String):void

128

Page 152: Programmez en Actionscript 3

CRÉER UNE CLASSE

2 {3 unAttribut = nouvelleValeur;4 }

Bien sûr, nous pouvons faire toutes sortes de manipulations à l’intérieur d’une méthodeet pas simplement affecter ou lire le contenu d’un attribut.

Contrairement à d’autres langages, l’Actionscript ne prend pas en compte lasurcharge de méthodes. Pour ceux qui découvrent ce terme, ne vous inquiétezpas, nous en reparlerons avant la fin de ce chapitre.

Enfin, les méthodes prennent également un mot-clé devant leur déclaration, qui estcette fois-ci public :1 public function uneMéthode ():void2 {3 // Instructions4 }

Les mots-clés private et public sont liés à la notion d’encapsulation quenous découvrirons plus en profondeur au cours du chapitre. En attendant,sachez que ces mots-clés existent et considérez qu’ils font partie de la décla-ration des propriétés d’une classe.

Constructeur

À présent, il est temps d’introduire une méthode un peu particulière : le constructeur !Le constructeur est la méthode appelée par défaut lors de l’initialisation d’un objet,vous savez lorsque vous utilisez lemot-clé new. Vous noterez que cette méthode possèdeobligatoirement le même nom que celui de la classe. Par exemple, pour notre classenommée Voiture, notre constructeur pourrait ressembler à ceci :1 public function Voiture ()2 {3 // Instructions4 }

Le constructeur d’une classe sert principalement à initialiser l’ensemble des attri-buts déclarés dans celle-ci.

Vous remarquerez que le constructeur ne peut pas renvoyer de valeur, aussiévitez d’insérer le mot-clé return à l’intérieur de celui-ci. Une instruction derenvoi serait ignorée à l’exécution, et pourrait entraîner des messages d’erreurlors de la compilation.

Ne vous inquiétez pas si certains points sont encore flous dans votre esprit, nous allonscréer ensemble une classe pas à pas à la fin du chapitre !

129

Page 153: Programmez en Actionscript 3

CHAPITRE 9. LES CLASSES (1ÈRE PARTIE)

Des paramètres facultatifs pour nos méthodes

La surcharge de méthodes

Dans beaucoup de langages utilisant la Programmation Orientée Objet, on re-trouve le concept de surcharge de méthodes, mais ce n’est pas le cas en ActionS-cript 3. Contrairement à son nom abominable, ce concept est relativement simple etconsiste a définir plusieurs méthodes portant le même nom. Il est alors possible dedéfinir des paramètres de types différents ou encore d’utiliser un nombre de paramètresdifférent. Ceci est très utile et permet, par exemple, de définir plusieurs constructeursn’ayant pas le même nombre de paramètres :

1 package2 {34 public class MaClasse5 {6 // Attribut7 private var _unAttribut:int;89 // Constructeurs

10 public function MaClasse ()11 {12 _unAttribut = 0;13 }1415 public function MaClasse(entier:int)16 {17 _unAttribut = entier;18 }1920 }2122 }

Dans l’exemple précédent, il serait possible d’instancier une classe sans renseigner deparamètres avec le premier constructeur, ou en précisant la valeur de l’entier avec lesecond. Cette technique servirait donc à rendre l’utilisation d’une classe plus simpleet plus souple, en permettant l’appel « d’une même fonction » avec des paramètresdifférents.

Malheureusement donc, la surcharge de méthodes est strictement interdite en Ac-tionscript, vous ne trouverez donc jamais deux méthodes ayant le même nom au seind’une classe, et ceci est aussi valable pour les constructeurs. En revanche, il est possiblede contourner le problème, voire même de le simplifier : c’est le rôle des paramètresfacultatifs !

130

Page 154: Programmez en Actionscript 3

DES PARAMÈTRES FACULTATIFS POUR NOS MÉTHODES

Les paramètres facultatifs

Définition

En Actionscript, il existe un concept qui permet d’obtenir une utilisation similaire àune surcharge de méthodes. Il s’agit des paramètres facultatifs ! Cette nouvellenotion est associée en réalité à la définition de fonctions et n’est donc pas limitée auxseules méthodes. Ainsi, pour insérer un paramètre facultatif, il suffit de lui préciserune valeur par défaut dans lors de la définition de la fonction, comme ceci :

1 function maFonction(entier:int , texte:String = "Valeur par défaut", nombre:Number = 0):void

2 {3 trace(nombre , texte);4 }

En utilisant ici des valeurs par défaut pour les deux derniers paramètres, il alors possiblede les « omettre » lors de l’appel de la fonction. Ainsi, contrairement à la surchargede méthode, nous n’avons pas besoin, en Actionscript, de réécrire l’intégralité ducontenu de la fonction pour chaque définition de nouveaux paramètres.

Attention cependant à l’ordre de définition des paramètres. Les paramètresfacultatifs doivent obligatoirement être placés à la fin de la liste des para-mètres. Ils doivent également être écrits dans un ordre d’utilisation précis quenous allons préciser en parlant des appels de ces fonctions.

Appels

Comme leur nom l’indique, les paramètres facultatifs peuvent être « omis » lors del’appel de la fonction. Ainsi, la fonction définie précédemment, peut être appelée enrenseignant uniquement le premier paramètre :

1 maFonction(10);

Il est également possible de renseigner les deux premiers paramètres, sans le troisième :

1 maFonction(10, "Nouveau texte");

Attention toutefois à l’ordre de définition des paramètres facultatifs. Eneffet, s’il est possible de renseigner le premier paramètre facultatif et d’omettrele second, l’inverse est impossible. Ainsi, l’appel suivant n’est pas correct :maFonction(10, 5). C’est pourquoi, vous devez être vigilant dans l’ordrede définition des paramètres facultatifs de vos fonctions !

Enfin, voici dernier appel possible de votre fonction, qui comprend l’intégralité desparamètres :

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

131

Page 155: Programmez en Actionscript 3

CHAPITRE 9. LES CLASSES (1ÈRE PARTIE)

Ainsi, grâce à la définition de paramètres facultatifs, nous avons trois manièresdifférentes d’appeler la même fonction !

Encapsulation

L’encapsulation que nous allons redécouvrir maintenant est l’un des concepts lesplus importants de la Programmation Orientée Objet ! Vous rappelez-vous dumot-clé private que nous avons introduit avant chacun de nos attributs ? Il permetde masquer la propriété à laquelle il est associé, celle-ci n’est donc pas visible depuisl’extérieur de la classe en question. Ainsi, à partir de maintenant, nous masqueronsobligatoirement l’ensemble de nos attributs ! Pour y accéder, nous serons donc dansl’obligation de faire appel à une méthode intermédiaire qui nous permettra de vérifierles données et d’affecter les attributs en conséquence, hors du champ de vision del’utilisateur.

L’intérêt de l’encapsulation est de simplifier l’utilisation des objets en masquant l’en-semble des attributs et des méthodes qui sont utiles simplement au fonctionnementde l’objet. Ainsi, vu de l’extérieur, nous pourrons manipuler ces objets facilement, sansnous soucier de leur fonctionnement interne.

Ce concept introduit donc la notion de droits d’accès que nous allons voir tout desuite !

Les différents droits d’accès

Il n’est pas possible de parler d’encapsulation sans toucher un mot des droits d’accèsou portées. Ces droits d’accès définissent la visibilité d’une propriété au sein de votrecode. En Actionscript, il existe trois portées qui sont public, private et internal.Ces mots-clés se placent juste avant la déclaration des propriétés auxquelles ilssont associés.

En réalité, il existe une quatrième portée nommée protected. Cependant,celle-ci est profondément liée à la notion d’héritage dont nous reparlons dansle chapitre qui lui est consacré.

Privés

Les droits d’accès dits « privés » s’utilisent avec le mot-clé private. Ils permettentde restreindre l’utilisation de la propriété à la classe où elle est définie. Ainsi, cettepropriété ne sera pas visible depuis l’extérieur de cette classe. Voici un attribut dontla portée est de type private :

1 private var _monAttribut:String;

132

Page 156: Programmez en Actionscript 3

ENCAPSULATION

Je rappelle que tous nos attributs doivent être invisibles depuis l’extérieur dela classe où ils sont définis, utilisez donc la portée private.

Publiques

Les droits d’accès « publics » sont associés au mot-clé public, que nous avons déjàcroisé plusieurs fois. Celui-ci permet de rendre visible partout dans le code la propriétéà laquelle il est associé. Ce sera donc le cas pour la majorité de vos méthodes. D’ailleurs,il est impossible d’affecter une autre portée que public à un constructeur :

1 public function MonConstructeur ():void2 {3 ...4 }

Internes

Les droits d’accès « internes » sont un peu spéciaux. Ils sont associés au mot-clé internal. Les propriétés définies avec ce type de portées sont visibles depuisl’ensemble du package, dont la classe où elle est déclarée appartient.

1 internal var _monAttribut:int;

Cette portée n’est pas très utilisée en général, mais sachez qu’il s’agit de laportée par défaut lorsqu’aucune autre n’est spécifiée.

Les accesseurs

Syntaxe

Il existe un type deméthodes un peu spécial, directement lié à la notion d’encapsulation :les accesseurs ! On désigne par accesseurs l’ensemble des accesseurs etmutateurs,également appelées getters et setters. Ceux-ci permettent l’accès direct à un attributde portée private en lecture par l’accesseur et en écriture par le mutateur. Ainsi,dans beaucoup de langages de programmation, on retrouve un ensemble d’accesseursdont le nom débute par get (de l’anglais to get qui signifie « obtenir ») et un ensemblede mutateurs dont le nom débute par set (de l’anglais to set qui signifie « définir »).

Pour gérer l’ensemble des accesseurs, l’Actionscript a introduit deux mots-clés getet set qui permettent notamment de donner un nom identique aux deux accesseurs.Illustrons cela par d’un exemple. Voici un attribut quelconque dont la portée est detype private :

133

Page 157: Programmez en Actionscript 3

CHAPITRE 9. LES CLASSES (1ÈRE PARTIE)

1 private var _texte:String;

Étant donné que cet attribut est de type private, il n’est pas accessible depuis l’exté-rieur de la classe où il a été défini. Cependant, il est probable que nous ayons besoin demodifier cet attribut depuis la classe principale. Si nous voulons respecter le conceptd’encapsulation, nous devons donc conserver la portée de cet attribut et définir desaccesseurs pour y avoir accès :

1 // Accesseur2 public function get texte():String3 {4 return _texte;5 }67 // Mutateur8 public function set texte(nouveauTexte:String):void9 {

10 _texte = nouveauTexte;11 }

Comme vous le voyez, mes deux accesseurs utilisent le même nom de fonction, cequi est drôlement pratique. Mais l’utilisation des accesseurs va plus loin que ça, carleur utilisation est un peu particulière. Ainsi, l’accesseur get d’une instance nomméeMonObjet s’utilise sans les parenthèses :

1 var maVariable:String = MonObjet.texte;

Quant à lui, le mutateur s’utilise également sans parenthèses, mais avec le symboleégal « = » qui est considéré comme un signe d’affectation :

1 MonObjet.texte = "Nouvelle chaîne de caractères";

Une telle utilisation des accesseurs est spécifique à l’Actionscript. Cette tech-nique permet de manipuler les accesseurs comme s’il s’agissait de l’attributlui-même. Cependant, en utilisant les getters et setters, vous respectez leconcept d’encapsulation. Ainsi, les propriétés créées à partir d’accesseurssont considérées comme étant des attributs, et non des méthodes.

Une raison supplémentaire d’utiliser les accesseurs

Lorsque vous utilisez des accesseurs, vous n’êtes pas obligés de vous contenter de lireun attribut dans un getter ou de lui affecter une nouvelle valeur dans un setter :en effet, il est tout à fait possible d’ajouter du code supplémentaire, voire de ne pasmanipuler d’attribut en particulier !

Prenons la classe suivante :

1 package2 {

134

Page 158: Programmez en Actionscript 3

ENCAPSULATION

3 /**4 * Une classe d'exemple5 */6 public class Voiture7 {8 private var _largeur:int;9

10 public function Voiture ()11 {1213 }1415 public function get largeur ():int16 {17 return _largeur;18 }1920 public function set largeur(value:int):void21 {22 _largeur = value;23 }2425 public function mettreAJour ():void26 {27 // Mettre à jour l'affichage28 }29 }3031 }

Dans un premier temps, imaginons que dans notre classe, nous disposions d’une mé-thode mettreAJour() qui met à jour l’affichage de notre objet en fonction de la valeurde l’attribut _largeur. Pour spécifier la largeur de la voiture, nous procéderions ainsi :

1 var voiture:Voiture = new Voiture ();2 voiture.largeur = 100; // Largeur de la voiture3 voiture.mettreAJour (); // Mettons à jour l'affichage de la

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

voiture pour une largeur de 150

Grâce aux accesseurs, il est possible de l’appeler automatiquement dès que l’on modifiela largeur de l’objet :

1 public function set largeur(value:int):void2 {3 _largeur = value;4 mettreAJour ();5 }

135

Page 159: Programmez en Actionscript 3

CHAPITRE 9. LES CLASSES (1ÈRE PARTIE)

Ainsi, au lieu d’avoir à appeler manuellement la méthode mettreAJour(), il suffit demodifier la largeur :

1 var voiture:Voiture = new Voiture ();2 voiture.largeur = 100; // Largeur de la voiture3 // L'affichage de la voiture est automatiquement mis à jour

dans l'accesseur set largeur !4 voiture.largeur = 150; // Changeons la largeur de la voiture5 // Encore une fois , l'affichage de la voiture est

automatiquement mis à jour , il n'y a rien d'autre à faire !

Maintenant, nous aimerions limiter les valeurs possibles de l’attribut largeur ; disonsqu’il doit être supérieur à 100 et inférieur à 200.

1 var voiture:Voiture = new Voiture ();2 voiture.largeur = 100; // Largeur de la voiture3 // On vérifie que la largeur est dans les limites4 if(voiture.largeur < 100)5 {6 voiture.largeur = 100;7 }8 else if(voiture.largeur > 200)9 {

10 voiture.largeur = 200;11 }12 trace(voiture.largeur); // Affiche: 1001314 voiture.largeur = 250; // Changeons la largeur de la voiture15 // On vérifie une fois de plus que la largeur est dans les

limites16 if(voiture.largeur < 100)17 {18 voiture.largeur = 100;19 }20 else if(voiture.largeur > 200)21 {22 voiture.largeur = 200;23 }24 trace(voiture.largeur); // Affiche: 200

Vous remarquerez que c’est plutôt fastidieux. Bien sûr, nous pourrions utiliser unefonction, mais il vaut mieux mettre dans la classe Voiture ce qui appartient à la classeVoiture ! Encore une fois, les accesseurs nous facilitent grandement la tâche, voyezplutôt :

1 public function set largeur(value:int):void2 {3 _largeur = value;45 // _largeur doit être comprise entre 100 et 2006 if (_largeur < 100)

136

Page 160: Programmez en Actionscript 3

ENCAPSULATION

7 {8 _largeur = 100;9 }

10 else if(_largeur > 200)11 {12 _largeur = 200;13 }1415 mettreAJour ();16 }

Le code principal serait alors écrit ainsi :

1 var voiture:Voiture = new Voiture ();2 voiture.largeur = 100; // Largeur de la voiture3 // Plus besoin de vérifier que la largeur est dans les limites ,

l'accesseur le fait pour nous !4 trace(voiture.largeur); // Affiche: 10056 voiture.largeur = 250; // Changeons la largeur de la voiture7 trace(voiture.largeur); // Affiche: 200

Avouez que c’est extrêmement pratique ! Je vous conseille d’appliquer cette façon defaire le plus souvent possible, cela vous rendra service.

Générateur de code dans Flashdevelop

Il existe un outil très pratique disponible dans la plupart des IDE, dont Flashdevelop,pour générer automatiquement des portions de codes. Nous pouvons l’utiliser, entreautres, pour générer les accesseurs de nos attributs ! Pour cela, il faut suivre troisétapes : voir les figures 9.2, 9.3 et 9.4.

Il est également possible de se passer de la deuxième étape en utilisant direc-tement le raccourci Ctrl + Maj + 1.

Le code ainsi généré, ressemblera à ceci :

1 public function get texte():String2 {3 return _texte;4 }56 public function set texte(value:String):void7 {8 _texte = value;9 }

137

Page 161: Programmez en Actionscript 3

CHAPITRE 9. LES CLASSES (1ÈRE PARTIE)

Figure 9.2 – 1. Placer le curseur sur la ligne de l’attribut dont il faut générer lesaccesseurs

Figure 9.3 – 2. Sélectionner l’option ’Code Generator’

138

Page 162: Programmez en Actionscript 3

EXERCICE : CRÉONS NOTRE PREMIÈRE CLASSE

Figure 9.4 – 3. Sélectionner une des trois options

Exercice : Créons notre première classe

Présentation de la classe

Description

Afin de mieux apprivoiser toutes ces nouvelles notions, nous allons maintenant écrirenotre première classe pas à pas ! Nous allons donc créer une classe Voiture, que je vouspropose de découvrir maintenant. Nous y intégrerons les attributs suivants, ainsi queles accesseurs correspondants :

– SaMarque : cet argument de type String permet de définir la marque de la voiture.Celui-ci sera défini dans le constructeur et il s’agit du seul attribut qui ne possè-dera pas de mutateur. En effet, une voiture peut être repeinte, modifiée par divers« accessoires » qui influeront sur sa longueur ou encore elle peut changer de plaqued’immatriculation. En revanche, elle ne peut pas changer sa marque de fabrique.

– SaCouleur : cet argument de type String représente la couleur de peinture de lavoiture. Celle-ci sera manipulée par les deux accesseurs nommés couleur.

– SaLongueur : la longueur du véhicule sera définie par une variable de type int. Deuxaccesseurs longueur permettront de manipuler cet élément. Lors d’une affectation,nous devrons vérifier si la valeur renseignée est positive. Dans le cas contraire, nousutiliserons la valeur -1 pour préciser que la longueur est « non renseignée ».

– SonImmatriculation : enfin l’immatriculation du véhicule sera stockée dans un at-tribut de type String, qui possèdera deux accesseurs immatriculation.

Lançons-nous donc dans la conception de cette classe. Lisez avec attention afin de noterles différentes étapes de création d’une classe.

139

Page 163: Programmez en Actionscript 3

CHAPITRE 9. LES CLASSES (1ÈRE PARTIE)

UML : Unified Modeling Language

Lorsque l’on programme, il est possible de représenter les différentes classes sur unschéma pour « résumer » leurs propriétés. Il existe différentes modélisations standardsdont l’Unified Modeling Language ou UML. Cette représentation est très souventassociée aux langages orientés objets comme l’Actionscript. Sans donner plus de dé-tails, je vous propose de découvrir à la figure 9.5 la représentation correspondant ànotre classe Voiture.

Figure 9.5 – Représentation UML de la classe Voiture

Comme vous le voyez, notre classe est divisée en deux parties : les attributs et lesméthodes ! Ceux-ci sont donc listés en spécifiant de quels types ils sont, ainsi queles paramètres à renseigner en ce qui concerne les méthodes. Cela permet de dresserune sorte de « plan de construction » de la classe à coder, mais également son moded’emploi pour d’éventuels autres programmeurs. Cela permet également de mettre enévidence les relations liant les classes les unes aux autres, comme nous le verrons aucours des chapitres à venir. Vous aurez très certainement remarqué les signes « - » et« + » qui précèdent l’ensemble de nos propriétés. Ceux-ci permettent de représenterles différents droits d’accès liés à chacune de nos propriétés de la manière suivante :« - » pour privés, « + » pour publiques, « ~ » pour internes et « # » pour protégés.

L’objectif du cours n’est pas de vous apprendre à utiliser l’UML, cependant,nous utiliserons quelques schémas qui sont souvent bien plus parlants que desmots. Vous apprendrez à lire et utiliser les bases de cette modélisation au fildes chapitres de cette partie.

Écriture du code

Préparation du nouveau fichier

Tout d’abord, pour créer une nouvelle classe, nous aurons besoin d’un nouveau fichierActionscript ! Nous allons donc insérer une classe nommée Voiture avec File > New> AS3 Document si vous êtes sous FlashDevelop ou créer un nouveau fichier nommé

140

Page 164: Programmez en Actionscript 3

EXERCICE : CRÉONS NOTRE PREMIÈRE CLASSE

Voiture.as si vous n’utilisez pas ce logiciel.

Puis, nous insèrerons à l’intérieur le code de définition de la classe, comme ceci :

1 package2 {3 public class Voiture4 {56 }78 }

Déclaration des attributs

Précédemment, nous avons défini les quatre attributs qui sont saMarque, saCouleur,saLongueur et sonImmatriculation. Tous ces attributs ont évidemment des droitsd’accès de type private, pour respecter le concept d’encapsulation.

Voici donc les différentes déclarations d’attributs :

1 private var _marque:String;2 private var _couleur:String;3 private var _longueur:int;4 private var _immatriculation:String;

Le constructeur

Comme nous l’avons rapidement introduit, le constructeur de cette classe devra rece-voir en paramètre la marque de fabrication du véhicule. Sachant que les autres attributspossèdent des setters, nous ne les introduirons pas dans la liste des paramètres à spé-cifier au constructeur. Néanmoins, ceux-ci devront tout de même être initialisés.

Il est recommandé d’utiliser, dès que cela est possible, les accesseurs et lesmutateurs au sein même de la classe, exception faite du constructeur, oùcela n’est généralement pas nécessaire.

Découvrons tout de suite ce constructeur :

1 public function Voiture(marque:String)2 {3 _marque = marque;4 _couleur = "Sans couleur";5 _longueur = -1;6 _immatriculation = "Non immatriculée";7 }

141

Page 165: Programmez en Actionscript 3

CHAPITRE 9. LES CLASSES (1ÈRE PARTIE)

Vous pouvez utiliser des noms de paramètres identiques aux noms de vospropriétés (ici marque) : ils sont en effet prioritaires. Pour pouvoir utiliserexplicitement une propriété de l’objet, il faut ajouter le mot-clé this de-vant : si nous avions un mutateur pour l’attribut marque, nous devrionsécrire this.marque = marque; pour l’utiliser.

Les accesseurs

Chaque attribut possède un ou deux accesseurs, nous ne les détaillerons donc pastous. Je vous propose plutôt de découvrir un getter et un setter. Nous allons prendrel’exemple des accesseurs longueur, dont voici le getter :

1 public function get longueur ():int2 {3 return _longueur;4 }

Cet accesseur n’a rien de très compliqué, nous ne nous y attarderons donc pas davan-tage. En revanche, pour le mutateur, nous devons vérifier si la valeur spécifiée estpositive, je vous rappelle. Nous devrons donc utiliser une condition en if...else pourfaire la vérification.

Voici donc le mutateur en question, que vous êtes normalement en mesure de com-prendre par vous-mêmes maintenant :

1 public function set longueur(nouvelleLongueur:int):void2 {3 if(nouvelleLongueur > 0)4 _longueur = nouvelleLongueur;5 else6 _longueur = -1;7 }

Félicitations, nous avons terminé l’écriture de votre première classe !

La classe complète

Parce qu’il est probable que certains ne soient pas pleinement satisfaits avant d’avoir vul’intégralité de celle-ci, je vous propose ici un récapitulatif intégral de la classe Voiture :

1 package2 {3 public class Voiture4 {5 /* ************** Attributs ************** */6 private var _marque:String;7 private var _couleur:String;8 private var _longueur:int;9 private var _immatriculation:String;

142

Page 166: Programmez en Actionscript 3

EXERCICE : CRÉONS NOTRE PREMIÈRE CLASSE

1011 /* ************ Constructeur ************ */12 public function Voiture(marque:String)13 {14 _marque = marque;15 _couleur = "Sans couleur";16 _longueur = -1;17 _immatriculation = "Non immatriculée";18 }1920 /* ************** Accesseurs ************** */21 public function get marque ():String22 {23 return _marque;24 }2526 public function get couleur ():String27 {28 return _couleur;29 }3031 public function get longueur ():int32 {33 return _longueur;34 }3536 public function get immatriculation ():String37 {38 return _immatriculation;39 }4041 /* ************** Mutateurs ************** */42 public function set couleur(nouvelleCouleur:String):

void43 {44 _couleur = nouvelleCouleur;45 }4647 public function set longueur(nouvelleLongueur:int):void48 {49 _longueur = (nouvelleLongueur > 0) ?

nouvelleLongueur : -1;50 }5152 public function set immatriculation(

nouvelleImmatriculation:String):void53 {54 _immatriculation = nouvelleImmatriculation;55 }56

143

Page 167: Programmez en Actionscript 3

CHAPITRE 9. LES CLASSES (1ÈRE PARTIE)

57 }5859 }

Vous pouvez l’afficher pour la copier en utilisant le code web ci-dessous.

B

�Classe Voiture

Code web : 255948

En résumé– Le mot-clé this fait référence à l’objet lui-même.– Les classes sont triées dans différents package en fonction du type d’objets qu’elles

représentent.– Le constructeur est une méthode particulière appelée à la création d’une instance,où on initialise généralement les attributs.

– Il est possible de définir des paramètres facultatifs à l’intérieur de nos fonctionset méthodes pour palier l’impossibilité de surcharger celles-ci.

– L’encapsulation est le concept permettant de masquer le fonctionnement interned’une classe.

– Pour gérer les droits d’accès, nous disposons des différents mots-clés public,private, internal et protected (que nous aborderons plus loin).

– Des accesseurs peuvent être déclarés à l’aide des mots-clés get et set, et simplifientl’accès aux attributs d’une classe.

144

Page 168: Programmez en Actionscript 3

Chapitre 10Les classes (2nde partie)

Difficulté :

Dans le chapitre précédent, nous avons présenté les bases de la théorie des classes. Nousallons maintenant introduire des notions complémentaires qui vous permettront de structu-rer votre code encore plus facilement et proprement. Contrairement à la plupart des notionsde cette partie sur la POO, celles que nous allons découvrir dans ce chapitre n’ont pas étéprésentées dans le premier chapitre et sont donc complètement nouvelles. Redoublez doncd’attention !

145

Page 169: Programmez en Actionscript 3

CHAPITRE 10. LES CLASSES (2NDE PARTIE)

Les éléments statiques

Peut-être que certains se rappellent de la classe Math que nous avons déjà utilisé. Ilsse demandent alors pourquoi nous l’avions utilisé en employant directement le nom dela classe et sans passer par une instance de celle-ci :

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

Comment cela est-ce possible ?

Maintenant que vous avez déjà quelques connaissances en POO, il est tout à faitjustifié de se poser ce genre de question. En fait, la classe Math utilise des élémentsqui sont un peu particuliers : les éléments statiques ! Comme nous le verrons, ceséléments statiques ne sont pas définis pour les instances d’une classe, mais pour laclasse elle-même. Il existe deux types d’éléments statiques qui sont :

– Les variables statiques.– Les méthodes statiques.

Nous verrons donc comment créer ces éléments et leur intérêt.

Les variables statiques

Les variables statiques sont déclarées à l’aide du mot-clé static, et sont associées,donc définies, pour la classe. Prenons l’exemple de notre classe Voiture du chapitreprécédent et ajoutons-y une variable statique représentant le nombre de fois où celle-cia été instanciée :

1 public static var occurences:int = 0;

Cette variable est donc partagée par la classe, elle n’appartient pas aux instances decelle-ci. Toutefois, cette variable est accessible depuis n’importe quel point de la classe.Nous pourrions notamment incrémenter cette variable à l’intérieur du constructeur dela classe Voiture afin de comptabiliser le nombre d’occurrences de celle-ci :

1 occurrences ++;

Grâce à cette variable statique, nous pourrions obtenir le nombre d’instances de laclasse Voiture, n’importe où dans le code. Pour cela, nul besoin de créer une nouvelleinstance de la classe, il suffit d’utiliser le nom de la classe lui-même :

1 var uneRenault:Voiture = new Voiture("Renault");2 var unePeugeot:Voiture = new Voiture("Peugeot");3 var uneCitroen:Voiture = new Voiture("Citroën");4 trace(Voiture.occurrences); // Affiche : 3

146

Page 170: Programmez en Actionscript 3

LES ÉLÉMENTS STATIQUES

Un élément statique ne peut être utilisé qu’avec la classe où celui-ci estdéclaré. Il est impossible de faire référence à un élément statique à l’aided’une instance de cette classe : des erreurs seraient alors engendrées.

Les méthodes statiques

Il existe un second type d’éléments statiques : il s’agit des méthodes statiques.Dans le chapitre précédent, je vous avais dit que les méthodes servaient principale-ment à la lecture ou à la modification d’un attribut. Nous pouvons donc introduire lesméthodes statiques comme l’ensemble des méthodes qui offrent des fonctionnalitésn’affectant pas au moins l’un des attributs d’une classe.

Ces éléments statiques sont également déclarés à l’aide du mot-clé static :

1 public static function uneMethode ():void2 {3 // Instructions4 }

À l’aide de ces méthodes statiques, il nous est possible de recréer la classe Math,que nous pourrions renommer MaClasseMath. Voici par exemple la redéfinition de laméthode pow() en puissance() :

1 public static function puissance(nombre:int , exposant:int):int2 {3 var resultat:int = nombre4 for(var i:int = 1; i < exposant; i++)5 {6 resultat *= nombre;7 }8 return resultat;9 }

Le code complet de la classe serait :

1 package2 {3 public class MaClasseMath4 {5 public static function puissance(nombre:int , exposant:

int):int6 {7 var resultat:int = nombre8 for(var i:int = 1; i < exposant; i++)9 {

10 resultat *= nombre;11 }12 return resultat;13 }14 }

147

Page 171: Programmez en Actionscript 3

CHAPITRE 10. LES CLASSES (2NDE PARTIE)

15 }

Vous remarquerez que cette classe ne possède pas de constructeur : en effet,il est permis de ne pas mettre de constructeur si vous ne vous en servirezpas. Ici, nous n’avons pas mis de constructeur car nous n’allons jamais créerd’instance de cette classe.

Nous pouvons ainsi l’utiliser sans créer d’occurrences de cette nouvelle classe :

1 var monNombre:int = MaClasseMath.puissance(2,10);2 trace(monNombre); // Affiche : 1024

Des classes telles que Math ont été conçues pour être utilisées uniquement grâce à deséléments statiques. En utilisant ce principe, vous pouvez ainsi regrouper un ensemblede fonctionnalités à l’intérieur d’une même classe. Vous n’aurez donc pas besoin de créerd’occurrences de celle-ci et vous ferez ainsi l’économie des instructions de déclarationset d’initialisations des instances.

Il est impossible d’utiliser le mot-clé this dans les méthodes statiques, carelles ne sont liées à aucun objet en particulier.

Une nouvelle sorte de « variable » : la constante !

Lorsque nous avons introduit les variables dans la première partie, nous n’avons pasparlé des constantes ! Comme son nom l’indique, la valeur d’une constante estfigée contrairement à celle d’une variable qui est vouée à évoluer au cours du pro-gramme. Ces constantes sont principalement utilisées en POO et représentent descaractéristiques constantes d’un objet.

Je vous invite à découvrir ce nouveau type d’élément sans plus attendre !

Présentation

Déclaration

De la même façon que nous avions l’instruction ou mot-clé var pour déclarer une va-riable, nous disposons du mot-clé const en ce qui concerne les constantes. Commeles variables, ces dernières possèdent également un type. Voici par exemple la décla-ration d’une constante de type String :

1 const MA_CONSTANTE:String;

148

Page 172: Programmez en Actionscript 3

UNE NOUVELLE SORTE DE « VARIABLE » : LA CONSTANTE !

Vous remarquerez qu’ici nous n’utilisons pas la notion Camel. Effectivement,il est de coutume d’écrire les noms de constantes en lettres majuscules. Celapermet de les différencier des variables, et de préciser qu’il s’agit bien d’uneconstante. Utilisez l’underscore « _ » pour séparer les différents mots à l’in-térieur du nom de votre constante.

Le code précédent n’a malheureusement aucun intérêt et ne sert à rien sans l’initialisationde la constante !

Initialisation

Tout comme une variable, il est important d’initialiser une constante. Vous pou-vez procéder exactement de la même manière que pour une variable. La techniqued’initialisation dépend bien entendu du type de la constante.

Voici donc comment initialiser notre constante précédente de type String :

1 const MA_CONSTANTE:String = "Valeur";

Contrairement aux variables, Il est strictement impossible d’initialiser la valeurd’une constante ailleurs que lors de sa déclaration. Étant donné que la valeurd’une constante est non modifiable, n’essayez pas non plus de procéder à uneaffectation.

Intérêt des constantes

Il y a certainement plus de la moitié, voire même les trois quarts d’entre vous qui sesont posé la question suivante :

À quoi ces constantes peuvent-elles bien servir ?

Contrairement à ce que vous pensez, les constantes ont plusieurs utilités.

– Tout d’abord, elles permettent de mettre des noms sur des valeurs. Votre programmene marchera pas mieux avec cela, c’est uniquement une question de clarificationdu code. Avouez qu’il est quand même plus aisé de comprendre la significationd’une expression si celle-ci utilise des noms plutôt que des valeurs : prixRoue *NOMBRE_DE_ROUES plutôt que prixRoue * 4. Dans le second cas, nous pourrionsnous demander s’il s’agit d’une augmentation du prix d’une roue, une conversion duprix des euros aux dollars, ou bien une multiplication par le nombre de roues. Dansla première expression, l’opération est tout à fait claire ; ce qui simplifie grandementle travail de relecture d’un code.

– Une autre utilité des constantes est de s’assurer de la pérennisation du code. Ima-ginez que le nombre de roues de votre voiture puisse servir à plusieurs calculs comme

149

Page 173: Programmez en Actionscript 3

CHAPITRE 10. LES CLASSES (2NDE PARTIE)

le prix de l’ensemble, son poids, etc. Vous devrez donc utiliser cette valeur plusieursfois dans votre code et à des endroits différents. Ainsi, en utilisant une constante à laplace de la valeur réelle, vous facilitez une éventuelle mise à jour de votre programmedans l’hypothèse de l’invention de la voiture à 6 roues ! Essayez d’imaginer le travailqu’il aurait fallu fournir pour remplacer chacune des valeurs présentes dans des coinsopposés de votre code.

N’utilisez pas non plus des constantes à tour de bras dans vos programmes.Leur but est de simplifier la lecture du code ; n’allez donc pas le compliquerdavantage !

Un objet dans un objet (dans un objet. . .)

Jusqu’à présent, nous n’avions utilisé qu’une seule classe à la fois. Mais là où la POOdevient vraiment intéressante, c’est lorsque nous combinons les classes entre elles !

Le problème du pétrole

Reprenons la classe Voiture :

1 package2 {3 public class Voiture4 {5 /* ************** Attributs ************** */6 private var _marque:String;7 private var _couleur:String;8 private var _longueur:int;9 private var _immatriculation:String;

1011 /* ************ Constructeur ************ */12 public function Voiture(marque:String)13 {14 _marque = marque;15 _couleur = "Sans couleur";16 _longueur = -1;17 _immatriculation = "Non immatriculée";18 }1920 /* ************** Accesseurs ************** */21 public function get marque ():String22 {23 return _marque;24 }2526 public function get couleur ():String

150

Page 174: Programmez en Actionscript 3

UN OBJET DANS UN OBJET (DANS UN OBJET. . .)

27 {28 return _couleur;29 }3031 public function get longueur ():int32 {33 return _longueur;34 }3536 public function get immatriculation ():String37 {38 return _immatriculation;39 }4041 /* ************** Mutateurs ************** */42 public function set couleur(nouvelleCouleur:String):

void43 {44 _couleur = nouvelleCouleur;45 }4647 public function set longueur(nouvelleLongueur:int):void48 {49 _longueur = (nouvelleLongueur > 0) ?

nouvelleLongueur : -1;50 }5152 public function set immatriculation(

nouvelleImmatriculation:String):void53 {54 _immatriculation = nouvelleImmatriculation;55 }5657 }5859 }

Nous voulons à présent que nos objets contiennent de l’essence. Pour cela, nous serionstenté de procéder ainsi :

1 package2 {3 public class Voiture4 {5 /* ************** Attributs ************** */6 private var _marque:String;7 private var _couleur:String;8 private var _longueur:int;9 private var _immatriculation:String;

1011 private var _typeEssence:String;

151

Page 175: Programmez en Actionscript 3

CHAPITRE 10. LES CLASSES (2NDE PARTIE)

12 private var _prixEssence:Number;13 private var _quantiteEssence:Number;1415 /* ************ Constructeur ************ */16 public function Voiture(marque:String)17 {18 _marque = marque;19 _couleur = "Sans couleur";20 _longueur = -1;21 _immatriculation = "Non immatriculée";22 _typeEssence = "Sans Plomb";23 _prixEssence = 1.4; // Euros par litre24 _quantiteEssence = 10; // Litres25 }2627 /* ************** Accesseurs ************** */28 public function get marque ():String29 {30 return _marque;31 }3233 public function get couleur ():String34 {35 return _couleur;36 }3738 public function get longueur ():int39 {40 return _longueur;41 }4243 public function get immatriculation ():String44 {45 return _immatriculation;46 }4748 public function get typeEssence ():String49 {50 return _typeEssence;51 }5253 public function get prixEssence ():Number54 {55 return _prixEssence;56 }5758 public function get quantiteEssence ():Number59 {60 return _quantiteEssence;61 }

152

Page 176: Programmez en Actionscript 3

UN OBJET DANS UN OBJET (DANS UN OBJET. . .)

6263 /* ************** Mutateurs ************** */64 public function set couleur(nouvelleCouleur:String):

void65 {66 _couleur = nouvelleCouleur;67 }6869 public function set longueur(nouvelleLongueur:int):void70 {71 _longueur = (nouvelleLongueur > 0) ?

nouvelleLongueur : -1;72 }7374 public function set immatriculation(

nouvelleImmatriculation:String):void75 {76 _immatriculation = nouvelleImmatriculation;77 }7879 public function set typeEssence(nouveauType:String):

void80 {81 _typeEssence = nouveauType;82 }8384 public function set prixEssence(nouveauPrix:Number):

void85 {86 _prixEssence = nouveauPrix;87 }8889 public function set quantiteEssence(nouvelleQuantite:

Number):void90 {91 _quantiteEssence = nouvelleQuantite;92 }9394 }9596 }

Notre classe commence à devenir compliquée, il vaudrait mieux créer une nouvelleclasse pour partager les propriétés.

Une nouvelle classe

Créons une classe Essence à mettre dans le fichier Essence.as :

1 package

153

Page 177: Programmez en Actionscript 3

CHAPITRE 10. LES CLASSES (2NDE PARTIE)

2 {3 public class Essence4 {5 /* ************** Attributs ************** */6 private var _type:String;7 private var _prix:Number;8 private var _quantite:Number;9

10 /* ************ Constructeur ************ */11 public function Essence ()12 {13 _type = "Sans Plomb";14 _prix = 1.4; // Euros par litre15 _quantite = 10; // Litres16 }1718 /* ************** Accesseurs ************** */19 public function get type():String20 {21 return _type;22 }2324 public function get prix():Number25 {26 return _prix;27 }2829 public function get quantite ():Number30 {31 return _quantite;32 }3334 /* ************** Mutateurs ************** */35 public function set type(nouveauType:String):void36 {37 _type = nouveauType;38 }3940 public function set prix(nouveauPrix:Number):void41 {42 _prix = nouveauPrix;43 }4445 public function set quantite(nouvelleQuantite:Number):

void46 {47 _quantite = nouvelleQuantite;48 }4950 }

154

Page 178: Programmez en Actionscript 3

UN OBJET DANS UN OBJET (DANS UN OBJET. . .)

5152 }

Vous pouvez l’afficher pour la copier en utilisant le code web ci-dessous.

B

�Classe Essence

Code web : 750046Nous transférons donc toutes les propriétés relatives à l’essence de la voiture dans lanouvelle classe. Il va falloir maintenant adapter la classe Voiture :

1 package2 {3 public class Voiture4 {5 /* ************** Attributs ************** */6 private var _marque:String;7 private var _couleur:String;8 private var _longueur:int;9 private var _immatriculation:String;

1011 private var _carburant:Essence; // Nouvel attribut

pointant sur un objet de classe Essence !1213 /* ************ Constructeur ************ */14 public function Voiture(marque:String)15 {16 _marque = marque;17 _couleur = "Sans couleur";18 _longueur = -1;19 _immatriculation = "Non immatriculée";20 _carburant = new Essence (); // Nous créons un objet

Essence par défaut dans le constructeur21 }2223 /* ************** Accesseurs ************** */24 public function get marque ():String25 {26 return _marque;27 }2829 public function get couleur ():String30 {31 return _couleur;32 }3334 public function get longueur ():int35 {36 return _longueur;37 }3839 public function get immatriculation ():String

155

Page 179: Programmez en Actionscript 3

CHAPITRE 10. LES CLASSES (2NDE PARTIE)

40 {41 return _immatriculation;42 }4344 public function get carburant ():Essence // Nouvel

accesseur , renvoyant un objet de classe Essence45 {46 return _carburant;47 }4849 /* ************** Mutateurs ************** */50 public function set couleur(nouvelleCouleur:String):

void51 {52 _couleur = nouvelleCouleur;53 }5455 public function set longueur(nouvelleLongueur:int):void56 {57 _longueur = (nouvelleLongueur > 0) ?

nouvelleLongueur : -1;58 }5960 public function set immatriculation(

nouvelleImmatriculation:String):void61 {62 _immatriculation = nouvelleImmatriculation;63 }6465 public function set carburant(nouveauCarburant:Essence)

:void // Nouveau mutateur , affectant un objet declasse Essence

66 {67 _carburant = nouveauCarburant;68 }69 }7071 }

Comme vous pouvez le constater, nous pouvons écrire des attributs pointant sur desobjets. Nous pourrions même mettre un attribut de type Voiture !

1 private var ancienneVoiture:Voiture; // L'ancienne voiture dupropriétaire

Pour modifier le carburant de notre voiture, il faut procéder ainsi :

1 var maVoiture = new Voiture("Peugeot");2 maVoiture.carburant.type = "Diesel";3 trace("Type de carburant : " + maVoiture.carburant.type); //

Affiche : Type de carburant : Diesel

156

Page 180: Programmez en Actionscript 3

EXERCICE : JEU DE RÔLE

Vous remarquerez que nous procédons de la même façon que pour toutes les propriétés,en utilisant le caractère point « . », comme nous l’avons vu dans le premier chapitrecette partie. Il suffit donc de mettre un point à chaque fois que nous voulons accéder àla propriété d’un objet :

– Une première fois lorsque nous voulons accéder à la propriété carburant de notreobjet maVoiture.

– Une seconde fois lorsque nous voulons modifier le type du carburant de la voiture.

Pour résumer la situation, je vous propose un petit schéma UML des classes Voitureet Essence que nous venons de créer (voir figure 10.1).

Figure 10.1 – Les classes Voiture et Essence

En réalité, nous combinons depuis le début la classe Voiture et la classeString : beaucoup de nos attributs sont du type String. Rappelez-vous :les chaînes de caractères sont aussi des objets !

Exercice : Jeu de rôle

Présentation de l’exercice

Le combat final contre le grand Méchant approche ! Votre personnage, son épée légen-daire au poing, se dresse devant cet immense monstre armé jusqu’aux dents !

Le moment est venu de passer à la pratique ! Je propose la réalisation d’un petit pro-gramme ressemblant à un jeu de rôle afin de bien revoir les notions essentielles duchapitre.

L’objectif de cet exercice est de créer la (ou les) classe(s) nécessaires au bon fonction-nement du programme principal (que nous adapterons si besoin). Voici le déroulementde ce programme :

– Nous créons un objet représentant votre personnage, puis nous l’armons.

157

Page 181: Programmez en Actionscript 3

CHAPITRE 10. LES CLASSES (2NDE PARTIE)

– Nous créons de façon similaire l’objet représentant le Méchant.– Le Méchant attaque une fois votre personnage.– Votre personnage riposte et attaque une fois le Méchant.

Pour apporter un peu de piment à ce programme, les personnages peuvent succomberaux attaques, et leur arme peut infliger un coup critique (elle a des chances d’infligerle double de dégâts à l’adversaire).

Nous allons passer par trois étapes successives, que j’ai nommées solutions, pour voircomment programmer correctement en Orienté Objet pas à pas : à chaque étape, nousaméliorerons notre code.

Il ne s’agit pas d’un TP : nous allons programmer ensemble et progressive-ment.

Solution initiale

Création de la classe

Commençons par créer notre première classe : j’ai choisi de l’appeler Personnage.En effet, ce sera la classe des objets représentant nos deux personnages (vous et leMéchant). Dans un nouveau fichier, appelé Personnage.as, écrivons la structure debase de notre classe : le package, la classe et le constructeur :

1 package2 {34 public class Personnage5 {67 // Constructeur8 public function Personnage ()9 {

1011 }12 }13 }

Les attributs

Ensuite, ajoutons les attributs de la classe. Pour cela, réfléchissons aux données utilespour notre combat. Comme dans tous les jeux avec des combats (ou presque), donnonsun niveau de santé à nos personnages, que nous initialiserons à 100. Et pour les armer,indiquons la puissance de l’attaque qu’ils vont porter à leur adversaire ainsi que leschances de coup critique :

1 // Santé du personnage

158

Page 182: Programmez en Actionscript 3

EXERCICE : JEU DE RÔLE

2 private var _sante:int;34 // Dégâts de base5 private var _degats:int;67 // Chances de faire une critique (sur 100)8 private var _chanceCritique:int;

Les accesseurs

N’oublions pas d’accompagner les attributs de leurs accesseurs :

1 public function get sante():int2 {3 return _sante;4 }56 public function set sante(value:int):void7 {8 _sante = value;9 }

1011 public function get degats ():int12 {13 return _degats;14 }1516 public function set degats(value:int):void17 {18 _degats = value;19 }2021 public function get chanceCritique ():int22 {23 return _chanceCritique;24 }2526 public function set chanceCritique(value:int):void27 {28 _chanceCritique = value;29 }

Le contructeur

Ensuite, initialisons nos attributs au sein du constructeur :

1 // Constructeur2 public function Personnage ()3 {

159

Page 183: Programmez en Actionscript 3

CHAPITRE 10. LES CLASSES (2NDE PARTIE)

4 sante = 100;5 degats = 0;6 chanceCritique = 0;7 }

La méthode

Enfin, ajoutons une méthode, afin que nos personnages puissent attaquer un autrepersonnage :1 public function attaquer(cible:Personnage):void2 {3 var degatsAppliques:int = degats;45 // On jette un dé à 100 faces : si le résultat est infé

rieur ou égal à la chance de coup critique , l'attaque fait un coup critique !

6 if (Math.random () * 100 <= chanceCritique)7 {8 trace("Critique !");9 // On double les dégâts !

10 degatsAppliques *= 2;11 }1213 // On applique les dégâts14 cible.sante -= degatsAppliques;1516 if (cible.sante <= 0)17 {18 trace("La cible est décédée.");19 }20 else21 {22 trace("Il reste " + cible.sante + " PV à la

cible.");23 }24 }

Comme vous pouvez le constater, nous passons en paramètre un objet de la classePersonnage, afin de rendre le code logique et surtout très lisible. Ainsi, pour qu’unpersonnage attaque un second, il faudra procéder ainsi :1 personnageA.attaquer(personnageB); // Le personnageA attaque le

personnageB ! S'en est fini de lui !

La classe complète

Si tout se passe bien, vous devriez normalement avoir une classe Personnage qui cor-respond à la description de la figure 10.2.

160

Page 184: Programmez en Actionscript 3

EXERCICE : JEU DE RÔLE

Figure 10.2 – La classe Personnage

Voici le code complet de notre classe Personnage, pour vérifier le vôtre :

1 package2 {34 public class Personnage5 {67 // Santé du personnage8 private var _sante:int;9

10 // Dégâts de base11 private var _degats:int;1213 // Chances de faire une critique (sur 100)14 private var _chanceCritique:int;1516 public function Personnage ()17 {18 sante = 100;19 degats = 0;20 chanceCritique = 0;21 }2223 public function get sante():int24 {25 return _sante;26 }2728 public function set sante(value:int):void29 {30 _sante = value;31 }3233 public function get degats ():int34 {35 return _degats;

161

Page 185: Programmez en Actionscript 3

CHAPITRE 10. LES CLASSES (2NDE PARTIE)

36 }3738 public function set degats(value:int):void39 {40 _degats = value;41 }4243 public function get chanceCritique ():int44 {45 return _chanceCritique;46 }4748 public function set chanceCritique(value:int):void49 {50 _chanceCritique = value;51 }5253 public function attaquer(cible:Personnage):void54 {55 var degatsAppliques:int = degats;5657 // On jette un dé à 100 faces : si le résultat est

inférieur ou égal à la chance de coup critique ,l'attaque fait un coup critique !

58 if (Math.random () * 100 <= chanceCritique)59 {60 trace("Critique !");61 // On double les dégâts !62 degatsAppliques *= 2;63 }6465 // On applique les dégâts66 cible.sante -= degatsAppliques;6768 if (cible.sante <= 0)69 {70 trace("La cible est décédée.");71 }72 else73 {74 trace("Il reste " + cible.sante + " PV à la

cible.");75 }76 }77 }78 }

162

Page 186: Programmez en Actionscript 3

EXERCICE : JEU DE RÔLE

Le programme principal

Votre classe Main vide (contenue dans le fichier Main.as) devrait ressembler à cela :

1 package {2 import flash.display.Sprite;3 import flash.events.Event;45 public class Main extends Sprite {67 public function Main():void {8 if (stage)9 init();

10 else11 addEventListener(Event.

ADDED_TO_STAGE , init);12 }1314 private function init(e:Event = null):void {15 removeEventListener(Event.

ADDED_TO_STAGE , init);16 // entry point1718 }19 }20 }

Rappel : il faut commencer à programmer après le commentaire // entrypoint («point d’entrée ») à la ligne 17.

Commençons par déclarer la variable qui pointera vers le premier objet de classePersonnage (celui qui vous représente) :

1 var moi:Personnage = new Personnage ();

Ensuite, donnons-lui son épée légendaire (elle fait 80 dégâts de base et a 80 chancessur 100 de faire un coup critique) :

1 moi.degats = 80;2 moi.chanceCritique = 80;

Le code pour créer le Méchant est très similaire :

1 var mechant:Personnage = new Personnage ();2 mechant.degats = 40;3 mechant.chanceCritique = 10;

Enfin, simulons le combat épique qui a lieu entre nos deux personnages ! Si vous voussouvenez de ma remarque sur la méthode attaquer() un peu plus haut, vous savezcomment procéder :

163

Page 187: Programmez en Actionscript 3

CHAPITRE 10. LES CLASSES (2NDE PARTIE)

1 trace("Le méchant m'attaque ! ");2 mechant.attaquer(moi);34 trace("Il va connaître ma fureur ! A l'attaque !");5 moi.attaquer(mechant);

Voici le code complet de notre classe Main :

1 package2 {3 import flash.display.Sprite;4 import flash.events.Event;56 public class Main extends Sprite7 {89 public function Main():void

10 {11 if (stage)12 init();13 else14 addEventListener(Event.

ADDED_TO_STAGE , init);15 }1617 private function init(e:Event = null):void18 {19 removeEventListener(Event.

ADDED_TO_STAGE , init);20 // entry point2122 // Création du personnage vous repré

sentant23 var moi:Personnage = new Personnage ();24 moi.degats = 80;25 moi.chanceCritique = 80;2627 // Création du personnage Méchant28 var mechant:Personnage = new Personnage

();29 mechant.degats = 40;30 mechant.chanceCritique = 10;3132 // Simulation du combat33 trace("Le méchant m'attaque ! ");34 mechant.attaquer(moi);35 trace("Il va connaître ma fureur ! A l'

attaque !");36 moi.attaquer(mechant);37 }38 }

164

Page 188: Programmez en Actionscript 3

EXERCICE : JEU DE RÔLE

39 }

Résultat

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 améliorée. . . Vous ne voyez pas en quoi ? Et bien, pensez au chapitre précédent :«Un objet dans un objet (dans un objet. . .) ». Maintenant, réfléchissez à cette pro-blématique : comment pourrait-on mieux séparer les données et les propriétés de maclasse Personnage ? En créant de nouvelles classes, pardi !

Une nouvelle classe

En effet, il serait judicieux de représenter les armes que portent nos personnages pardes objets à part entière : cela semble logique, et cela respecte les principes de la POO.En outre, cela nous faciliterait énormément la tâche si nous devions gérer un inventairepar exemple : nous pourrions mettre autant d’objets que l’on veut, et équiper nospersonnages avec, tout ceci de façon très souple et naturelle !

La classe Arme

L’idée est donc de transférer toutes les propriétés relatives aux armes dans une nouvelleclasse Arme, comme à la figure 10.3.

Figure 10.3 – Transfert des propriétés dans la classe Arme

Il nous faudra donc créer une nouvelle classe (ici dans le fichier Arme.as) :

165

Page 189: Programmez en Actionscript 3

CHAPITRE 10. LES CLASSES (2NDE PARTIE)

1 package2 {34 public class Arme5 {67 // Dégâts de l'arme8 private var _degats:int;9

10 // Chances de faire un coup critique (sur 100)11 private var _chanceCritique:int;1213 public function Arme()14 {15 degats = 0;16 chanceCritique = 0;17 }1819 public function get chanceCritique ():int20 {21 return _chanceCritique;22 }2324 public function set chanceCritique(value:int):void25 {26 _chanceCritique = value;27 }2829 public function get degats ():int30 {31 return _degats;32 }3334 public function set degats(value:int):void35 {36 _degats = value;37 }38 }39 }

La classe Personnage

N’oublions pas d’adapter la classe Personnage, comme nous l’avons fait dans le chapitreprécédent :

1 package2 {34 public class Personnage

166

Page 190: Programmez en Actionscript 3

EXERCICE : JEU DE RÔLE

5 {67 // Santé du personnage8 private var _sante:int;9

10 // Arme équipée11 private var _armeEquipee:Arme; // Nouvel attribut

pointant sur l'arme équipée1213 public function Personnage ()14 {15 sante = 100;16 }1718 public function get sante():int19 {20 return _sante;21 }2223 public function set sante(value:int):void24 {25 _sante = value;26 }2728 public function get armeEquipee ():Arme // Nouvel

accesseur29 {30 return _armeEquipee;31 }3233 public function set armeEquipee(value:Arme):void //

Nouveau mutateur34 {35 _armeEquipee = value;36 }3738 public function attaquer(cible:Personnage):void39 {40 // Au cas où aucun arme n'est équipée (l'objet

armeEquipee est null)41 if (armeEquipee == null)42 {43 trace("Aucune arme équipée : l'attaque échoue."

);44 }45 else46 {47 var degatsAppliques:int = armeEquipee.degats;

// Désormais , on utilise les propriétés de l'objet armeEquipee

167

Page 191: Programmez en Actionscript 3

CHAPITRE 10. LES CLASSES (2NDE PARTIE)

4849 if (Math.random () * 100 <= armeEquipee.

chanceCritique) // Ici aussi , on utilise lespropriétés de l'objet armeEquipee

50 {51 trace("Critique !");52 // On double les dégâts !53 degatsAppliques *= 2;54 }5556 // On applique les dégâts57 cible.sante -= degatsAppliques;5859 if (cible.sante <= 0)60 {61 trace("La cible est décédée.");62 }63 else64 {65 trace("Il reste " + cible.sante + " PV à la

cible.");66 }67 }68 }69 }70 }

Le programme principal

Là aussi, il va falloir adapter un peu : au lieu d’affecter directement les dégâts et leschances de coup critique aux personnages, nous créons dans un premier temps les armesvia des objets de classe Arme, pour ensuite les équiper aux personnages :

1 var epeeLegendaire:Arme = new Arme();2 epeeLegendaire.degats = 80;3 epeeLegendaire.chanceCritique = 50;45 var hacheDeGuerre:Arme = new Arme();6 hacheDeGuerre.degats = 40;7 hacheDeGuerre.chanceCritique = 10;89 var moi:Personnage = new Personnage ();

10 moi.armeEquipee = epeeLegendaire;1112 var mechant:Personnage = new Personnage ();13 mechant.armeEquipee = hacheDeGuerre;1415 trace("Le méchant m'attaque ! ");16 mechant.attaquer(moi);

168

Page 192: Programmez en Actionscript 3

EXERCICE : JEU DE RÔLE

17 trace("Il va connaître ma fureur ! A l'attaque !");18 moi.attaquer(mechant);

Vous avouerez que ce code est quand même plus clair que le précédent !

Résultat

Et voici le résultat à la console lorsque l’on teste le projet :

Le méchant m’attaque !Il reste 60 PV à la cible.Il va connaître ma fureur ! A l’attaque !Critique !La cible est décédée.

Rien n’a vraiment changé (à part ma chance qui s’est envolée !) : ce n’esttoutefois pas pour rien que nous avons modifié notre code. En effet, il estprimordial de programmer correctement pour que vos projets soient lisibles,facilement modifiables et maintenables.

Malheureusement, notre code pose encore problème : il ne respecte pas bien le principed’encapsulation. Si vous regardez bien la méthode attaquer(), nous utilisons despropriétés de la classe Arme et reproduisons son comportement (à savoir : les coupscritiques) dans la classe Personnage : en toute logique, si une arme devrait faire uncoup critique, nous devrions le déterminer dans la bonne classe, autrement dit la classeArme !

La bonne solution

La bonne façon de procéder consiste donc à appliquer les dégâts qui vont être fait dansla classe Arme. Pour cela, créons dans cette classe une nouvelle méthode frapper() :

1 public function frapper(cible:Personnage):void2 {3 var degatsAppliques:int = degats;45 // On jette un dé à 100 faces : si le résultat est infé

rieur ou égal à la chance de coup critique , l'attaque fait un coup critique !

6 if (Math.random () * 100 <= chanceCritique)7 {8 trace("Critique !");9 // On double les dégâts !

10 degatsAppliques *= 2;11 }1213 // On applique les dégâts

169

Page 193: Programmez en Actionscript 3

CHAPITRE 10. LES CLASSES (2NDE PARTIE)

14 cible.sante -= degatsAppliques;15 }

Il va donc falloir appeler cette nouvelle méthode dans la méthode attaquer() de laclasse Personnage :

1 public function attaquer(cible:Personnage):void2 {3 if (armeEquipee == null)4 {5 trace("Aucune arme équipée : l'attaque échoue."

);6 }7 else8 {9 armeEquipee.frapper(cible); // Nous appelons la

nouvelle méthode ici1011 if (cible.sante <= 0)12 {13 trace("La cible est décédée.");14 }15 else16 {17 trace("Il reste " + cible.sante + " PV

à la cible.");18 }19 }20 }

Les classes

L’un des intérêts de l’utilisation de la représentation UML est justement de fa-ciliter cette étape de conception et d’organisation des différentes classes d’un mêmeprogramme. Cela permet de visualiser la structure d’un projet en ne faisant ressortirque les informations utiles et ainsi, programmer plus rapidement et de manière pluspropre.

Finalement, vos classes devraient ressembler à la figure 10.4.

Voici le code complet de nos classes :

1 package2 {34 public class Personnage5 {67 // Santé du personnage8 private var _sante:int;9

170

Page 194: Programmez en Actionscript 3

EXERCICE : JEU DE RÔLE

Figure 10.4 – Les classes Personnage et Arme

10 // Amre équipée11 private var _armeEquipee:Arme;1213 public function Personnage ()14 {15 sante = 100;16 }1718 public function get sante():int19 {20 return _sante;21 }2223 public function set sante(value:int):void24 {25 _sante = value;26 }2728 public function get armeEquipee ():Arme29 {30 return _armeEquipee;31 }3233 public function set armeEquipee(value:Arme):void34 {35 _armeEquipee = value;36 }3738 public function attaquer(cible:Personnage):void39 {40 if (armeEquipee == null)41 {42 trace("Aucune arme équipée : l'attaque échoue."

);43 }44 else

171

Page 195: Programmez en Actionscript 3

CHAPITRE 10. LES CLASSES (2NDE PARTIE)

45 {46 armeEquipee.frapper(cible);4748 if (cible.sante <= 0)49 {50 trace("La cible est décédée.");51 }52 else53 {54 trace("Il reste " + cible.sante + " PV à la

cible.");55 }56 }57 }58 }59 }

1 package2 {34 public class Arme5 {67 // Dégâts de l'arme8 private var _degats:int;9

10 // Chances de faire un coup critique (sur 100)11 private var _chanceCritique:int;1213 public function Arme()14 {15 degats = 0;16 chanceCritique = 0;17 }1819 public function get chanceCritique ():int20 {21 return _chanceCritique;22 }2324 public function set chanceCritique(value:int):void25 {26 _chanceCritique = value;27 }2829 public function get degats ():int30 {31 return _degats;32 }33

172

Page 196: Programmez en Actionscript 3

EXERCICE : JEU DE RÔLE

34 public function set degats(value:int):void35 {36 _degats = value;37 }3839 public function frapper(cible:Personnage):void40 {41 var degatsAppliques:int = degats;4243 // On jette un dé à 100 faces : si le résultat est

inférieur ou égal à la chance de coup critique ,l'attaque fait un coup critique !

44 if (Math.random () * 100 <= chanceCritique)45 {46 trace("Critique !");47 // On double les dégâts !48 degatsAppliques *= 2;49 }5051 // On applique les dégâts52 cible.sante -= degatsAppliques;53 }54 }55 }

Le programme

Le programme principal ne change pas par rapport à la solution précédente :

1 var epeeLegendaire:Arme = new Arme();2 epeeLegendaire.degats = 80;3 epeeLegendaire.chanceCritique = 50;45 var hacheDeGuerre:Arme = new Arme();6 hacheDeGuerre.degats = 40;7 hacheDeGuerre.chanceCritique = 10;89 var moi:Personnage = new Personnage ();

10 moi.armeEquipee = epeeLegendaire;1112 var mechant:Personnage = new Personnage ();13 mechant.armeEquipee = hacheDeGuerre;1415 trace("Le méchant m'attaque ! ");16 mechant.attaquer(moi);17 trace("Il va connaître ma fureur ! A l'attaque !");18 moi.attaquer(mechant);

173

Page 197: Programmez en Actionscript 3

CHAPITRE 10. LES CLASSES (2NDE PARTIE)

Résultat

Enfin, voici le résultat de l’exécution de notre programme :

Le méchant m’attaque !Il reste 60 PV à la cible.Il va connaître ma fureur ! A l’attaque !Il reste 20 PV à la cible.

En résumé– Il est possible d’utiliser des éléments dits statiques qui sont directement liés à laclasse et non à ses instances.

– Ces éléments statiques sont déclarés à l’aide du mot-clé static et facilitentl’ajout de fonctionnalités au programme.

– Il est impossible d’utiliser le mot-clé this dans les méthodes statiques.– Nous pouvons créer des constantes qui sont similaires aux variables, mais qui nepeuvent pas être modifiées.

– Pour déclarer une constante, nous devons utiliser le mot-clé const.– Il est possible de combiner les classes entre elles : les objets peuvent alors contenird’autres objets.

174

Page 198: Programmez en Actionscript 3

Chapitre 11L’héritage

Difficulté :

Dans ce chapitre, nous allons parler d’héritage ! Sachez qu’il s’agit de l’une des notions lesplus importantes de la Programmation Orientée Objet et qui en font tout son intérêt !Nous détaillerons ce concept tout au long du chapitre, mais pour vous situer rapidementce dont il s’agit, cela permet de créer une ou des nouvelles classes en se basant sur uneautre. Ainsi, nous pouvons écrire des classes qui sont similaires en utilisant une autre classequi regroupe l’ensemble des propriétés communes. Dans ce chapitre, la seule difficulté quevous aurez à affronter sera la notion d’héritage en elle-même. Au niveau du code, il n’yaura pas énormément de nouveautés, ce qui vous simplifiera la vie !

175

Page 199: Programmez en Actionscript 3

CHAPITRE 11. L’HÉRITAGE

La notion d’héritage

Nous avons déjà brièvement présenté le concept dans les parties précédentes, cependant,vu son importance, il n’est pas superflu d’y revenir ! L’héritage permet de créer une oudes nouvelles classes en réutilisant le code d’une classe déjà existante. On parle alorsde classe de base ou superclasse ou encore classe-mère pour cette dernière, etde sous-classes ou classes-filles pour les classes héritées de celle-ci. L’idée est doncici d’étendre une classe de base, notamment en lui ajoutant de nouvelles propriétés.D’ailleurs, le mot-clé qui permet d’étendre une classe est extends :

1 public class Hello extends Sprite {23 }

Nous reviendrons sur la syntaxe Actionscript plus tard. Pour l’instant, nous allonsprincipalement nous focaliser sur la notion d’héritage.

Quand est-ce utile d’utiliser l’héritage ?

C’est en effet une question à laquelle les débutants ont souvent du mal à répondre. Enréalité, nous pouvons introduire une relation d’héritage lorsque la condition suivanteest respectée : la sous-classe est un sous-ensemble de la superclasse.

Ce terme mathématique barbare signifie que la sous-classe appartient à l’ensemblede la superclasse. Si ce n’est pas encore bien clair, voici quelques exemples qui vousaideront à bien comprendre :

– L’Actionscript appartient à l’ensemble des langages de programmation.– Les fourmis appartiennent à l’ensemble des insectes.– Les avions appartiennent à l’ensemble des véhicules.– Les voitures appartiennent également à l’ensemble des véhicules.– Les 4L appartiennent à l’ensemble des voitures.

Comme vous pouvez le constater, les relations précédentes ne peuvent s’effectuer quedans un seul sens. Vous remarquerez également, d’après les deux derniers exemples,qu’il est possible d’avoir plusieurs niveaux d’héritage.

En quoi est-ce différent d’une instance de classe ?

Il est vrai qu’il serait possible, par exemple, de créer des instances Avion et Voitured’une classe Vehicule. Nous pourrions de cette manière définir des valeurs distinctespour chacun des attributs afin de les différencier. En utilisant le concept d’héritage,nous pourrions écrire deux sous-classes Avion et Voiture qui hériteraient de l’ensembledes attributs et méthodes de la superclasse, et ce sans réécrire le code à l’intérieur decelles-ci. Mais tout l’intérêt vient du fait que l’utilisation de l’héritage nous permet de

176

Page 200: Programmez en Actionscript 3

CONSTRUCTION D’UN HÉRITAGE

définir de nouveaux attributs et de nouvelles méthodes pour nos sous-classes. Sachezqu’il est également possible de redéfinir des méthodes de la superclasse, maisnous en reparlerons quand nous introduirons le polymorphisme plus loin dans cechapitre !

Construction d’un héritage

Dans la suite de ce chapitre, nous allons principalement nous intéresser aux manipula-tions du côté des classes-filles. Cependant, nous aurons besoin d’une superclasse àpartir de laquelle nous pourrons travailler. Ainsi, je vous propose une classe Vehicule,dont le code est donné ci-dessous :

1 package2 {3 public class Vehicule4 {5 protected var _marque:String;6 protected var _vitesse:int;78 public function Vehicule(marque:String , vitesse:int)9 {

10 _marque = marque;11 _vitesse = vitesse;12 }1314 public function get marque ():String15 {16 return _marque;17 }1819 public function get vitesse ():int20 {21 return _vitesse;22 }2324 public function set vitesse(vitesse:int):void25 {26 _vitesse = vitesse;27 }2829 }3031 }

177

Page 201: Programmez en Actionscript 3

CHAPITRE 11. L’HÉRITAGE

La portée protected

Nous avions rapidement mentionné cette portée sans en expliquer vraiment le fonction-nement. Maintenant vous savez comment fonctionne l’héritage, nous allons pouvoirutiliser cette nouvelle portée qu’est protected ! Cette portée a été introduite afin derendre les propriétés visibles non seulement depuis la classe où elles sont définies commeprivate, mais également depuis l’ensemble de ses sous-classes. Voyez les attributs dela classe Vehicule définie juste avant :

1 protected var _marque:String;2 protected var _vitesse:int;

Ces attributs seront donc visibles depuis les éventuelles sous-classes que nous pourronsdéfinir.

Lorsque nous avions introduit le concept d’encapsulation, nous avions ditqu’il fallait spécifier une portée de type private à tous vos attributs. Or,comme nous l’avons dit, les attributs de ce type ne sont accessibles que depuisla classe où ils ont été déclarés. C’est pourquoi, il est maintenant préférabled’opter pour la portée protected à chaque fois que l’une de vos classes estsusceptible devenir une superclasse. En pratique, on utilise quasiment toutle temps cette portée dans l’hypothèse d’un héritage futur.

À présent, vous connaissez l’ensemble des portées que propose l’Actionscript, dontvoici un petit récapitulatif :

– public : propriété visible n’importe où.– private : propriété visible uniquement à l’intérieur de la classe qui l’a définie.– protected : propriété visible depuis la classe où elle est définie ainsi que depuis

l’ensemble de ses sous-classes.– internal : propriété visible depuis l’ensemble du package où elle est définie.

Construction des sous-classes

L’héritage

Comme nous l’avons dit en début de chapitre, l’héritage se fait en « étendant » uneclasse à l’aide du mot-clé extends comme ceci :

1 package2 {3 public class Voiture extends Vehicule4 {56 }7 }

178

Page 202: Programmez en Actionscript 3

CONSTRUCTION D’UN HÉRITAGE

Attention à l’ordre dans lequel sont placés les différents éléments. Noussommes ici en train de déclarer une nouvelle classe nommée Voiture quihérite de la classe Vehicule.

Par cette simple extension, la classe Voiture hérite donc de l’ensemble des propriétés dela classe Vehicule. Il est toutefois nécessaire de lui rajouter au moins un constructeur,et, éventuellement, quelques propriétés supplémentaires pour lui donner de l’intérêt.Par exemple, nous pourrions introduire un attribut _traction pour définir si la voitureest une traction ou non, ou encore un attribut _immatriculation pour identifier celle-ci :

1 package2 {3 public class Voiture extends Vehicule4 {5 protected var _traction:Boolean;6 protected var _immatriculation:String;7 }8 }

Le constructeur

Comme toute classe, notre sous-classe Voiture doit posséder un constructeur. Ce-pendant, celle-ci hérite d’une classe-mère qui possède son propre constructeur quiest nécessaire à l’initialisation des attributs. Depuis une classe-fille, il est possibled’appeler le constructeur de sa superclasse par la fonction super() :

1 public function Voiture ()2 {3 super();4 // Instructions supplémentaires5 }

L’appel du constructeur super() de la superclasse doit obligatoirement êtrela première instruction du constructeur de votre sous-classe. Les nouvellesinstructions seront placées à la suite pour permettre l’initialisation de vosnouvelles variables.

Voici donc un exemple de constructeur pour notre classe Voiture :

1 public function Voiture(marque:String , vitesse:int ,immatriculation:String)

2 {3 super(marque , vitesse);4 _immatriculation = immatriculation;5 _traction = true;6 }

179

Page 203: Programmez en Actionscript 3

CHAPITRE 11. L’HÉRITAGE

Vous remarquerez que la fonction super() est le constructeur de la super-classe. Il est donc normal de retrouver les différents paramètres du construc-teur défini plus haut.

Les méthodes

En plus de pouvoir définir de nouveaux attributs, il est possible de rajouter autant deméthodes que nous souhaitons à l’intérieur d’une sous-classe. Étant donné nous utili-sons encore le concept d’encapsulation, nous commencerons par créer des accesseursà ce nouvel attribut. Je vous propose de découvrir quelques-uns d’entre eux :

1 public function set immatriculation(nouvelleImmatriculation:String):void

2 {3 _immatriculation = nouvelleImmatriculation;4 }56 public function get immatriculation ():String7 {8 return _immatriculation;9 }

Comme vous pouvez le voir, ces méthodes fonctionnent exactement de la même ma-nière que pour une classe quelconque. En revanche, ce qui peut être intéressant, c’estd’utiliser les méthodes définies à l’intérieur de la classe mère. Ainsi, si les méthodes devotre classe mère ont une portée public ou protected, celles-ci sont accessibles depuisles classes filles. Nous avons ainsi un mot-clé super qui nous permet de faire référenceà la superclasse et d’utiliser ses propriétés. Voici, par exemple, une méthode nomméeaccelerer() qui permet d’augmenter la vitesse du véhicule :

1 public function accelerer ():void2 {3 var nouvelleVitesse:int = super.vitesse + 15;4 super.vitesse = nouvelleVitesse;5 }

Vous noterez que nous aurions pu utiliser directement l’attribut _vitesse dela classe Vehicule pour définir la variable nouvelleVitesse. En revanche,nous sommes obligés d’utiliser l’accesseur vitesse() pour modifier la valeurde l’attribut. En effet, seules les propriétés définies par le mot-clé function,donc les méthodes, peuvent être redéfinies. Nous reviendrons là-dessus justeaprès, lorsque nous parlerons du polymorphisme.

Le mot-clé super fait référence à l’objet via la classe-mère, par oppositionau mot-clé this qui pointe sur l’objet en lui-même.

180

Page 204: Programmez en Actionscript 3

CONSTRUCTION D’UN HÉRITAGE

Néanmoins, le mot-clé super est facultatif dans la plupart des cas. Le code ci-dessousest tout à fait fonctionnel :

1 public function accelerer ():void2 {3 var nouvelleVitesse:int = vitesse + 15; // L'accesseur de

la classe -mère sera automatiquement sélectionné4 vitesse = nouvelleVitesse;5 }

Il peut même être simplifié (vu que vous avez compris le principe) :

1 public function accelerer ():void2 {3 vitesse += 15;4 }

Rappel : les accesseurs simulent le fonctionnement des attributs. Il est doncpossible d’utiliser ici tous les opérateurs mathématiques : vitesse est consi-déré comme un nombre.

Comme je n’ai pas tout réécrit, je vous propose tout de même un schéma UMLrésumant les propriétés des deux classes Vehicule et Voiture ainsi que le lien qui lesunit à la figure 11.1.

Figure 11.1 – Héritage entre les classes Vehicule et Voiture

181

Page 205: Programmez en Actionscript 3

CHAPITRE 11. L’HÉRITAGE

La substitution d’une sous-classe à une superclasse

Un autre avantage de l’utilisation de l’héritage est le fait de pouvoir substituerune sous-classe à une superclasse. C’est-à-dire qu’il est possible de manipuler uneclasse-fille comme s’il s’agissait d’une instance de la classe-mère.

Parce qu’un exemple vaut mille mots, prenons le code suivant :

1 var MesVehicules:Array = new Array();2 MesVehicules.push(new Vehicule("Airbus A380", 900));3 MesVehicules.push(new Vehicule("Bicyclette", 25));4 MesVehicules.push(new Voiture("Renault 4L", 100 , "911 SDZ 15"))

;5 for (var i:int = 0; i < MesVehicules.length; i++)6 {7 trace("Un véhicule de type " + MesVehicules[i]. marque + "

peut se déplacer à la vitesse de " + MesVehicules[i].vitesse + "km/h.");

8 }9 /* Affiche :

10 Un véhicule de type Airbus A380 peut se déplacer à la vitessede 900km/h.

11 Un véhicule de type Bicyclette peut se déplacer à la vitesse de25km/h.

12 Un véhicule de type Renault 4L peut se déplacer à la vitesse de100km/h.

13 */

Il n’y a rien de surprenant dans cet exemple, les accesseurs de la classe Vehicule sontbien accessibles depuis la classe Voiture. En revanche, ce qui deviendrait intéressant,ce serait de créer une méthode presenter() qui permet de présenter un objet de typeVehicule, comme ci-dessous :

1 var MesVehicules:Array = new Array();2 MesVehicules.push(new Vehicule("Airbus A380", 900));3 MesVehicules.push(new Vehicule("Bicyclette", 25));4 MesVehicules.push(new Voiture("Renault 4L", 100 , "911 SDZ 15"))

;5 function presenter(unVehicule:Vehicule):void6 {7 trace("Un véhicule de type " + unVehicule.marque + " peut

se déplacer à la vitesse de " + unVehicule.vitesse + "km/h.");

8 }9 for (var i:int = 0; i < MesVehicules.length; i++)

10 {11 presenter(MesVehicules[i]);12 }13 /* Affiche :14 Un véhicule de type Airbus A380 peut se déplacer à la vitesse

de 900km/h.

182

Page 206: Programmez en Actionscript 3

LE POLYMORPHISME

15 Un véhicule de type Bicyclette peut se déplacer à la vitesse de25km/h.

16 Un véhicule de type Renault 4L peut se déplacer à la vitesse de100km/h.

17 */

Comment se fait-il qu’il n’y ait pas d’erreur pour l’objet de type Voiture ?

Comme nous l’avons dit plus haut dans ce cours, nous pouvons substituer une sous-classe à une superclasse. En d’autres termes, il est possible d’utiliser une classe-fillecomme s’il s’agissait de la classe-mère. D’ailleurs, si vous vous rappelez bien nousavions dit qu’une sous-classe était un sous-ensemble de la superclasse, ce qui veutdire qu’une Voiture est un Vehicule. Il n’est donc pas surprenant de pouvoir utiliserun objet de type Voiture en tant que Vehicule.

Encore une fois, attention au sens de l’héritage ! Dans notre exemple, il n’estpas 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 nombarbare associé à un concept qui n’est pas si compliqué en réalité.

Précédemment, nous avons appris à étendre une superclasse en ajoutant de nouvellesméthodes à l’intérieur d’une sous-classe. Cependant, il est également possible de re-définir (réécrire) une méthode. Ainsi, nous avons la possibilité d’utiliser un nom deméthode commun pour une méthode qui se comportera différemment suivant le typede l’objet.

Pour vous montrer cela, nous allons insérer une nouvelle méthode qu’on nommerasePresenter() à l’intérieur de la classe Vehicule :1 public function sePresenter ():void2 {3 trace("Un véhicule de type " + marque + " peut se déplacer

à la vitesse de " + vitesse + "km/h.");4 }

Rappel : il est conseillé d’utiliser les accesseurs dans la classe elle-même (saufdans le constructeur).

Si nous ne faisons rien, la classe Voiture héritera de cette nouvelle méthode et nous

183

Page 207: Programmez en Actionscript 3

CHAPITRE 11. L’HÉRITAGE

pourrons l’utiliser sans problème. Cependant, nous aimerions personnaliser le message,notamment en rajoutant son numéro d’immatriculation qui permet également de l’iden-tifier. Nous devrons donc réécrire la méthode sePresenter() pour la classe Voiture.Heureusement, nous disposons d’un mot-clé override, qui permet justement de re-définir une méthode. Voici comment l’utiliser :

1 override public function sePresenter ():void2 {3 trace("Une voiture " + marque + " peut se déplacer à la

vitesse de " + vitesse + "km/h.");4 trace("Son immatriculation est : " + immatriculation);5 }

Ainsi, nous pouvons utiliser la méthode sePresenter() sans nous soucier du typed’objets que nous sommes en train de manipuler.

1 var MesVehicules:Array = new Array();2 MesVehicules.push(new Vehicule("Airbus A380", 900));3 MesVehicules.push(new Vehicule("Bicyclette", 25));4 MesVehicules.push(new Voiture("Renault 4L", 100 , "911 SDZ 75"))

;5 for (var i:int = 0; i < MesVehicules.length; i++)6 {7 MesVehicules[i]. sePresenter ();8 }9 /* Affiche :

10 Un véhicule de type Airbus A380 peut se déplacer à la vitessede 900km/h.

11 Un véhicule de type Bicyclette peut se déplacer à la vitesse de25km/h.

12 Une voiture Renault 4L peut se déplacer à la vitesse de 100km/h.

13 Son immatriculation est : 911 SDZ 7514 */

Pour résumer, le polymorphisme est une technique très puissante, surtoutlorsqu’elle est associée à la substitution d’une sous-classe à une superclasse.Nous pouvons ainsi définir des méthodes « par défaut » dans la classe-mère,puis de les redéfinir pour différentes classes-filles. Il est ensuite possible d’uti-liser ces différents objets de la même façon comme s’il s’agissait de la mêmeclasse. Vous verrez dans la suite que c’est un atout non négligeable !

Les attributs de classe

Lorsque nous avions parlé d’encapsulation, nous avions introduit les droits d’accèspour les différentes propriétés d’une classe. Or, pour ceux qui l’auraient également

184

Page 208: Programmez en Actionscript 3

LES ATTRIBUTS DE CLASSE

remarqué, nous avons depuis le départ toujours inséré le mot-clé public devant ladéfinition de chacune de nos classes.

Il existe aussi des droits d’accès pour les classes ?

En effet, tout comme les propriétés, les classes possèdent des droits d’accès quipermettent de définir comment nous pouvons accéder à la classe et même la modifier.En réalité, on parle d’attributs de classes et d’attributs de propriétés de classes,cependant, nous emploierons dans ce cours, le terme « droits d’accès » pour éviter laconfusion avec les variables internes aux classes appelées également attributs.

Les différents droits d’accès

En ce qui concerne la définition de classes, l’Actionscript propose quatre droitsd’accès différents. Sans plus attendre, je vous propose de les découvrir :

– public : les droits d’accès « publics » permettent comme pour les propriétés, derendre la classe visible et accessible partout dans le code. Il s’agit des droits d’accèsrecommandés dans la majorité des cas.

– internal : identiquement aux propriétés, les droits d’accès « internes » re-streignent l’accessibilité de la classe au package où elle est définie uniquement. Cesdroits d’accès ne sont pas très utilisés, mais il s’agit de la valeur par défaut lors d’unedéfinition de classe.

– final : ces droits d’accès sont directement liés à la notion d’héritage. Le terme« final » fait ici référence au fait que la classe ne peut plus être étendue par uneautre classe.

– dynamic : ce mot-clé permet de définir une classe dynamique, c’est-à-dire modifiabledepuis l’extérieur de celle-ci, à l’opposé des classes classiques dites scellées. Nousreviendrons sur ce concept un peu particulier dans le prochain chapitre.

Pour résumer tout ce qui concerne les droits d’accès et l’encapsulation, vousdevez vous rappeler qu’on doit principalement limiter l’accès aux attributs enutilisant préférentiellement le mot-clé protected. Pour les méthodes et lesclasses en général, vous privilégierez principalement un accès « publique »à l’aide du mot-clé public. Il existe néanmoins divers autres droits d’accèsqui ne sont utiles que dans de rares occasions.

Exemple d’utilisation

Vous l’aurez compris, ces droits d’accès s’utilisent également devant la déclarationde la classe en question. Voici par exemple la définition de la classe Vehicule quenous avons réalisée au début du chapitre :

185

Page 209: Programmez en Actionscript 3

CHAPITRE 11. L’HÉRITAGE

1 public class Vehicule2 {34 }

Nous allons essayer ici de comprendre un peu mieux l’utilité du mot-clé final, étroi-tement lié au concept d’héritage ! Ce mot-clé permet de définir la classe à laquelle ilest associé, comme étant la dernière classe qui finalise l’arborescence d’héritage. Celasignifie que cette classe peut très bien hériter d’une autre classe, mais en aucun casvous ne pourrez créer de classes-filles à celle-ci. Je vous propose donc une petite mani-pulation afin de vérifier la véracité de ces propos. Redéfinissez donc la classe Vehiculede type final :

1 package2 {3 final class Vehicule4 {5 protected var _marque:String;6 protected var _vitesse:int;78 public function Vehicule(marque:String , vitesse:int)9 {

10 _marque = marque;11 _vitesse = vitesse;12 }1314 public function get marque ():String15 {16 return _marque;17 }1819 public function get vitesse ():int20 {21 return _vitesse;22 }2324 public function set vitesse(vitesse:int):void25 {26 _vitesse = vitesse;27 }2829 }3031 }

Nous avons donc maintenant une classe Vehicule qu’il nous est interdit d’étendre.Voyons donc ce qui se passe lorsqu’on tente d’en créer une sous-classe :

1 package2 {3 public class Voiture extends Vehicule

186

Page 210: Programmez en Actionscript 3

LES ATTRIBUTS DE CLASSE

4 {56 }7 }

Si vous tentez donc de lancer votre programme, le compilateur refusera de compiler leprojet en vous précisant l’erreur suivante : « Base class is final. », qui signifie que laclasse dont on essaie d’hériter est de type final et que notre héritage est donc contraireà cette définition de classe.

Comme vous pouvez le constater, ce mot-clé final n’apporte aucune réellefonctionnalité, mais il s’agit plutôt d’une sécurité. Néanmoins, l’utilité de cetype de droits d’accès est assez restreinte et vous définirez majoritairementdes classes de type public.

En résumé– L’héritage permet de créer une ou des nouvelles classes en utilisant le code d’uneclasse déjà existante.

– Pour hériter d’une classe, il faut utiliser le mot-clé extends.– La portée protected est spécifique à l’héritage.– Le constructeur de la superclasse peut être appelé par la fonction super().– Dans le cas d’une relation par héritage, il est possible de substituer une sous-classeà une superclasse.

– Le polymorphisme permet de redéfinir une méthode de la superclasse par l’inter-médiaire du mot-clé override.

– Les différents droits d’accès liés à la définition d’une classe sont public, internal,final et dynamic.

187

Page 211: Programmez en Actionscript 3

CHAPITRE 11. L’HÉRITAGE

188

Page 212: Programmez en Actionscript 3

Chapitre 12Notions avancées de la POO

Difficulté :

Nous allons maintenant découvrir des notions disons plus. . . « avancées » de la POO.Avant de démarrer ce chapitre, laissez-moi vous préciser que les concepts abordés ici sontgénéralement réservés aux projets complexes ou d’envergure. Il est donc fort probable quevous n’utilisiez pas ces concepts dans vos premiers projets et même que vous n’en voyezpas encore l’utilité. C’est pourquoi, il n’est pas essentiel pour la suite du cours d’êtretotalement au clair avec ces notions. Lisez donc attentivement ce chapitre, mais n’hésitezpas à y revenir plus tard pour effectuer une lecture plus approfondie.

189

Page 213: Programmez en Actionscript 3

CHAPITRE 12. NOTIONS AVANCÉES DE LA POO

Les classes dynamiques

Définition de la classe de base

Nous allons ici revenir sur la notion de classes dynamiques présentée dans le cha-pitre précédent. Contrairement aux classes normales dites « scellées », le principe desclasses dynamiques est de pouvoir rajouter de nouvelles propriétés lors de l’exé-cution du programme. Bien évidemment, avant d’ajouter de nouvelles propriétés, ilest d’abord nécessaire de définir une classe de base, mais cette fois à l’aide du typedynamic.

Nous allons donc partir d’une classe Personnage très basique :

1 package2 {34 dynamic class Personnage5 {67 protected var _sante:int;89 public function Personnage ()

10 {11 sante = 100;12 }1314 public function get sante():int15 {16 return _sante;17 }1819 public function set sante(value:int):void20 {21 _sante = value;22 }23 }24 }

Nous en reparlerons un peu plus loin, mais notez toutefois qu’une classedynamique respecte le principe d’encapsulation. Nous avons ainsi nos at-tributs qui sont restreints à la classe ainsi qu’à d’éventuelles sous-classes.

Nous pouvons ainsi instancier autant de fois qu’on veut cette classe Personnage, commeci-dessous :

1 var guerrier:Personnage = new Personnage ();2 var magicien:Personnage = new Personnage ();

Nous allons maintenant voir comment étendre les fonctionnalités de notre classe durant

190

Page 214: Programmez en Actionscript 3

LES CLASSES DYNAMIQUES

l’exécution en ajoutant de nouvelles propriétés à celle-ci.

Définition de propriétés hors de la classe

En pratique

Maintenant que notre classe Personnage est définie de type dynamic, nous allons pou-voir créer une instance de celle-ci, puis lui ajouter de nouvelles propriétés. Commevous avez pu le deviner, la définition de nouvelles propriétés se fait à partir d’une oc-currence de la classe en question. Nous allons donc prendre l’exemple d’un magicien :

1 var magicien:Personnage = new Personnage ();

Ce type de personnage pourrait donc être doté de facultés magiques. Nous allons donclui rajouter un nouvel attribut _mana qui définit la réserve de magie du personnage :

1 magicien._mana = 50;

Nous avons ainsi créé ici un nouvel attribut nommé _mana. Cette nouvelle propriété seraalors effective à l’exécution du code et sera liée uniquement à l’occurrence magiciende la classe Personnage. C’est pourquoi, un nouvel objet guerrier de cette classe, nedisposerait pas de cet attribut.

L’utilisation de classes dynamiques ne se limite pas simplement à la définition de nou-veaux attributs, mais s’étend également la définition de nouvelles méthodes. Définis-sons par exemple une nouvelle méthode lancerSort() spécifique à l’instance magiciende la classe Personnage :

1 magicien.lancerSort = function (cible:Personnage):void2 {3 cible.sante -= 25;4 _mana -= 20;5 };

Nous pouvons ainsi appeler cette méthode comme n’importe quelle autre de la classede base :

1 magicien.lancerSort(guerrier);

Comme vous pouvez le constater, les expressions de fonction sont particu-lièrement utiles pour la définition de méthodes de classes dynamiques.

Remarques importantes

Vous aurez certainement remarqué l’absence de droits d’accès liés aux nouvellespropriétés. En effet, il n’est pas nécessaire de les spécifier, étant donné que ces propriétés

191

Page 215: Programmez en Actionscript 3

CHAPITRE 12. NOTIONS AVANCÉES DE LA POO

sont liées à l’instance de la classe et non à la classe elle-même. Ainsi, celles-ci ne sontaccessibles qu’à partir de l’occurrence où elles ont été définies.

Pour revenir sur la notion d’encapsulation, les portées private et protected li-mitent l’accès des propriétés auxquelles elles sont associées à la classe uniquement, ouéventuellement aux classes filles. Ainsi dans le cas des classes dynamiques, la défi-nition de nouvelles propriétés se fait à l’extérieur de la classe de base. C’est pourquoinous n’avons pas accès aux propriétés « privées » dans la définition de ces nouvellespropriétés lors de l’exécution du code.

Pourquoi passer par des classes dynamiques alors que l’héritage permetdéjà de faire tout cela ?

Il est vrai que dans la quasi totalité des cas, vous n’aurez pas besoin de passer parla définition de classes dynamiques. D’ailleurs, ces dernières ne permettent pas deséparer la définition d’une classe de son utilisation par la création d’instances. C’estla raison pour laquelle, il est toujours préférable de passer par la conception de classesnon dynamiques. Cependant, ces classes dynamiques peuvent trouver leur utilitélorsque des propriétés dépendent de certaines données dont on ne dispose pas à lacompilation. Quoi qu’il en soit, si vous ne savez pas quelle solution utiliser, préférezl’héritage aux classes dynamiques à chaque fois que cela est possible !

Les interfaces

Problème

Introduction

Pour introduire les interfaces, nous allons nous servir d’un exemple. Nous allons re-prendre l’idée de créer des personnages pour un jeu quelconque. Pour cela, nous allonsgarder notre classe de base nommée Personnage. Cependant, nous voulons dans notrejeu, non pas avoir de simples instances de la classe Personnage, mais plutôt des lu-tins, des elfes et des ogres qui héritent de cette classe de base. Ceux-ci possèdent alorsdes aptitudes différentes que l’on pourrait classer dans deux catégories : Magicien etGuerrier !

Voici donc une présentation des différentes races :

– Lutin : ces petits bonhommes aux pouvoirs sensationnels se servent exclusivementde la magie et possèdent donc uniquement les aptitudes de la catégorie Magicien.

– Elfes : ces êtres baignés dans la magie, ont également un certain talent dans laconception et l’utilisation d’armes ; ils sont donc à la fois Magicien et Guerrier.

– Ogres : ces brutes tout droit sorties des grottes n’ont aucun sens de la magie, etpossèdent donc seulement les aptitudes de la catégorie Guerrier.

Nous allons donc voir ici les problèmes auxquels nous allons nous heurter pour conce-

192

Page 216: Programmez en Actionscript 3

LES INTERFACES

voir le code de ces différentes classes, toutefois, nous verrons qu’il est possible de lescontourner.

Les limites de l’héritage

L’objectif ici est donc de concevoir trois classes pour notre jeu : Lutin, Elfe et Ogre.Pour réaliser cela, vous pourriez avoir l’idée d’utiliser de concept d’héritage. Nouspourrions donc organiser nos différentes classes suivant un double héritage. Ainsi, nousaurions donc une classe de base Personnage, dont hériteraient les deux classes sui-vantes : Magicien et Guerrier. Puis nos trois classes Lutin, Elfe et Ogre seraient desclasses filles à ces deux dernières. Ceci ne poserait aucun problème en ce qui concerneles classes Lutin et Ogre. Seulement voilà, la classe Elfe devrait alors hériter en mêmetemps des deux classes Magicien et Guerrier, or ceci est interdit.

En effet, si dans certains langages tels que le C++, les héritages multiplessont autorisés, cette pratique est interdite en Actionscript. Ainsi, une classene peut hériter que d’une unique superclasse !

Cependant, il existe un concept en Actionscript qui permet de contourner ce pro-blème : les interfaces !

Utilisation des interfaces

Le principe

Une interface n’est pas vraiment une classe, il s’agit plutôt d’une collection de dé-clarations de méthodes. Contrairement aux classes, vous ne trouverez ni attribut niconstructeur au sein d’une interface. De plus, le terme « déclaration » de la défini-tion précédente nous indique que nous nous contenterons de « décrire » les méthodes.Ainsi, nous définirons la manière dont doit être construite chacune des méthodes sansen préciser le fonctionnement interne. Voici comment procéder pour une déclarationd’une méthode :

1 function uneMethode(param:String):void;

De la même façon que pour une déclaration de variable, vous remarquerez qu’on« omet » le contenu de la méthode normalement placé entre accolades. Toutefois, nousretrouvons dans cette déclaration l’ensemble des informations utiles de la méthode, àsavoir : le nom de la fonction, les différents paramètres, le type de valeur renvoyé.

Une interface sera donc un ensemble de déclarations de méthodes, regroupéesautour d’une utilité commune. Nous pourrons ainsi créer de nouvelles classes qui uti-lisent ces interfaces et nous redéfinirons l’ensemble des méthodes. On appelle celal’implémentation !

193

Page 217: Programmez en Actionscript 3

CHAPITRE 12. NOTIONS AVANCÉES DE LA POO

Quel est l’intérêt des interfaces si il faut redéfinir l’ensemble des méthodes ?

Étant donné que le contenu desméthodes n’est pas défini à l’intérieur des interfaces, ilva bien évidemment falloir le faire dans les classes qui les implémentent. C’est pourquoi,il est fort probable que vous vous demandiez à quoi pourrait bien vous servir ce concept.Je vais donc essayer de vous l’expliquer en quelques mots.

Lorsque nous avions vu la notion d’encapsulation, je vous avais précisé le fait que nousdevions masquer le fonctionnement interne d’une classe à l’utilisateur de celle-ci. Ainsi,l’utilisation de la classe devenait plus aisée car nous n’avions plus qu’à manipuler desméthodes explicites qui se chargeaient du travail laborieux. Une interface va donc nousservir à décrire « l’interface » d’une pseudo-classe, c’est-à-dire, présenter celle-ci tellequ’elle est vue de l’extérieur. Nous obtiendrons donc une sorte de « mode d’emploi »qui explique comment cette pseudo-classe doit être manipulée.

Nous conviendrons que le concept d’interfaces n’a d’utilité que dans de grosprojets. Cela permet de définir les normes à respecter, et ainsi, de garantirla compatibilité des classes qui les implémenteront. Ces dernières pourrontalors être utilisées de la même manière malgré les différences de contenu àl’intérieur de chacune des méthodes. Cela vient donc compléter la notion depolymorphisme et l’idée de pouvoir utiliser des objets différents comme s’ils’agissait du même.

Ce morceau conséquent de théorie va maintenant laisser place à la pratique qui, je suisd’accord avec vous, permet en général de mieux cerner la chose.

Les bases de la conception

À présent, nous allons reprendre notre problème de personnages concernant des lutins,des elfes et des ogres ! Parce qu’un schéma est toujours plus explicite qu’un long dis-cours, je vous laisse découvrir à la figure 12.1 l’ensemble de ces classes et interfaces quenous allons réaliser.

En premier lieu, nous allons créer une classe Personnage en tant que superclasse pourla suite. Celle-ci n’a rien d’extraordinaire puisqu’elle est identique à ce que nous avonsréalisée précédemment. Je vous laisse néanmoins le temps de la reprendre avant depasser à la suite :

1 package2 {34 public class Personnage5 {67 protected var _sante:int;8

194

Page 218: Programmez en Actionscript 3

LES INTERFACES

Figure 12.1 – Les classes et les interfaces que nous allons réaliser

9 public function Personnage ()10 {11 sante = 100;12 }1314 public function get sante():int15 {16 return _sante;17 }1819 public function set sante(value:int):void20 {21 _sante = value;22 }23 }24 }

Les interfaces

Nous voilà enfin au cœur du problème, nous allons devoir créer les deux interfacesMagicien et Guerrier ! Étant donné qu’il s’agit d’un exemple, nous n’allons pas réa-liser des dizaines de déclarations de méthodes. Je vous propose ainsi de lier deux mé-thodes lancerSort et guerison à notre interface Magicien. Voici donc notre premièreinterface :

1 package2 {

195

Page 219: Programmez en Actionscript 3

CHAPITRE 12. NOTIONS AVANCÉES DE LA POO

3 public interface Magicien4 {5 function lancerSort(cible:Personnage):void;6 function guerison ():void;7 }8 }

Déclarons également deux méthodes pour notre seconde interface, nommées assenerCoupet seSoigner. En voici le résultat :

1 package2 {3 public interface Guerrier4 {5 function assenerCoup(cible:Personnage):void;6 function seSoigner ():void;7 }8 }

À présent, nous disposons des bases nécessaires à la création de nos classes « réelles »,c’est-à-dire celles que nous utiliserons dans la pratique. Nous pourrons ainsi combinerles notions d’héritage et d’implémentation pour réaliser celles-ci.

Notez que dans cet exemple nous utilisons simultanément les notionsd’héritage et d’implémentation. Toutefois, en pratique, il n’est pas d’obli-gatoire de procéder à un héritage pour utiliser les interfaces. Il est donctout à fait possible d’utiliser uniquement la notion d’implémentation.

L’implémentation

Tout comme nous avions le mot-clé extends pour l’héritage, nous utiliserons implementspour implémenter une interface dans une classe. Étant donné que le contenu dechacune des méthodes n’est pas défini dans les interfaces, nous allons devoir le faire ici.

Je vous propose donc de découvrir les trois classes « finales » qui implémenteront doncles interfaces définies juste avant. Commençons par la classe Lutin :

1 package2 {34 public class Lutin extends Personnage implements Magicien5 {67 public function Lutin ()8 {9 super();

10 }1112 public function lancerSort(cible:Personnage):void

196

Page 220: Programmez en Actionscript 3

LES INTERFACES

13 {14 cible.sante -= 10;15 trace("Sort : Boule de feu");16 }17 public function guerison ():void18 {19 this.sante += 10;20 trace("Sort : Guérison");21 }22 }23 }

La classe Elfe est sans doute la plus complexe, puisqu’elle implémente les deux inter-faces à la fois :

1 package2 {34 public class Elfe extends Personnage implements Magicien ,

Guerrier5 {67 public function Elfe()8 {9 super();

10 }1112 public function lancerSort(cible:Personnage):void13 {14 cible.sante -= 5;15 trace("Sort : Tornade");16 }1718 public function guerison ():void19 {20 this.sante += 5;21 trace("Sort : Guérison");22 }2324 public function assenerCoup(cible:Personnage):void25 {26 cible.sante -= 5;27 trace("Coup : Épée");28 }29 public function seSoigner ():void30 {31 this.sante += 5;32 trace("Soin : Herbe médicinale");33 }34 }35 }

197

Page 221: Programmez en Actionscript 3

CHAPITRE 12. NOTIONS AVANCÉES DE LA POO

Lorsque l’on réalise un héritage et une ou plusieurs implémentations enmême temps, l’héritage doit toujours être effectué en premier. C’est pour-quoi le mot-clé extends sera toujours placé avant implements dans ladéclaration de la classe. Vous remarquerez également que les différentesinterfaces implémentées ici sont séparées par une virgule.

Enfin, la classe Ogre ne devrait maintenant plus poser de problèmes :

1 package2 {34 public class Ogre extends Personnage implements Guerrier5 {67 public function Ogre()8 {9 super();

10 }1112 public function assenerCoup(cible:Personnage):void13 {14 cible.sante -= 10;15 trace("Coup : Hache de guerre");16 }17 public function seSoigner ():void18 {19 this.sante += 10;20 trace("Soin : Bandage");21 }22 }23 }

Sachant que les méthodes sont déclarées uniquement à l’intérieur des inter-faces, celles-ci doivent obligatoirement être redéfinies dans les classes qui lesimplémentent. Veillez donc à bien toutes les redéfinir sous peine de messagesd’erreurs lors de la compilation de votre projet.

Plus loin avec les interfaces

Nous avons vu le principe des interfaces, mais je vais ici vous présenter une utilisationqui en fait tout leur intérêt !

Imaginez maintenant que vous vouliez créer un jeu beaucoup plus complet, qui risqued’évoluer dans une version ultérieure. Vous voulez cette fois multiplier le nombredes races des personnages avec, par exemple, les classes Humain, Nain, Lutin, Elfe,Centaure, Minotaure, Ogre, Gnome et Troll. Cette fois, vous n’avez plus de simplesmagiciens ou de purs guerriers, mais chacune des races dispose de l’ensemble des facul-

198

Page 222: Programmez en Actionscript 3

LES INTERFACES

tés. Ainsi, chaque espèce est capable de lancer des sorts ou de se battre avec n’importequel type d’armes. En revanche, chacun possède une liste limitée de sorts au départ,mais peut la développer au fil du jeu. Tous ces sorts sont utilisés de la manière, seulsleurs effets et leurs dégâts sont différents de l’un à l’autre.

Une architecture judicieuse de vos classes serait alors de créer une interface Sort, quiserait implémentée par chacun de vos divers sorts. L’intérêt serait alors de pouvoir créerune liste de sort de type Vector.<Sort> comme attribut de votre classe Personnage.Chaque sort serait alors utilisé de la même façon quel que soit celui-ci.

Voici un schéma à la figure 12.2 qui résume la situation et qui devrait plus facilementvous séduire.

Figure 12.2 – Créez une interface « Sort »

Vous pouvez ainsi créer un nouvel Ogre nommé budoc. Héritant de la classe Personnage,votre personnage va pouvoir apprendre de nouveaux sorts au fil du jeu. Voici, parexemple, notre ami budoc qui apprend les sorts Guerison et Eclair :

1 var budoc:Ogre = new Ogre();2 budoc.ajouterSort(new Guerison ());3 budoc.ajouterSort(new Eclair ());

Je vous ai présenté le concept avec les interfaces, mais sachez que cettepratique peut également être utilisée avec la relation d’héritage, même sicela est moins courant. Au risque de me répéter encore une fois, une desgrandes forces de la POO est justement de pouvoir se servir d’objets différentsde la même manière grâce à ces techniques d’héritage, de polymorphismeet d’implémentation.

Nous sommes maintenant arrivés au bout de ces explications sur les interfaces. J’espèrevous avoir convaincus de leur utilité et j’ose croire que vous les utiliserez de la bonnefaçon.

199

Page 223: Programmez en Actionscript 3

CHAPITRE 12. NOTIONS AVANCÉES DE LA POO

Les classes abstraites

Le concept

Une classe abstraite est une classe que l’on ne peut pas instancier, c’est-à-dire que l’onne peut pas directement créer d’objet de cette classe avec le mot-clé new. Lorsque l’onchoisit de rendre une classe abstraite, on restreint ainsi ses possibilités d’utilisation.Par contre, les sous-classes de cette classe abstraite ne sont pas forcément abstraites,à moins de l’indiquer à chaque fois !

Pour comprendre pourquoi cela pourrait améliorer la cohérence de votre code, repre-nons l’exemple des véhicules sur l’autoroute (voir figure 12.3).

Figure 12.3 – Diagramme UML des classes Vehicule et Voiture

Il était alors possible de créer directement un véhicule :

1 var vehicule:Vehicule = new Vehicule('Renault ', 0);

Maintenant, si notre application ne s’occupe que de voitures, il serait inutile d’utiliserdirectement la classe Vehicule alors que nous disposons de sa sous-classe Voiture. Sinous laissions à d’autres programmeurs la possibilité de créer des véhicules au lieu devoitures, ils auraient une chance sur deux de se tromper et d’oublier d’utiliser la classeVoiture. Pour cela, il faut rendre la classe Vehicule abstraite (voir figure 12.4) !

Par opposition à une classe abstraite, une classe qui peut être instanciée estune classe concrète.

200

Page 224: Programmez en Actionscript 3

LES CLASSES ABSTRAITES

Figure 12.4 – Diagramme UML de la classe abstraite Vehicule et de sa sous-classe

Rappel : une sous-classe d’une classe abstraite n’est pas forcément abstraite ;il faut le spécifier à chaque fois. Dans notre exemple, on peut donc instancierla classe Voiture, mais pas la classe Vehicule.

Ainsi, nous sommes désormais obligés d’utiliser la classe Voiture pour créer un objetvoiture : notre code est cohérent !

1 var vehicule:Vehicule = new Vehicule('Renault ', 0); // Interdit!

23 var voiture:Voiture = new Voiture('Renault ', 0, 'BX6F57 '); //

Autorisé

Application à l’ActionScript 3

Malheureusement, ce principe de classes abstraites ne dispose pas de mécanismesofficiels au sein du langage, il faut donc le « programmer » soi-même. Cela ne signifiepas qu’il ne faut pas l’utiliser, et plusieurs classes fournies par Flash sont des classesabstraites ! Mais rassurez-vous, c’est en réalité très simple.

Le principe est le suivant : nous allons faire une vérification dans le constructeur de laclasse-mère abstraite, à l’aide d’un paramètre et du mot-clé this. En effet, seule unesous-classe de cette classe peut passer en paramètre du constructeur le mot-clé this !

Voici le code de la classe abstraite :

1 package2 {

201

Page 225: Programmez en Actionscript 3

CHAPITRE 12. NOTIONS AVANCÉES DE LA POO

3 import flash.errors.IllegalOperationError;4 /**5 * Une classe abstraite6 */7 public class MaClasseAbstraite8 {9

10 public function MaClasseAbstraite(moi:MaClasseAbstraite)

11 {12 // Nous vérifions si le paramètre de vérification

correspond à l'objet13 if (moi != this)14 {15 // Sinon , quelqu 'un tente d'instancier cette

classe , nous envoyons donc une erreur16 // car seule une sous -classe peut passer le mot

-clé 'this' en paramètre au constructeur17 throw new IllegalOperationError("

MaClasseAbstraite est une classe abstraiteet ne peut donc pas être directementinstanciée.");

18 }19 }2021 }2223 }

Le mot-clé throw permet d’envoyer une erreur ; iciIllegalOperationError, qui indique qu’il s’agit d’une opération illé-gale. Pour l’instant, il n’est pas nécessaire que vous vous attardiez sur cetteinstruction, nous reviendrons sur la gestion des erreurs dans un chapitredédié plus loin dans ce cours.

Nous demandons dans le constructeur un paramètre moi obligatoire, du même typeque la classe elle-même : ainsi, seuls les objets des sous-classes de MaClasseAbstraiteseront acceptés. Ensuite, nous vérifions que ce paramètre pointe vers le même objet,c’est-à-dire que cet objet qui vient d’être créé est bien une instance d’une sous-classe.

Rappel : le mot-clé this est une référence qui pointe sur l’unique objet quifait actuellement travailler le corps de la classe. Même en remontant entre lessous-classes, cette référence pointe toujours sur le même objet (qui appartientà toutes ces classes en même temps, comme nous l’avons vu dans le chapitresur l’héritage).

Voici le code de la sous-classe concrète :

202

Page 226: Programmez en Actionscript 3

LES TYPES INCONNUS

1 package2 {3 /**4 * Une sous -classe concrète.5 */6 public class MaClasseConcrete extends MaClasseAbstraite7 {89 public function MaClasseConcrete ()

10 {11 // On envoie la référence de l'objet qui vient d'ê

tre créé à la classe mère pour passer la vérification

12 super(this);1314 }1516 }1718 }

Dans le constructeur de la classe-fille concrète, nous appelons le constructeur de laclasse-mère abstraite à l’aide du mot-clé super pour passer la vérification.

Voici ce que cela donne lorsque nous voulons créer un objet de chaque classe :

1 var objet1:MaClasseAbstraite = new MaClasseAbstraite (); // Uneerreur va être envoyée

23 var objet2:MaClasseConcrete = new MaClasseConcrete (); // Tout

va bien.

Les types inconnus

Déterminer si un objet est une occurrence d’une certaine classe

Le mot-clé is permet de renvoyer un booléen pour savoir si un objet quelconque estune occurrence d’une certaine classe ou d’une sous-classe.

1 var entier:int = -23;2 var entierPositif:uint = 42;3 var nombre:Number = 3.14;4 var chaine:String = 'Hello world!';56 // entier est du type int7 trace(entier is int); // Affiche: true8 // entier n'est pas du type uint9 trace(entier is uint); // Affiche: false

10 // La classe int est une sous -classe de Number

203

Page 227: Programmez en Actionscript 3

CHAPITRE 12. NOTIONS AVANCÉES DE LA POO

11 trace(entier is Number); // Affiche: true1213 trace(entierPositif is uint); // Affiche: true14 // La classe uint est aussi une sous -classe de Number15 trace(entierPositif is Number); // Affiche: true1617 trace(nombre is int); // Affiche: false18 trace(nombre is Number); // Affiche: true1920 trace(chaine is String); // Affiche: true21 trace(chaine is int); // Affiche: false

Cela fonctionne également avec les fonctions ! Car il faut toujours se rappeler qu’enActionScript 3, tout est objet : les variables, les fonctions, les objets de la classeVoiture, leurs attributs, leurs méthodes. . . Les fonctions sont de classe Function,comme on peut le confirmer dans cet exemple :

1 function maFonction ():void2 {3 trace('Je suis dans une fonction !');4 }56 // Toute fonction est une instance de la classe Function !7 trace(maFonction is Function); // Affiche: true8 // Mais chaine n'est pas une fonction9 trace(chaine is Function); // Affiche: false

1011 // Tout objet est une instance de la classe Object !12 trace(entier is Object); // Affiche: true13 trace(chaine is Object); // Affiche: true14 trace(maFonction is Object); // Affiche: true

Des paramètres de type inconnu

Dans les fonctions, il est possible de demander des paramètres de type inconnu,c’est-à-dire dont nous ne pouvons pas connaître la classe à l’avance ! Pour cela, nouspouvons utiliser la classe Object qui est la classe-mère de tous les objets en ActionS-cript 3.

1 function quiSuisJe(quelqueChose:Object):void2 {3 if(quelqueChose is Function)4 {5 trace('Je suis une fonction !');6 }7 }

Il existe un raccourci pour spécifier que le type d’un paramètre est inconnu : le caractère« * » ! Reprenons l’exemple précédent en utilisant ce raccourci :

204

Page 228: Programmez en Actionscript 3

LES TYPES INCONNUS

1 function quiSuisJe(quelqueChose :*):void2 {3 if(quelqueChose is Function)4 {5 trace('Je suis une fonction !');6 }7 }

Essayons cette fonction avec une autre fonction :

1 function maFonction ():void2 {3 trace('Je suis dans une fonction !');4 }56 function quiSuisJe(quelqueChose :*):void7 {8 if(quelqueChose is Function)9 {

10 trace('Je suis une fonction !');11 }12 }1314 // Nous passons l'objet maFonction de classe Function en paramè

tre !15 quiSuisJe(maFonction); // Affiche: Je suis une fonction !

L’objet maFonction est une occurrence de la classe Function (étant donné que c’estune fonction), donc le test est positif et le message « Je suis une fonction ! » est affiché.

Nous pourrions ensuite appeler la fonction à l’aide de la méthode call() de la classeFunction :

1 function maFonction ():void2 {3 trace('Je suis dans une fonction !');4 }56 function quiSuisJe(quelqueChose :*):void7 {8 if(quelqueChose is Function)9 {

10 trace('Je suis une fonction !');11 // On appelle la fonction !12 quelqueChose.call();13 }14 }1516 // Nous passons l'objet maFonction de classe Function en paramè

tre17 quiSuisJe(maFonction); // Affiche: Je suis une fonction ! Je

suis dans une fonction !

205

Page 229: Programmez en Actionscript 3

CHAPITRE 12. NOTIONS AVANCÉES DE LA POO

Accéder dynamiquement aux propriétés

En ActionScript 3, il est possible d’accéder à une propriété d’un objet en connais-sant son nom uniquement à l’exécution. Par exemple, vous obtenez le nom d’un attributdans une variable de type String, et vous voulez ensuite modifier sa valeur pour faireune animation ou autre chose.

Prenons une classe Voiture disposant d’un attribut vitesse et d’une méthode accelerer :

1 package2 {3 public class Voiture4 {56 private var _vitesse:int;78 public function Voiture ()9 {

10 vitesse = 10;11 }1213 public function get vitesse ():int14 {15 return _vitesse;16 }1718 public function set vitesse(value:int):void19 {20 _vitesse = value;21 }2223 public function accelerer(combien:int = 1):void24 {25 vitesse += combien;26 }27 }2829 }

La syntaxe à respecter pour accéder à l’attribut de nom ’vitesse’ est la suivante :

1 var objet:Voiture = new Voiture ();2 var nomDeLaPropriete:String = 'vitesse ';34 trace(objet[nomDeLaPropriete ]); // Affiche la vitesse de la

voiture: 10

Ou plus simplement :

1 var objet:Voiture = new Voiture ();2 trace(objet['vitesse ']); // Affiche: 10

206

Page 230: Programmez en Actionscript 3

ACCÉDER DYNAMIQUEMENT AUX PROPRIÉTÉS

Rappel : une propriété constituée d’un ou plusieurs accesseurs est consi-dérée comme un attribut.

En guise d’exemple, supposons que nous voulons disposer d’une fonction qui augmentede 10 n’importe quel attribut numérique d’un objet quelconque, sans avoir besoin deplus de précisions concernant sa classe.

1 function augmenter(objet:Object , propriete:String):void2 {3 // On vérifie le type de la propriété : il faut que ce soit

un nombre4 if(objet[propriete] is int || objet[propriete] is uint ||

objet[propriete] is Number)5 {6 objet[propriete] += 10;7 }8 else9 {

10 trace("Attention : La propriété " + propriete + " sur l'objet " + objet + " n'est pas un nombre.");

11 }12 }

Écrivons un petit programme principal qui crée un objet Voiture et qui utilise cettefonction pour augmenter sa vitesse :

1 package2 {3 import flash.display.Sprite;4 import flash.events.Event;56 /**7 * Programme principal8 */9 public class Main extends Sprite

10 {1112 public function Main():void13 {14 if (stage)15 init();16 else17 addEventListener(Event.ADDED_TO_STAGE , init);18 }1920 private function init(e:Event = null):void21 {22 removeEventListener(Event.ADDED_TO_STAGE , init);23 // entry point24

207

Page 231: Programmez en Actionscript 3

CHAPITRE 12. NOTIONS AVANCÉES DE LA POO

25 // On créé une voiture26 var voiture:Voiture = new Voiture ();27 // On initialise sa vitesse à 1028 voiture.vitesse = 10;29 // On augmente sa vitesse de 1030 augmenter(voiture , 'vitesse ');31 trace(voiture.vitesse); // Affiche: 203233 }3435 public function augmenter(objet:Object , propriete:

String):void36 {37 // On vérifie le type de la propriété : il faut que

ce soit un nombre38 if (objet[propriete] is int || objet[propriete] is

uint || objet[propriete] is Number)39 {40 objet[propriete] += 10;41 }42 else43 {44 trace("Attention : La propriété " + propriete +

" sur l'objet " + objet + " n'est pas unnombre.");

45 }46 }4748 }4950 }

Est-ce que cela fonctionne pour les méthodes ?

La réponse est oui, nous pouvons aussi le faire pour les méthodes ! Il suffit d’ajouterdes paramètres comme pour n’importe quel appel de fonction. Par exemple :

1 var voiture:Voiture = new Voiture ();2 voiture.vitesse = 10;34 // Appelons la méthode 'accelerer ' de notre objet voiture !5 voiture['accelerer '](5);6 trace(voiture.vitesse); // Affiche: 1578 // Ce qui revient à écrire :9 voiture.accelerer(5);

10 trace(voiture.vitesse); // Affiche: 20

208

Page 232: Programmez en Actionscript 3

LES OBJETS ANONYMES

1112 // Avec les accesseurs , la propriété vitesse est concidérée

comme un attribut13 trace(voiture['vitesse '] is Function); // Affiche: false14 // Alors que accelerer est bien une méthode15 trace(voiture['accelerer '] is Function); // Affiche: true

Voici un exemple plus concret. Nous pourrions coder une fonction qui anime une pro-priété numérique d’un objet d’une valeur à une autre pendant un certain temps mais,malheureusement, nous ne sommes pas encore assez avancé dans le cours pour pou-voir faire cela. Toutefois, je vous montre à quoi pourrait ressembler la signature de lafonction et un exemple d’utilisation :

1 function animer(objet:Object , propriete:String , valeurDepart :*,valeurArrivee :*, duree:Number):void

2 {3 // Animation à l'aide de objet[propriete]4 }

J’utilise la notation avec l’étoile pour le type de valeurDepart etvaleurArrivee pour que l’on puisse passer des nombres de type int, uintou Number. Attention toutefoisà vérifier leurs types dans le corps de la fonc-tion.

Dans notre classe Main, nous pourrions écrire :

1 var voiture:Voiture = new Voiture ();23 // Accélérons !4 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 n’importe quel attribut de n’importequel objet !

Les objets anonymes

Créer un objet anonyme

Un objet anonyme est un objet dynamique qui n’a pas de classe (autre que laclasse Object). On peut modifier ses propriétés de manière totalement libre : créer denouveaux attributs ou de nouvelles méthodes, les modifier après coup. . . En effet, sespropriétés ne sont pas décrite dans une classe particulière, donc on peut faire ce quel’on veut (ce qui peut parfois poser problème, où l’on devra effectuer de nombreux testssur l’objet anonyme car on ne sait pas à l’avance comment il sera structuré).

Pour créer un objet anonyme, il y a deux façons de procéder. La première est decréer une instance de la classe Object comme ceci :

209

Page 233: Programmez en Actionscript 3

CHAPITRE 12. NOTIONS AVANCÉES DE LA POO

1 var objetAnonyme:Object = new Object ();

Puis on peut lui affecter des propriétés librement :

1 // Ajoutons quelques attributs2 objetAnonyme.nom = "Site du Zéro";3 objetAnonyme.adresse = "www.siteduzero.com";45 trace(objet.nom + " : " + objet.adresse);

Nous obtenons dans la console :

Site du Zéro : www.siteduzero.com

On peut également créer un objet anonyme avec des accolades en spécifiant directe-ment ses propriétés séparées par des virgules ainsi :

1 {2 nomPropriete1:valeur1 ,3 nomPropriete2:valeur2 ,4 nomPropriete3:valeur3 ,5 ...6 }

Reprenons notre exemple en utilisant cette méthode :

1 var objet:Object = {2 nom: "Site du Zéro",3 adresse: "www.siteduzero.com"4 };56 trace(objet.nom + " : " + objet.adresse);

Ce qui nous donne à nouveau :

Site du Zéro : www.siteduzero.com

Il peut parfois être utile, comme dans le cas où une fonction attend beaucoup deparamètres facultatifs. Par exemple, nous pourrions avoir une fonction attendant neufparamètres facultatifs (j’ai volontairement mis en forme les paramètres pour qu’ilssoient plus lisibles) :

1 function creerEmailBrouillon(2 objet:String = "",3 message:String = "",4 date:Date = null ,5 emailsDestinataires:Array = null ,6 emailsCC:Array = null ,7 emailsCCI:Array = null ,8 emailExpediteur:String = "",9 piecesJointes:Array = null ,

210

Page 234: Programmez en Actionscript 3

LES OBJETS ANONYMES

10 demanderConfirmationLecture:Boolean = false11 ):void12 {13 // Code ici14 }

Cette fonction créé un brouillon d’e-mail : aucun champ n’est obligatoire car tous lesparamètres ont une valeur par défaut. En effet, lorsque vous enregistrez un brouillond’e-mail, vous n’êtes pas obligé de remplir tous les champs. Nous pouvons donc appelercette fonction sans lui passer de paramètre :

1 creerEmailBrouillon (); // Tous les paramètres auront leurvaleur par défaut

Mais que devrions-nous faire si nous ne voulons enregistrer que l’e-mail de l’expéditeurseul ? Et bien, il faudrait spécifier quand-même des valeurs pour les paramètres précé-dent le paramètre emailExpediteur, ce qui serait fastidieux et peu commode ! Voyezplutôt :

1 creerEmailBrouillon("", "", null , null , null , null , "[email protected]");

Pour remédier à ce problème, nous pouvons n’utiliser qu’un seul paramètre : un objetanonyme !

1 function creerEmailBrouillon(options:Object = null):void2 {3 // Code ici4 }

Nous pouvons maintenant nous contenter de passer uniquement les paramètres quinous intéressent lors de l’appel de la fonction :

1 creerEmailBrouillon ({2 emailExpediteur:"[email protected]"3 });

Il faut avouer que c’est tout de même plus lisible et moins fastidieux à taper. Dansla fonction creerEmailBrouillon, il va falloir faire plusieurs tests sur les paramètres,afin de savoir s’ils ont été passés avant de les utiliser. On commence d’abord par testerl’existence de l’objet options, puis on regarde si chaque paramètre est défini, c’est-à-dire s’il est différent de undefined (indéfini en anglais) et si son type est correct.

1 function creerEmailBrouillon(options:Object = null):void2 {3 if (options) // Equivaut à : options != null4 {5 // On vérifie si le paramètre objet est défini et est

de type String6 if (options.objet != undefined && options.objet is

String)7 {

211

Page 235: Programmez en Actionscript 3

CHAPITRE 12. NOTIONS AVANCÉES DE LA POO

8 // Traiter l'objet9 trace("Objet: " + options.objet);

10 }1112 if (options.message != undefined && options.message is

String)13 {14 // Traiter le message15 trace("Message: " + options.message);16 }1718 if (options.date != undefined && options.date is Date)19 {20 // Traiter la date de l'email21 trace("Date: " + options.date);22 }2324 if (options.emailsDestinataires != undefined && options

.emailsDestinataires is Array)25 {26 // Traiter la liste des destinataires27 trace("Emails destinataires: " + options.

emailsDestinataires.join(", ")); // On afficheles emails séparés par des virgules grâce aujoin (",")

28 }2930 if (options.emailsCC != undefined && options.emailsCC

is Array)31 {32 // Traiter la liste des destinataires en copie33 trace("Emails destinataires en copie: " + options.

emailsCC.join(", "));34 }3536 if (options.emailsCCI != undefined && options.emailsCCI

is Array)37 {38 // Traiter la liste des destinataires en copie cach

ée39 trace("Emails destinataires en copie cachée: " +

options.emailsCCI.join(", "));40 }4142 if (options.emailExpediteur != undefined && options.

emailExpediteur is String)43 {44 // Traiter d'adresse de l'expéditeur45 trace("Email de l'expéditeur: " + options.

emailExpediteur);

212

Page 236: Programmez en Actionscript 3

LES OBJETS ANONYMES

46 }4748 if (options.piecesJointes != undefined && options.

piecesJointes is Array)49 {50 // Traiter la liste des pièces jointes51 trace("URL des pièces jointes: " + options.

piecesJointes.join(", "));52 }5354 if (options.demanderConfirmationLecture != undefined &&

options.demanderConfirmationLecture is Boolean)55 {56 // Traiter l'option de demande de confirmation de

lecture57 trace("Confirmation de lecture: " + options.

demanderConfirmationLecture);58 }59 }6061 // Suite éventuelle du code ici62 }

Il est nécessaire de bien documenter cette fonction en détaillant les différentsparamètres afin que l’on puisse par la suite l’utiliser facilement.

Avec ce squelette de code, nous obtenons dans la console :

Email de l’expéditeur: [email protected]

Seul le paramètre emailExpediteur a été détecté et son type a bien été validé.

Essayons de passer plusieurs paramètres :

1 creerEmailBrouillon ({2 date:new Date(), // Date d'aujourd 'hui3 emailsDestinataires :["[email protected]", "

[email protected]", "[email protected]"], //Destinataires

4 emailExpediteur:"[email protected]" // Expéditeur5 });

Ce qui nous donne dans la console :

Date: Wed Nov 6 16:11:31 GMT +0100 2013Emails destinataires: [email protected] ,

[email protected] , [email protected] de l’expéditeur: [email protected]

213

Page 237: Programmez en Actionscript 3

CHAPITRE 12. NOTIONS AVANCÉES DE LA POO

Les fonctions anonymes

Une fonction anonyme est une fonction dont on ne précise pas le nom. Par exemple,cette fonction est anonyme :

1 function ():void2 {3 trace("Hello world!");4 }

Comme vous pouvez le constater, cette fonction n’a pas de nom définit entre lemot-cléfunction et les parenthèses des paramètres. On ne peut donc pas l’appeler directement.Par contre, on peut l’affecter à une variable de type Function comme ceci :

1 var hello:Function = function ():void2 {3 trace("Hello world!");4 }

Pour l’appeler, on considère que la variable est directement la fonction :

1 hello(); // Appelle la fonction contenue dans la variable hello

Nous pouvons ainsi créer des méthodes sur un objet anonyme en affectant une fonctionanonyme à une propriété de cet objet :

1 var anonyme:Object = new Object ();2 anonyme.hello = function ():void3 {4 trace("Hello world!");5 };67 anonyme.hello (); // Affiche : Hello world!

En résumé– Il est possible de créer des classes dynamiques que l’on peut modifier durant

l’exécution, grâce au type dynamic.– Les interfaces permettent d’hériter en quelque sorte de plusieurs classes pour par-

tager des propriétés communes.– Nos classes peuvent être abstraites : dans ce cas, on renvoie une erreur si quelqu’unessaye d’en créer une instance.

– Le type des variables que nous manipulons peut être indéfini ; on peut alors le testerà l’aide du mot-clé is.

– Il est possible d’accéder dynamiquement à des propriétés dont on connaît le nom.– Un objet anonyme est un objet sans classe que l’on peut modifier librement, etune fonction anonyme est une fonction sans nom.

214

Page 238: Programmez en Actionscript 3

Troisième partie

L’affichage

215

Page 239: Programmez en Actionscript 3
Page 240: Programmez en Actionscript 3

Chapitre 13Les objets d’affichage

Difficulté :

Dans ce chapitre, nous allons aborder le système qui va nous permettre (enfin !) d’afficherdes éléments (texte, dessins, images, etc.) à l’écran ! Mais en pratique, nous ne pourronsréellement afficher quelque chose qu’au chapitre suivant car il nous faut aborder quelquesnotions de base auparavant.

Nous allons voir notamment :

– Comment décrire une couleur en ActionScript.– Le fonctionnement de l’affichage sur un écran.– Le système d’affichage de Flash.

C’est parti !

217

Page 241: Programmez en Actionscript 3

CHAPITRE 13. LES OBJETS D’AFFICHAGE

Introduction

Les couleurs

Composer une couleur

En informatique, les couleurs sont décomposées en couleurs principales : le rouge, levert et le bleu. À partir de ces trois couleurs, il est possible de créer n’importe quelleautre couleur en les dosant (voir figure 13.1).

Figure 13.1 – Les couleurs principales de la lumière

Exemple : je souhaite créer une couleur orange. L’orange est constitué de jaune et derouge. Ainsi, il nous faut d’abord faire du jaune (rouge + vert), puis rajouter du rouge(voir figure 13.2). Au final, l’orange se crée grosso-modo avec deux quantités de rougepour une quantité de vert.

Figure 13.2 – Composition de la couleur orange

218

Page 242: Programmez en Actionscript 3

INTRODUCTION

Notation hexadécimale

Pour décrire une couleur composée de rouge, de vert et de bleu, nous utiliserons lanotation hexadécimale. On commence par écrire 0x pour signifier que l’on utilisela notation hexadécimale, puis on décrit les quantités de chacune des trois couleursrouge, vert et bleu : deux chiffres, allant de 0 (le minimum) à F (le maximum) pourchacune, ce qui fait six chiffres.

Pourquoi jusqu’à F ? Depuis quand F est un chiffre ?

Excellente question ! En réalité, il existe différents systèmes de notation pour les nombres.Celle que vous et moi utilisons tous les jours s’appelle la notation décimale. Celasignifie que nous utilisons les chiffres de 0 à 9 pour écrire les nombres. On dit aussi quenous écrivons les nombres en base dix. Une autre notation très connue est la notationbinaire : nous décrivons les nombres avec seulement les chiffres 0 et 1. On parle alorsde base deux. Par exemple, 5 en base dix s’écrit 101 en base deux !

La notation hexadécimale utilise non pas dix, mais seize chiffres ! On parle de baseseize pour cette notation. Les chiffres vont de 0 à 15. Avouez cependant qu’écrireun chiffre à l’aide de deux chiffres serait plutôt embêtant. . . Comment faire alors ladifférence entre 12 (le chiffre) et 12 (le nombre composé du chiffre 1 et du chiffre 2) ?Impossible !

Ainsi, nous utilisons les 6 premières lettres de l’alphabet pour remplacer les chiffres 10à 15, ce qui est tout de même bien plus pratique.

Chiffre (décimal) Notation hexadécimale10 A11 B12 C13 D14 E15 F

En dehors de l’ActionScript, on utilise plus généralement le # pour commen-cer une notation hexadécimale.

Ainsi, pour écrire notre chiffre 12, nous utilisons C ! Voici quelques exemples de nombreen base dix convertis en base seize :

Afin de décrire une couleur, nous utiliserons donc deux chiffres en hexadécimal pour lerouge, le vert et le bleu, de 00 à FF, ce qui fait de 0 à 255 en décimal. Par exemple,pour notre couleur orange, nous écrirons : 0xFF8000, car il y a deux doses de rougepour une dose de vert (voir figure 13.3).

219

Page 243: Programmez en Actionscript 3

CHAPITRE 13. LES OBJETS D’AFFICHAGE

Base dix Base seize12 C5 531 1F32 2016 10160 A066 42

Figure 13.3 – Notation hexadécimale de la couleur orange

La plupart des logiciels de dessin et retouche d’image affichent la notationhexadécimale des couleurs qu’il est alors facile de copier-coller. Il existe éga-lement des outils ou des sites Internet spécialisés dans la création de couleurqui fournissent cette notation (comme par exemple ColRD). Attention tou-tefois, il ne faut pas oublier qu’en ActionScript, la notation hexadécimalecommence par 0x et non pas par # !

Stocker une couleur dans une variable

Le type qu’il faut utiliser pour stocker un nombre en notation hexadécimale est letype uint :

1 var orange:uint = 0xFF8000;2 var orange2:uint = 0xff8000; // Les lettres peuvent aussi être

notées en minuscule

La variable ainsi créée peut être manipulée comme n’importe quelle autre variable :

1 trace("La couleur orange vaut " + orange + " en base dix."); //16744448

2 trace("La couleur orange vaut " + orange.toString(10) + " enbase dix."); // 16744448

3 trace("La couleur orange vaut " + orange.toString(16) + " enbase seize."); // FF8000

4 trace("La couleur orange vaut " + orange.toString(2) + " enbase deux."); // 1111 1111 1000 0000 0000 0000

220

Page 244: Programmez en Actionscript 3

INTRODUCTION

Vous remarquerez que la couleur est stockée sous la notation décimale, c’est,en effet, la seule notation supportée par les types de nombres. Par contre, ilest facile de retrouver la notation hexadécimale ou binaire grâce à la méthodetoString() comme dans l’exemple ci-dessus.

L’affichage sur un écran

Tous les écrans d’affichage sont composés d’une grille de petits carrés de lumière quel’on nomme pixels (voir figure 13.4). Nous allons voir comment utiliser cette grillepour positionner des objets.

Figure 13.4 – L’écran est composé d’une grille de pixels

Le repère

Les pixels forment donc une grille suivant deux axes : l’axe des X et l’axe des Y. Onse situe alors sur un espace en 2D. Pour mieux visualiser la grille, nous allons utiliserà la figure 13.5 un repère qui nous montre les axes et l’origine de la grille.

Une position (c’est-à-dire un point précis de ce repère) est décrite par deux coordon-nées : la position en X, et la position en Y. On écrit toujours les coordonnées en 2Ddans cet ordre : d’abord les X, puis les Y. Ainsi, il n’est pas nécessaire de tout le tempspréciser qui est quoi. Dans l’exemple à la figure 13.6, le pixel que l’on a colorié en bleuse trouve à la position (5,6), c’est-à-dire à 5 pixels du bord gauche de l’écran, et à 6pixels du bord supérieur de l’écran.

Tout au long du cours, il faudra avoir ce repère en tête dès qu’il s’agirade positionner un objet à l’écran. Il faut savoir qu’il est possible que lescoordonnées soient négatives, mais, dans ce cas, les pixels qui dépassent neseront pas affichés (faute de pixels sur votre écran).

221

Page 245: Programmez en Actionscript 3

CHAPITRE 13. LES OBJETS D’AFFICHAGE

Figure 13.5 – Repère de l’affichage

Figure 13.6 – Exemple de position sur l’écran

222

Page 246: Programmez en Actionscript 3

L’ARBRE DES OBJETS D’AFFICHAGE

L’arbre des objets d’affichage

L’arbre d’affichage

Pour bien comprendre de quoi il s’agit, commençons par un exemple concret, et reve-nons sur notre chère voiture. Nous voulons maintenant l’afficher et l’animer sur notreécran ! Nous allons utiliser un modèle simplifié, celui de la figure 13.7.

Figure 13.7 – Votre magnifique voiture simplifiée

Supposons que cette voiture soit composée d’une carrosserie et de deux roues. Vue del’extérieur, la voiture est un objet et un seul (voir figure 13.8).

Figure 13.8 – La voiture vue de l’extérieur

Mais en réalité, il y a trois objets à l’intérieur de cet objet (voir figure 13.9) : lacarrosserie en orange et les deux roues en bleu.

Figure 13.9 – L’objet Voiture est composé d’autres objets

Lorsque nous voudrons afficher la voiture, nous créerons tout d’abord un conteneur(par exemple, avec la classe Sprite), puis nous ajouterons à l’intérieur trois autresobjets d’affichage (voir figure 13.10) : un pour la carrosserie, et un pour chaque roue.

223

Page 247: Programmez en Actionscript 3

CHAPITRE 13. LES OBJETS D’AFFICHAGE

Figure 13.10 – Nous disposons les différents objets dans le conteneur Voiture

Ainsi, si nous bougeons le conteneur « voiture », les roues se déplaceront en mêmetemps que la carrosserie ; si nous tournons le conteneur, l’ensemble fera une rotationcomme s’il s’agissait d’un unique objet, à l’instar de ce qui se passerait dans la vraievie ! La voiture pourrait elle-même se trouver dans un autre conteneur « rue », que l’onpourrait faire défiler comme un tout. . .

Ainsi, l’arbre d’affichage est une arborescence d’objets d’affichage inclus les unsdans les autres dans une certaine logique. Voici un schéma à la figure 13.11 représentantl’arbre d’affichage de notre application.

Figure 13.11 – L’arbre d’affichage de la voiture

Vous remarquerez que la racine de l’arbre est composée d’un objet que j’aiappelé scène principale. C’est un objet spécial de la classe Stage qui esttoujours présent pour la gestion de l’affichage.

Maintenant, si nous voulons qu’il y ait deux voitures dans la rue, il suffit d’en ajouterune autre dans le conteneur « rue » (voir figure 13.12).

224

Page 248: Programmez en Actionscript 3

L’ARBRE DES OBJETS D’AFFICHAGE

Figure 13.12 – Plusieurs voitures dans l’arbre d’affichage

Il est important de se rappeler que modifier l’apparence ou la position d’unconteneur impactera tous les enfants comme s’il s’agissait d’un seul et uniqueobjet. Il est néanmoins possible de modifier les enfants séparément.

Les classes d’affichage

En ActionScript, il existe plusieurs classes différentes dédiées à l’affichage, commeon peut le constater à la figure 13.13.

Figure 13.13 – Extrait de l’arbre d’héritage des classes d’affichage

225

Page 249: Programmez en Actionscript 3

CHAPITRE 13. LES OBJETS D’AFFICHAGE

Par exemple, la classe TextField sert à afficher du texte ; nous en reparlerons dans leprochain chapitre. Elle est une sous-classe de InteractiveObject (pour les objets in-teractifs), elle-même sous-classe de DisplayObject. Ainsi, toutes les classes d’affichagesont des sous-classes de la classe DisplayObject.

Rappel : les classes abstraites ne peuvent pas être instanciées directement,c’est-à-dire que l’on ne peut pas créer de nouveaux objets de ces classes avecle mot-clé new. Il est toutefois possible de spécifier des paramètres de typede classes abstraites dans les méthodes, ce n’est pas gênant.

La classe DisplayObject (abstraite)

Il s’agit de la classe d’affichage de base. C’est à partir d’elle que toutes les autres classesd’affichage sont dérivées ; elle contient les propriétés utiles pour manipuler des objetsd’affichage simples. Encore une fois, étant donné qu’il s’agit d’une classe abstraite,inutile d’essayer de créer un objet de la classe DisplayObject.

La classe Bitmap

Cette classe permet d’afficher des images composées de pixels. Les objets de cette classesont purement visuels ; il est impossible de gérer directement les clics de souris dessuspar exemple. Nous apprendrons à manipuler des images dans les prochains chapitres.

La classe Shape

Cette classe permet de créer des objets légers permettant de dessiner à l’écran : tracerdes lignes, des formes, remplir. . . À l’instar des objets de la classe Bitmap, les objetsde la classe Shape sont purement visuels.

La classe Video

Comme vous vous en doutez, cette classe permet l’affichage de vidéos (avec le son).C’est aussi une classe créant des objets purement visuels.

La classe InteractiveObject (abstraite)

Cette classe permet d’introduire de l’interactivité pour nos objets d’affichage : il seraainsi possible de savoir si l’utilisateur clique sur un objet d’une sous-classe de la classeInteractiveObject.

226

Page 250: Programmez en Actionscript 3

L’ARBRE DES OBJETS D’AFFICHAGE

La classe SimpleButton

Cette classe permet de fabriquer des boutons basiques rapidement : on peut ainsi luispécifier quel objet sera affiché dans différents états (normal, souris au-dessus, cliqué,. . .), et automatiquement changer le curseur de la souris au-dessus en doigt. Cette classeest utilisée par Flash Pro d’Adobe pour créer les boutons.

La classe TextField

Avec cette classe, nous présenterons du texte à l’écran pendant le prochain chapitre. Ilest possible de formater le texte à l’aide d’une forme très allégée d’HTML (le langageprincipal utilisé pour créer des sites web).

La classe DisplayObjectContainer (abstraite)

Cette dernière classe abstraite introduit la notion de conteneur : il est désormaispossible d’ajouter plusieurs objets d’affichage enfants dans un seul conteneur, afin de lesmanipuler ensemble comme s’il s’agissait d’un seul objet (pensez à la fonction Grouperdes logiciels de bureautique).

La classe Loader

Cette classe nous permettra de charger du contenu externe à notre application, àcondition qu’il soit visuel.

La classe Stage (abstraite)

Les objets de cette classe sont des objets spéciaux qui représentent la scène d’affichagede l’application. Il est bien évidemment impossible de créer directement une instancede la classe Stage. Attention, la plupart des propriétés héritées des classes-mères nefonctionnent pas sur eux (comme par exemple la position, l’opacité, etc.).

La classe Sprite

Non, il ne s’agit pas de la boisson ! :-˚ Les objets de cette classe sont les plus utilisésen tant que conteneurs, et en tant que dessins interactifs. Vous en userez (et abuserez)en programmant en ActionScript !

La classe MovieClip

Cette classe dérivée de la classe Sprite ajoute un composant complexe et plutôt lourd :une ligne de temps (ou timeline en anglais). Cela consiste en une série d’images-cléspouvant être réparties sur différents niveaux, afin de créer des animations complexes(voir figure 13.14). Cette classe a tout d’abord été conçue pour être utilisée dans le

227

Page 251: Programmez en Actionscript 3

CHAPITRE 13. LES OBJETS D’AFFICHAGE

logiciel d’animation Flash Pro d’Adobe ; ainsi, étant d’un intérêt limité pour une uti-lisation en ActionScript, nous ne l’utiliserons quasiment pas dans ce cours.

Figure 13.14 – Un exemple de timeline dans Flash Pro

Il existe d’autres classes d’affichage que je n’ai pas mentionnées ici : nous neles aborderons pas, elles sont trop avancées et donc inutiles dans le cadre de cecours. Mais si vous êtes curieux, vous pouvez toujours explorer les possibilitéssupplémentaires qui s’offrent à vous en visitant la documentation.

Si nous reprenions notre exemple de la voiture, les schémas des arbres d’affichageressembleraient aux deux figures 13.15 et 13.16.

Figure 13.15 – L’arbre d’affichage de la voiture

Manipuler les conteneurs

Toutes les nouvelles propriétés (attributs et méthodes) que nous allons voirsont issues de la classe DisplayObjectContainer. Je vous conseille d’al-ler lire en parallèle la documentation officielle du langage ActionScript 3 enfrançais. N’hésitez surtout pas à l’utiliser aussi souvent que vous en sentez lebesoin, elle est très pratique !

228

Page 252: Programmez en Actionscript 3

MANIPULER LES CONTENEURS

Figure 13.16 – Plusieurs voitures dans l’arbre d’affichage

B

�Documentation officielle

Code web : 403326.

Buvez du Sprite !

Comme nous l’avons vu précédemment, la classe Sprite va nous permettre de créer desconteneurs d’affichage très polyvalents tout en restant légers. Commençons par créerun conteneur que nous appellerons voiture.

1 // Création du conteneur 'voiture '2 var voiture:Sprite = new Sprite ();

Comme vous pouvez le remarquer, le constructeur de la classe Sprite neprend pas de paramètre.

Ajouter des enfants

Pour ajouter des objets d’affichage enfants dans notre conteneur voiture, il faut utiliserla méthode addChild(enfant:DisplayObject):void fournie par la classe DisplayObjectContainer. Elle prend en paramètre l’enfant à ajouter dans le conteneur.

1 // Créons une roue2 var roue:Sprite = new Sprite ();3 // Ajoutons -la dans la voiture4 voiture.addChild(roue);56 // Créons la rue et ajoutons la voiture dans la rue7 var rue:Sprite = new Sprite ();8 rue.addChild(voiture);

229

Page 253: Programmez en Actionscript 3

CHAPITRE 13. LES OBJETS D’AFFICHAGE

L’objet roue1 est désormais affiché à l’intérieur du conteneur voiture, lui-même affichédans le conteneur rue. Mais il manque quelque chose : il faut ajouter l’objet rue dansla scène principale, sinon il ne sera pas affiché !

Afficher un objet sur la scène principale

Dans notre projet, nous utilisons une classe principale que nous avons appelée Main(dans le fichier Main.as) :

1 package {2 import flash.display.Sprite;3 import flash.events.Event;45 /**6 * ...7 * @author Guillaume8 */9 public class Main extends Sprite {

1011 public function Main():void {12 if (stage)13 init();14 else15 addEventListener(Event.ADDED_TO_STAGE , init);16 }1718 private function init(e:Event = null):void {19 removeEventListener(Event.ADDED_TO_STAGE , init);20 // entry point2122 trace("Hello world !");23 }2425 }2627 }

Regardez droit dans les yeux la déclaration de la classe Main : c’est une sous-classede Sprite ! Notre classe principale est donc un conteneur, qui est automatiquementajouté à la scène au démarrage 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 scène principale, nous procéderons ainsi :

1 this.addChild(rue);

Le code peut être raccourci en enlevant le mot-clé this :

1 addChild(rue);

230

Page 254: Programmez en Actionscript 3

MANIPULER LES CONTENEURS

Rappel : le mot-clé this permet d’accéder à l’objet courant. Si nous l’utili-sons dans des méthodes non statiques de la classe Main, nous pointerons surl’objet qui représente notre application. Il est toutefois possible d’omettre lemot-clé this si cela ne pose pas de problème de conflit de noms (typique-ment, lorsque vous avez à la fois un attribut dans votre classe et un paramètredu même nom dans la méthode, il faut utiliser this pour accéder à l’attributde la classe). Du coup, le code ci-dessus ne fonctionnera pas dans une autreclasse ; il faudrait alors utiliser une variable pointant sur l’objet de la classeMain.

Voici le code complet de la classe Main :

1 package {2 import flash.display.Sprite;3 import flash.events.Event;45 /**6 * ...7 * @author Guillaume8 */9 public class Main extends Sprite {

1011 public function Main():void {12 if (stage)13 init();14 else15 addEventListener(Event.ADDED_TO_STAGE , init);16 }1718 private function init(e:Event = null):void {19 removeEventListener(Event.ADDED_TO_STAGE , init);20 // entry point2122 // Création du conteneur 'voiture '23 var voiture:Sprite = new Sprite ();2425 // Créons une roue26 var roue:Sprite = new Sprite ();27 // Ajoutons -la dans la voiture28 voiture.addChild(roue);2930 // Créons la rue et ajoutons la voiture dans la rue31 var rue:Sprite = new Sprite ();32 rue.addChild(voiture);3334 // On ajoute la rue sur la scène principale35 addChild(rue);36 }3738 }

231

Page 255: Programmez en Actionscript 3

CHAPITRE 13. LES OBJETS D’AFFICHAGE

3940 }

Si vous testez le code à ce stade, vous risquez d’être un peu déçus : en effet,les conteneurs sont vides par défaut ! Vous devrez vous contenter d’une tristescène vide, mais nous allons bientôt remédier à cela.

Reprenons maintenant le schéma représentant l’arbre d’affichage, que nous avons dé-taillé plus haut (voir figure 13.17).

Figure 13.17 – L’arbre d’affichage de la voiture

Corrigeons-le pour y inclure notre objet de la classe Main (voir figure 13.18).

Figure 13.18 – L’arbre d’affichage de notre application

232

Page 256: Programmez en Actionscript 3

MANIPULER LES CONTENEURS

Un objet ne peut être affiché à deux endroits différents ; si jamais vous l’ajou-tez à un conteneur alors que l’objet est déjà dans un autre conteneur, il seraautomatiquement retiré de ce dernier avant d’être ajouté dans le nouveauconteneur.

L’index d’affichage

Cette notion correspond à l’ordre d’affichage des enfants dans un conteneur. Si un objeta un index plus grand qu’un autre, il sera affiché devant, et inversement. L’index estcompris entre 0 et conteneur.numChildren - 1 (le nombre d’enfants moins un).

À la figure 13.19 par exemple, la voiture bleue est au-dessus des autres car elle a l’indexd’affichage le plus élevé. En revanche, la voiture orange est tout en dessous car elle aun index égal à zéro.

Figure 13.19 – L’index d’affichage de trois voitures superposées

Il est impossible de mettre un enfant à un index en dehors des bornes quenous avons définies : ainsi, on ne peut pas mettre un objet à un index inférieurà 0 ou supérieur à conteneur.numChildren - 1.

On peut obtenir l’index d’un enfant en utilisant la méthode getChildIndex():int(renvoyant un int), qui prend en paramètre l’objet enfant en question :

1 // On crée la rue2 var rue:Sprite = new Sprite ();34 // On ajoute trois voiture dans la rue5 var voiture1:Sprite = new Sprite ();6 rue.addChild(voiture1);78 var voiture2:Sprite = new Sprite ();

233

Page 257: Programmez en Actionscript 3

CHAPITRE 13. LES OBJETS D’AFFICHAGE

9 rue.addChild(voiture2);1011 var voiture3:Sprite = new Sprite ();12 rue.addChild(voiture3);1314 trace("La voiture1 est à l'index " + rue.getChildIndex(voiture1

)); // Affiche 015 trace("La voiture2 est à l'index " + rue.getChildIndex(voiture2

)); // Affiche 116 trace("La voiture3 est à l'index " + rue.getChildIndex(voiture3

)); // Affiche 2

Ajouter un enfant à un index précis

Il existe une variante de la méthode addChild que nous avons vue il y a peu de temps.Il s’agit de la méthode addChildAt(enfant:DisplayObject, index:int):void, quiprend deux paramètres : l’enfant à ajouter, puis l’index d’affichage où il faut l’ajouter.

Voici un exemple, où l’on ajoute chaque nouvelle voiture en arrière-plan :

1 // On crée la rue2 var rue:Sprite = new Sprite ();34 // On ajoute des voitures à la rue , en les mettant à l'arrière-

plan à chaque fois5 var voiture1:Sprite = new Sprite ();6 rue.addChildAt(voiture1 , 0);78 var voiture2:Sprite = new Sprite ();9 rue.addChildAt(voiture2 , 0);

1011 var voiture3:Sprite = new Sprite ();12 rue.addChildAt(voiture3 , 0);1314 trace("La voiture1 est à l'index " + rue.getChildIndex(voiture1

)); // Affiche 215 trace("La voiture2 est à l'index " + rue.getChildIndex(voiture2

)); // Affiche 116 trace("La voiture3 est à l'index " + rue.getChildIndex(voiture3

)); // Affiche 0

Comme vous pouvez le constater, l’index d’affichage de chaque objet varie,car il représente à tout instant la position en profondeur de celui-ci ; si jamaisun objet passe derrière un autre par exemple, son index sera automatiquementmodifié en conséquence !

234

Page 258: Programmez en Actionscript 3

MANIPULER LES CONTENEURS

Opérations sur les enfants

Nombre d’enfants

Pour obtenir le nombre d’enfants que contient un conteneur, vous pouvez utiliser legetter numChildren de type int.

Attention, c’est un attribut en lecture seule car aucun setter n’est défini dansla classe DisplayObjectContainer !

1 // On crée une rue2 var rue:Sprite = new Sprite ();34 // On ajoute trois voitures dans la rue5 var voiture1:Sprite = new Sprite ();6 rue.addChild(voiture1);7 var voiture2:Sprite = new Sprite ();8 rue.addChild(voiture2);9 var voiture3:Sprite = new Sprite ();

10 rue.addChild(voiture3);1112 trace("Il y a " + rue.numChildren + " voitures dans la rue.");

// Affiche 3.

Accéder au parent d’un objet d’affichage

L’attribut parent permet d’accéder au conteneur parent qui contient l’objet d’affichage.Cette propriété est notamment utile à l’intérieur d’une classe, quand on ne peut passavoir quel est le conteneur.

1 trace(rue == voiture1.parent); // Affiche true23 trace("Nombre de voitures : " + rue.numChildren); // Affiche 34 trace("Nombre de voitures : " + voiture1.parent.numChildren);

// Affiche 3 également

Modifier l’index d’un enfant

Une fois un objet d’affichage enfant ajouté à un conteneur, il est possible de modifier sonindex d’affichage. Pour cela, nous utiliserons la méthode setChildIndex(enfant:DisplayObject,index:int):void qui prend en paramètre l’enfant en question puis son nouvel index.

1 // On met successivement les voitures au premier -plan2 rue.setChildIndex(voiture1 , 2);3 rue.setChildIndex(voiture2 , 2);4 rue.setChildIndex(voiture3 , 2);

235

Page 259: Programmez en Actionscript 3

CHAPITRE 13. LES OBJETS D’AFFICHAGE

56 trace("La voiture1 est à l'index " + rue.getChildIndex(voiture1

)); // Affiche 07 trace("La voiture2 est à l'index " + rue.getChildIndex(voiture2

)); // Affiche 18 trace("La voiture3 est à l'index " + rue.getChildIndex(voiture3

)); // Affiche 2

Rappel : la valeur de l’index doit être située entre 0 etconteneur.numChildren - 1 !

Échanger les index d’affichage de deux enfants

Il existe deux méthodes de la classe DisplayObjectContainer pour échanger la profon-deur de deux objets enfants : swapChildren() qui prend en paramètre deux référencesdes enfants du conteneur et swapChildrenAt() qui prend en paramètre deux indexdifférents à échanger.

1 rue.swapChildren(voiture1 , voiture2);2 trace("La voiture1 est à l'index " + rue.getChildIndex(voiture1

)); // Affiche 13 trace("La voiture2 est à l'index " + rue.getChildIndex(voiture2

)); // Affiche 04 // La voiture 1 est affichée devant la voiture 256 rue.swapChildrenAt(0, 1);7 trace("La voiture1 est à l'index " + rue.getChildIndex(voiture1

)); // Affiche 08 trace("La voiture2 est à l'index " + rue.getChildIndex(voiture2

)); // Affiche 19 // La voiture 1 est affichée en dessous de la voiture 2

Déterminer si un objet est enfant d’un conteneur

Une méthode très pratique de la classe DisplayObjectContainer renvoie un booléenpour le savoir : j’ai nommé contains() ! Elle prend en paramètre un objet de la classeDisplayObject et retourne true si cet objet est dans la liste d’affichage du conteneur(y compris parmi les petits-enfants, parmi les enfants des petits-enfants, etc.), ou s’ils’agit du conteneur lui-même (nous considérons que le conteneur se contient lui-même).Sinon, elle renvoie false.

1 var sprite1:Sprite = new Sprite ();2 var sprite2:Sprite = new Sprite ();3 var sprite3:Sprite = new Sprite ();4 var sprite4:Sprite = new Sprite ();5

236

Page 260: Programmez en Actionscript 3

MANIPULER LES CONTENEURS

6 sprite1.addChild(sprite2);7 sprite2.addChild(sprite3);89 trace(sprite1.contains(sprite1)); // Affiche: true

10 trace(sprite1.contains(sprite2)); // Affiche: true11 trace(sprite1.contains(sprite3)); // Affiche: true12 trace(sprite1.contains(sprite4)); // Affiche: false

Retirer des enfants

Pour retirer un enfant d’un parent, la méthode removeChild(enfant:DisplayObject):voidest toute indiquée ! À l’instar de la méthode addChild(), cette fonction prend en pa-ramètre l’enfant à enlever de l’affichage.

1 // On enlève les trois voitures de la rue2 rue.removeChild(voiture1);3 rue.removeChild(voiture2);4 rue.removeChild(voiture3);

Il est également possible de supprimer un enfant à un certain index, sans savoir pré-cisément duquel il s’agit, à l’aide de la méthode removeChildAt(index:int):void.Le paramètre que nous passons correspond à l’index de l’enfant que nous souhaitonsenlever.

1 // On crée la rue2 var rue:Sprite = new Sprite ();34 // On ajoute des voitures à la rue , en les mettant à l'arrière-

plan à chaque fois5 var voiture1:Sprite = new Sprite ();6 rue.addChildAt(voiture1 , 0);78 var voiture2:Sprite = new Sprite ();9 rue.addChildAt(voiture2 , 0);

1011 var voiture3:Sprite = new Sprite ();12 rue.addChildAt(voiture3 , 0);1314 trace("La voiture1 est à l'index " + rue.getChildIndex(voiture1

)); // Affiche 215 trace("La voiture2 est à l'index " + rue.getChildIndex(voiture2

)); // Affiche 116 trace("La voiture3 est à l'index " + rue.getChildIndex(voiture3

)); // Affiche 01718 // On enlève a voiture le plus au fond19 rue.removeChildAt(0); // voiture3 enlevée !2021 // On peut enlever les deux autres de la même manière

237

Page 261: Programmez en Actionscript 3

CHAPITRE 13. LES OBJETS D’AFFICHAGE

22 rue.removeChildAt(0); // voiture2 enlevée !23 rue.removeChildAt(0); // voiture1 enlevée !

Et si on souhaite enlever tous les enfants du conteneur, n’y a-t-il pas unmoyen moins fastidieux ?

La réponse est oui, grâce à la méthode removeChildren(beginIndex:int = 0, endIndex:int= 0x7fffffff):void qui permet de supprimer plusieurs enfants d’un coup d’un seul !Les deux paramètres facultatifs spécifient à partir de quel index on supprime, et jus-qu’à quel index. Par défaut, tous les enfants sont supprimés, donc si c’est ce que voussouhaitez faire, laissez les parenthèses vides.

1 rue.removeChildren (); // Toutes les voitures sont enlevées d'uncoup !

Propriétés utiles des objets d’affichage

Nous allons maintenant aborder des propriétés communes à tous les objets d’affichage,qui s’avèreront très utiles ! Toutefois, nous nous limiterons pour l’instant à l’affichage2D dans le repère mentionné en début de chapitre.

Les attributs et méthodes que nous allons voir sont des propriétés de la classeDisplayObject, dont la documentation est disponible en ligne.

B

��

DocumentationDisplayObjectCode web : 329657

Position

Tout d’abord, commençons par la position de l’objet d’affichage : deux attributs, x et y,permettent de contrôler respectivement la position horizontale et verticale de l’origined’un objet d’affichage.

Reprenons l’exemple de l’introduction, visible à la figure 13.20.

Pour déplacer l’origine d’un objet à cet endroit précis (5, 6), nous écrirons ceci :

1 var monObjet:Sprite = new Sprite ();2 // Modifions la position de l'objet !3 monObjet.x = 5;4 monObjet.y = 6;5 addChild(monObjet);

238

Page 262: Programmez en Actionscript 3

PROPRIÉTÉS UTILES DES OBJETS D’AFFICHAGE

Figure 13.20 – Exemple de position sur l’écran

La position par défaut de tout nouvel objet d’affichage est (0, 0), c’est-à-direque x vaut 0 et que y vaut 0 si vous n’y touchez pas.

Un mot sur l’origine

L’origine d’un objet d’affichage est le point qui représente sa position actuelle. Pardéfaut, elle est située en haut à gauche (voir figure 13.21), et elle ne peut pas êtredéplacée (voir figure 13.22).

Figure 13.21 – L’origine est en haut à gauche par défaut

Comment modifier l’origine de notre conteneur si on ne peut pas la déplacer ?

239

Page 263: Programmez en Actionscript 3

CHAPITRE 13. LES OBJETS D’AFFICHAGE

Figure 13.22 – Rotation du conteneur avec l’origine par défaut

Et bien, c’est très simple, il suffit de déplacer les enfants à l’intérieur de notre conteneur,pour donner l’illusion de modifier l’origine (voir figure 13.23) !

Figure 13.23 – On déplace l’image de voiture à l’intérieur du conteneur

Et c’est gagné (voir figure 13.24) !

Figure 13.24 – Rotation du conteneur avec la nouvelle origine

L’affichage à l’écran de la voiture à la position (0, 0) ressemblerait alors à la figure13.25 ou bien 13.26.

Par exemple, si vous ajoutez un objet d’affichage voiture dans votre conteneur rue, etque vous positionnez la voiture en négatif à 100 pixels de l’origine de la rue, une partiede votre voiture sera très certainement en dehors de l’écran. Mais l’origine de la rue n’a

240

Page 264: Programmez en Actionscript 3

PROPRIÉTÉS UTILES DES OBJETS D’AFFICHAGE

Figure 13.25 – Dans le cas de l’origine par défaut

Figure 13.26 – Dans le cas où l’on a centré l’origine

241

Page 265: Programmez en Actionscript 3

CHAPITRE 13. LES OBJETS D’AFFICHAGE

pas changé entre-temps : elle est toujours à sa position de départ (0, 0). Maintenant,vous pouvez faire réapparaître la voiture en entier en déplaçant la rue de 100 pixelsvers la droite ! Son origine va ainsi changer et devenir (100, 0), ainsi la position de lavoiture par rapport à la scène sera (0, 0) ! Tout est relatif !

Taille

Taille absolue

La taille absolue d’un objet d’affichage, c’est-à-dire la taille qu’il prend à l’écran, peutêtre lue ou modifiée à l’aide des attributs width (longueur) et height (hauteur), enpixels. La taille est toujours exprimée en valeurs positives.

1 var maVoiture:Voiture= new Voiture ();2 // Modifions la taille de la voiture pour qu'elle fasse 100x100

pixels !3 maVoiture.width = 100;4 maVoiture.height = 100;5 addChild(maVoiture);

Modifier la taille d’un conteneur vide et sans dessin n’a aucun sens, et nedonnera aucun résultat. Ses deux attributs width et height seront toujourségaux à 0.

Taille relative

On peut également redimensionner un objet d’affichage à l’aide de pourcentages, grâcesaux attributs scaleX pour redimensionner en longueur, et scaleY en hauteur. Lespourcentages ne sont pas directement exprimés en tant que tel : par exemple, scaleX= 1 signifie que la longueur de l’objet est à 100%, scaleY = 2 signifie que l’objet estdeux fois plus haut que sa taille absolue d’origine et scaleY = 0.5 signifie que l’objetest moitié moins haut.

1 var maVoiture:Voiture= new Voiture ();2 // Modifions la taille de la voiture pour qu'elle fasse 100x100

pixels !3 maVoiture.width = 100;4 maVoiture.height = 100;56 // Réduisons la taille de la voiture de moitié !7 maVoiture.scaleX = 0.5;8 maVoiture.scaleY = 0.5;9 trace(maVoiture.width); // Affiche: 50

10 trace(maVoiture.height); // Affiche: 501112 // Remettons -là à sa taille normale :

242

Page 266: Programmez en Actionscript 3

PROPRIÉTÉS UTILES DES OBJETS D’AFFICHAGE

13 maVoiture.scaleX = 1;14 maVoiture.scaleY = 1;15 trace(maVoiture.width); // Affiche: 10016 trace(maVoiture.height); // Affiche: 10017 addChild(maVoiture);

Avec ses propriétés, il est possible d’inverser un objet d’affichage à l’aide de valeursnégatives :

1 var maVoiture:Voiture= new Voiture ();2 // Modifions la taille de la voiture pour qu'elle fasse 100x100

pixels !3 maVoiture.width = 100;4 maVoiture.height = 100;56 // Inversons horizontalement la voiture !7 maVoiture.scaleX = -1;8 trace(maVoiture.width); // Affiche: 1009 trace(maVoiture.height); // Affiche: 100

10 addChild(maVoiture);

Rappel : les attributs de taille width et height sont toujours positifs.

Rotation

L’attribut rotation permet de faire tourner des objets d’affichage autour de leur ori-gine (voir figure 13.27), en utilisant des degrés. Les valeurs comprises entre 0 et 180représentent la rotation en sens horaire ; les valeurs comprises entre 0 et -180 repré-sentent la rotation en sens antihoraire. Les valeurs hors de cette plage sont alors réajus-tées (ajoutées ou soustraites de 360) pour obtenir une valeur comprise dans la plage.Par exemple, l’instruction 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 lesconvertir en degrés avant d’utiliser l’attribut rotation : on écrira par exemplevoiture.rotation = maValeurEnRadians / Math.PI * 180; en utili-sant la constant Math.PI qui contient une valeur assez précise du nombrepi.

243

Page 267: Programmez en Actionscript 3

CHAPITRE 13. LES OBJETS D’AFFICHAGE

Figure 13.27 – Rotation d’un objet (avec l’origine par défaut)

Transparence

Visibilité

L’attribut visible vaut true si l’objet est visible, false s’il est invisible. Par défaut,sa valeur est true (l’objet est visible).

1 var maVoiture:Voiture= new Voiture ();2 // Rien ne sera affiché à l'écran3 maVoiture.visible = false;4 addChild(maVoiture);

Un objet d’affichage avec une visibilité à faux n’est pas du tout rendu à l’écran,et ne peut donc pas interagir avec la souris par exemple. Cela permet toutefoisd’économiser des ressources de l’ordinateur pour améliorer les performances.Un bon conseil : si un objet doit être invisible, utilisez cette propriété à chaquefois que vous le pouvez !

Opacité

L’attribut alpha de type Number détermine l’opacité d’un objet d’affichage, c’est-à-dires’il est plus ou moins transparent. Les valeurs vont de 0 (invisible) à 1 (opaque).

244

Page 268: Programmez en Actionscript 3

SUPPRIMER UN OBJET D’AFFICHAGE DE LA MÉMOIRE

1 var maVoiture:Sprite = new Sprite ();2 // La voiture sera à moitié transparente3 maVoiture.alpha = 0.5;4 addChild(maVoiture);

L’opacité d’un conteneur est un multiplicateur de l’opacité de tous ces enfants, et ainside suite. Par exemple, si un enfant a une opacité de 0.5, et que le conteneur a uneopacité de 0.5, l’opacité réelle de l’enfant sera de 0.5 x 0.5 = 0.25 : l’enfant est donc àtrois quarts transparent.

1 var enfant:Sprite = new Voiture ();2 // L'enfant sera à moitié transparent3 enfant.alpha = 0.5;45 var conteneur:Sprite = new Sprite ();6 // Le conteneur sera aussi à moitié transparent7 conteneur.alpha = 0.5;8 conteneur.addChild(maVoiture);9

10 // Au final , l'opacité de l'enfant vaut 0.25

Il est possible de mettre une valeur supérieure à 1 : cela aura pour effetd’augmenter l’opacité des enfants de l’objet. Par exemple, si un enfant apour opacité 0.5, et que l’on met l’opacité de son conteneur à 2, l’opacité del’enfant réelle sera 0.5 x 2 = 1 : l’enfant est donc entièrement opaque.

Un objet visible mais transparent (c’est-à-dire que sa visibilité est à vrai maisque son opacité est à 0) est quand même rendu à l’écran, et donc consommedes ressources de l’ordinateur. Toutefois, il reste interactif, il est possible decliquer dessus par exemple.

Supprimer un objet d’affichage de la mémoire

À ce stade du cours, pour supprimer un objet d’affichage de la mémoire, il est nécessairede respecter les points suivants :

– l’objet ne doit pas faire partie de la liste d’affichage, c’est-à-dire qu’il ne doit pasêtre l’enfant d’un conteneur ;

– il ne doit plus y avoir une seule référence à cet objet.

Nous étofferons cette liste au fur-et-à-mesure du cours, lorsque nous aborderons denouvelles notions, afin que vous soyez experts en mémoire non-saturée !

Pour supprimer un objet de la liste d’affichage, vous pouvez utiliser la méthode removeChild()de la classe DisplayObjectContainer :

1 var maVoiture:Voiture = new Voiture ();

245

Page 269: Programmez en Actionscript 3

CHAPITRE 13. LES OBJETS D’AFFICHAGE

2 rue.addChild(maVoiture);3 // Supprimons la voiture de la liste d'affichage4 rue.removeChild(maVoiture);

L’objet en question doit être un enfant du conteneur, sinon, une erreur seraenvoyée à l’appel de la méthode removeChild().

Si jamais vous voulez supprimer l’objet d’affichage depuis sa propre classe, il faututiliser l’attribut parent et ruser un peu :

1 package2 {3 import flash.display.Sprite;45 public class Voiture extends Sprite6 {7 public function Voiture ()8 {9

10 }1112 public function removeFromParent ():void13 {14 // Vérifions que la voiture est sur la liste d'

affichage (cad. que le parent existe) avant d'appeler removeChild ()

15 if (parent != null)16 {17 // Supprimons l'objet de la liste d'affichage18 parent.removeChild(this);19 }20 }21 }2223 }

Mais comment supprimer une référence à un objet ?

C’est très simple : il suffit d’affecter la variable en question avec le mot-clé null :

1 var maVoiture:Voiture = new Voiture ();2 rue.addChild(maVoiture);3 // Supprimons la voiture de la liste d'affichage4 rue.removeChild(maVoiture);5 // Supprimons la référence à la voiture !6 maVoiture = null;

246

Page 270: Programmez en Actionscript 3

SUPPRIMER UN OBJET D’AFFICHAGE DE LA MÉMOIRE

À ce stade, l’objet de la classe Voiture n’a pas encore été supprimé : il est encore dans lamémoire de votre ordinateur. Il sera effectivement supprimé lorsque le ramasse-miette(garbage-collector en anglais) sera passé pour nettoyer la mémoire. Seulement, pourque le ramasse-miette puisse faire son travail, et déterminer quels objets doivent êtresupprimés, il faut respecter les points énumérés ci-dessus. On dit alors que ces objetssont éligibles au nettoyage par le ramasse-miette.

Vous remarquerez ainsi qu’il n’existe aucun moyen de supprimer un objetdirectement de la mémoire, sauf pour quelques rares exceptions. La plupartdu temps, il faut laisser le ramasse-miette le faire à notre place. Cela marchedonc pour tous les objets, pas seulement les objets d’affichage ; mais dans cecas, inutile d’essayer de retirer de la liste d’affichage des objets qui n’ont rienà voir ! Supprimer leurs références suffit pour l’instant.

En résumé– En ActionScript 3, les couleurs sont décrites en notation hexadécimale, précé-dées des caractères 0x (’zéro’ et ’x’).

– L’affichage sur un écran se fait dans un repère partant du coin supérieur gauche del’écran. Les coordonnés en x vont de gauche à droite, et en y de haut en bas.

– Les objets d’affichage sont contenus dans un arbre : ils peuvent contenirchacun des enfants pouvant eux-même contenir d’autres enfants.

– On peut manipuler les enfants des conteneurs à l’aide des propriétés de la classeDisplayObjectContainer.

– Une multitude de propriétés de la classe DisplayObject permet de manipuler lesobjets d’affichage.

– Il faut respecter quelques consignes pour qu’un objet d’affichage soit supprimé dela mémoire par le ramasse-miette.

247

Page 271: Programmez en Actionscript 3

CHAPITRE 13. LES OBJETS D’AFFICHAGE

248

Page 272: Programmez en Actionscript 3

Chapitre 14Afficher du texte

Difficulté :

Mesdames, Messieurs, j’ai l’honneur de vous présenter le premier chapitre où nous allonspouvoir afficher quelque chose sur notre fenêtre encore jusqu’à présent si désespérémentvide ! Et il s’agit rien de moins que du texte, grâce à une classe que nous allons retournerdans tous les sens : TextField.

Que le spectacle commence !

249

Page 273: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

Une histoire de TextField

La classe

Comme vous l’aurez sûrement compris, nous allons utiliser dans ce chapitre la classeTextField. Pour vous aidez à vous situer, reprenons le diagramme des classes desobjets d’affichage à la figure 14.1.

Figure 14.1 – TextField parmi l’arbre des classes d’affichage

Comme vous pouvez le voir, la classe TextField est une sous-classe de InteractiveObject,elle hérite donc de toutes les fonctionnalités qui permettent à l’utilisateur d’interagiravec les objets TextField (clic, sélection de texte, frappe au clavier, etc.). Mais c’estaussi un objet d’affichage comme les autres car la classe InteractiveObject est fillede la classe DisplayObject : nous pouvons donc bouger, redimensionner ou tournernos champs de texte comme bon nous semble, voir les rendre semi-transparents !

Comme d’habitude, je vous conseille de lire la documentation sur la classedisponible en ligne.

B

�Documentation TextField

Code web : 535015

250

Page 274: Programmez en Actionscript 3

UNE HISTOIRE DE TEXTFIELD

Utilisation de base

Créer un champ de texte

Comme toutes les classes des objets d’affichage, la classe TextField dispose d’unconstructeur sans paramètre. Nous allons donc l’utiliser pour créer des champsde texte comme suit :

1 var monSuperTexte:TextField = new TextField ();

Du texte brut

L’attribut text contient le texte brut (c’est-à-dire non formaté) qui est affiché dans lechamp de texte. Par défaut, le texte est vide, c’est-à-dire que l’attribut contient unechaîne de caractères vide : "".

Il s’utilise comme n’importe quel autre attribut :

1 // Affectation d'un texte brut2 monSuperTexte.text = 'Hello World!';34 // Avec une variable :5 var maSuperChaine:String = 'Je m\'apelle Zozor !';6 monSuperTexte.text = maSuperChaine;78 // Lecture du contenu brut du champ de texte :9 trace('Zozor a dit : "' + monSuperTexte.text + '"'); // Affiche

: Zozor a dit : "Je m'appelle Zozor !"

À ne pas oublier !

Pour que notre champ de texte soit affiché, il ne faut surtout pas oublier de l’ajoutersur la liste d’affichage, c’est-à-dire qu’il faut l’ajouter parmi les enfants d’un conteneur !Ainsi, dans notre classe Main, écrivons ceci :

1 // Ajoutons le champ de texte sur la scène principale :2 addChild(monSuperTexte);

Rappel : la classe Main est une sous-classe de la classe Sprite, elle-mêmeune sous-classe de la classe DisplayObjectContainer ! Nous pouvons doncy ajouter des objets d’affichage (nous serions bien embêtés sinon).

Le résultat

Par défaut, la couleur du texte est le noir et sans décoration (bordure ou fond), lapolice utilisée est une police par défaut de votre système (Times New Roman sur

251

Page 275: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

Windows/Linux et Times sur Mac), la taille est de 12 points et le texte n’est paséditable. Mais ne vous inquiétez pas, tout ceci est entièrement paramétrable commecertains ont pu le remarquer en lisant la documentation en ligne.

Pour que vous puissiez vérifier votre code, voici l’ensemble de la classe Main permettantd’afficher du texte à l’écran :1 package2 {3 import flash.display.Sprite;4 import flash.events.Event;5 import flash.text.TextField;67 /**8 * Cette application sait afficher du texte !9 */

10 [SWF(width="800",height="600",backgroundColor="#ffffff")]1112 public class Main extends Sprite13 {1415 public function Main():void16 {17 if (stage)18 init();19 else20 addEventListener(Event.ADDED_TO_STAGE , init);21 }2223 private function init(e:Event = null):void24 {25 removeEventListener(Event.ADDED_TO_STAGE , init);26 // entry point2728 // Mon premier champ de texte ! \o/29 var monSuperTexte:TextField = new TextField ();30 monSuperTexte.text = 'Hello World!';31 addChild(monSuperTexte);32 }33 }3435 }

Pour que vous puissiez voir quelque chose, vérifiez quela couleur de fond de votre animation est en blanc :[SWF(width="800",height="600",backgroundColor="#ffffff")].Du texte noir sur fond noir par exemple, ce n’est pas ce qu’il y a de pluslisible.

La figure 14.2 vous montre ce que cela donne à l’écran.

252

Page 276: Programmez en Actionscript 3

UNE HISTOIRE DE TEXTFIELD

Figure 14.2 – Notre premier champ de texte !

J’avoue que ce n’est pas très joli, mais nous allons améliorer cela dans peu de temps.

La taille par défaut d’un champ de texte est 100 pixels de largeur et 100 pixelsde hauteur. Il est bien entendu possible de la modifier.

Pour le vérifier visuellement, nous pouvons afficher une bordure autour du champ detexte :

1 monSuperTexte.border = true;

Ce qui donne à l’écran la figure 14.3.

Figure 14.3 – Le champ de texte, avec sa bordure

Ce n’est pas ce qu’il y a de plus esthétique, alors enlevons la bordure en commentantla ligne que nous venons d’ajouter :

1 // monSuperTexte.border = true;

Maintenant que nous avons un véritable objet d’affichage sous la main, exerçons-nousà utiliser ses propriétés.

Commençons par déplacer notre champ de texte à la position (200, 100) :

1 monSuperTexte.x = 200;2 monSuperTexte.y = 100;

Vous devriez maintenant avoir quelque chose ressemblant à la figure 14.4.

Je le trouve un peu trop petit, pas vous ? Allez, triplons sa taille :

253

Page 277: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

Figure 14.4 – Position à (200, 100)

1 // Taille x3 !2 monSuperTexte.scaleX = 3;3 monSuperTexte.scaleY = 3;

Ce qui donne à l’écran la figure 14.5.

Désormais, la taille de notre champ de texte est 300 pixels de largeur et 300 pixels dehauteur. Pour mieux le voir, nous pouvons remettre la bordure à notre champ de texteen décommentant cette ligne :

1 monSuperTexte.border = true;

Ce qui donne à l’écran la figure 14.6.

Pour récapituler (voir figure 14.7), nous avons :

– Créé une instance de la classe TextField.– Défini le texte du champ de texte.– Ajouté le champ de texte à l’affichage.– Modifié sa position.– Modifié son échelle de taille.

Il est impossible de faire tourner du texte ou de changer son opacité dansl’état actuel, car nous utilisons le système pour rendre les caractères, ce quiimplique ces limitations. Si vous changez tout de même la rotation ou l’opacitédu champ de texte, les caractères ne seront plus affichés. Pour contourner ceproblème, il faut utiliser des polices de caractères embarquées afin que lescaractères soient rendus directement par le lecteur Flash. Nous apprendronscomment faire à la fin de ce chapitre.

254

Page 278: Programmez en Actionscript 3

UNE HISTOIRE DE TEXTFIELD

Figure 14.5 – Notre champ de texte, quatre fois plus grand

Figure 14.6 – Le champ de texte agrandi, avec sa bordure

255

Page 279: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

Figure 14.7 – Récapitulatif des opérations

Sélection du texte

Curseur d’insertion

Tous les champs de texte disposent d’un curseur d’insertion, représenté par unebarre verticale. Lorsque le champ de texte n’est pas éditable, on dit qu’il est statique.Dans ce cas, le curseur d’insertion est toujours invisible. Jusqu’ici, notre champ detexte est statique.

Définir une sélection

Il est possible de sélectionner une portion de texte directement à l’aide de la méthodesetSelection() de la classe TextField, qui prend en paramètre la position du premiercaractère à sélectionner et la position du caractère après le dernier caractère de lasélection. Par exemple, pour sélectionner les deux premières lettres, on écrira ceci :

1 monSuperTexte.setSelection(0, 2);

Nous mettons 2 en deuxième paramètre, car il faut passer la position ducaractère après le dernier caractère à sélectionner, c’est-à-dire la position dudernier caractère à sélectionner (le numéro 1) plus une.

256

Page 280: Programmez en Actionscript 3

UNE HISTOIRE DE TEXTFIELD

Si vous testez le programme maintenant, vous ne verrez pas le texte sélectionné : c’estnormal, car par défaut les champs de texte qui n’ont pas le focus, c’est-à-dire qui nesont pas actifs, n’affichent pas la sélection du texte. Pour rendre un champ de texteactif, la manière la plus simple est de cliquer dessus. Il existe cependant un moyend’afficher tout de même la sélection, même si le champ de texte n’a pas le focus : onmet l’attribut alwaysShowSelection à true :

1 monSuperTexte.alwaysShowSelection = true;

Ce qui nous donne à l’écran la figure 14.8.

Figure 14.8 – Les deux premières lettres sont sélectionnées.

Accéder à la sélection

Il est possible de savoir à quelles positions le texte sélectionné débute et se termine. Nousdisposons pour cela des attributs selectionBeginIndex, position du premier caractèresélectionné, et selectionEndIndex, position du dernier caractère sélectionné :

1 trace("Sélection : " + monSuperTexte.selectionBeginIndex + " ->" + monSuperTexte.selectionEndIndex); // Affiche 0 -> 2

Pour obtenir le texte sélectionné, nous utiliserons la méthode substring de l’attributtext:String du champ de texte :

1 trace("Texte sélectionné : " + monSuperTexte.text.substring(monSuperTexte.selectionBeginIndex , monSuperTexte.selectionEndIndex)); // Affiche : He

La valeur renvoyée par selectionEndIndex correspond à la position ducaractère après le dernier caractère sélectionné (autrement dit, la positiondu dernier caractère sélectionné + 1). Cela tombe bien car la méthodesubstring prend les caractères jusqu’à la deuxième position passée en para-mètre moins une. Nous obtenons donc le bon texte.

Empêcher la sélection du texte

Par défaut, le texte contenu par un champ de texte peut être sélectionné par l’utili-sateur, puis éventuellement copié. Le curseur se change alors en curseur de texte.Ce comportement peut être gênant, par exemple, si vous utilisez un champ de textepour créer un bouton. Pour le désactiver, il suffit de mettre l’attribut selectable dela classe TextField à false :

257

Page 281: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

1 monSuperTexte.selectable = false;

Centrer le champ de texte

De la manière dont nous l’avons placé jusqu’ici, notre texte n’est pas exactement aucentre de la fenêtre. Pour remédier à cela, il nous faut connaître la taille exacte de lascène !

Un mot sur la scène principale

La classe Stage

Comme nous l’avons vu précédemment, une instance de la classe Stage est automati-quement créée au lancement de notre programme : il s’agit de la scène principale.La scène principale est un objet d’affichage comme on peut le voir sur le schéma desclasses d’affichage à la figure 14.9.

Figure 14.9 – La classe Stage parmis les autres classes d’affichage

La classe Stage est donc une sous-classe de la classe DisplayObjectContainer : ellehérite donc de toutes ses propriétés et s’apparente à un conteneur comme ceux quenous avons vu au chapitre précédent. Il y a tout de même quelques différences :

– On ne peut pas créer de scènes principales nous-même car la classe Stage estabstraite.

– La plupart des propriétés de la classe DisplayObjectContainer ne fonctionnent pas.– La classe Stage dispose de nouvelles propriétés spécifiques.

Voici une liste des propriétés que nous avons déjà abordées et qui sont sans effet pourla classe Stage :

258

Page 282: Programmez en Actionscript 3

CENTRER LE CHAMP DE TEXTE

– alpha– rotation– scaleX– scaleY– visible– x– y

Inutile donc d’essayer de modifier ces attributs, cela n’aura aucun impact sur la scèneprincipale. Par contre, il est toujours possible d’utiliser les attributs de l’instance denotre classe Main afin d’avoir un impact sur l’ensemble de notre arbre d’affichage. Parexemple, si l’on veut rendre la scène invisible, nous pouvons mettre ce code dans notreclasse Main :

1 // Dans la classe Main2 this.visible = false; // Toute la scène est invisible !34 visible = false; // On peut omettre le mot -clé this

Il est possible d’accéder à la scène principale grâce à l’attribut stage disponible surn’importe quel objet d’affichage dérivé de la classe DisplayObject, à condition que cetobjet soit présent dans l’arbre d’affichage.

1 // On ne peut accéder à la scène depuis notre objet voitureseulement s'il est présent dans l'arbre d'affichage :

2 var voiture:Sprite = new Sprite ();3 trace(voiture.stage); // Affiche null4 addChild(voiture);5 trace(voiture.stage); // Affiche [object Stage]

Cela signifie que l’on peut accéder à la scène principale depuis notre classe Maincomme ceci :

1 // Dans la classe Main , dans la méthode init()2 trace(this.stage); // Affiche [object Stage]34 // Comme d'habitude , il est possible d'omettre le mot -clé this

:5 trace(stage); // Affiche [object Stage]

Le code par défaut proposé par FlashDevelop

Il est temps de vous expliquer pourquoi le code par défaut de notre classe Main contientplus de choses que pour les autres classes que nous avons créées lorsque nous utilisonsFlashDevelop. Comme nous l’avons vu précédemment, on ne peut accéder à la scèned’affichage que si notre objet est présent dans l’arbre d’affichage. Ainsi, le codepar défaut de notre classe Main permet de vérifier si notre objet de la classe est bienprésent dans l’arbre avant d’appeler la méthode init(). Si jamais ce n’était pas encorele cas (par exemple, si le lecteur Flash met un peut de temps à lancer le programme),

259

Page 283: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

nous aurions des problèmes pour utiliser les propriétés de la scène principale : eneffet, l’attribut stage serait à null ! Reprenons le code par défaut de la classe Main etcommentons un peu pour mieux comprendre :

1 package2 {3 // Classes nécessaires4 import flash.display.Sprite;5 import flash.events.Event;67 /**8 * La classe de base sans modification.9 */

10 [SWF(width="640",height="480",backgroundColor="#ffffff")]1112 public class Main extends Sprite13 {14 // Constructeur15 public function Main():void16 {17 if (stage) // Si l'attribut stage est défini (c'est

-à-dire , si il est différent de null)18 init(); // Alors , on appelle la méthode init()

tout de suite19 else // Sinon20 addEventListener(Event.ADDED_TO_STAGE , init);

// On attend que notre instance de la classeMain soit ajoutée à l'arbre de l'affichage

21 }2223 private function init(e:Event = null):void24 {25 removeEventListener(Event.ADDED_TO_STAGE , init); //

On arrête d'attendre2627 // Nous pouvons commencer à coder ici en tout séré

nité28 }29 }3031 }

Le code qui permet d’attendre que l’objet soit ajouté à l’arbre d’affichageutilise la notion d’événement, notion que nous aborderons dans la partiesuivante.

260

Page 284: Programmez en Actionscript 3

CENTRER LE CHAMP DE TEXTE

La taille de la scène

Revenons à nos moutons et intéressons-nous à la taille de la fenêtre de notre programme.On peut y accéder grâce à deux attributs de la classe Stage (voir figure 14.10) :

– stageWidth pour connaître la largeur de la scène.– stageHeight pour la hauteur.

Figure 14.10 – La taille de la scène principale

Par exemple, nous pouvons écrire ceci dans notre classe Main pour afficher la taille dela scène principale :

1 trace("La scène principale a pour dimensions " + stage.stageWidth + "x" + stage.stageHeight);

La console affichera alors :

La scène principale a pour dimensions 640 x480

Cela correspond à la configuration de notre programme qui se trouve à cette ligne :

1 [SWF(width="640",height="480",backgroundColor="#ffffff")]

261

Page 285: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

Il ne faut pas confondre les attributs stageWidth et stageHeight quidonnent les dimensions de la scène principale, avec les attributs width etheight qui donnent la taille du contenu de la scène !

En effet, nous n’obtenons pas le même résultat dans les deux cas. Pour le vérifiez,ajoutons ce code :

1 trace("Le contenu de la scène principale a pour taille " +stage.width + "x" + stage.height);

Ensuite, la console affiche ceci :

La scène principale a pour dimensions 640 x480Le contenu de la scène principale a pour taille 300 x300

Comme le montre la figure 14.11, la taille du contenu de la scène est souvent différentedes dimensions de la scène.

Figure 14.11 – La taille du contenu de la scène par rapport aux dimensions de la scène

Adapter la taille du champ de texte au texte

Pour centrer le champ de texte, il serait intéressant que celui-ci fasse la même tailleque celle du texte à l’intérieur. Pour l’instant, notre champ de texte fait 300 pixels de

262

Page 286: Programmez en Actionscript 3

CENTRER LE CHAMP DE TEXTE

largeur et 300 pixels de hauteur, ce qui est beaucoup trop. Nous pouvons dire au champde texte d’adapter sa taille grâce à son attribut autoSize :

1 monSuperTexte.autoSize = TextFieldAutoSize.LEFT;

Sans oublier d’importer la classe TextFieldAutoSize (qui contient les valeurs autoriséespour l’attribut autoSize) :

1 import flash.text.TextFieldAutoSize;

Petite astuce si vous programmez avec FlashDevelop : appuyez simulta-nément sur Ctrl + Alt + Espace (au lieu de l’habituel Ctrl + Espace)et commencez à taper Text, l’auto-complétion va vous proposer toutes lesclasses possibles dont celle qui nous intéresse ici.

Désormais, nous avons à l’écran la figure 14.12.

Figure 14.12 – La taille du champ de texte correspond à la taille du texte

Nous pouvons afficher la taille du champ de texte pour être sûr de nous :

1 trace("Taille : " + monSuperTexte.width + "x" + monSuperTexte.height); // Affiche 199.95x52.95

263

Page 287: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

Modifier la position du champ de texte

Il est temps de centrer notre champ de texte ! Nous allons procéder en trois étapes pourbien détailler l’opération.

Etape 1

Commençons par placer l’origine de notre champ de texte au centre de l’écran. Pourcela, il suffit d’utiliser les attributs stageWidth et stageHeight que nous venons devoir :

1 monSuperTexte.x = stage.stageWidth / 2;2 monSuperTexte.y = stage.stageHeight / 2;

Ce qui nous donne à l’écran la figure 14.13.

Figure 14.13 – L’origine du champ de texte est centrée

Notre champ de texte n’est pas encore entièrement centré, mais nous y sommes presque !

Etape 2

Nous allons maintenant retrancher la moitié de la largeur de notre champ de texte àsa position x pour centrer notre champ de texte horizontalement :

264

Page 288: Programmez en Actionscript 3

CENTRER LE CHAMP DE TEXTE

1 monSuperTexte.x -= monSuperTexte.width / 2;

Ce qui nous donne à l’écran la figure 14.14.

Figure 14.14 – Notre champ de texte, centré horizontalement

Etape 3

Pour finir, nous répétons la même chose, mais verticalement : nous retranchons lamoitié de la hauteur de notre champ de texte à sa position y :

1 monSuperTexte.y -= monSuperTexte.height / 2;

Ce qui nous donne la figure 14.15.

En résumé

L’opération s’est donc déroulée en trois étapes :

– On centre l’origine de l’objet en utilisant stage.stageWidth et stage.stageHeight.– On retranche la moitié de sa largeur à sa position horizontale x.– On retranche la moitié de sa hauteur à sa position verticale y.

Et voici le code complet concernant notre champ de texte :

265

Page 289: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

Figure 14.15 – Notre champ de texte, au centre de la scène !

266

Page 290: Programmez en Actionscript 3

CENTRER LE CHAMP DE TEXTE

1 // Créons notre champ de texte2 var monSuperTexte:TextField = new TextField ();3 monSuperTexte.text = 'Hello World!';4 addChild(monSuperTexte);56 // Multiplions sa taille par quatre7 monSuperTexte.scaleX = 4;8 monSuperTexte.scaleY = 4;9

10 // Activons la bordure11 monSuperTexte.border = true;1213 // Adaptons la taille du champ de texte au texte14 monSuperTexte.autoSize = TextFieldAutoSize.LEFT;1516 // Centrons l'origine17 monSuperTexte.x = stage.stageWidth / 2;18 monSuperTexte.y = stage.stageHeight / 2;1920 // Retranchons la moitié de sa taille à sa position21 monSuperTexte.x -= monSuperTexte.width / 2;22 monSuperTexte.y -= monSuperTexte.height / 2;

Nous pouvons compacter la dernière partie de notre code qui permet de centrer lechamp de texte :

1 // Centrons le champ de texte2 monSuperTexte.x = stage.stageWidth / 2 - monSuperTexte.width /

2;3 monSuperTexte.y = stage.stageHeight / 2 - monSuperTexte.height

/ 2;

Nous pouvons encore simplifier en factorisant :

1 // Centrons le champ de texte2 monSuperTexte.x = (stage.stageWidth - monSuperTexte.width) / 2;3 monSuperTexte.y = (stage.stageHeight - monSuperTexte.height) /

2;

Cette méthode pour aligner au centre de la scène fonctionne bien évidemmentavec tous les objets d’affichage, pas seulement les champs de texte.

Pour l’instant, il nous est impossible de faire tourner notre champ de textecar il utilise une police de votre système pour le rendu. Pour contourner ceproblème, il nous faut embarquer notre propre police de caractère, commenous le verrons dans un prochain chapitre.

267

Page 291: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

La mise en forme

Formatons notre champ de texte

Mise en forme par défaut

Formater du texte est possible grâce à la classe TextFormat (dont la documenta-tion est disponible en ligne). Tout objet de classe TextField dispose d’un attributdefaultTextFormat de type TextFormat. Cet attribut permet de modifier la mise enforme par défaut du texte contenu dans le champ de texte, cela signifie qu’un texte quin’a pas de mise en forme spécifique recevra automatiquement cette mise en forme pardéfaut.

B

�Documentation TextFormat

Code web : 348025

La mise en forme par défaut doit être appliquée avant de définir le texte.

Pour modifier la mise en forme par défaut de notre champ de texte, nous procéderonsainsi :

1 // Création de l'instance du champ de texte2 var monSuperTexte:TextField = new TextField ();34 // Création de l'instance de la classe TextFormat5 var format:TextFormat = new TextFormat ();67 // Modifications du format ici89 // Application du format au champ de texte

10 monSuperTexte.defaultTextFormat = format;1112 // Texte à afficher - après la mise en forme par défaut13 monSuperTexte.text = "Hello World!";1415 // Ajout du champ de texte à l'affichage16 addChild(monSuperTexte);

La mise en forme par défaut n’est mise à jour que si nous affectons un objetde classe TextFormat à l’attribut defaultTextFormat. Si nous modifionsdirectement les attributs de defaultTextFormat, il ne se passera rien. N’ou-bliez pas qu’il faut que le texte soit défini après avoir mis à jour la mise enforme par défaut.

268

Page 292: Programmez en Actionscript 3

LA MISE EN FORME

L’heure du changement est arrivée

Nous allons dans un premier temps modifier la taille, la police de caractère et la cou-leur de notre texte. En se renseignant dans la documentation, nous pouvons noter lesdifférents attributs correspondants :

– size:Object (entier) pour la taille du texte en pixels.– font:String (chaîne de caractère) pour le nom de la police de caractère à 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 // monSuperTexte.scaleX = 3;2 // monSuperTexte.scaleY = 3;

Exerçons-nous à modifier la mise en forme de notre champ de texte : notre texte doitêtre de taille 42, utilisant la police de caractère Arial et colorié en bleu (dont le codehexadécimal est 0x0000ff).

1 // Création de l'instance du champ de texte2 var monSuperTexte:TextField = new TextField ();34 // Création de l'instance de la classe TextFormat5 var format:TextFormat = new TextFormat ();67 // Mise en forme8 format.size = 42;9 format.font = "Arial";

10 format.color = 0x0000ff;1112 // Application du format au champ de texte13 monSuperTexte.defaultTextFormat = format;1415 // Texte16 monSuperTexte.text = "Hello World!";1718 // Bordure19 monSuperTexte.border = true;2021 // Taille adaptative22 monSuperTexte.autoSize = TextFieldAutoSize.LEFT;2324 // Centrons le champ de texte25 monSuperTexte.x = (stage.stageWidth - monSuperTexte.width) / 2;26 monSuperTexte.y = (stage.stageHeight - monSuperTexte.height) /

2;2728 // Ajout du champ de texte à l'affichage29 addChild(monSuperTexte);

Ce qui nous donne la figure 14.16.

269

Page 293: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

Figure 14.16 – Le texte bleu, en Arial et en taille 42

Vous remarquerez qu’il est possible de positionner l’objet d’affichage avantqu’il ne soit ajouté à l’arbre d’affichage.

Si vous vous trompez en écrivant le nom de la police, ou que celle-ci n’estpas installée sur le système de l’utilisateur, la police par défaut sera utilisée àla place.

Pourquoi certains de ces attributs ont pour type Object au lieu de int ouuint ?

C’est très simple : les attributs de la classe TextFormat ont pour valeur par défautnull, pour signifier qu’il faut utiliser les valeurs par défaut de mise en forme (que l’onpeut trouver dans la documentation, en haut de la page). Or, les attributs de type intou uint ne peuvent pas valoir null, donc on est obligé d’utiliser le type Object (typeindéfini, 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 définir directement certains attri-buts. Ainsi, nous pourrions simplifier notre code en utilisant le constructeur de la classeTextFormat ainsi que nous l’indique la documentation en ligne.

1 TextFormat(font:String = null , size:Object = null , color:Object= null , bold:Object = null , italic:Object = null , underline

:Object = null ,2 url:String = null , target:String = null , align:String =

null , leftMargin:Object = null , rightMargin:Object =null , indent:Object = null , leading:Object = null)

Nous pouvons donc écrire :

1 // Création de l'instance de la classe TextFormat2 var format:TextFormat = new TextFormat("Arial", 42 , 0x0000ff);34 // Application du format au champ de texte5 monSuperTexte.defaultTextFormat = format;

Nous pouvons également mettre le texte en gras, italique, ou souligné, grâce à cesattributs de la classe TextFormat :

– bold:Object (booléen) pour mettre le texte en gras.– italic:Object (booléen) pour le mettre en italique.

270

Page 294: Programmez en Actionscript 3

LA MISE EN FORME

– underline:Object (booléen) pour le souligner.

Notre code pour la mise en forme ressemble maintenant à ceci :

1 // Mise en forme2 format.size = 42;3 format.font = "Arial";4 format.color = 0x0000ff;5 format.bold = true;6 format.italic = true;7 format.underline = true;

Nous pouvons également utiliser le constructeur :

1 // Création de l'instance de la classe TextFormat2 var format:TextFormat = new TextFormat("Arial", 42 , 0x0000ff ,

true , true , true);34 // Application du format au champ de texte5 monSuperTexte.defaultTextFormat = format;

Ce qui nous donne la figure 14.17.

Figure 14.17 – Le texte en gras, italique et souligné

Nous avons seulement vu les principaux attributs, mais rien ne vous empêche de jeterun coup d’œil à la documentation pour voir tout ce qu’il est possible de faire.

Modifier la mise en forme par défaut

Une fois la mise en forme par défaut définie, le texte que nous ajoutons à notre champde texte prend par défaut cette mise en forme. Ensuite, vous aurez sûrement envie demodifier cette mise en forme par défaut. Avec un peu d’astuce, c’est possible ! Il suffitd’affecter de nouveau notre objet de classe TextFormat à l’attribut defaultTextFormatde notre champ de texte, puis réaffecter son texte :

1 // Création de l'instance du champ de texte2 var monSuperTexte:TextField = new TextField ();34 // Création de l'instance de la classe TextFormat5 var format:TextFormat = new TextFormat ();67 // Mise en forme8 format.size = 42;9 format.font = "Arial";

10 format.color = 0x0000ff;11 format.bold = true;

271

Page 295: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

12 format.italic = true;13 format.underline = true;1415 // Application du format au champ de texte16 monSuperTexte.defaultTextFormat = format;1718 // Texte19 monSuperTexte.text = "Hello World!";2021 // Bordure22 monSuperTexte.border = true;2324 // Taille adaptative25 monSuperTexte.autoSize = TextFieldAutoSize.LEFT;2627 // Centrons le champ de texte28 monSuperTexte.x = (stage.stageWidth - monSuperTexte.width) / 2;29 monSuperTexte.y = (stage.stageHeight - monSuperTexte.height) /

2;3031 // Ajout du champ de texte à l'affichage32 addChild(monSuperTexte);3334 // ...3536 // Changeons en cours de route pour du rouge37 format.color = 0xff0000;3839 // Mise à jour du format par défaut40 monSuperTexte.defaultTextFormat = format;4142 // Il faut redéfinir le texte pour appliquer la nouvelle mise

en forme par défaut43 monSuperTexte.text = monSuperTexte.text;

Ce qui affiche la figure 14.18.

Figure 14.18 – Nous avons troqué le bleu pour du rouge

Mise en forme spécifique

Il est possible d’écraser la mise en forme par défaut, pour tout ou une partie du texte,grâce à la méthode setTextFormat() de la classe TextField, qui prend en paramètreun objet de la classe TextFormat, la position du premier caractère et la position ducaractère après le dernier caractère du texte dont on souhaite modifier la mise en forme.

272

Page 296: Programmez en Actionscript 3

LA MISE EN FORME

Ces deux positions commencent par zéro, comme pour les tableaux.

Rappel : si vous ne souhaitez pas changer des attributs dans la mise en formespécifique, il faut que ces attributs valent null. Ainsi ils n’aurons pas d’effetsur le texte. Ainsi, il est préférable de créer une nouvelle instance de la classeTextFormat, pour être sûr que tous les attributs sont à null.

Changeons la taille de la première lettre pour 72. La première lettre est à la position0, et la lettre après elle est à la position 1 :

1 // Nouvelle instance de la classe TextFormat (on peut réutiliser le même pointeur "format ")

2 format = new TextFormat ();34 format.size = 72;56 // Application du nouveau format à la première lettre7 monSuperTexte.setTextFormat(format , 0, 1);

Ce qui nous donne la figure 14.19.

Figure 14.19 – La première lettre est en taille 72

Comme vous pouver le remarquer, notre lettre est coupée en haut à droite ; c’est un effetde bord de l’italique. Nous pouvons remédier à cela grâce à l’attribut letterSpacingqui spécifie la largeur de l’espace entre les lettres. Mettons-la à 3 pixels :

1 // Nouvelle instance de la classe TextFormat (on peut réutiliser le même pointeur "format ")

2 format = new TextFormat ();34 format.size = 72;5 format.letterSpacing = 3;67 // Application du nouveau format à la première lettre8 monSuperTexte.setTextFormat(format , 0, 1);

Ainsi, il y aura 3 pixels d’espace entre la première lettre et la deuxième (voir figure14.20).

Essayons de colorier le mot « World » en bleu et de lui enlever l’italique !

1 // Je stocke le mot que je veux colorier2 var motBleu:String = "World";3

273

Page 297: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

Figure 14.20 – Le défaut est corrigé !

4 // Je cherche les positions adéquates pour la méthodesetTextFormat

5 // Position de début , grâce à la méthode indexOf de la classeString

6 var positionDebut:int = monSuperTexte.text.indexOf(motBleu);7 // Position de fin , en ajoutant la longueur du mot8 var positionFin:int = positionDebut + motBleu.length;9

10 // Je créé le format11 format = new TextFormat ();12 format.color = 0x0000ff;13 format.italic = false;1415 // J'applique le format aux positions que nous avons calculées16 monSuperTexte.setTextFormat(format , positionDebut , positionFin)

;

Ce qui nous donne la figure 14.21.

Figure 14.21 – Le mot World en bleu sans l’italique

Gestion du multi-ligne

Champ de texte à taille fixe

Nous allons maintenant découvrir comment gérer un champ de texte multi-lignes.Tout d’abord, il nous faut un texte plus long que « Hello World ! ». Vous pouvez trouverdu Lorem Ipsum (texte latin de remplissage) en ligne.

B

�Lorem Ipsum

Code web : 951790

1 var monSuperTexte:TextField = new TextField ();23 var format:TextFormat = new TextFormat("Arial", 14 , 0x000000);4 monSuperTexte.defaultTextFormat = format;

274

Page 298: Programmez en Actionscript 3

LA MISE EN FORME

56 // Texte suffisamment long7 monSuperTexte.text = "Lorem ipsum dolor sit amet , consectetur

adipiscing elit. In pharetra magna imperdiet elit pretium amalesuada nisl pellentesque.";

89 monSuperTexte.border = true;

1011 addChild(monSuperTexte);1213 // Centre14 monSuperTexte.x = (stage.stageWidth - monSuperTexte.width) / 2;15 monSuperTexte.y = (stage.stageHeight - monSuperTexte.height) /

2;

Pour l’instant, cela donne la figure 14.22.

Figure 14.22 – Le texte sort du champ de texte

Nous aimerions bien que le texte revienne automatiquement à la ligne. Pour cela, ilfaut mettre l’attribut multiline de la classe TextField à true pour activer les lignesmultiples, et l’attribut wordWrap à true également, pour activer le retour à la ligneautomatique :

1 monSuperTexte.multiline = true;2 monSuperTexte.wordWrap = true;

275

Page 299: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

Ce qui donne à l’écran la figure 14.23.

Figure 14.23 – Retour à la ligne automatique

Le texte dépasse désormais en bas du champ de texte. Toutefois, par défaut, on peutdéfiler dans le champ de texte avec la molette de la souris. Si vous voulez désactiver cecomportement, il faut mettre l’attribut mouseWheelEnabled de la classe TextField àfalse :

1 monSuperTexte.mouseWheelEnabled = false;

Le champ de texte est peut-être un peu trop étroit, augmentons sa largeur (avant lecode qui le centre) :

1 // Modifions la largeur du champ de texte2 monSuperTexte.width = 300;34 // Centre5 monSuperTexte.x = (stage.stageWidth - monSuperTexte.width) / 2;6 monSuperTexte.y = (stage.stageHeight - monSuperTexte.height) /

2;

Ce qui nous donne la figure 14.24.

Figure 14.24 – Largeur de 300 pixels

Aligner le texte

Il est possible de changer l’alignement du texte grâce à l’attribut align de la classeTextFormat. Cet attribut accepte les valeurs constantes définies dans la classe TextFormatAlign.Par exemple, pour que notre texte soit aligné au centre :

1 var format:TextFormat = new TextFormat("Arial", 14 , 0x000000);2 format.align = TextFormatAlign.CENTER; // Texte aligné au

centre3 monSuperTexte.defaultTextFormat = format;

Sans oublier de bien importer la classe TextFormatAlign au début du package :

276

Page 300: Programmez en Actionscript 3

LA MISE EN FORME

1 import flash.text.TextFormatAlign;

Cela nous donne la figure 14.25.

Figure 14.25 – Texte aligné au centre

Nous pouvons également centrer le texte à droite ou le justifier (voir figures 14.26 et14.27) :

1 // Texte aligné à droite2 format.align = TextFormatAlign.RIGHT;34 // Texte justifié5 format.align = TextFormatAlign.JUSTIFY;

Figure 14.26 – Texte aligné à droite

Figure 14.27 – Texte justifié

Un texte justifié est un texte dont les mots sont espacés de telle sorte que leslignes de chaque paragraphes remplissent toutes la largeur disponibles, saufles dernières lignes. Par exemple, cet « alignement » est souvent utilisé dansles journaux.

Champ de texte à hauteur dynamique

Il est possible d’adapter la hauteur du champ de texte à son texte s’il est multi-ligne,de la même manière que nous avions adapté la taille de notre champ de texte contenantle texte "Hello World!" au chapitre précédent : avec l’attribut autoSize de la classeTextField :

277

Page 301: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

1 monSuperTexte.autoSize = TextFieldAutoSize.LEFT;

Ce qui nous donne la figure 14.28.

Figure 14.28 – La hauteur est automatiquement adaptée au texte

Contrairement à ce que nous avons vu au chapitre précédent, seule la hauteurest adaptée au texte ; la largeur est fixe et c’est vous qui la définissez. Ceciest uniquement valable si le champ de texte est multi-lignes, quand l’attributmultiline du champ de texte est à true.

Retour à la ligne

Il est possible d’effectuer des retours à la ligne en écrivant \n dans le texte :

1 monSuperTexte.text = "Lorem ipsum dolor sit amet ,\ nconsecteturadipiscing elit.\nIn pharetra magna imperdiet elit pretium amalesuada nisl pellentesque.";

Ce qui nous donne la figure 14.29.

Figure 14.29 – Deux retours à la ligne

En HTML dans le texte

Introduction

Le langage HTML

Le langage HTML est utilisé sur les sites web pour structurer le texte, ajouter desparagraphes, des images, des liens hyper-texte. . . Le langage est un dérivé du langageXML, ce qui signifie que sa syntaxe est basée sur des balises.

Une balise dispose d’un nom, mis entre chevrons, et elle est répétée deux fois :

1 <nom ></nom >

278

Page 302: Programmez en Actionscript 3

EN HTML DANS LE TEXTE

La première balise <nom> est la balise ouvrante, et la dernière balise </nom> est labalise fermante.

Il ne faut pas oublier le slash / pour signifier qu’il s’agit d’une balise fermante.

Il est possible d’imbriquer des balises dans d’autres :

1 <balise1 >2 <balise2 ></balise2 >3 <balise3 >4 <balise4 ></balise4 >5 </balise3 >6 </balise1 >

Ici, la balise 4 est contenue dans la balise 3. Les balises 2 et 3 sont contenues dans labalise 1.

Attention à bien faire correspondre les noms des balises ouvrantes et fer-mantes !

Chaque balise ouvrante peut disposer d’attributs, ayant chacun un nom et une valeurentre guillemets doubles :

1 <nom attribut1="valeur" attribut2="valeur" ></nom >

Si une balise ne contient rien, on peut utiliser sa forme raccourcie :

1 <balise/>

Reprenons l’exemple des balises imbriquées pour voir ce que cela donnerait :

1 <balise1 >2 <balise2/>3 <balise3 >4 <balise4/>5 </balise3 >6 </balise1 >

Enfin, il est possible de mettre du texte brut à l’intérieur d’une balise :

1 <balise >Quel temps fera -t-il demain ?</balise >

On peut également mélanger des balises et du texte brut :

1 <balise1 >Salut !<balise2 >Comment va la famille ?</balise2 ></balise1 >

L’HTML est donc du XML avec des balises spéciales que nous allons découvrir unpeu plus loin.

279

Page 303: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

Seule une toute petite partie de ces balises est supportée par la classeTextField ! Nous ne verrons que celles-ci, mais sachez qu’il en existe beau-coup d’autres. Par ailleurs, il peut y avoir quelques différences au niveau desattributs par rapport au « vrai » HTML.

Du HTML dans nos champs de texte

Il est possible d’utiliser une version très simplifiée de l’HTML dans nos champs detexte en utilisant l’attribut htmlText de la classe TextField à la place de l’attributtext que nous avons utilisé jusque là :

1 // Activation du multi -ligne avant de sépicifier le texte HTML2 monSuperTexte.multiline = true;34 // Texte HTML5 monSuperTexte.htmlText = 'Lorem ipsum dolor sit amet ,

consectetur adipiscing elit. In pharetra magna imperdietelit pretium a malesuada nisl pellentesque.';

Il faut mettre l’attribut multiline à true avant de spécifier le texte HTML,sinon les retours à la ligne seront ignorés, même si vous mettez multilineà true ensuite.

Balises principales

Retour à la ligne

Pour effectuer un retour à la ligne dans un texte HTML, nous utiliserons la balise<br/> comme ceci :

1 monSuperTexte.htmlText = 'Lorem ipsum dolor sit amet ,consectetur adipiscing elit.In pharetra magna imperdiet elitpretium a malesuada nisl pellentesque.';

Ce qui nous donne la figure 14.30.

Figure 14.30 – Deux retours à la ligne

280

Page 304: Programmez en Actionscript 3

EN HTML DANS LE TEXTE

Paragraphe

Un paragraphe est un bloc de texte pouvant être aligné, qui se termine par un retour àla ligne. La balise à utiliser est la balise <p align="alignement">...</p>. L’attributalign peut prendre les valeurs suivantes :

– left pour aligner le texte à gauche.– right pour l’aligner à droite.– center pour le centrer.– justify pour le justifier.

Voici un exemple où notre texte est aligné à droite :

1 monSuperTexte.htmlText = '<p align=" right">Lorem ipsum dolorsit amet , consectetur adipiscing elit. In pharetra magnaimperdiet elit pretium a malesuada nisl pellentesque .</p>';

Ce qui nous donne la figure 14.31.

Figure 14.31 – Paragraphe de texte aligné à droite

Voici un autre exemple avec plusieurs paragraphes :

1 monSuperTexte.htmlText = '<p align=" right">Lorem ipsum dolorsit amet , consectetur adipiscing elit. In pharetra magnaimperdiet elit pretium a malesuada nisl pellentesque .</p>' +

2 '<p align ="left">Lorem ipsum dolor sit amet , consecteturadipiscing elit. In pharetra magna imperdiet elitpretium a malesuada nisl pellentesque .</p>';

Vous remarquerez que j’ai utilisé la concaténation de chaînes de caractèresavec l’opérateur + pour pouvoir écrire le texte en plusieurs lignes.

Nous avons alors à l’écran la figure 14.32.

Figure 14.32 – Deux paragraphes alignés différemment

281

Page 305: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

Lien

Un lien est une balise cliquable qui permet d’effectuer une action, le plus souventpermettant de changer de site web ou d’aller sur une autre page. Nous pouvons créerun lien à l’aide de la balise <a href="adresse" target="cible">nom du lien</a>.L’attribut href contient l’adresse vers laquelle pointe le lien. L’attribut target permetde spécifier la cible du lien, c’est à dire où l’adresse va s’ouvrir si l’on clique dessus. Ilpeut prendre les valeurs suivantes :

– _self : ouvre le lien dans la même page.– _blank : ouvre le lien dans une nouvelle fenêtre, ou un nouvel onglet si le navigateurle permet.

Bien sûr, ces valeurs n’ont d’intérêt que si votre animation Flash est incorporée dansun site web. Dans les autres cas (par exemple lorsque l’on teste le programme), celaouvrira une nouvelle fenêtre (ou un nouvel onglet) dans votre navigateur, même si lavaleur de l’attribut target est _self.

Voici un exemple de texte HTML disposant d’un lien pointant sur le Site du Zéro :

1 monSuperTexte.htmlText = 'Voulez -vous apprendre à partir de zéro ? <a href="http ://www.siteduzero.com/" target =" _blank">Cliquez ici !</a>';

Ce qui nous donne la figure 14.33.

Figure 14.33 – Une partie du texte est cliquable

Pour tester l’attribut target, vous pouvez ouvrir votre fichier swf dans votrenavigateur favori (à condition qu’il dispose du lecteur Flash). Vous verrezalors la page d’accueil du Site du Zéro se charger dans la même page ous’ouvrir dans une nouvelle fenêtre ou un nouvel onglet

Image

Il est possible de charger une image locale dans un champ de texte grâce à la ba-lise <img src="adresse" width="largeur" height="hauteur" align="alignement"hspace="espacement horizontal" vspace="espacement vertical"/>.

Essayons d’afficher Zozor dans notre champ de texte (voir figure 17.1). Tout d’abord,téléchargez l’image de Zozor et placez-la dans le dossier de votre fichier swf.

B

�Téléchargez Zozor

Code web : 634351

282

Page 306: Programmez en Actionscript 3

EN HTML DANS LE TEXTE

Figure 14.34 – Zozor, la mascotte du Site du Zéro

Ensuite, renommez l’image en zozor.png. Enfin, écrivons ce code pour charger l’imagedans notre texte HTML :

1 monSuperTexte.htmlText = 'Voici Zozor !<img src=" zozor.png"width="150" height ="150" align ="right"/>';

Ce qui nous donne la figure 14.35.

Figure 14.35 – Zozor est dans notre champ de texte !

Il est impossible d’aligner une image au centre. Il s’agit d’une limitation duchamp de texte, on ne peut rien y faire.

Si on met un texte plus long à côté de l’image, il sera détouré. Pour illustrer ceci,prenons un texte beaucoup plus long à côté de Zozor, et alignons-le en justifié. :

1 monSuperTexte.htmlText = '<img src=" zozor.png" width="150"height ="150" align="right"/>' +

2 '<p align =" justify">Lorem ipsum dolor sit amet , consecteturadipiscing elit. Sed pharetra semper ullamcorper.' +

3 'Sed at urna in elit mollis egestas eu id lectus. Integeraliquam urna vitae massa varius sed cursus maurisaliquam.' +

4 'Curabitur mauris massa , imperdiet a venenatis ac, vehiculaeu ipsum. Nulla turpis enim , tincidunt at imperdiet nec

,' +5 'mollis vitae nunc. Morbi viverra iaculis neque et

tincidunt. Nullam ultrices mi mi, eu pellentesque leo.</p>' +

283

Page 307: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

6 '<p align=" justify">Pellentesque sed felis nulla. Phaselluslaoreet sagittis ante at fringilla.' +

7 'Duis iaculis , mi sed bibendum posuere , nisi velit cursuselit , vitae tincidunt augue diam quis elit.' +

8 'Sed et nisi risus. Vestibulum lobortis auctor viverra.Mauris eleifend nisl ut orci ultricies eget egestas ' +

9 'ante lacinia. Pellentesque ut diam turpis.</p>';

Ce qui nous donne la figure 14.36.

Figure 14.36 – Cela ressemble à un article de journal n’est-ce pas ?

Liste à puces

Il est possible de faire des listes à puces grâce à la balise <li>...</li> répétéeautant de fois qu’il y a de lignes dans la liste :

1 monSuperTexte.htmlText = 'Voici une liste à puces :<li>Ligne 1</li><li>Ligne 2</li><li>Ligne 3</li >';

Ce qui nous donne la figure 14.37.

Figure 14.37 – Une liste à puce

284

Page 308: Programmez en Actionscript 3

EN HTML DANS LE TEXTE

Balises de mise en forme

Gras

Pour mettre du texte en gras, rien de plus simple ! Il suffit de l’encadrer d’une balise<b>...</b> (b comme bold, signifiant gras en anglais) comme ceci :

1 monSuperTexte.htmlText = 'Lorem ipsum dolor sit amet ,consectetur adipiscing elit. <b>In pharetra magna imperdietelit pretium a malesuada nisl pellentesque .</b>';

Ce qui nous donne la figure 14.38.

Figure 14.38 – La deuxième phrase est en gras.

Italique

Pour mettre le texte en italique, c’est tout aussi simple : seule la balise change. Cettefois, il s’agit de <i>...</i> :

1 monSuperTexte.htmlText = 'Lorem ipsum dolor sit amet ,consectetur adipiscing elit. <i>In pharetra magna imperdietelit pretium a malesuada nisl pellentesque .</i>';

Ce qui nous donne la figure 14.39.

Figure 14.39 – La deuxième phrase est en italique.

Souligner

Il est possible de souligner du texte grâce à la balise <u>...</u> comme ceci :

1 monSuperTexte.htmlText = 'Lorem ipsum dolor sit amet ,consectetur adipiscing elit. <u>In pharetra magna imperdietelit pretium a malesuada nisl pellentesque .</u>';

Ce qui nous donne la figure 14.40.

285

Page 309: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

Figure 14.40 – La deuxième phrase est soulignée.

Police, couleur et taille

Pour modifier la police de caractère, la couleur ou la taille des caractères dutexte, la balise <font face="police" color="couleur" size="taille">...</font>est tout indiquée. L’attribut face peut recevoir comme valeur le nom d’une policede caractère, comme par exemple face="Arial". L’attribut color permet de défi-nir une couleur en hexadécimal, précédée d’un dièse. Exemple de couleur orange :color="#ff8800". Enfin, l’attribut size modifie la taille des caractères du texte. Onpeut définir une taille absolue en pixels, ou une taille relative en ajoutant un + ou un -devant. Exemple de taille absolue : size="42". Exemple de taille relative : size="-5",ce qui signifie la taille actuelle du texte moins cinq pixels.

Par exemple, nous pouvons colorier une partie de notre texte en bleu :

1 monSuperTexte.htmlText = 'Lorem ipsum dolor sit amet ,consectetur adipiscing elit. <font color ="# 0000ff">Inpharetra magna imperdiet elit pretium a malesuada nislpellentesque .</font >';

Ce qui nous donne la figure 14.41.

Figure 14.41 – La deuxième phrase en bleu !

Nous aurions pu, au lieu de cela, augmenter la taille de notre texte :

1 monSuperTexte.htmlText = 'Lorem ipsum dolor sit amet ,consectetur adipiscing elit.<font size="42">In pharetramagna imperdiet elit pretium a malesuada nisl pellentesque.</font >';

Ce qui aurait donné la figure 14.42.

286

Page 310: Programmez en Actionscript 3

LES POLICES DE CARACTÈRES EMBARQUÉES

Figure 14.42 – La deuxième phrase en taille 42 cette fois-ci.

Les polices de caractères embarquées

Embarquer des polices

Pourquoi ?

Jusqu’à présent, les polices que nous utilisons sont des polices fournies par le systèmed’exploitation sur lequel notre programme est lancé. Si nous vouons appliquer une policeparticulière à notre texte, mais qu’elle n’est pas présente sur le système, la police pardéfaut sera utilisée. De plus, il nous est impossible de faire tourner notre texte ou dechanger son opacité, ce qui est un peu dommage, vous en conviendrez !

Cependant, il existe une solution à ces problèmes : les polices de caractères em-barquées ! Il s’agit d’inclure un fichier contenant une police directement dans notreprogramme : ainsi, le lecteur Flash peut la rendre directement à l’écran, même si lesystème de dispose pas de cette police en particulier ! De plus, cela permet de lisser lescaractères du texte afin de les rendre plus lisibles et plus attractifs.

Bien évidemment, embarquer des fichiers directement dans le programmeaugmente sa taille. Cela peut éventuellement être gênant, mais embarquerles polices de caractère présente tant d’avantages que l’on passera souventoutre cet unique inconvénient.

Préparation

Tout d’abord, il faut se munir du fichier de la police de caractère à embarquer dansnotre programme. Seules les polices de format TrueType sont reconnues, mais c’estle format le plus répandu, donc cela pose rarement problème.

287

Page 311: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

Par exemple, vous pouvez prendre une police installée sur votre système. Sur Windows,les polices sont situées dans le dossier C:\Windows\Fonts. Sur Mac, il peut y en avoir àplusieurs endroits : ~/Library/Fonts/, /Library/Fonts/, /Network/Library/Fonts/,/System/Library/Fonts/ ou /System Folder/Fonts/. Enfin, sur Linux, on peut lestrouver dans ces dossiers : /usr/share/fonts, /usr/local/share/fonts ou ~/.fonts.

Ou bien vous pouvez vous rendre sur un site proposant gratuitement des polices decaractères, comme FontSquirrel. Prenons par exemple la police Walkway (voir figure14.43). Téléchargez-la sur le site en cliquant sur le bouton DOWNLOAD TTF.

B

��

Téléchargez Walkway surFontSquirrelCode web : 187739

.

Figure 14.43 – Page de téléchargement de la police Walkway

Vous obtenez une archive zip, contenant différents fichiers de police (voir figure 14.44).

Nous aurons besoins de quatre de ces fichiers, un par style de notre police, comme lemontre le tableau suivant.

Style Nom du fichierNormal Walkway_SemiBold.ttfGras Walkway_UltraBold.ttfItalique Walkway_Oblique_SemiBold.ttfGras Italique Walkway_Oblique_UltraBold.ttf

288

Page 312: Programmez en Actionscript 3

LES POLICES DE CARACTÈRES EMBARQUÉES

Figure 14.44 – Contenu de l’archive téléchargée

289

Page 313: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

Vous pouvez incorporer une police de caractères dont il manque certainsstyles, mais vous ne pourrez pas utiliser les styles manquant. Par exemple, sivous n’avez pas le fichier pour l’italique, vous ne pourrez pas mettre de texteen italique avec cette police.

Dans le répertoire du projet, créez un dossier lib s’il n’est pas déjà présent, puis créezun dossier à l’intérieur nommé fonts. Enfin, extrayez les quatre fichiers dont nousavons besoin dans ce dossier (voir figure 14.45).

Figure 14.45 – Les fichiers de police prêts à l’emploi

Implémentation

Une fois que nos fichiers sont prêts, il faut les incorporer à notre programme, puisles enregistrer sous le nom "walkway" pour pouvoir utiliser la police de caractèreembarquée partout dans notre projet. Créez une nouvelle classe EmbedFonts (dansun fichier nommé EmbedFonts.as) à côté de la classe Main et collez-y le code completsuivant :

1 package2 {3 import flash.text.Font;45 /**6 * Gestionnaire des polices de caractères embarquées.7 * 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 :

8 * [Embed(source ='../lib/fonts/verdana.ttf ',fontName='Fverdana ',fontWeight =" normal",embedAsCFF=false)]

9 * private static var F_VERDANA:Class;

290

Page 314: Programmez en Actionscript 3

LES POLICES DE CARACTÈRES EMBARQUÉES

10 * puis enregistrez -la dans la méthode init() ainsi :11 * Font.registerFont(F_VERDANA);12 * @author Guillaume CHAU13 */14 public class EmbedFonts15 {1617 // Incorporation des polices de caractères1819 ///// Walkway20 // Normal21 [Embed(source='../ lib/fonts/Walkway_SemiBold.ttf',

fontName='walkway ',fontWeight="normal",embedAsCFF=false)]

22 private static var F_WALKWAY:Class;23 // Gras24 [Embed(source='../ lib/fonts/Walkway_UltraBold.ttf',

fontName='walkway ',fontWeight='bold',embedAsCFF=false)]

25 private static var F_WALKWAY_BOLD:Class;26 // Italique27 [Embed(source='../ lib/fonts/Walkway_Oblique_SemiBold.

ttf',fontName='walkway ',fontStyle='italic ',embedAsCFF=false)]

28 private static var F_WALKWAY_ITALIC:Class;29 // Gras Italique30 [Embed(source='../ lib/fonts/Walkway_Oblique_UltraBold.

ttf',fontName='walkway ',fontStyle='italic ',fontWeight='bold',embedAsCFF=false)]

31 private static var F_WALKWAY_BOLD_ITALIC:Class;3233 /**34 * Initialisation des polices de caractères. A appeler

une fois au lancement de l'application , afin queles polices soient prises en compte.

35 */36 public static function init():void37 {38 // Enregistrement des polices de caractères3940 Font.registerFont(F_WALKWAY);41 Font.registerFont(F_WALKWAY_BOLD);42 Font.registerFont(F_WALKWAY_BOLD_ITALIC);43 Font.registerFont(F_WALKWAY_ITALIC);44 }4546 }4748 }

291

Page 315: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

Vous pouvez l’afficher pour la copier en utilisant le code web ci-dessous.

B

�Classe EmbedFonts

Code web : 139762Nous commençons par importer chaque fichier au début de la classe grâce une instruc-tion spéciale, destinée au compilateur :

1 [Embed(source='../ lib/fonts/Walkway_SemiBold.ttf',fontName='walkway ',fontWeight="normal",embedAsCFF=false)]

J’ai l’impression d’avoir déjà vu quelque chose de similaire. . .

Très juste ! Nous avons déjà écrit une instruction spéciale dans notre classe Main pourrégler la taille et la couleur de fond de notre fenêtre :

1 [SWF(width="640",height="480",backgroundColor="#ffffff")]

Ici, le mot-clé SWF signifie que nous allons modifier des propriétés de notre programme.

Cette fois, le mot-clé Embed signifie que nous allons inclure un fichier dans notre pro-gramme. Les fichiers inclus sont directement contenus dans le programme : il sont doncutilisables à tout moment, étant chargés en même temps.

1 source='../ lib/fonts/Walkway_SemiBold.ttf'

L’attribut source indique le chemin du fichier à inclure, ici../lib/fonts/Walkway_SemiBold.ttf.

1 fontName='walkway '

L’attribut fontName spécifie le nom de la police de caractère, nom qui nous servira àl’utiliser ensuite.

1 fontWeight="normal"

Les attributs fontStyle (style) et fontWeight (épaisseur) permettent de préciser dequel style il s’agit. En combinant les deux, il est possible de créer un style grasitalique :

1 fontStyle='italic ',fontWeight='bold'

Enfin, le dernier attribut embedAsCFF est obligatoire et doit être mis à false. Celapermet d’éviter tout problème lors de l’utilisation de polices embarquées, à caused’un changement entre Flex SDK 3 et Flex SDK 4.

Sur la ligne suivante, nous déclarons un attribut privé de type Class qui contiendra lefichier de police embarquée :

1 private static var F_WALKWAY:Class;

Ce qui nous donne pour nos quatre fichiers :

292

Page 316: Programmez en Actionscript 3

LES POLICES DE CARACTÈRES EMBARQUÉES

1 ///// Walkway2 // Normal3 [Embed(source='../ lib/fonts/Walkway_SemiBold.ttf',fontName='

walkway ',fontWeight="normal",embedAsCFF=false)]4 private static var F_WALKWAY:Class;5 // Gras6 [Embed(source='../ lib/fonts/Walkway_UltraBold.ttf',fontName='

walkway ',fontWeight='bold',embedAsCFF=false)]7 private static var F_WALKWAY_BOLD:Class;8 // Italique9 [Embed(source='../ lib/fonts/Walkway_Oblique_SemiBold.ttf',

fontName='walkway ',fontStyle='italic ',embedAsCFF=false)]10 private static var F_WALKWAY_ITALIC:Class;11 // Gras Italique12 [Embed(source='../ lib/fonts/Walkway_Oblique_UltraBold.ttf',

fontName='walkway ',fontStyle='italic ',fontWeight='bold',embedAsCFF=false)]

13 private static var F_WALKWAY_BOLD_ITALIC:Class;

Une fois que tous les fichiers sont incorporés, nous déclarons une méthode publiquestatique init():void qui nous permet d’enregistrer la police de caractère, qui seraappelée au tout début de notre programme :

1 /**2 * Initialisation des polices de caractères. A appeler une fois

au lancement de l'application , afin que les polices soientprises en compte.

3 */4 public static function init():void5 {6 // Enregistrement des polices de caractères7 }

Dans cette méthode, nous enregistrons les classes contenant les fichiers des polices decaractères grâce à la méthode statique registerFont de la classe Font :

1 Font.registerFont(F_WALKWAY);

Ce qui donne :

1 /**2 * Initialisation des polices de caractères. A appeler une fois

au lancement de l'application , afin que les polices soientprises en compte.

3 */4 public static function init():void5 {6 // Enregistrement des polices de caractères78 Font.registerFont(F_WALKWAY);9 Font.registerFont(F_WALKWAY_BOLD);

10 Font.registerFont(F_WALKWAY_BOLD_ITALIC);

293

Page 317: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

11 Font.registerFont(F_WALKWAY_ITALIC);12 }

Enfin, dans notre classe Main, nous appelons la méthode statique init de notre classeEmbedFonts :

1 package2 {3 import flash.display.Sprite;4 import flash.display.StageAlign;5 import flash.display.StageScaleMode;6 import flash.events.Event;78 /**9 * Notre application embarque des polices de caractères

embarquées !10 */11 [SWF(width="640",height="480",backgroundColor="#ffffff")]1213 public class Main extends Sprite14 {1516 public function Main():void17 {18 if (stage)19 init();20 else21 addEventListener(Event.ADDED_TO_STAGE , init);22 }2324 private function init(e:Event = null):void25 {26 removeEventListener(Event.ADDED_TO_STAGE , init);27 // entry point2829 stage.scaleMode = StageScaleMode.NO_SCALE;30 stage.align = StageAlign.TOP_LEFT;3132 // Polices embarquées33 EmbedFonts.init();34 }35 }3637 }

Vous remarquerez qu’il n’est pas nécessaire d’importer la classe EmbedFontscar elle est dans le package principal (elle est placée dans le dossier racine dela source, ici src/).

294

Page 318: Programmez en Actionscript 3

LES POLICES DE CARACTÈRES EMBARQUÉES

Utilisation

Et voilà ! Notre police de caractère embarquée est prête à l’emploi ! Pour quenotre champ de texte utilise les polices de caractères embarquées au lieu des polices dusystème d’exploitation, il faut mettre l’attribut embedFonts de la classe TextField àtrue, sans oublier de changer le nom de la police utilisée :1 // Police utilisée : walkway2 var format:TextFormat = new TextFormat("walkway", 42 , 0x000000)

;3 monSuperTexte.defaultTextFormat = format;45 // On utilise les polices embarquées6 monSuperTexte.embedFonts = true;

Voici le code complet pour afficher un champ de texte avec une police de caractèresembarquée :1 // Enregistrement des polices embarquées2 EmbedFonts.init();34 // Création de l'instance du champ de texte5 var monSuperTexte:TextField = new TextField ();67 // Police utilisée : walkway8 var format:TextFormat = new TextFormat("walkway", 42 , 0x000000)

;9 monSuperTexte.defaultTextFormat = format;

1011 // On utilise les polices embarquées12 monSuperTexte.embedFonts = true;1314 // Taille automatique15 monSuperTexte.autoSize = TextFieldAutoSize.LEFT;1617 // Texte HTML18 monSuperTexte.htmlText = "Normal <b>Gras </b> <i>Italique </i> <b

><i>Gras Italique </i></b>";1920 // Ajout à la scène21 addChild(monSuperTexte);2223 // Alignement au centre24 monSuperTexte.x = (stage.stageWidth - monSuperTexte.width) / 2;25 monSuperTexte.y = (stage.stageHeight - monSuperTexte.height) /

2;

Ce qui nous donne à l’écran la figure 14.46.

Désormais, notre texte s’affichera avec cette police même si l’utilisateur ne l’a pasinstallée ; de plus, il est possible de rendre le texte transparent et de lui appliquer unerotation !

295

Page 319: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

Figure 14.46 – Notre police embarquée en action !

296

Page 320: Programmez en Actionscript 3

LES POLICES DE CARACTÈRES EMBARQUÉES

Rotation sur soi-même

Et si nous décidions de tourner notre champ de texte sur lui-même ? Disons 50˚ dansle sens anti-horaire ? C’est désormais possible, étant donné que nous utilisons notrepropre police embarquée. Commençons par écrire le code pour créer un champ de texteutilisant une police de caractères embarquée :

1 // Polices embarquées2 EmbedFonts.init();34 // Création du champ de texte5 var monSuperTexte:TextField = new TextField ();6 var format:TextFormat = new TextFormat("walkway", 50 , 0x000000)

;7 monSuperTexte.defaultTextFormat = format;8 monSuperTexte.embedFonts = true;9 monSuperTexte.autoSize = TextFieldAutoSize.LEFT;

10 monSuperTexte.text = "Tournez -moi !";11 addChild(monSuperTexte);1213 // Alignement au centre14 monSuperTexte.x = (stage.stageWidth - monSuperTexte.width) / 2;15 monSuperTexte.y = (stage.stageHeight - monSuperTexte.height) /

2;

Ce qui nous donne la figure 14.47.

Essayons d’effectuer une rotation à notre champ de texte :

1 // Rotation de 50˚ dans le sens anti -horaire2 monSuperTexte.rotation = - 50;

Ce qui nous donne la figure 14.48.

Ce n’est pas exactement ce que nous voulons accomplir ! En effet, l’objet tourne toujourspar rapport à son origine, en haut à gauche : cela explique que le champ de texte soittourné par rapport à la lettre « T ». Malheureusement, nous ne pouvons pas modifierdirectement l’origine d’un objet d’affichage.

Il est néanmoins possible de changer artificiellement l’origine de l’objet en question,comme nous l’avons vu dans le chapitre précédent, en l’ajoutant dans un conteneurintermédiaire de classe Sprite que j’appellerai « la boîte » :

1 // Conteneur intermédiaire2 var boite:Sprite = new Sprite ();3 addChild(boite);45 // Création du champ de texte6 var monSuperTexte:TextField = new TextField ();7 var format:TextFormat = new TextFormat("walkway", 50 , 0x000000)

;8 monSuperTexte.defaultTextFormat = format;9 monSuperTexte.embedFonts = true;

297

Page 321: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

Figure 14.47 – Notre champ de texte à tourner

298

Page 322: Programmez en Actionscript 3

LES POLICES DE CARACTÈRES EMBARQUÉES

Figure 14.48 – Rotation par rapport à l’origine de l’objet

299

Page 323: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

10 monSuperTexte.autoSize = TextFieldAutoSize.LEFT;11 monSuperTexte.text = "Tournez -moi !";1213 // On ajoute le champ de texte dans le conteneur14 boite.addChild(monSuperTexte);

Une fois que le champ de texte est dans la boîte, on déplace le champ de texte de lamoitié de sa taille, à la fois vers le haut et vers la gauche, ainsi l’origine de la boite setrouvera au centre du champ de texte (voir figure 14.49).

Figure 14.49 – Origine de la boite centrée sur le champ de texte

Ainsi, l’origine de la boite se retrouve au centre du champ de texte. Si on fait abstractionde la boîte, l’origine de notre objet est le centre du champ de texte, donc il tournerapar rapport à son centre ! Voici le code de cette opération :

1 // On modifie artificiellement l'origine en la plaçant aucentre du champ de texte :

2 monSuperTexte.x = -monSuperTexte.width / 2;3 monSuperTexte.y = -monSuperTexte.height / 2;

Enfin, on applique toutes les transformations à la boîte à la place de les appliquer auchamp de texte, comme si la boîte était le champ de texte lui-même :

1 // Alignement au centre2 // On aligne le conteneur au lieu du champ de texte3 boite.x = stage.stageWidth / 2;4 boite.y = stage.stageHeight / 2;56 // Rotation de 50˚ dans le sens anti -horaire7 // On tourne le conteneur au lieu du champ de texte8 boite.rotation = - 50;

Ce qui nous donne ce que nous voulons (voir figure 14.50).

Enfin ! Notre champ de texte a consenti à tourner sur lui-même par rapport à soncentre ! Vous serez souvent amené à utiliser cette méthode, par exemple si vous voulezanimer une image en la faisant tourner sur elle-même, tout en la déplaçant. . .

Vous auriez peut-être pensé à recentrer le champ de texte après chaque rota-tion, mais, croyez-moi, il est beaucoup plus simple de passer par un conteneurintermédiaire.

300

Page 324: Programmez en Actionscript 3

LES POLICES DE CARACTÈRES EMBARQUÉES

Figure 14.50 – Le texte tourne sur lui-même !

301

Page 325: Programmez en Actionscript 3

CHAPITRE 14. AFFICHER DU TEXTE

En résumé– La classe TextField permet d’afficher du texte à l’écran. Il est possible de manipuler

la sélection du texte.– On peut centrer un objet grâce aux propriétés de la scène principale de classe Stage.– La classe TextFormat permet de mettre en forme tout ou des portions du texte,c’est-à-dire change la police, la taille, la couleur. . .

– Il est possible d’afficher du texte structuré enHTML simplifié avec l’attribut htmlText.– Il est très souvent intéressant d’embarquer les polices de caractères dans l’application,sans oublier de mettre l’attribut embedFonts à true.

– Utiliser un conteneur intermédiaire permet d’effectuer la rotation d’un objetautour de son centre (ou d’un autre point que son origine initiale).

302

Page 326: Programmez en Actionscript 3

Chapitre 15Dessiner avec l’Actionscript

Difficulté :

Dans ce chapitre, nous allons apprendre à dessiner directement depuis l’Actionscript ! Jesuis certain que beaucoup parmi vous attendaient ce moment depuis fort longtemps, c’estpourquoi nous essaierons de présenter un maximum de notions tout en prenant le temps debien les expliquer. Nous présenterons en premier la classe Graphics qui est à l’origine detout tracé en Actionscript. Puis nous présenterons alors les différentes méthodes de dessinque possède cette classe.

Enfin, je vous proposerais un petit exercice où nous réaliserons ensemble une illustrationd’un mouton. Ce sera alors l’occasion de revenir sur ces méthodes de dessin et mieuxcomprendre toute la philosophie qui se cache derrière le dessin en Flash !

303

Page 327: Programmez en Actionscript 3

CHAPITRE 15. DESSINER AVEC L’ACTIONSCRIPT

L’objet Graphics

Introduction

Une propriété de type Graphics

Nous avons vu précédemment qu’il existait différents types d’objets d’affichage.Parmi eux, certains possèdent déjà tout le nécessaire pour dessiner. Il s’agit des classesShape, Sprite et MovieClip (voir figure 15.1) !

Figure 15.1 – La classe Shape dans l’arbre des classes d’affichage

Ce qui les différencie des autres classes c’est que celles-ci ont un attribut très particulier :une instance de la classe Graphics. En réalité, c’est cette dernière classe qui disposede l’ensemble des méthodes permettant de tracer différentes formes. Ainsi, en déclarantdes objets de type Shape, Sprite ou MovieClip, vous pourrez dessiner à l’intérieur deceux-ci. En particulier, la classe Shape est spécialement faite pour cela puisque celle-cine contient que cet attribut et l’accesseur correspondant comme vous pouvez le voir àla figure 15.2.

Cette classe est allégée, ce qui implique de meilleures performances, mais une instancede la classe Shape ne peut pas contenir d’enfants et elle n’est pas interactive (il estimpossible de savoir si l’utilisateur clique dessus).

Pourquoi ne pas utiliser directement l’objet Graphics ?

304

Page 328: Programmez en Actionscript 3

L’OBJET GRAPHICS

Figure 15.2 – La classe Shape exclusivement utilisé pour sa propriété graphics

Il se peut que vous vous soyez déjà demandé pourquoi ne pas créer directement uneoccurrence de la classe Graphics et utiliser ainsi ses différentes méthodes de dessin. Enréalité, l’Actionscript favorise l’utilisation des sous-classes de DisplayObject dontn’hérite pas la classe Graphics. C’est pourquoi celle-ci est non instanciable : vous nepourrez donc pas utiliser la syntaxe « new Graphics() » et vous serez donc obligés depasser par l’utilisation de l’une des trois classes décrites plus haut. De plus, elle estde type final, ce qui signifie que l’on ne peut pas créer de sous-classes héritant de laclasse Graphics.

Je vous invite donc à créer une instance de la classe Shape que nous utiliserons dansla suite :

1 var monDessin:Shape = new Shape();

Dessin vectoriel

La classe Graphics est utilisée pour créer des dessins vectoriels ! Ce terme est peut-être nouveau pour vous, mais ne vous inquiétez pas, nous allons ici présenter ce quidifférencie ce type d’images par rapport aux images « bitmap ». Vous ne vous êtesjamais demandés comment les images étaient stockées à l’intérieur de votre ordinateur ?En fait le stockage des images peut être réalisé de deux manières différentes. Lorsquel’on parle d’images « bitmap », celles-ci sont enregistrées à partir des couleurs dechacun des pixels. En revanche, dans les images vectorielles, ce sont les formes enelles-mêmes qui sont sauvegardées. Cela fait donc une énorme différence lors de lalecture du fichier et de l’affichage à l’écran.

Pour mieux comprendre ce dont il s’agit, nous allons prendre l’exemple de la figure15.3.

Figure 15.3 – Image de base

Cette image est quelconque et pourrait très bien être enregistrée en tant qu’image« bitmap » ou vectorielle. L’inconvénient du format « bitmap » est justement qu’il

305

Page 329: Programmez en Actionscript 3

CHAPITRE 15. DESSINER AVEC L’ACTIONSCRIPT

retient des pixels. Ainsi, si vous ne respectez plus les dimensions des pixels, l’image vaêtre déformée. Je m’explique ; imaginez que vous ayez besoin, pour une raison quel-conque, d’agrandir votre image. Les pixels vont donc être redimensionnés et l’imagen’aura plus l’aspect lisse qu’elle avait au départ. Au contraire, une image vectorielleest définie à partir de formes. Ainsi, lorsque celle-ci va être redimensionnée, l’affichagesera adapté pour correspondre à nouveau à la forme désirée.

Voyez plutôt la différence à la figure 15.4 entre l’image « bitmap » à gauche etl’image vectorielle à droite, toutes les deux redimensionnées à 300%.

Figure 15.4 – Redimensionnement de l’image de base

Dans ce chapitre, nous allons donc parler exclusivement de dessin vectoriel, l’un desatouts de cette technologie Flash !

Des contours et des remplissages

Le principe

Si vous avez déjà utilisé des classes de dessin dans d’autres langages de programmation,vous allez voir qu’ici le principe est assez différent. Avant d’entrer plus avant dans lesdétails, je vous invite à découvrir les différents termes que nous serons amenés à utiliserdans la suite de ce chapitre. Pour cela je vous propose tout d’abord un petit dessind’exemple à la figure 15.5.

Figure 15.5 – Composition d’un élément graphique

Dans cet exemple, nous pouvons voir une bulle de pensée comme on en trouve dans lesbandes dessinées. Cette bulle est composée de 4 objets : un « nuage » et trois ovales.Ces objets correspondent à des tracés différents qu’il faudrait réaliser les uns après lesautres. Chaque tracé est donc défini de la façon suivante :

– Le remplissage : surface représentée en bleu sur le dessin précédent.– Le contour : ligne qui délimite le remplissage.

306

Page 330: Programmez en Actionscript 3

L’OBJET GRAPHICS

– La ligne : trait visible qui suit le contour et pouvant avoir différentes apparences.

Ainsi, pour réaliser un tracé en Flash, il nous faut définir le contour de celui-ci enindiquant quel style adopter pour le remplissage et la ligne.

Définir le style des lignes

Tout d’abord, veuillez noter que nous parlons ici de lignes et non de contours, il s’agitdonc uniquement du côté esthétique des traits qui effectivement suivent le contour.Pour définir le style des lignes, nous utiliserons la méthode lineStyle() de la classeGraphics. Cette méthode possède beaucoup de paramètres, mais tous sont facultatifs.C’est pourquoi, je ne vous parlerai ici que des trois premiers qui sont les plus intéres-sants. Le premier sert à définir la largeur de la ligne, le deuxième sa couleur, et enfinle dernier permet de préciser l’opacité de celle-ci. Voici un exemple dans lequel nousdéfinissons des lignes de largeur 2, de couleur noire et transparentes à 50% :1 monDessin.graphics.lineStyle(2, 0x000000 , 0.5);

Comme nous l’avons dit, la méthode lineStyle() ne possède que des paramètresfacultatifs. Ainsi, si vous ne souhaitez pas de lignes sur votre tracé mais uniquementun remplissage, il vous suffit d’utiliser cette méthode sans paramètres, comme ceci :1 monDessin.graphics.lineStyle ();

Définir un remplissage

Contrairement aux lignes, les remplissages nécessitent l’utilisation de deux méthodes :beginFill() et endFill(). La première permet de définir les différentes caractéris-tiques du remplissage, à savoir sa couleur et son opacité. En revanche, dans notrecas de figure, la couleur est un paramètre obligatoire et ne peut donc pas être omise.Voici par exemple comment définir une couleur blanche au remplissage :1 monDessin.graphics.beginFill(0xFFFFFF);

L’utilisation de la seconde méthode est justifiée par la définition même d’un rem-plissage. En effet, pour remplir l’intérieur d’un contour, celui-ci doit être fermé ! Laméthode endFill() sert donc à refermer un contour, pour pouvoir lui appliquerun remplissage. Ainsi, si lors du tracé de votre contour, le point final n’est pas iden-tique au premier, une ligne droite sera alors tracée entre ces deux points pour fermerle contour. Cette méthode endFill() ne prend aucun paramètre et s’utilise donc sim-plement de la manière suivante :1 monDessin.graphics.endFill ();

Notez que la méthode beginFill() doit être appelée avant endFill(), etque la définition du contour s’effectue entre ces instructions. Sachez éga-lement que tout tracé effectué à l’extérieur de ces deux instructions seracomposé uniquement de lignes et donc sera sans remplissage.

307

Page 331: Programmez en Actionscript 3

CHAPITRE 15. DESSINER AVEC L’ACTIONSCRIPT

Dessinez, c’est gagné !

Ça y est, vous allez enfin pouvoir dessiner en Actionscript ! Nous allons maintenantvoir quelles sont les différentes méthodes de la classe Graphics, et apprendre à nousen servir. Ensuite, nous réaliserons un petit exercice à la fin de ce chapitre qui devraitvous aider à mieux utiliser cette classe.

Les lignes et les courbes

Une histoire de curseur

À l’origine, l’ensemble des tracés en Flash étaient conçus à l’intérieur du logiciel FlashProfessionnal. Ceux-ci étaient donc réalisés graphiquement à l’aide de votre souris,aussi connue sous le nom de curseur. Depuis l’arrivée de l’Actionscript 3, il n’estplus nécessaire de posséder le logiciel pour pouvoir effectuer des tracés. En effet, il estmaintenant possible de faire exactement la même chose grâce au code. Cependant, lesinstructions s’exécutent en conservant la logique utilisée pour dessiner dans le logiciel.

Ainsi, lorsque vous dessinerez en Actionscript, vous devrez imaginez les différentsgestes que vous réaliseriez avec la souris de votre ordinateur. Par exemple, si voussouhaitez tracer une ligne, vous déplacerez d’abord votre curseur à l’endroit où vousvoudrez démarrer celle-ci, puis vous la tracerez. Une fois celle-ci dessinée, votre curseurse trouverait alors à l’autre extrémité de la ligne. Vous pourriez alors continuer votretracé à partir du même point ou bien déplacer avant votre curseur vers une autre partiede l’écran.

Revenons maintenant à ce qui nous intéresse : l’Actionscript ! Lorsque vous dessinezgrâce à la classe Graphics, vous disposez un curseur fictif que vous pouvez déplacern’importe où sur l’écran. Pour modifier la position de celui-ci, vous devez utiliser laméthode moveTo() en spécifiant le nouvel emplacement, comme ci-dessous :

1 var _x:Number = 25;2 var _y:Number = 50;3 monDessin.graphics.moveTo(_x , _y);

Lorsque vous tracerez des lignes et des courbes, rappelez-vous que vous devezau préalable modifier la position de votre curseur. N’oubliez pas égalementqu’après un tracé, sa position est automatiquement mise à jour, ce qui facilitela succession de diverses lignes et courbes.

Les lignes droites

Pour réaliser des contours, il est possible de créer des lignes droites. Pour cela, laclasse Graphics dispose de la méthode lineTo(), qui trace une ligne entre la positionactuelle du curseur et le nouveau point spécifié en paramètre. Voici un exemple qui

308

Page 332: Programmez en Actionscript 3

DESSINEZ, C’EST GAGNÉ !

permet de tracer une droite horizontale d’épaisseur 10 entre les points de coordonnées(10,10) et (10,100) :

1 monDessin.graphics.lineStyle(10 , 0x000000);2 monDessin.graphics.moveTo(10 , 10);3 monDessin.graphics.lineTo(200 , 10);

Si vous lancez votre projet, vous verrez apparaître la belle ligne visible à la figure 15.6.

Figure 15.6 – Une ligne

Remarquez qu’ici nous n’avons pas utilisé les méthodes beginFill() etendFill(), nous avons donc tracé un contour sans remplissage, en utili-sant uniquement un style de ligne. Notez également que nous avons d’aborddéplacé notre curseur avant de dessiner la ligne.

À la suite de votre ligne horizontale, vous pourriez très bien continuer le tracé de votrecontour avec une ligne verticale par exemple :

1 monDessin.graphics.lineTo(200 , 200); // Le curseur est à laposition (200 ,10) avant l'instruction

Les courbes

Les lignes droites c’est bien, mais celles-ci sont vite limitées lorsqu’il s’agit de réaliserun dessin complexe avec des formes arrondies. Par conséquent, il a été mis en placece qu’on appelle les courbes de Bézier ! Le principe de ces courbes est d’utiliser unpoint de contrôle en plus des deux points d’ancrage. Ce point de contrôle sert àdéfinir la courbure de la ligne en direction de ce point. Pour mieux comprendre l’effetde celui-ci sur la courbe, je vous propose un exemple :

1 monDessin.graphics.lineStyle(4, 0x000000);2 monDessin.graphics.beginFill(0x55BBFF);3 monDessin.graphics.moveTo(10 , 100);4 monDessin.graphics.curveTo(100 , 10, 200 , 100);5 monDessin.graphics.endFill ();

Ici, la méthode curveTo() prend deux paires de coordonnées en paramètres. La pre-mière correspond au point de contrôle et la seconde au point d’ancrage final.Voyez plutôt à la figure 15.7 le résultat du tracé où j’ai ajouté les trois points.

Dans l’exemple précédent, nous avons défini un remplissage à l’aide de laméthode beginFill(). Vous constaterez alors que le contour a été au-tomatiquement refermé par une ligne droite lors de l’appel de la méthodeendFill().

309

Page 333: Programmez en Actionscript 3

CHAPITRE 15. DESSINER AVEC L’ACTIONSCRIPT

Figure 15.7 – Une courbe décrite par trois points

Les formes prédéfinies

Pour les formes géométriques particulières, il existe des méthodes permettantde simplifier leur tracé. Nous pouvons notamment citer les cercles, les ellipses et lesrectangles.

Les formes elliptiques

Lorsqu’on parle de formes elliptiques, on inclut généralement les cercles et les el-lipses. Nous allons donc voir à présent comment tracer chacune de ces formes. Toutd’abord, occupons-nous des cercles. Nous disposons pour cela d’une méthode nomméedrawCircle(), dans laquelle nous devons spécifier les coordonnées x et y du centre ducercle ainsi que le rayon r de celui-ci :

1 monDessin.graphics.drawCircle(x, y, r);

Pour les ellipses, la méthode a utiliser est drawEllipse(). Celle-ci prend cette foisquatre paramètres différents : la largeur et la hauteur de l’ellipse ainsi que les coor-données x et y du coin supérieur gauche de la zone à tracer :

1 monDessin.graphics.drawEllipse(x, y, largeur , hauteur);

Nous verrons dans l’exercice à venir comment utiliser ces fonctions, mais je vous invitegrandement à faire des tests de votre côté pour bien voir l’influence des différentsparamètres. N’oubliez pas également de définir un style de ligne ou un remplissageavant l’utilisation de telles méthodes.

Les rectangles

En plus des formes elliptiques, la classe Graphics vous permet de tracer des formesrectangulaires. La méthode drawRect() est ainsi définie exactement de la mêmefaçon que drawEllipse(), à la seule différence qu’elle trace cette fois un rectangle.L’instruction ci-dessous ne présente donc aucune surprise :

1 monDessin.graphics.drawRect(x, y, largeur , hauteur);

Il se peut que vous ayez besoin, à un moment ou à un autre, de tracer un rec-tangle dont les angles sont arrondis. Pour cela, vous disposez également de la méthodedrawRoundRect(), où vous devrez renseigner en plus la valeur de l’arrondi :

310

Page 334: Programmez en Actionscript 3

DESSINEZ, C’EST GAGNÉ !

1 monDessin.graphics.drawRoundRect(x, y, largeur , hauteur ,arrondi);

La méthode drawRoundRect() prend en réalité un sixième paramètre si vousdésirez des arrondis non uniformes en hauteur et en largeur. Ainsi, le cinquièmeparamètre définit la largeur des arrondis et le sixième leur hauteur.

Techniques avancées

Dessiner une trajectoire

Lorsque vous créerez des contours à l’aide des méthodes lineTo() et curveTo(), ilest probable que vous ayez une série d’instructions similaires afin de parcourir l’en-semble de votre contour. C’est pourquoi, il existe une méthode drawPath() qui permetd’effectuer l’ensemble de ces tracés en une seule instruction. Cette méthode prend doncen paramètres deux tableaux de type Vector.<int> et Vector.<Number>. Le premierpermet de définir le type de commande, quant au second, il contient l’ensemble des co-ordonnées des différents points d’ancrage et points de contrôle. En ce qui concerneles commandes, celles-ci sont définies comme suit :

– 1 → moveTo().– 2 → lineTo().– 3 → curveTo().

Pour mieux comprendre ce dont il est question, je vous propose de prendre l’exemplesuivant :1 monDessin.graphics.lineStyle(2, 0x000000);2 monDessin.graphics.moveTo(0, 0);3 monDessin.graphics.lineTo(100 , 0);4 monDessin.graphics.curveTo(200 , 0, 200 , 100);

L’ensemble de ces tracés pourrait également être réalisés grâce à la méthode drawPath()de la façon suivante :1 var commandes:Vector.<int > = new Vector.<int >();2 commandes.push(1, 2, 3);3 var coordonnees:Vector.<Number > = new Vector.<Number >();4 coordonnees.push(0, 0);5 coordonnees.push(100 , 0);6 coordonnees.push(200 , 0, 200 , 100);7 monDessin.graphics.lineStyle(2, 0x000000);8 mouton.graphics.drawPath(commandes , coordonnees);

Vous remarquerez que nous aurions pu ajouter l’ensemble des coordonnées enune seule instruction avec la méthode push(). Néanmoins, pour garder unmaximum de lisibilité, je vous conseille de les ajouter par commande, commesi vous utilisiez directement les méthodes correspondantes.

311

Page 335: Programmez en Actionscript 3

CHAPITRE 15. DESSINER AVEC L’ACTIONSCRIPT

N’est-ce pas plus compliqué et plus long au final ?

Je vous avoue que cette écriture fait peur et est au final plus longue à écrire que laversion originale. Cependant, mettez-vous en tête que cette nouvelle version s’exécuteplus rapidement que la précédente. Ceci vient du fait que le tracé à l’écran se fait enune seule fois contrairement au premier code où il faut retracer à chaque instruction.Utilisez donc cette méthode au maximum dès que vous le pouvez.

Superposition de remplissages

Lorsque vous tracez différents contours, ceux-ci peuvent être amenés à se superposer.Dans ce cas, il est alors possible de supprimer le remplissage dans la zone de super-position. Pour cela, définissez les deux contours à l’intérieur d’un même remplissage,c’est-à-dire sans fermeture du contour entre les deux par la fonction endFill(). Pourvous montrer l’effet créé, voici le code que je vous invite à tester :

1 monDessin.graphics.lineStyle(4, 0x000000);2 monDessin.graphics.beginFill(0x0000FF);3 monDessin.graphics.drawCircle(100 , 100 , 50);4 monDessin.graphics.drawCircle(175 , 100 , 50);5 monDessin.graphics.endFill ();

Vous verrez alors deux disques de couleur bleu dont l’intersection est non rempliecomme sur la figure 15.8.

Figure 15.8 – Exclusion des deux cercles

Un petit pas vers la 3D

Avant de terminer la théorie sur cette classe Graphics, je vais rapidement vous parlerd’une méthode un peu spéciale : drawTriangles(). Comme son nom l’indique, cetteméthode permet de dessiner des triangles. Cette manière de découper une géométrieen faces triangulaires, est une pratique courante lorsqu’il s’agit de 3D. Cela permetnotamment de pouvoir déformer une image en la divisant sur plusieurs faces orientéesdifféremment. Ainsi, il est possible d’appliquer ce que l’on appelle une texture, sur unobjet 3D modélisé à partir d’une multitude de faces.

Dans ce chapitre, nous n’aborderons pas toutes ces techniques qui sont un peu tropavancées pour nous. Toutefois, je vais vous présenter tout de même comment utiliser

312

Page 336: Programmez en Actionscript 3

DESSINEZ, C’EST GAGNÉ !

cette méthode drawTriangles() avec des lignes et des remplissages. Le principe estde créer une liste de points que nous nommerons des sommets, à l’intérieur d’untableau de type Vector.<Number> contenant leurs coordonnées. Ces sommets sontalors numérotés dans l’ordre de leur déclaration avec pour premier indice 0. Un secondtableau de type Vector.<int> permet ensuite créer des triangles en reliant les sommetspar trois. Ainsi, le premier triangle est généralement constitué des sommets 0, 1 et 2.

Conscient que tout cela est certainement encore flou dans votre tête, je vous proposeun petit exemple où nous aurons 5 sommets. Ensuite, nous allons créer quatre trianglescomposés respectivement des sommets (0,1,2), (1,2,3), (2,3,4) et enfin (2,4,5). Voici lecode correspondant à ces manipulations :

1 var sommets:Vector.<Number > = Vector.<Number >([10, 10 , 10 , 100 ,100 , 10, 100 , 100 , 190 , 100 , 190 , 10]);

2 var indices:Vector.<int > = Vector.<int >([0, 1, 2, 1, 2, 3, 2, 3, 4, 2, 4, 5]);

3 monDessin.graphics.lineStyle(4, 0x000000);4 monDessin.graphics.beginFill(0xAA00FF);5 monDessin.graphics.drawTriangles(sommets , indices);6 monDessin.graphics.endFill ();

Vous verrez donc apparaître nos quatre triangles formant ensemble un rectangle quipourrait être la base de la modélisation d’un intérieur quelconque par exemple. Voyezà la figure 15.9 l’affichage correspondant, où j’ai volontairement rajouté les indices dessommets pour que vous puissiez mieux comprendre.

Figure 15.9 – Conception à base de triangles

Cette méthode drawTriangles() est principalement utilisé pour la 3D, c’estpourquoi il n’est pas nécessaire que vous compreniez son fonctionnementdans le détail. Néanmoins, pour les intéressés, un troisième paramètre per-met de créer de l’UV Mapping. Ainsi, vous pouvez renseigner un vecteurVector.<Number> de coordonnées UV pour appliquer une texture à chaqueface. Pour chaque sommet de triangles, vous devez alors faire correspondreun point d’une image en coordonnées UV. Ces coordonnées UV sont alorsstandardisées à (0,0) pour le coin supérieur gauche de l’image bitmap et(1,1) pour le coin inférieur droit. Ne pouvant pas m’attarder davantage surle sujet, j’invite les intéressés à se rendre dans la rubrique correspondante dela documentation officielle.

313

Page 337: Programmez en Actionscript 3

CHAPITRE 15. DESSINER AVEC L’ACTIONSCRIPT

B

��

DocumentationdrawTriangles()Code web : 924409

Exercice : Dessine-moi un mouton

Conception du dessin

Introduction

Dans cet exercice, nous allons réaliser une petite illustration représentant un mouton,pas à pas.

Avant de nous lancer tête baissée, je vous invite à préparer votre projet afin d’obtenir unrésultat similaire au mien à la fin de l’exercice. Vous allez donc changer les dimensionsde votre scène principale pour que celle-ci fasse 280 x 220 pixels. Vous pouvez laisserla couleur d’arrière-plan en blanc étant donné que nous allons redéfinir un fond danspeu de temps. Nous allons également déclarer deux variables _x et _y pour contrôlerla position du mouton, puis une variable Mouton de type Shape qui nous servira àeffectuer l’ensemble de nos tracés. Enfin, n’oubliez pas d’ajouter notre Mouton à notreconteneur principal grâce à la fonction addChild().

Voici donc notre classe Main au début de l’exercice :

1 package2 {3 import flash.display.Sprite;4 import flash.events.Event;5 import flash.display.Shape;67 public class Main extends Sprite8 {9 private var _x:int;

10 private var _y:int;1112 public function Main():void13 {14 if (stage) init();15 else addEventListener(Event.ADDED_TO_STAGE , init);16 }1718 private function init(e:Event = null):void19 {20 removeEventListener(Event.ADDED_TO_STAGE , init);21 // entry point22 _x = 160;23 _y = 40;24 var mouton:Shape = new Shape();25

314

Page 338: Programmez en Actionscript 3

EXERCICE : DESSINE-MOI UN MOUTON

26 this.addChild(mouton);27 }2829 }3031 }

Le fond

Afin de faire ressortir notre mouton blanc, nous allons tracer une zone rectangulairede couleur bleue comme arrière-plan de notre dessin. Pour cela, nous nous servirons dela fonction drawRoundRect() qui permet d’obtenir un rectangle aux coins arrondis, cequi rendra l’ensemble plus esthétique. Ici, aucune difficulté, nous aurons donc le codesuivant :

1 // Fond2 mouton.graphics.beginFill(0x10879D);3 mouton.graphics.drawRoundRect(0, 0, 280 , 220 , 40 , 40);4 mouton.graphics.endFill ();

Le corps

La réalisation du corps du mouton est certainement la partie la plus longue et fastidieusede cet exercice. Néanmoins, j’ai déjà effectué l’opération, vous n’aurez donc qu’à suivremes instructions. Pour dessiner le corps du mouton, nous allons dans un premier tempsdéfinir les différents paramètres de remplissage et de contour. Puis, nous commenceronspar tracer une courbe de Bézier qui sera le point de départ pour la suite. Voici doncun premier bout de code :

1 // Corps2 mouton.graphics.lineStyle(4, 0x3A281E , 1.0);3 mouton.graphics.beginFill(0xFFFFFF);4 mouton.graphics.moveTo(_x, _y);5 mouton.graphics.curveTo(_x + 20 , _y - 20, _x + 40, _y);6 mouton.graphics.endFill ();

Comme vous l’imaginez, nous ne pouvons pas dessiner l’intégralité du corps du moutond’une seule traite. Ainsi, comme vous pouvez le voir aux figures 15.10 et 15.11, il fautprocéder étape par étape.

Tracer chaque « bosse » du corps est une étape qui peut être extrêmement longuesuivant vos talents en dessin. De plus, il est peu probable que vous obteniez rapidementun rendu proche du mien, c’est pourquoi je vous épargne cette tâche périlleuse et jevous propose déjà le code final permettant de dessiner l’intégralité du corps :

1 // Corps2 mouton.graphics.lineStyle(4, 0x3A281E , 1.0);3 mouton.graphics.beginFill(0xFFFFFF);

315

Page 339: Programmez en Actionscript 3

CHAPITRE 15. DESSINER AVEC L’ACTIONSCRIPT

Figure 15.10 – Mise en place du premier arrondi

Figure 15.11 – Création pas à pas du corps

4 mouton.graphics.moveTo(_x, _y);5 mouton.graphics.curveTo(_x + 20 , _y - 20, _x + 40, _y);6 mouton.graphics.curveTo(_x + 60 , _y - 10, _x + 70, _y + 10);7 mouton.graphics.curveTo(_x + 90 , _y + 10, _x + 90, _y + 30);8 mouton.graphics.curveTo(_x + 110 , _y + 40, _x + 100 , _y + 60);9 mouton.graphics.curveTo(_x + 120 , _y + 80, _x + 100 , _y + 90);

10 mouton.graphics.curveTo(_x + 110 , _y + 110 , _x + 90, _y + 110);11 mouton.graphics.curveTo(_x + 80 , _y + 140 , _x + 60, _y + 120);12 mouton.graphics.curveTo(_x + 40 , _y + 150 , _x + 20, _y + 130);13 mouton.graphics.curveTo(_x, _y + 150 , _x -20 , _y + 130);14 mouton.graphics.curveTo(_x -40 , _y + 140 , _x -50 , _y + 120);15 mouton.graphics.curveTo(_x -70 , _y + 120 , _x -70 , _y + 100);16 mouton.graphics.curveTo(_x -100 , _y + 90, _x -90 , _y + 70);17 mouton.graphics.curveTo(_x -110 , _y + 50, _x -90 , _y + 40);18 mouton.graphics.curveTo(_x -90 , _y + 20, _x -60 , _y + 20);19 mouton.graphics.curveTo(_x -50 , _y , _x -30, _y + 10);20 mouton.graphics.curveTo(_x -20 , _y -10, _x, _y);21 mouton.graphics.endFill ();

Vous devriez maintenant avoir un beau corps de mouton (voir figure 15.12) qui, jel’avoue, ressemble pour l’instant plus à un nuage qu’à autre chose.

316

Page 340: Programmez en Actionscript 3

EXERCICE : DESSINE-MOI UN MOUTON

Figure 15.12 – Le corps du mouton

La tête

À présent, nous allons nous occuper de la tête de notre mouton. Nous lui ferons doncdeux oreilles, puis nous ajouterons la forme globale de sa tête. Les yeux, quant à eux,seront réalisés plus tard car ils demanderont un peu plus de travail.

Commençons par les oreilles, que nous créerons à partir de courbes de Bézier. Lapartie haute des oreilles sera dissimulée plus tard, il est donc inutile de s’attarderdessus. C’est pourquoi nous tracerons uniquement une courbe pour chaque oreille etnous laisserons le soin à la fonction endFill() de refermer chacun de nos remplissages.Ainsi, le code présenté ci-dessous permet de réaliser les deux oreilles de la bête :

1 // Tête2 mouton.graphics.beginFill(0xF9D092);3 mouton.graphics.moveTo(_x - 30 , _y + 50);4 mouton.graphics.curveTo(_x - 90 , _y + 165 , _x - 10, _y + 60);5 mouton.graphics.endFill ();6 mouton.graphics.beginFill(0xF9D092);7 mouton.graphics.moveTo(_x + 50 , _y + 50);8 mouton.graphics.curveTo(_x + 100 , _y + 165 , _x + 30, _y + 60);9 mouton.graphics.endFill ();

Bien évidemment, nous avons utilisé une nouvelle couleur de remplissage pour donnerun effet de peau à nos oreilles que vous pouvez voir sur la figure 15.13.

Figure 15.13 – Mise en place des oreilles

317

Page 341: Programmez en Actionscript 3

CHAPITRE 15. DESSINER AVEC L’ACTIONSCRIPT

Je suggère maintenant que nous passions à la tête. Pour dessiner celle-ci, nous allonscommencer par tracer une ellipse. Puis nous utiliserons une ligne droite ainsi qu’unecourbe de Bézier sans remplissage pour représenter le museau de l’animal. Làencore, il n’y a aucune difficulté, il suffit de faire les choses dans l’ordre :

1 mouton.graphics.beginFill(0xF9D092);2 mouton.graphics.drawEllipse(_x - 30 , _y +20, 80 , 150);3 mouton.graphics.endFill ();4 mouton.graphics.moveTo(_x - 5, _y + 155);5 mouton.graphics.curveTo(_x + 10 , _y + 165 , _x + 25, _y + 155);6 mouton.graphics.moveTo(_x + 10 , _y + 160);7 mouton.graphics.lineTo(_x + 10 , _y + 170);

Voici donc notre mouton qui commence doucement à prendre forme comme le montrela figure 15.14.

Figure 15.14 – Notre mouton et sa tête

Les cheveux

Nous allons à présent dessiner ce que j’ai appelé les « cheveux », mais qui corresponden réalité à la petite touffe de laine présente sur le dessus de la tête. La techniqueutilisée ici est similaire à celle employée pour le corps, cependant nous allons utilisercette fois la méthode drawPath(). Afin de rendre le code plus lisible, je vous conseilleencore une fois d’ajouter les différentes coordonnées par commande. Voici donc le codeque j’ai réalisé pour tracer les cheveux de notre beau mouton :

1 // Cheveux2 var commandes:Vector.<int > = new Vector.<int >();3 commandes.push(1, 3, 3, 3, 3, 3, 3, 3, 3);4 var coordonnees:Vector.<Number > = new Vector.<Number >();5 coordonnees.push(_x - 20 , _y + 20);6 coordonnees.push(_x, _y - 10 , _x + 20 , _y + 10);7 coordonnees.push(_x + 40 , _y , _x + 50 , _y + 30);8 coordonnees.push(_x + 80 , _y + 30, _x + 60, _y + 50);9 coordonnees.push(_x + 70 , _y + 70, _x + 40, _y + 70);

10 coordonnees.push(_x + 20 , _y + 90, _x , _y + 70);11 coordonnees.push(_x - 20 , _y + 90, _x - 30, _y + 60);

318

Page 342: Programmez en Actionscript 3

EXERCICE : DESSINE-MOI UN MOUTON

12 coordonnees.push(_x - 60 , _y + 50, _x - 40, _y + 30);13 coordonnees.push(_x - 40 , _y , _x - 20 , _y + 20);14 mouton.graphics.beginFill(0xFFFFFF);15 mouton.graphics.drawPath(commandes , coordonnees);16 mouton.graphics.endFill ();

Nous avons cette fois quelque chose qui commence réellement à ressembler à un mouton(voir figure 15.15).

Figure 15.15 – Mise en place des cheveux

Les pattes

Continuons l’exercice en dessinant les pattes pour lesquelles je n’ai pas réussi à trouverl’effet que je souhaitais. Ce n’est pas grave, contentons-nous de dessiner deux rectanglesarrondis en guise de pieds. Rien de plus simple, ceci est réalisable en quatre instructions :

1 // Pattes2 mouton.graphics.beginFill(0xF9D092);3 mouton.graphics.drawRoundRect(_x - 60 , _y + 155 , 40, 20, 20 , 20

);4 mouton.graphics.drawRoundRect(_x + 40 , _y + 155 , 40, 20, 20 , 20

);5 mouton.graphics.endFill ();

Voici donc à la figure 15.16 notre mouton qui peut à présent se tenir debout sur sespattes.

Les yeux

Notre mouton est très beau, mais il est pour l’instant aveugle ! Nous allons maintenantnous occuper des yeux. Pour ceux-ci, nous n’utiliserons que des cercles, ou plutôtdes disques. Il nous en faudra trois pour chaque œil : un pour l’œil en lui-même, unpour la pupille et enfin un dernier pour simuler le reflet blanc à l’intérieur de celle-ci.Un petit détail supplémentaire, nous n’aurons pas besoin de contours pour les deuxderniers disques. C’est pourquoi, nous définirons un style de lignes transparent pour

319

Page 343: Programmez en Actionscript 3

CHAPITRE 15. DESSINER AVEC L’ACTIONSCRIPT

Figure 15.16 – Notre mouton se tient debout

ceux-ci. Je vous propose donc de découvrir le code correspondant à l’ensemble de cesmanipulations :

1 // Yeux2 mouton.graphics.beginFill(0xFFFFFF);3 mouton.graphics.drawCircle(_x - 10 , _y + 100 , 15);4 mouton.graphics.drawCircle(_x + 25 , _y + 100 , 20);5 mouton.graphics.endFill ();6 mouton.graphics.lineStyle(1, 0x3A281E , 0.0);7 mouton.graphics.beginFill(0x000000);8 mouton.graphics.drawCircle(_x - 10 , _y + 100 , 8);9 mouton.graphics.drawCircle(_x + 25 , _y + 100 , 8);

10 mouton.graphics.endFill ();11 mouton.graphics.beginFill(0xFFFFFF);12 mouton.graphics.drawCircle(_x - 8, _y + 98 , 2);13 mouton.graphics.drawCircle(_x + 27 , _y + 98 , 2);14 mouton.graphics.endFill ();

Cette petite touche finale vient donner vie à notre mouton qui nous scrute maintenantdu regard (voir figure 15.17) !

Figure 15.17 – Le mouton intégral

320

Page 344: Programmez en Actionscript 3

EXERCICE : DESSINE-MOI UN MOUTON

La bulle

J’aurai pu laisser ce « chef-d’œuvre » tel quel, mais je trouvais qu’il manquait un petitquelque chose. J’ai donc ajouté une bulle au mouton comme si on se trouvait dans unebande dessinée. Rien de nouveau ici, il s’agit presque exclusivement de cercles remplisainsi que d’un rectangle arrondi. Encore une fois, la seule difficulté est de placer leséléments au bon endroit. Voici comment faire :

1 // Bulle2 mouton.graphics.beginFill(0x3A281E);3 mouton.graphics.drawCircle(_x - 60 , _y + 70 , 5);4 mouton.graphics.drawCircle(_x - 80 , _y + 50 , 10);5 mouton.graphics.drawRoundRect(_x - 150 , _y - 25 , 90, 60, 60 , 60

);6 mouton.graphics.endFill ();7 mouton.graphics.beginFill(0xFFFFFF);8 mouton.graphics.drawCircle(_x - 120 , _y + 15 , 5);9 mouton.graphics.drawCircle(_x - 105 , _y + 15 , 5);

10 mouton.graphics.drawCircle(_x - 90 , _y + 15 , 5);11 mouton.graphics.endFill ();

Cette fois, nous avons à la figure 15.18 le résultat final de notre dessin.

Figure 15.18 – L’illustration complète

Malgré ce que vous avez peut-être ressenti au cours de cet exercice, la réa-lisation de ce mouton a demandé beaucoup de travail, je m’y suis repris àplusieurs fois pour arriver à ce résultat. N’hésitez pas à essayer de réaliserd’autres dessins plus simples pour vous faire la main avec les méthodes decette classe Graphics !

Code final

Pour terminer ce chapitre, je vous ai réécrit l’intégralité du code afin que vous puissiezeffectuer vos propres tests.

1 package

321

Page 345: Programmez en Actionscript 3

CHAPITRE 15. DESSINER AVEC L’ACTIONSCRIPT

2 {3 import flash.display.Sprite;4 import flash.events.Event;5 import flash.display.Shape;67 public class Main extends Sprite8 {9 private var _x:int;

10 private var _y:int;1112 public function Main():void13 {14 if (stage) init();15 else addEventListener(Event.ADDED_TO_STAGE , init);16 }1718 private function init(e:Event = null):void19 {20 removeEventListener(Event.ADDED_TO_STAGE , init);21 // entry point22 _x = 160;23 _y = 40;24 var mouton:Shape = new Shape();2526 // Fond27 mouton.graphics.beginFill(0x10879D);28 mouton.graphics.drawRoundRect(0, 0, 280 , 220 , 40 ,

40);29 mouton.graphics.endFill ();3031 // Corps32 mouton.graphics.lineStyle(4, 0x3A281E , 1.0);33 mouton.graphics.beginFill(0xFFFFFF);34 mouton.graphics.moveTo(_x, _y);35 mouton.graphics.curveTo(_x + 20 , _y - 20, _x + 40,

_y);36 mouton.graphics.curveTo(_x + 60 , _y - 10, _x + 70,

_y + 10);37 mouton.graphics.curveTo(_x + 90 , _y + 10, _x + 90,

_y + 30);38 mouton.graphics.curveTo(_x + 110 , _y + 40, _x + 100

, _y + 60);39 mouton.graphics.curveTo(_x + 120 , _y + 80, _x + 100

, _y + 90);40 mouton.graphics.curveTo(_x + 110 , _y + 110 , _x + 90

, _y + 110);41 mouton.graphics.curveTo(_x + 80 , _y + 140 , _x + 60,

_y + 120);42 mouton.graphics.curveTo(_x + 40 , _y + 150 , _x + 20,

_y + 130);

322

Page 346: Programmez en Actionscript 3

EXERCICE : DESSINE-MOI UN MOUTON

43 mouton.graphics.curveTo(_x, _y + 150 , _x -20 , _y +130);

44 mouton.graphics.curveTo(_x -40, _y + 140 , _x -50 ,_y + 120);

45 mouton.graphics.curveTo(_x -70, _y + 120 , _x -70 ,_y + 100);

46 mouton.graphics.curveTo(_x -100 , _y + 90, _x -90 ,_y + 70);

47 mouton.graphics.curveTo(_x -110 , _y + 50, _x -90 ,_y + 40);

48 mouton.graphics.curveTo(_x -90, _y + 20, _x -60 , _y+ 20);

49 mouton.graphics.curveTo(_x -50, _y , _x -30, _y + 10);

50 mouton.graphics.curveTo(_x -20, _y -10, _x, _y);51 mouton.graphics.endFill ();5253 // Tête54 mouton.graphics.beginFill(0xF9D092);55 mouton.graphics.moveTo(_x - 30 , _y + 50);56 mouton.graphics.curveTo(_x - 90 , _y + 165 , _x - 10,

_y + 60);57 mouton.graphics.endFill ();58 mouton.graphics.beginFill(0xF9D092);59 mouton.graphics.moveTo(_x + 50 , _y + 50);60 mouton.graphics.curveTo(_x + 100 , _y + 165 , _x + 30

, _y + 60);61 mouton.graphics.endFill ();62 mouton.graphics.beginFill(0xF9D092);63 mouton.graphics.drawEllipse(_x - 30 , _y +20, 80 ,

150);64 mouton.graphics.endFill ();65 mouton.graphics.moveTo(_x - 5, _y + 155);66 mouton.graphics.curveTo(_x + 10 , _y + 165 , _x + 25,

_y + 155);67 mouton.graphics.moveTo(_x + 10 , _y + 160);68 mouton.graphics.lineTo(_x + 10 , _y + 170);6970 // Cheveux71 var commandes:Vector.<int > = new Vector.<int >();72 commandes.push(1, 3, 3, 3, 3, 3, 3, 3, 3);73 var coordonnees:Vector.<Number > = new Vector.<

Number >();74 coordonnees.push(_x - 20 , _y + 20);75 coordonnees.push(_x, _y - 10 , _x + 20 , _y + 10);76 coordonnees.push(_x + 40 , _y , _x + 50 , _y + 30);77 coordonnees.push(_x + 80 , _y + 30, _x + 60, _y + 50

);78 coordonnees.push(_x + 70 , _y + 70, _x + 40, _y + 70

);

323

Page 347: Programmez en Actionscript 3

CHAPITRE 15. DESSINER AVEC L’ACTIONSCRIPT

79 coordonnees.push(_x + 20 , _y + 90, _x , _y + 70);80 coordonnees.push(_x - 20 , _y + 90, _x - 30, _y + 60

);81 coordonnees.push(_x - 60 , _y + 50, _x - 40, _y + 30

);82 coordonnees.push(_x - 40 , _y , _x - 20 , _y + 20);83 mouton.graphics.beginFill(0xFFFFFF);84 mouton.graphics.drawPath(commandes , coordonnees);85 mouton.graphics.endFill ();8687 // Pattes88 mouton.graphics.beginFill(0xF9D092);89 mouton.graphics.drawRoundRect(_x - 60, _y + 155 , 40

, 20 , 20, 20);90 mouton.graphics.drawRoundRect(_x + 40, _y + 155 , 40

, 20 , 20, 20);91 mouton.graphics.endFill ();9293 // Yeux94 mouton.graphics.beginFill(0xFFFFFF);95 mouton.graphics.drawCircle(_x - 10 , _y + 100 , 15);96 mouton.graphics.drawCircle(_x + 25 , _y + 100 , 20);97 mouton.graphics.endFill ();98 mouton.graphics.lineStyle(1, 0x3A281E , 0.0);99 mouton.graphics.beginFill(0x000000);

100 mouton.graphics.drawCircle(_x - 10 , _y + 100 , 8);101 mouton.graphics.drawCircle(_x + 25 , _y + 100 , 8);102 mouton.graphics.endFill ();103 mouton.graphics.beginFill(0xFFFFFF);104 mouton.graphics.drawCircle(_x - 8, _y + 98 , 2);105 mouton.graphics.drawCircle(_x + 27 , _y + 98 , 2);106 mouton.graphics.endFill ();107108 // Bulle109 mouton.graphics.beginFill(0x3A281E);110 mouton.graphics.drawCircle(_x - 60 , _y + 70 , 5);111 mouton.graphics.drawCircle(_x - 80 , _y + 50 , 10);112 mouton.graphics.drawRoundRect(_x - 150 , _y - 25 , 90

, 60 , 60, 60);113 mouton.graphics.endFill ();114 mouton.graphics.beginFill(0xFFFFFF);115 mouton.graphics.drawCircle(_x - 120 , _y + 15 , 5);116 mouton.graphics.drawCircle(_x - 105 , _y + 15 , 5);117 mouton.graphics.drawCircle(_x - 90 , _y + 15 , 5);118 mouton.graphics.endFill ();119120 this.addChild(mouton);121 }122123 }

324

Page 348: Programmez en Actionscript 3

EXERCICE : DESSINE-MOI UN MOUTON

124125 }

Vous pouvez l’afficher pour le copier en utilisant le code web ci-dessous.

B

�Code final

Code web : 285951

En résumé– La classe Graphics renferme toutes les méthodes permettant de dessiner directementdepuis le code.

– Pour accéder à cette classe Graphics, il est nécessaire de passer par l’instanciationde l’une de ces trois classes : Shape, Sprite ou MovieClip.

– En Flash, les dessins réalisés sont de type vectoriels et s’adaptent à la taille del’affichage.

– Pour dessiner en Actionscript, nous devons définir un contour puis spécifier lesstyles de remplissages et de lignes qui doivent lui être appliqués.

– Les contours peuvent être réalisés grâce à des lignes droites ou des courbes deBézier.

– Des formes prédéfinies facilitent le tracé de formes géométriques simples, telles queles cercles, les ellipses et les rectangles.

325

Page 349: Programmez en Actionscript 3

CHAPITRE 15. DESSINER AVEC L’ACTIONSCRIPT

326

Page 350: Programmez en Actionscript 3

Chapitre 16Utilisation des matrices

Difficulté :

Nous allons à présent nous pencher sur les matrices ! N’ayez pas peur, ce chapitre nesera pas aussi complexe qu’il en à l’air. En fait, l’utilisation de ces matrices est gran-dement facilitée en Actionscript. En effet, vous verrez que nous disposons d’une classenommée Matrix qui permet de manipuler une matrice sans besoin de comprendre com-ment elle fonctionne réellement. Là encore, je pense que nous pouvons remercier la POOet l’encapsulation.

Nous verrons donc comment utiliser cette classe pour décrire comment appliquer un dégradédans un tracé ou encore faire effectuer des transformations géométriques à nos objetsd’affichage.

327

Page 351: Programmez en Actionscript 3

CHAPITRE 16. UTILISATION DES MATRICES

Les matrices ou la classe Matrix

Introduction aux matrices

Les bases

Avant d’aller plus loin, je pense qu’il serait bien de vous expliquer un peu ce qu’est unematrice, si vous ne le savez pas déjà. Ne vous inquiétez pas, il ne s’agit pas d’un coursde mathématiques ! Nous ne verrons donc pas de longues formules où vous risqueriezde vous arracher les cheveux !

Malgré son nom barbare, une matrice n’est en réalité rien d’autre qu’un tableau devaleurs. Les nombres qui y sont stockés peuvent représenter tout un tas de choses sui-vant l’utilisation que l’on peut en avoir. Les matrices peuvent donc être utilisées pourdes applications simples, mais permettent également de représenter des concepts ma-thématiques complexes. Toutefois, en ce qui nous concerne, nous nous contenterons dedire qu’une matrice est un tableau de nombres et nous nous limiterons aux matricesbidimensionnelles. Ainsi, toute matrice est de taille m × n où m est le nombre delignes et n le nombre de colonnes. Voici par exemple une matrice 3 × 3 quelconque :1 2 3

4 5 67 8 9

Comme dans un tableau, il est alors possible de désigner un élément particulier grâce àun couple d’indices noté (i, j). Dans l’exemple précédent, supposons que nous nommionsla matrice A. Nous pourrions par exemple préciser que A(2, 1) = 4. En mathématiques,il est possible de réaliser tout un tas d’opérations avec les matrices. Cependant, dansle cadre de ce cours, l’objectif n’est pas de vous les présenter toutes, cela serait bientrop long et n’aurait pas vraiment d’utilité dans notre cas. Toutefois, retenez qu’ilexiste une matrice un peu particulière où les coefficients diagonaux sont égaux à 1 etles autres coefficients sont tous nuls : la matrice identité. En voici une :1 0 0

0 1 00 0 1

Pour les débutants en la matière, vous retiendrez donc qu’une matrice peut globalementse manipuler comme un tableau de nombres.

Théorie pour les initiés

Malgré le titre, j’invite également les novices en termes de matrices à lire la suite neserait-ce que pour le plaisir ! En deux dimensions, nous avons l’habitude d’utiliser uncouple de coordonnées noté (x, y) pour repérer un point sur le plan. Lorsque l’on utilisela notation matricielle, il est alors préférable de noter ces coordonnées en vertical etnous appellerons cette nouvelle notation un vecteur. Voici donc notre vecteur :

328

Page 352: Programmez en Actionscript 3

LES MATRICES OU LA CLASSE MATRIX

[xy

]Une des propriétés des matrices est la multiplication. Elle permet ainsi de multiplierdeux matrices entre elles mais également une matrice avec un vecteur. Toutefois, lesdimensions des deux entités de l’opération doivent être cohérentes. Dans notre cas,pour pouvoir multiplier notre vecteur de dimension 2 × 1, nous devrons utiliser unematrice 2 × 2. L’intérêt de tout cela est qu’à l’intérieur de notre matrice 2 × 2, nouspouvons définir différentes transformations géométriques :[

sx 00 sy

]×[

xy

]L’exemple ci-dessus est une opération de mise à l’échelle où sx correspond au redimen-sionnement horizontal et sy au vertical. Ainsi, après multiplication, nous obtenonsun nouveau vecteur où les nouvelles coordonnées ont été modifiées suivant la transfor-mation. Une opération qui, sans doute, vous fera certainement peur est la rotation.Nous y retrouvons nos fonctions préférés : sinus et cosinus. Voici donc comment seréalise une rotation d’un angle θ :[

cos θ − sin θsin θ cos θ

]×[

xy

]Nous arrivons maintenant au petit point pour lequel il nous a fallu faire toutes cesprécisions. Lorsque l’on utilise une matrice de dimension 2 × 2, il est possible deréaliser beaucoup de transformations. Toutefois, la translation ne peut pas être priseen compte dans ces conditions. C’est pourquoi, il est impératif d’ajouter une dimensionsupplémentaire à l’ensemble de l’opération. Il devient alors possible de réaliser unetranslation de la manière suivante : 1 0 tx

0 1 ty0 0 1

× x

y1

Dans l’exemple précédent, les valeurs tx et ty représentent les déplacements respecti-vement suivant les axes −→x et −→y .

Le fait de rajouter une dimension au vecteur de coordonnées n’a de sens quepour l’opération mathématique. Ainsi, les coordonnées 2D du point considéréseront toujours les deux premières, la troisième étant tout simplement ignorée.

Vous noterez que toute cette théorie sur les matrices permet de vous aider àmieux cerner leur intérêt. Dans la suite, vous verrez que toutes ces opérationssont simplifiées grâce à l’encapsulation de la classe Matrix, qui disposede méthodes simples pour définir ces transformations. Ce n’est donc pasdramatique si vous n’avez pas tout compris sur la théorie des matrices !

329

Page 353: Programmez en Actionscript 3

CHAPITRE 16. UTILISATION DES MATRICES

L’objet Matrix

Suite à cette petite introduction aux matrices, vous devriez maintenant être plus àl’aise et, surtout, vous ne devriez pas être surpris par tout ce qui va suivre.

Introduction

Comme vous l’imaginez maintenant, la classe Matrix permet de définir une matrice àl’intérieur du code. Celle-ci permettra donc de définir l’ensemble des transformations àappliquer à un objet. Si vous avez bien suivi tout ce qui a été dit sur les matrices précé-demment, vous ne devriez donc pas être surpris par la forme des matrices manipuléespar cette classe :

a c txb d ty0 0 1

Nous retrouvons donc quatre coefficients a, b, c et d qui permettent de réaliser lestransformations classiques telles que le redimensionnement, la rotation mais égalementl’inclinaison. Nous disposons également des valeurs de translation tx et ty, permettantde déplacer un objet. Cette classe Matrix va donc nous permettre de définir une matricequi combinera une ou plusieurs de ces transformations en même temps.

Déclaration et initialisation

Comme toute classe, un objet Matrix s’initiale grâce au constructeur de la classedans une variable. Voici donc comment procéder :

1 var maTransformation:Matrix = new Matrix ();

Lorsque vous initialisez une matrice comme ceci, le constructeur crée une ma-trice identité, qui, en termes de transformations, ne fait strictement rien. En fait,ce constructeur possède les différents paramètres facultatifs suivant : a, b, c, d, tx etty. Toutefois, comme nous ne voulons pas nous prendre la tête avec les mathématiques,nous utiliserons plutôt les méthodes de la classe qui simplifient énormément la gestiondes transformations.

Création de dégradés

Dans le chapitre précédent, j’ai volontairement omis de vous parler des dégradés. Nousverrons dans la suite de ce chapitre que l’utilisation des matrices permet de mieuxcontrôler le dégradé en lui-même et ainsi parvenir plus facilement au rendu désiré.

330

Page 354: Programmez en Actionscript 3

CRÉATION DE DÉGRADÉS

Présentation des dégradés

La gestion des dégradés en Actionscript peut paraître complexe au premier abord,cependant ses possibilités sont larges. Vous verrez au fil des explications que la créationd’un dégradé se fait par étapes, de la même manière qu’on le ferait dans un logicielde graphisme. Nous allons donc dans un premier temps définir le dégradé à l’aidede différents tableaux Array, comme ceci :

1 var couleurs:Array = [0xFF0000 , 0x00FF00 ];2 var alphas:Array = [1, 1];3 var ratios:Array = [0, 255];

Dans l’exemple précédent, nous avons déclaré et initialisé trois tableaux : couleurs,alphas et ratios. Comme son nom l’indique, le premier sert à lister les différentescouleurs du dégradé, ici rouge et vert. Le deuxième permet de définir l’opacité dechacune des couleurs précédentes dans le même ordre. Enfin, la variable ratios nouspermet de gérer la position des couleurs les unes par rapport aux autres. Pour comparer,vous pouvez imaginer qu’il s’agit des petits curseurs que vous pourriez déplacer dansun éditeur de dégradé, ici représentés par des valeurs comprises entre 0 l’extrémitégauche et 255 l’extrémité droite, comme le montre la figure 16.1.

Figure 16.1 – Un dégradé et des curseurs

Un des intérêts de l’utilisation de tableaux vient du fait que leur taille peutêtre quelconque. Ainsi, vous pouvez rajouter autant de couleurs que vous sou-haitez, en rajoutant autant valeurs dans chacun des trois tableaux précédents.C’est principalement en ajoutant de nouvelles couleurs que la variable ratiosprend de l’importance et permet alors de bien situer les couleurs entre elles.

En théorie, il est possible d’appliquer un dégradé tel quel à un remplissage par exemple.Nous reviendrons dessus plus tard, mais vous pourriez très bien utiliser le code suivant :

1 var monDessin:Shape = new Shape;2 monDessin.graphics.beginGradientFill(GradientType.LINEAR ,

couleurs , alphas , ratios);3 monDessin.graphics.drawRect(0, 0, 100 , 100);4 addChild(monDessin);

Néanmoins, il est quasiment indispensable de se servir des matrices pour décrire com-ment les dégradés doivent être appliqués. Hormis les valeurs GradientType.LINEARet GradientType.RADIAL qui permettent de définir le dégradé de type linéaire ou ra-dial, il est nécessaire de préciser la largeur, la hauteur ou encore l’angle de ce dernier àl’intérieur du futur remplissage. Ainsi un objet de type Matrix va permettre de mettreen place ces différents paramètres à l’intérieur d’une même matrice.

331

Page 355: Programmez en Actionscript 3

CHAPITRE 16. UTILISATION DES MATRICES

Ajouter une matrice de description

Pré-requis

Vous noterez que l’utilisation des matrices ici n’est pas tout à fait identique auxtransformations décrites auparavant. Toutefois, vous verrez qu’au final, la descriptiondes dégradés y est très similaire et que les matrices seront alors définies de la mêmemanière.

Dans la suite de ce cours, nous partirons du dégradé blanc et noir défini ci-dessous :

1 var couleurs:Array = [0xFFFFFF , 0x000000 ];2 var alphas:Array = [1, 1];3 var ratios:Array = [0, 255];

Préparation de la matrice

Comme nous l’avons dit, la classe Matrix possède des méthodes qui facilitent ladéfinition d’une matrice. Parmi elles, la méthode createGradientBox() est parti-culièrement utile pour décrire la mise en place d’un dégradé. Les différents paramètresde cette méthode sont listés dans le code d’exemple ci-dessous :

1 var matrix:Matrix = new Matrix ();2 var largeur:Number = 100;3 var hauteur:Number = 100;4 var rotation:Number = 0;5 var tx:Number = 0;6 var ty:Number = 0;7 matrix.createGradientBox(largeur , hauteur , rotation , tx , ty);

Notez que seuls la largeur et la hauteur sont des paramètres obligatoires.Vous pouvez donc aisément vous passer des derniers paramètres si ceux-cisont nuls, et ainsi alléger votre code. Ce sera notamment souvent le cas pourles valeurs de décalage du dégradé tx et ty.

Le nom des variables dans l’exemple précédent est assez explicite, cependant je vouspropose à la figure 16.2 un tableau montrant l’influence de ces différents paramètressur le remplissage final.

Comme c’est souvent le cas en programmation, les angles sont exprimés enradians. Toutefois, l’utilisation de la classe Math vous permet de récupérer lavaleur de \pi et donc d’exprimer facilement les angles dans cette unité. Ainsi,la conversion en radians se fait à l’aide du facteur \frac{\pi}{180} .

332

Page 356: Programmez en Actionscript 3

CRÉATION DE DÉGRADÉS

Figure 16.2 – Les paramètres modifient l’affichage

Appliquer un dégradé

Pour appliquer un dégradé à un remplissage, vous devez utiliser la méthodebeginGradientFill() que nous avions rapidement vu précédemment. Vous pouvezalors définir le remplissage en renseignant les différents paramètres dans l’ordre suivant :

1 monDessin.graphics.beginGradientFill(GradientType.LINEAR ,couleurs , alphas , ratios , matrix);

Je rappelle qu’un dégradé peut être linéaire ou radial, défini par les constantesGradientType.LINEAR et GradientType.RADIAL. Comme pour la méthode beginFill(),le remplissage est terminé lors de l’appel de la fonction endFill() qui termine le tracéd’un contour.

Contrairement à ce que vous pourriez croire, un dégradé peut tout autant s’appliqueraux lignes. Pour cela, utilisez la méthode lineGradientStyle() exactement de lamême manière que beginGradientFill(). Toutefois, n’oubliez pas de définir la largeurde la ligne à l’aide de la méthode lineStyle(), sans quoi celle-ci ne sera pas visible.Voici donc comment procéder :

1 monDessin.graphics.lineStyle(2);2 monDessin.graphics.lineGradientStyle(GradientType.LINEAR ,

couleurs , alphas , ratios , matrix);

333

Page 357: Programmez en Actionscript 3

CHAPITRE 16. UTILISATION DES MATRICES

Exemple : création d’un bouton

Pour terminer les explications sur les dégradés, je vous propose de réaliser un petitbouton comme vous pourriez en trouver sur n’importe quelle page web. Pour ce faire,nous allons donc utiliser un dégradé linéaire vertical que nous utiliserons commeremplissage. Nous dessinerons alors un rectangles aux coins arrondis avec une ligne decouleur pour marquer le contour de notre bouton. Sans plus attendre, voici le codecorrespondant à la définition du dégradé et au tracé de ce bouton :

1 // Dégradé de base2 var couleurs:Array = [0xEEBBBB , 0xDD0000 ];3 var alphas:Array = [1, 1];4 var ratios:Array = [0, 255];56 // Matrice de description7 var matrix:Matrix = new Matrix ();8 var largeur:Number = 100;9 var hauteur:Number = 15;

10 var rotation:Number = Math.PI/2;11 var tx:Number = 0;12 var ty:Number = 0;13 matrix.createGradientBox(largeur , hauteur , rotation , tx , ty);1415 // Tracé du bouton16 var monBouton:Shape = new Shape;17 monBouton.graphics.lineStyle(1, 0x880000);18 monBouton.graphics.beginGradientFill(GradientType.LINEAR ,

couleurs , alphas , ratios , matrix);19 monBouton.graphics.drawRoundRect(0, 0, 100 , 25, 10);20 addChild(monBouton);

Nous avons donc ici réalisé la base d’un bouton typique d’une page Internet. Il manqueencore le texte par-dessus celui-ci mais vous devriez normalement pouvoir vous enoccuper vous-mêmes. La figure 16.3 montre à quoi ressemble notre bouton.

Figure 16.3 – Notre bouton

Pour ajouter du texte grâce à l’objet TextField, vous devrez utiliser unconteneur de type Sprite pour réaliser ce bouton. Vous pourrez alors in-sérer l’objet Shape à l’intérieur ou dessiner directement depuis la propriétégraphics du conteneur.

334

Page 358: Programmez en Actionscript 3

LES TRANSFORMATIONS MATRICIELLES

Les transformations matricielles

Un objet à transformer

Création de l’objet

Nous allons d’abord créer une forme que nous pourrons déformer plus tard. Pour nepas se compliquer la vie, nous tracerons donc un carré dans un objet de type Shape.Nous partirons du code ci-dessous pour la suite de ce chapitre :

1 var monObjet:Shape = new Shape();2 monObjet.graphics.beginFill(0x6688FF);3 monObjet.graphics.drawRect(0, 0, 100 , 100);4 this.addChild(monObjet);

Pour que vous puissiez mieux comparer les effets des différentes transformations, voici,à la figure 16.4, l’original que nous venons de créer.

Figure 16.4 – Notre image originale

Lorsque vous créez n’importe quel objet d’affichage, il lui est associé un centrede transformation. Par défaut, le centre d’un objet est placé au point (0,0).Veillez donc à en tenir compte lors de la création de vos affichages car cepoint influera sur la transformation, et il est probable que vous ayez alorsbesoin de replacer vos objets après chacune d’elles.

La matrice de transformation

Tout objet héritant de la classe DisplayObject possède une matrice de transfor-mation. Celle-ci n’a aucune incidence sur l’affichage s’il s’agit d’une matrice identitéou si sa valeur est null. Pour y accéder, vous devez atteindre la propriété matrix d’unepropriété de votre objet nommée transform. Voici donc comment y parvenir :

1 monObjet.transform.matrix = matrix;

Notez que la propriété de type Transform possède également une matrice detype Matrix3D qui permet de gérer les transformations en trois dimensions.Nous n’en parlerons pas ici, mais sachez que vous ne pouvez utiliser ces deuxmatrices simultanément. La modification de l’une des deux entraîne forcémentl’autre à une valeur null.

335

Page 359: Programmez en Actionscript 3

CHAPITRE 16. UTILISATION DES MATRICES

Bien qu’il soit possible de modifier directement les valeurs à l’intérieur d’une matrice,nous préfèrerons utiliser les méthodes de la classe Matrix pour effectuer nos transfor-mations.

Création d’une matrice de transformation

Méthodes de transformations individuelles

Pour commencer, nous allons voir revenir très souvent une matrice identité. Celacorrespond à une matrice n’appliquant aucune transformation à l’objet. Pour cela,utilisez la fonction identity() simplement comme ceci :

1 matrix.identity ();

Ensuite, voyons comment redimensionner notre objet d’affichage. Pour cela, nous utili-serons la méthode scale() où nous pouvons spécifier les valeurs de redimensionnementhorizontal sx et vertical sx, la taille d’origine étant fixée à 1. Voici donc comment pro-céder :

1 matrix.scale(sx , sy);

Je vais maintenant vous présenter la méthode rotate() permettant de faire pivoter unobjet par rapport à son centre. Il suffit alors uniquement de préciser l’angle de rotationen radians :

1 matrix.rotate(angle);

Voyons à présent ensemble la translation. Rien de plus simple, il suffit de préciser lesdécalages dx et dy à la méthode translate() de la façon suivante :

1 matrix.translate(dx , dy);

Enfin, je vous propose une série de transformations dans l’exemple suivant :

1 var matrix:Matrix = new Matrix ();2 matrix.identity ();3 matrix.scale(2, 1);4 matrix.rotate(Math.PI / 4);5 matrix.translate(72 , 0);6 // Application des transformations7 monObjet.transform.matrix = matrix;

Dans l’exemple précédent, nous avons donc doublé notre objet dans le sens horizontal.Puis nous l’avons fait tourner de 45˚ par rapport à son centre confondu au coin supé-rieur gauche du rectangle. Enfin, nous avons translaté l’objet afin qu’il soit à nouveauentièrement dans la zone visible de l’écran. Regardez le résultat final à la figure 16.5.

336

Page 360: Programmez en Actionscript 3

LES TRANSFORMATIONS MATRICIELLES

Figure 16.5 – Le résultat final

N’oubliez pas que lorsque vous effectuez des transformations, celles-ci sonttoujours réalisées par rapport au centre de votre objet. Ainsi, si celui-ci n’estpositionné en (0,0), vous verrez sans nul doute votre objet de déplacer éga-lement en rapport des transformations que vous pourrez lui appliquer. Soyezdonc prévoyant au moment de la création de objet pour essayer d’anticiperces repositionnements.

Une petite exception : l’inclinaison

Il est aussi possible de déformer réellement votre objet en l’inclinant. Toutefois, la classeMatrix ne possède pas de méthode pour ce genre de transformations. Cependant, ilest possible de modifier directement les valeurs à l’intérieur de la matrice. C’est doncce que nous ferons pour réaliser ceci, en agissant sur la valeur b pour une inclinaisonverticale et sur la c pour une horizontale. Voici donc comment faire :

1 matrix.c = - Math.tan(2);

Dans cet exemple, nous inclinons notre objet d’une valeur de 2 horizontalement. Ainsi,chaque pixel va être décalé vers la droite de deux fois sa distance verticale au centrede l’objet. Voyez plutôt le résultat à la figure 16.6.

Figure 16.6 – Le résultat final

Plusieurs transformations à la fois

Contrairement à ce que pourrait vous laissez croire le titre, les méthodes précédentespermettent également de combiner plusieurs transformations en une seule matrice. Nous

337

Page 361: Programmez en Actionscript 3

CHAPITRE 16. UTILISATION DES MATRICES

allons créer une matrice combinant plusieurs transformations à l’aide d’une uniqueméthode : createBox().

Cette méthode permet de combiner un redimensionnement avec une rotationet une translation. Néanmoins, il faut être vigilant quant à l’ordre d’applica-tion de chacune de ces transformations. L’ordre des opérations est le suivant :identité -> rotation -> redimensionnement -> translation.

Ainsi, lorsque vous utiliserez cette méthode, la matrice sera « réinitialisée » et effaceradonc toute transformation de la matrice. Voici donc comment s’utilise cette méthode :1 matrix.createBox(sx , sx, angle , dx , dy);

Je vous propose donc un petit exemple d’utilisation :1 var matrix:Matrix = new Matrix ();2 matrix.createBox(2, 1, Math.PI/4, 150 , 0);3 monObjet.transform.matrix = matrix;

Les opérations sont donc insérées en une seule fois à l’intérieur de la matrice et pro-duisent la figure 16.7.

Figure 16.7 – Le résultat final

Remarquez que les transformations n’ont pas été effectuées dans le mêmeordre que précédemment, notamment la rotation qui est réalisée avant leredimensionnement. Il est donc normal que notre objet ait été déformé etqu’il ressemble maintenant davantage à un losange qu’à un carré.

Pour finir avec les matrices

Ajouter des transformations

Depuis le départ, nous ne faisons qu’affecter une matrice de transformation à unobjet. Pour faire ça, nous utilisons donc l’instruction suivante :1 monObjet.transform.matrix = matrix;

Cependant, en effectuant cette affectation, vous effacez également d’éventuelles trans-formations déjà appliquées à l’objet. Or vous souhaiteriez peut-être conserver ces an-ciennes transformations et appliquer en plus les nouvelles. Pour faire cela, vous aurez

338

Page 362: Programmez en Actionscript 3

LES TRANSFORMATIONS MATRICIELLES

donc besoin de récupérer la matrice existante, avant d’y ajouter de nouvelles opérationsde transformation. Voilà donc comment nous pourrions rajouter une rotation de 45˚à notre objet, sans réinitialiser l’ensemble des transformations déjà existantes :

1 // Récupération de la matrice de l'objet2 var matrix:Matrix = new Matrix ();3 matrix = monObjet.transform.matrix;4 // Ajout d'une transformation5 matrix.rotate(Math.PI / 4);6 // Application des transformations7 monObjet.transform.matrix = matrix;

Si vous avez bien suivi, vous devriez vous rappeler qu’en utilisant la méthode createBox(),vous commencez par redéfinir l’objet Matrix comme matrice identité, éliminant ainsitoute trace d’anciennes transformations. Il faut donc procéder différemment si vous sou-haitez conserver ces transformations. Pour cela, la classe Matrix dispose d’une méthodenommée concat() qui permet de concaténer une matrice avec une autre, c’est-à-direde combiner les effets géométriques des deux matrices. Voilà donc comment je voussuggère de procéder :

1 // Récupération de la matrice de l'objet2 var matrix:Matrix = new Matrix ();3 matrix = monObjet.transform.matrix;4 // Création de la matrice de transformation5 var transformation:Matrix = new Matrix ();6 transformation.createBox(2, 1, Math.PI/4, 150 , 0);7 // Combinaison des matrices8 matrix.concat(transformation);9 // Application des transformations

10 monObjet.transform.matrix = matrix;

Soyez attentif toutefois à la manière de concaténer vos deux matrices. Eneffet, il faut bien ici ajouter les modifications de la matrice transformationà la matrice d’origine matrix. C’est pourquoi nous utilisons la méthodeconcat() de matrix et non celle de transformation, qui aurait pour effetd’appliquer les nouvelles transformations avant les anciennes.

Intérêt des transformations matricielles

Il est probable que vous vous demandiez depuis le début quel est l’intérêt d’utiliser lesmatrices alors que les propriétés x, y, rotation, scaleX et scaleY permettent de fairela même chose.

En réalité, les transformations matricielles sont plus puissantes, notamment carelles permettent les déformations impossibles avec les propriétés précédentes. Un autreavantage est également de limiter les modifications liées à l’affichage. En effet, lorsquevous modifiez les propriétés d’un objet d’affichage, celui-ci doit être entièrement retracé,c’est-à-dire pixel par pixel. Cette opération peut donc être longue suivant les dimensions

339

Page 363: Programmez en Actionscript 3

CHAPITRE 16. UTILISATION DES MATRICES

de vos tracés et autres objets d’affichage. C’est pourquoi, utiliser les transformationsmatricielles accélère cette étape en combinant plusieurs opérations en une seule ins-truction de mise à jour de l’affichage. Ainsi, il est préférable d’utiliser cette techniquepour diminuer le temps d’exécution de ces transformations et fluidifier au maximumvotre affichage.

En résumé– Une matrice est un tableau de nombres à m lignes et n colonnes.– La classe Matrix sert à créer et manipuler des matrices plus simplement.– Cette classe permet notamment de faciliter la mise en place des dégradés grâce à saméthode createGradientBox().

– L’objet Matrix est beaucoup utilisé pour effectuer des transformations matri-cielles.

– Pour les transformations classiques, il existe les différentes méthodes scale(), rotate()et translate().

– Il est possible de combiner plusieurs opérations géométriques grâce à la méthodecreateBox()

– L’utilisation des matrices pour les transformations géométriques permet d’accélérerle rendu de l’affichage.

340

Page 364: Programmez en Actionscript 3

Chapitre 17Manipuler des images

Difficulté :

Il est temps d’embellir notre application à l’aide d’images. Dans ce chapitre, nous verronscomment incorporer des images à notre application, comment les afficher sur la scène,nous aborderons également quelques manipulations utiles. Toutefois, nous n’évoqueronspas ici le chargement dynamique d’images.

341

Page 365: Programmez en Actionscript 3

CHAPITRE 17. MANIPULER DES IMAGES

Embarquer des images

Préparation de l’image

Dans un premier temps, il faut préparer l’image que nous voulons incorporer dans notreapplication. Reprenons l’image de Zozor (voir figure 17.1) que nous avons utilisée pourafficher une image dans un champ de texte.

Figure 17.1 – Zozor, la mascotte du Site du Zéro

Créez un dossier lib s’il n’existe pas déjà dans le répertoire de votre projet, puis créez-yun dossier img. Enfin, copiez dans ce dossier img l’image de Zozor. Voilà ! Notre imagede Zozor est prête à être incorporée dans notre application !

Librairie d’images

Une nouvelle classe

Pour que notre projet soit un peu organisé, nous allons embarquer nos images dansune classe qui représentera notre bibliothèque d’images. Créez une nouvelle classeImageLibrary à côté de notre classe Main :1 package2 {3 /**4 * Librairie contenant nos images embarquées.5 * @author Guillaume CHAU6 */7 public class ImageLibrary8 {9

10 }1112 }

Incorporer une image

Pour embarquer une image, nous allons utiliser une instruction spéciale pour lecompilateur, de la même manière que nous avons embarqué une police de caractère,grâce au mot-clé Embed :

342

Page 366: Programmez en Actionscript 3

EMBARQUER DES IMAGES

1 [Embed(source="../lib/img/zozor.png")]

Le code est plus simple : il suffit d’indiquer le chemin de l’image dans le paramètresource. Petite astuce si vous utilisez FlashDevelop : dans l’arborescence du projet,faites un clic droit sur l’image à incorporer, puis sélectionnez Generate Embed Code,comme à la figure 17.2.

Figure 17.2 – FlashDevelop facilite l’incorporation d’images

FlashDevelop insère alors l’instruction spéciale automatiquement, à l’endroit où votrecurseur d’insertion se trouve dans la classe.

Puis, sur la ligne suivante, il faut déclarer un attribut statique de type Class, commepour les polices de caractères embarquées :

1 public static var Zozor:Class;

Voici le code complet de la classe :

1 package2 {3 /**4 * Librairie contenant nos images embarquées.5 * @author Guillaume CHAU6 */7 public class ImageLibrary8 {9

10 [Embed(source="../lib/img/zozor.png")]

343

Page 367: Programmez en Actionscript 3

CHAPITRE 17. MANIPULER DES IMAGES

11 public static var Zozor:Class;1213 }1415 }

Notre librairie d’images embarquées est maintenant prête à l’emploi !

Afficher des images

La classe Bitmap

Pour afficher une image, nous allons utiliser la classe Bitmap (voir figure 17.3).

Figure 17.3 – La classe Bitmap dans l’arbre des classes d’affichage

Si nous utilisons maintenant le constructeur de la classe Bitmap, nous obtiendrons uneimage vide :

1 // Image vide2 var zozor:Bitmap = new Bitmap ();

À la place, nous allons utiliser la classe contenue dans l’attribut statique que nousavons déclaré dans notre classe ImageLibrary :

1 var zozor:Bitmap = new ImageLibrary.Zozor ();

Voici le code complet pour afficher notre image de Zozor :

344

Page 368: Programmez en Actionscript 3

AFFICHER DES IMAGES

1 // Création de l'image2 var zozor:Bitmap = new ImageLibrary.Zozor ();3 addChild(zozor);45 // Alignement au centre6 zozor.x = (stage.stageWidth - zozor.width) / 2;7 zozor.y = (stage.stageHeight - zozor.height) / 2;

Ce qui nous donne à l’écran la figure 17.4.

Figure 17.4 – Zozor !

Redimensionnement

Je vous propose d’essayer de redimensionner notre image de Zozor : doublez sa taillesans regarder la solution pour vérifier que vous vous souvenez bien des attributs néces-saires.

Vous devriez obtenir la figure 17.5.

Voici une solution possible :

1 // Création de l'image

345

Page 369: Programmez en Actionscript 3

CHAPITRE 17. MANIPULER DES IMAGES

Figure 17.5 – Zozor a pris du poids.

346

Page 370: Programmez en Actionscript 3

AFFICHER DES IMAGES

2 var zozor:Bitmap = new ImageLibrary.Zozor ();3 addChild(zozor);45 // Redimensionnement6 zozor.scaleX = 2;7 zozor.scaleY = zozor.scaleX;89 // Alignement au centre

10 zozor.x = (stage.stageWidth - zozor.width) / 2;11 zozor.y = (stage.stageHeight - zozor.height) / 2;

À l’aide des attributs scaleX et scaleY de la classe DisplayObject dont hérite la classeBitmap, nous pouvons très facilement appliquer un coefficient multipliant la taille denotre objet d’affichage.

L’image est devenue affreuse avec ces gros pixels. . . Peut-on y remédier ?

Plus ou moins. En vérité, il n’y a pas de formule magique pour rendre l’image aussinette qu’elle n’était à sa taille d’origine, mais il est néanmoins possible d’améliorer lerendu obtenu lors de tels redimensionnements jusqu’à une certaine mesure. Pour ceteffet, la classe Bitmap dispose d’un attribut smoothing qui indique si les pixels del’image doivent être lissés si elle est redimensionnée :

1 // Lissage des pixels2 zozor.smoothing = true;

Ce qui nous donne à l’écran la figure 17.6.

C’est déjà un peu mieux ! Mais l’effet de cet attribut se fait surtout ressentir lorsquel’on diminue la taille des images. Au lieu de doubler la taille de Zozor, mettons-la à70%, sans utiliser le lissage :

1 // Création de l'image2 var zozor:Bitmap = new ImageLibrary.Zozor ();3 addChild(zozor);45 // Lissage des pixels6 //zozor.smoothing = true;78 // Redimensionnement9 zozor.scaleX = 0.7;

10 zozor.scaleY = zozor.scaleX;1112 // Alignement au centre13 zozor.x = (stage.stageWidth - zozor.width) / 2;14 zozor.y = (stage.stageHeight - zozor.height) / 2;

Ce qui nous donne la figure 17.7.

347

Page 371: Programmez en Actionscript 3

CHAPITRE 17. MANIPULER DES IMAGES

Figure 17.6 – Les pixels sont lissés.

Figure 17.7 – Taille à 70% de l’original

348

Page 372: Programmez en Actionscript 3

OPÉRATIONS SUR LES IMAGES

Comme vous pouvez le constater, le rendu que nous avons obtenu est loin d’êtreagréable. Pour remédier à cela, réactivons le lissage :

1 // Création de l'image2 var zozor:Bitmap = new ImageLibrary.Zozor ();3 addChild(zozor);45 // Lissage des pixels6 zozor.smoothing = true;78 // Redimensionnement9 zozor.scaleX = 0.7;

10 zozor.scaleY = zozor.scaleX;1112 // Alignement au centre13 zozor.x = (stage.stageWidth - zozor.width) / 2;14 zozor.y = (stage.stageHeight - zozor.height) / 2;

Ce qui nous donne à l’écran la figure 17.8.

Figure 17.8 – Taille à 70% avec lissage

C’est tout de même beaucoup mieux ! Pour mieux voir les différences entre les deuxrendus, voici à la figure 17.9 une comparaison avec zoom.

N’abusez pas du lissage si vous affichez beaucoup d’images, cela risqueraitde dégrader les performances de votre application.

Opérations sur les images

La classe BitmapData

Tout objet de la classe Bitmap dispose d’un attribut bitmapData de la classe BitmapData(voir figure 17.10). Cet objet représente les pixels de l’image stockés en mémoire. L’ins-tance de la classe Bitmap ne contient pas de pixels, elle n’est là que pour les afficher.

349

Page 373: Programmez en Actionscript 3

CHAPITRE 17. MANIPULER DES IMAGES

Figure 17.9 – Comparaison avec et sans lissage

Figure 17.10 – Tout objet de la classe Bitmap dispose d’un attribut bitmapData dela classe BitmapData

350

Page 374: Programmez en Actionscript 3

OPÉRATIONS SUR LES IMAGES

Il est possible d’utiliser un seul objet BitmapData pour plusieurs imagesBitmap. N’hésitez pas à le faire si vous devez afficher plusieurs fois la mêmeimage, cette astuce améliore grandement les performances d’affichage desimages concernées.

Créer notre première image

Pour créer une image vide, nous pouvons créer une instance de la classe Bitmapsans lui passer de paramètre :

1 // Création de l'image2 var image:Bitmap = new Bitmap ();3 addChild(image);

Notre objet image n’a aucun pixel à sa disposition, donc il n’affiche rien et a une taillenulle :

1 trace("taille de l'image : " + image.width + " x " + image.height);

Nous obtenons ceci dans la console :

taille de l’image : 0 x 0

Ne nous arrêtons pas là et créons notre première image grâce à la classe BitmapData :

1 // Création des données de l'image (les pixels)2 var imageData:BitmapData = new BitmapData(300 , 300 , false ,

0x0000ff);

Le premier paramètre est la largeur du tableau de pixel (donc de l’image), le deuxièmeest sa hauteur. Ensuite, un booléen nous permet d’indiquer si l’image vide est trans-parente ou non. Pour finir, nous devons passer la couleur de remplissage initiale. Ici,notre image sera donc un carré de 300 pixels de côté, rempli de couleur bleue.

Ensuite, il faut dire à notre objet image d’utiliser les données contenues dans notreobjet imageData :

1 // Données pour l'image2 image.bitmapData = imageData;

Nous avons désormais la figure 17.11 à l’écran.

Nous avons créé une image à partir de rien !

Dessiner sur des images

Nous allons maintenant nous atteler à rendre ce morne carré bleu un peu plus intéres-sant en manipulant les pixels qui le composent.

351

Page 375: Programmez en Actionscript 3

CHAPITRE 17. MANIPULER DES IMAGES

Figure 17.11 – Un carré bleu

352

Page 376: Programmez en Actionscript 3

OPÉRATIONS SUR LES IMAGES

Pipette

Nous avons à disposition d’une sorte de pipette, comme dans les logiciels de dessin,qui nous permet de connaître la couleur d’un pixel. Cette pipette est la méthodegetPixel(x, y) de la classe BitmapData. En paramètre, nous lui fournissons les coor-données du pixel dont nous voulons la couleur et elle nous la renvoie (si nous donnonsdes coordonnées qui sortent de l’image, elle nous renvoie 0).

1 // Prenons la couleur d'un de nos pixels (celui du centre)2 var couleur:uint = imageData.getPixel(150 , 150);3 trace("couleur du pixel : " + couleur.toString(16)); // Affiche

: ff (équivalent de 0000ff)

Il existe une deuxième pipette qui nous renvoie la couleur d’un pixel avec son opacité :getPixel32(x, y).

1 // Avec l'opacité2 couleur = imageData.getPixel32(150 , 150);3 trace("couleur ARVB du pixel : " + couleur.toString(16)); //

Affiche: ff0000ff

Comme vous pouvez le remarquer, il y a deux caractères supplémentaires par rapportà une couleur classique : ce sont les deux premiers. Ils représentent l’opacité de lacouleur en quelque sorte, notée en hexadécimal de 00 à ff, comme pour le rouge, levert et le bleu. Ainsi, 0x00000000 est une couleur totalement transparente, 0x880000ffreprésente du bleu à moitié transparent et 0xff0000ff du bleu totalement opaque.

Colorier un pixel

Il est grand temps de barbouiller notre carré de couleur ! Commençons avec la méthodesetPixel(x, y, couleur), qui permet de colorier un pixel aux coordonnées que nouspassons en paramètre, avec une certaine couleur (sans gestion de l’opacité) :

1 // Colorions le pixel du centre en rouge2 couleur = 0xff0000;3 imageData.setPixel(150 , 150 , couleur);

Nous obtenons la figure 17.12 (j’ai agrandi l’image pour que l’on puisse mieux voir).

Comme nous l’avons vu précédemment, il existe également la méthode setPixel32(x,y, couleur) qui permet de colorier un pixel avec une couleur contenant unevaleur de transparence.

Exercice

Essayons-nous à plus de fantaisies ! Je vous propose un petit exercice : coloriez chaquepixel de notre carré avec une couleur aléatoire opaque. Essayez de ne pas regarder lasolution trop vite !

Quelques conseils :

353

Page 377: Programmez en Actionscript 3

CHAPITRE 17. MANIPULER DES IMAGES

Figure 17.12 – Pixel rouge au milieu de pixels bleus.

354

Page 378: Programmez en Actionscript 3

OPÉRATIONS SUR LES IMAGES

– Utilisez deux boucles imbriquées pour « parcourir » les pixels de l’image.– Utilisez la méthode Math.random() pour générer un nombre aléatoire de 0 à 1 (quevous pouvez multiplier par 0xffffff pour avoir une couleur aléatoire).

– La classe BitmapData dispose des attributs width et height permettant d’obtenirla taille de l’image stockée dans l’objet, un peu comme pour les objets d’affichage.

J’obtiens la figure 17.13.

Figure 17.13 – Un beau tas de pixels.

Ne regardez pas tout de suite la solution que je vous propose si vous n’avez pas réfléchiau code qu’il faut écrire. Essayez d’obtenir un bon résultat et, même si vous n’y arrivezpas, rassurez-vous, le simple fait d’avoir essayé est déjà un grand pas vers la maîtrisedu langage.

Si vous avez réussi (ou que vous êtes sur le point de vous jeter par la fenêtre !), vouspouvez comparer votre code avec le mien (je n’ai vraiment pas envie d’avoir votre mortsur la conscience) :1 // Création de l'image2 var image:Bitmap = new Bitmap ();3 addChild(image);45 // Création des données de l'image (les pixels)6 var imageData:BitmapData = new BitmapData(300 , 300 , false ,

0x0000ff);78 // Données pour l'image9 image.bitmapData = imageData;

1011 ///// Barbouillage !12 // On parcourt chaque pixel de l'image13 // Lignes14 for (var x:int = 0; x < imageData.width; x ++)15 {16 // Colonnes17 for (var y:int = 0; y < imageData.height; y ++)

355

Page 379: Programmez en Actionscript 3

CHAPITRE 17. MANIPULER DES IMAGES

18 {19 // Couleur aléatoire20 couleur = Math.random () * 0xffffff;2122 // Colorions le pixel actuel23 imageData.setPixel32(x, y, couleur);24 }25 }

Et c’est tout ! Finalement, c’est plutôt simple non ?

Exercice : variante

Et si nous corsions un peu les choses ? Modifions l’exercice : il faut désormais que tousles pixels de l’image soient remplis avec une couleur choisie aléatoirement parmi unchoix limité : rouge, vert, bleu.

Quelques conseils :

– Utilisez un tableau pour stocker les couleurs autorisées.– Réutilisez la méthode Math.random() et la propriété length de votre tableau pourchoisir aléatoirement une couleur parmi celle du tableau.

J’obtiens cette fois-ci la figure 17.14.

Figure 17.14 – Pixels de trois couleurs

Solution :

1 ///// Barbouillage v 2.02 // On définit d'abord les couleurs possibles3 var couleurs:Array = [0xff0000 , 0x00ff00 , 0x0000ff ];45 // On parcourt chaque pixel de l'image6 // Lignes7 for (var x:int = 0; x < imageData.width; x ++)8 {

356

Page 380: Programmez en Actionscript 3

OPÉRATIONS SUR LES IMAGES

9 // Colonnes10 for (var y:int = 0; y < imageData.height; y ++)11 {12 // Choix de la couleur13 var choix:int = Math.random () * couleurs.length

;1415 // Couleur choisie16 couleur = couleurs[choix ];1718 // Colorions le pixel actuel19 imageData.setPixel32(x, y, couleur);20 }21 }

Remplissage un rectangle de couleur

Une autre méthode bien utile permet de remplir une zone rectangulaire avec unecouleur (avec transparence), ce qui nous simplifie tout de même la vie. Il s’agit defillRect(rectangle, couleur) de la classe BitmapData, qui prend en paramètre unobjet de la classe Rectangle et une couleur avec transparence.1 // Traçons un rectangle rouge2 imageData.fillRect(new Rectangle(0, 0, 150 , 100), 0xffff0000);

Notre image ressemble désormais à la figure 17.15.

Figure 17.15 – Un rectangle rouge sur fond bleu

Exercice : deuxième variante

Encore le même exercice ! Mais cette fois-ci, remplissons notre image avec de gros carrésde 25 pixels de côté d’une couleur choisie aléatoirement parmi le même choix limité :rouge, vert, bleu.

357

Page 381: Programmez en Actionscript 3

CHAPITRE 17. MANIPULER DES IMAGES

Quelques conseils :

– Utilisez un objet de la classe Rectangle pour stocker les coordonnées et la taille descarrés.

– Bien entendu, utilisez la méthode que nous venons de voir, fillRect() !

J’obtiens la figure 17.16.

Figure 17.16 – Le rendu

Et voici ce que j’ai écrit :

1 ///// Barbouillage v 3.02 // On définit d'abord les couleurs possibles3 var couleur:uint;4 var couleurs:Array = [0xff0000 , 0x00ff00 , 0x0000ff ];56 // On définit la taille des rectangles7 var rectangle:Rectangle = new Rectangle(0, 0, 25 , 25);89 // On parcourt l'image pour la remplir de rectangles

10 // Lignes11 for (rectangle.x = 0; rectangle.x < imageData.width; rectangle.

x += rectangle.width)12 {13 // Colonnes14 for (rectangle.y = 0; rectangle.y < imageData.height;

rectangle.y += rectangle.height)15 {16 // Choix de la couleur17 var choix:int = Math.random () * couleurs.length;1819 // Couleur choisie20 couleur = couleurs[choix ];2122 // Colorions le rectangle actuel23 imageData.fillRect(rectangle , couleur);

358

Page 382: Programmez en Actionscript 3

OPÉRATIONS SUR LES IMAGES

24 }25 }

Comme vous pouvez le remarquer, j’ai utilisé l’objet rectangle directement dans lesboucles for : le code en est d’autant plus logique et lisible.

En résumé– Pour embarquer une image, il suffit d’utiliser l’instruction spéciale Embed et définir

un attribut de type Class, comme pour les polices embarquées.– L’affichage d’une image se fait via la classe Bitmap dont la définition peut se fairegrâce aux images embarquées.

– La classe Bitmap dispose d’une propriété smoothing qui permet de lisser les pixelsd’une image, principalement utile après une transformation.

– L’ensemble des pixels d’une image sont stockés en mémoire à l’aide une instance dela classe BitmapData.

– La classe Bitmap possède donc une propriété nommée bitmapData de type BitmapDatadont l’édition est possible.

359

Page 383: Programmez en Actionscript 3

CHAPITRE 17. MANIPULER DES IMAGES

360

Page 384: Programmez en Actionscript 3

Chapitre 18Filtres et modes de fusion

Difficulté :

Dans ce chapitre, nous allons introduire les filtres et les modes de fusion ! Ils permettentde modifier facilement l’apparence de vos éléments graphiques à votre guise. Si certainsen ont déjà entendu parler dans divers logiciels de graphisme, vous ne serez pas perduspuisque le principe est le même et les effets sont assez semblables.

Avant de vous lancer dans la lecture de ce chapitre, je dois vous mettre en garde. Effec-tivement, celui-ci est composé de deux glossaires qui regroupent l’ensemble des filtres etmodes de fusion. Leur but est de pouvoir vous être utile plus tard lorsque vous en aurezbesoin, ne passez donc pas trop de temps dessus pour le moment, retenez simplement leprincipe général de ces effets.

361

Page 385: Programmez en Actionscript 3

CHAPITRE 18. FILTRES ET MODES DE FUSION

Les filtres

Introduction

Pour améliorer simplement le visuel de vos animations, vous pouvez utiliser les diffé-rents filtres proposés par l’Actionscript. Il s’agit d’effets graphiques que vous pouvezajouter à l’ensemble de vos éléments visuels. Vous disposez donc de neuf filtres quevous pouvez combiner selon vos préférences pour changer l’apparence d’un objet. Voici,par exemple, à la figure 18.1 une combinaison de deux filtres ajoutée à une image.

Figure 18.1 – Deux filtres ont été ajoutés à une image

Vous constaterez donc qu’il est alors possible de transformer radicalement le rendu finald’une scène. Parmi les filtres, vous trouverez plusieurs effets :

– Le flou.– L’ombre portée.– La lueur.– Le biseau.– Etc.

Avant de vous énumérer l’ensemble des filtres disponibles je vous propose de voir en-semble le principe d’utilisation de ceux-ci.

Création d’un exemple

Pour comprendre le fonctionnement des filtres, nous allons prendre un exemple.Je suggère donc que nous reprenions l’image ainsi que l’effet précédent. La figure 18.2représente l’image originale telle qu’elle est chargée à l’intérieur de l’animation. Vouspouvez évidemment travailler sur une image différente.

Nous allons donc charger notre image comme vous savez maintenant le faire :1 [Embed(source = 'images/Photo.png')]2 private var Photo:Class;

Puis nous allons l’instancier et l’ajouter à la liste d’affichage :1 var maPhoto:Bitmap = new Photo();2 this.addChild(maPhoto);

362

Page 386: Programmez en Actionscript 3

LES FILTRES

Figure 18.2 – L’image originale

Ajout de filtres

Chacun des neufs filtres est en fait défini par sa propre classe. Ainsi, ils pos-sèdent chacun leurs propres propriétés permettant de paramétrer l’effet correspon-dant. Dans l’exemple précédent, nous avons utilisé les deux classes BlurFilter etColorMatrixFilter. Nous apprendrons à utiliser ces classes plus tard, c’est pourquoi,je vous propose directement le code de ces deux effets.

Flou

1 var flou:BlurFilter = new BlurFilter ();2 flou.blurX = 2;3 flou.blurY = 2;4 flou.quality = BitmapFilterQuality.HIGH;

Correction colorimétrique

1 var matrix:Array = new Array ();2 matrix.push(0.75 , 0.75, 0.75, 0, 0); // Rouge3 matrix.push(0.50 , 0.50, 0.50, 0, 0); // Vert4 matrix.push(0.25 , 0.25, 0.25, 0, 0); // Bleu5 matrix.push(0, 0, 0, 1, 0); // Alpha6 var correctionCouleur:ColorMatrixFilter = new ColorMatrixFilter

(matrix);

363

Page 387: Programmez en Actionscript 3

CHAPITRE 18. FILTRES ET MODES DE FUSION

Application des filtres

Tout objet DisplayObject possède une propriété filters de type Array. Il est ainsipossible d’ajouter des filtres à sa guise en manipulant ce tableau. Ajoutons donc nosdeux filtres à l’initialisation de notre tableau filters :

1 maPhoto.filters = new Array(correctionCouleur , flou);

Nous obtenons ainsi notre image avec une correction de couleur et un flou comme lemontre la figure 18.3.

Figure 18.3 – L’image a été modifiée

Glossaire des filtres

Les filtres de base

Flou

Pour flouter un élément graphique, nous disposons de la classe BlurFilter :

1 var flou:BlurFilter = new BlurFilter ();2 flou.blurX = 5;3 flou.blurY = 5;4 flou.quality = BitmapFilterQuality.MEDIUM;

Le flou est ainsi définit par les propriétés suivantes :

– blurX : quantité de flou horizontal.

364

Page 388: Programmez en Actionscript 3

GLOSSAIRE DES FILTRES

– blurY : quantité de flou vertical.– quality : qualité du flou définie par les valeurs de la classe BitmapFilterQuality.

Le résultat se trouve à la figure 18.4.

Figure 18.4 – L’image est floutée

Ombres portées

Les ombres portées sont définies grâce à la classe DropShadowFilter :

1 var ombre:DropShadowFilter = new DropShadowFilter ();2 ombre.color = 0x333333;3 ombre.distance = 5;4 ombre.angle = -30;

Pour paramétrer votre ombre portée, utilisez les propriétés suivantes :

– color : couleur de l’ombre.– distance : distance « fictive » de l’objet à la surface derrière elle.– angle : orientation de la lumière et donc de l’ombre.

Le résultat se trouve à la figure 18.5.

Figure 18.5 – Une ombre portée a été ajoutée

365

Page 389: Programmez en Actionscript 3

CHAPITRE 18. FILTRES ET MODES DE FUSION

Lueur simple

Il est possible de créer une lueur ou un rayonnement derrière l’objet grâce à la classeGlowFilter :

1 var lueur:GlowFilter = new GlowFilter ();2 lueur.color = 0xFFAA66;3 lueur.blurX = 15;4 lueur.blurY = 15;5 lueur.quality = BitmapFilterQuality.MEDIUM;

Nous retrouvons ici des propriétés semblables à celles que nous avons déjà vu précé-demment, auxquelles vous pouvez en ajouter de nouvelles :

– alpha : opacité de la lueur.– strength : intensité du rayonnement.– inner : indique si l’ombre est interne ou non.– hideObject : indique si l’objet doit être visible ou non.

Le résultat se trouve à la figure 18.6.

Figure 18.6 – Une lueur simple

Lueur en dégradé

L’effet de rayonnement que nous venons d’aborder peut être personnalisé en ajou-tant un dégradé à la lueur. Pour cela, nous disposons de la classe GradientGlowFilter :

1 var lueur:GradientGlowFilter = new GradientGlowFilter ();2 lueur.distance = 0;3 lueur.angle = 45;4 lueur.colors = [0xFF0000 , 0x333333 ];5 lueur.alphas = [0, 1];6 lueur.ratios = [0, 255];7 lueur.blurX = 15;8 lueur.blurY = 15;9 lueur.strength = 2;

10 lueur.quality = BitmapFilterQuality.HIGH;11 lueur.type = BitmapFilterType.OUTER;

366

Page 390: Programmez en Actionscript 3

GLOSSAIRE DES FILTRES

Dans ce cas de figure, nous observons plusieurs nouveautés comme la définition dudégradé grâce aux propriétés colors, alphas et ratios ainsi que la définition de lalueur en interne ou en externe par le biais de la classe BitmapFilterType.

Le résultat se trouve à la figure 18.7.

Figure 18.7 – Une lueur en dégradé

Biseau simple

Pour donner du relief à un objet, vous pouvez définir un biseau à l’aide de la classeBevelFilter :

1 var biseau:BevelFilter = new BevelFilter ();2 biseau.distance = 5;3 biseau.angle = 45;4 biseau.highlightColor = 0xFFFFFF;5 biseau.highlightAlpha = 0.5;6 biseau.shadowColor = 0x000000;7 biseau.shadowAlpha = 0.5;8 biseau.blurX = 3;9 biseau.blurY = 3;

10 biseau.strength = 3;11 biseau.quality = BitmapFilterQuality.HIGH;12 biseau.type = BitmapFilterType.INNER;

Pour définir ce filtre, vous aurez principalement besoin de définir la distance de l’effetainsi que des effets de lueurs et d’ombres définis par les couleurs et opacités highlightColor,highlightAlpha, shadowColor et shadowAlpha.

Le résultat se trouve à la figure 18.8.

Biseau en dégradé

Une variante de biseau existe grâce à l’utilisation d’un dégradé dans la classe GradientBevelFilter :

1 var biseau:GradientBevelFilter = new GradientBevelFilter ();

367

Page 391: Programmez en Actionscript 3

CHAPITRE 18. FILTRES ET MODES DE FUSION

Figure 18.8 – Un biseau simple

2 biseau.distance = 6;3 biseau.angle = 60;4 biseau.colors = [0x000000 , 0x006666 , 0xFFFFFF ];5 biseau.alphas = [1, 0, 1];6 biseau.ratios = [0, 128 , 255];7 biseau.blurX = 6;8 biseau.blurY = 6;9 biseau.quality = BitmapFilterQuality.HIGH;

Là encore, la principale différence par rapport à la version simple est la définition d’undégradé de couleurs.

Le résultat se trouve à la figure 18.9.

Figure 18.9 – Un biseau en dégradé

Correction de couleurs

Un peu de théorie

Pour effectuer des corrections au niveau des couleurs, il existe la classe ColorMatrixFilter.Comme son nom l’indique, elle est composée d’une matrice qui permet de redéfinirla couleur d’un pixel. Ainsi, les lignes redéfinissent, dans l’ordre, les composantes sui-vantes d’un pixel : rouge, vert, bleu et alpha. Les différentes composantes de celles-cipeuvent alors s’écrire suivant la forme suivante :

368

Page 392: Programmez en Actionscript 3

GLOSSAIRE DES FILTRES

fcanal(x, y) = αR × srouge(x, y) + αV × svert(x, y) + αB × sbleu(x, y) + αA × salpha(x, y) + α.Où :

– srouge(x, y), svert(x, y), sbleu(x, y) et salpha(x, y) sont les composantes rouge, vert,bleu et alpha du pixel source.

– αR, αV , αB et αA représentent leur contribution dans la valeur du canal de sortie.– α est une constante.

En réalité, cette matrice est décrite à l’intérieur d’un tableau de 20 éléments. Chaqueligne est alors définie par une succession de 5 coefficients. Voici donc notre « pseudo-matrice » A dans laquelle les colonnes correspondent aux composantes du pixel d’origineet les lignes aux composantes du pixel final :

srouge svert sbleu salphafrouge A[0] A[1] A[2] A[3] A[4]fvert A[5] A[6] A[7] A[8] A[9]fbleu A[10] A[11] A[12] A[13] A[14]falpha A[15] A[16] A[17] A[18] A[19]

En suivant cette logique, l’image serait inchangée par application de la matrice sui-vante :

1 0 0 0 00 1 0 0 00 0 1 0 00 0 0 1 0

Afin de mieux comprendre ce dont il est question, je vous propose à la suite diversexemples d’utilisation de cette classe ColorMatrixFilter.

Saturation

Cette technique consiste à saturer les couleurs afin d’obtenir une image finale en noiret blanc. Il faut alors que chaque pixel dispose au final de la même quantité de rouge,de vert et de bleu. Voici comment réaliser cela :

1 var matrix:Array = new Array ();2 matrix.push(0.33 , 0.33, 0.33, 0, 0); // Rouge3 matrix.push(0.33 , 0.33, 0.33, 0, 0); // Vert4 matrix.push(0.33 , 0.33, 0.33, 0, 0); // Bleu5 matrix.push(0, 0, 0, 1, 0); // Alpha6 var correctionCouleur:ColorMatrixFilter = new ColorMatrixFilter

(matrix);

Le résultat se trouve à la figure 18.10.

Pour ne pas modifier la luminosité globale de l’image, veillez à obtenir untotal de 1 sur l’ensemble d’une ligne. Autrement, les valeurs originalementcomprise entre 0 et 255 seront disproportionnées et l’image n’aura pas lerendu désiré.

369

Page 393: Programmez en Actionscript 3

CHAPITRE 18. FILTRES ET MODES DE FUSION

Figure 18.10 – Un effet de saturation

Luminosité

En parlant de luminosité, il est justement possible de la contrôler en jouant sur lavaleur de ces coefficients. Nous pouvons alors diminuer cette luminosité par exemple :

1 var matrix:Array = new Array();2 matrix.push(0.5, 0, 0, 0, 0); // Rouge3 matrix.push(0, 0.5, 0, 0, 0); // Vert4 matrix.push(0, 0, 0.5, 0, 0); // Bleu5 matrix.push(0, 0, 0, 1, 0); // Alpha6 var correctionCouleur:ColorMatrixFilter = new ColorMatrixFilter

(matrix);

Le résultat se trouve à la figure 18.11.

Figure 18.11 – Il est possible de jouer sur la luminosité

Le réglage de la luminosité est le seul cas où vous pouvez modifier la sommetotale des coefficients. Pour tout le reste, respectez au maximum cette règle.

370

Page 394: Programmez en Actionscript 3

GLOSSAIRE DES FILTRES

Teinte

La teinte est plus difficile à gérer car la « rotation » des couleurs est généralementsuivie d’une saturation. Toutefois, je vous donne l’exemple d’un décalage de 120˚ dansles couleurs, ce qui revient à décaler le vert au rouge, le bleu au vert, etc. :

1 var matrix:Array = new Array ();2 matrix.push(0, 0, 1, 0, 0); // Rouge3 matrix.push(1, 0, 0, 0, 0); // Vert4 matrix.push(0, 1, 0, 0, 0); // Bleu5 matrix.push(0, 0, 0, 1, 0); // Alpha6 var correctionCouleur:ColorMatrixFilter = new ColorMatrixFilter

(matrix);

Le résultat se trouve à la figure 18.12.

Figure 18.12 – Il est possible de « décaler » les couleurs

Pour ce genre de manipulations, je vous conseille plutôt de passer par votrelogiciel de graphisme préféré.

Négatif

Un effet négatif consiste à inverser les couleurs, c’est-à-dire soustraire les valeursd’origine à la valeur maximale 255. Dans ce cas, nous aurons alors besoin d’utiliser uneconstante, comme vous pouvez le voir ci-dessous :

1 var matrix:Array = new Array ();2 matrix.push(-1, 0, 0, 0, 255); // Rouge3 matrix.push(0, -1, 0, 0, 255); // Vert4 matrix.push(0, 0, -1, 0, 255); // Bleu5 matrix.push(0, 0, 0, 1, 0); // Alpha6 var correctionCouleur:ColorMatrixFilter = new ColorMatrixFilter

(matrix);

Le résultat se trouve à la figure 18.13.

371

Page 395: Programmez en Actionscript 3

CHAPITRE 18. FILTRES ET MODES DE FUSION

Figure 18.13 – L’image en négatif

Les constantes ne sont pas des coefficients comme les précédents. Ainsi,ceux-ci ne s’utilisent pas entre -1 et 1 comme les autres, mais plutôt entre-255 et 255.

Convolution

Introduction

La convolution utilisée par la classe ConvolutionFilter fonctionne également à l’aided’une matrice. Néanmoins, celle-ci est une représentation d’un pixel et de ses voisinsproches. Cette matrice peut théoriquement être de dimension quelconque, toutefoisnous nous contenterons d’une matrice 3 × 3 pour la suite. Ainsi, la valeur centralereprésente le pixel actuel et les autres valeurs, les pixels alentours. La couleur finaled’un pixel est alors déterminée à partir de sa valeur initiale et de celles des pixelsvoisins. Une image intacte est donc composé uniquement de la valeur 1 au centre de lamatrice :

0 0 00 1 00 0 0

Ici, la valeur de chaque pixel est une combinaison de la valeurs de plusieurspixels. Ainsi, il est important d’avoir un total égal à 1 pour conserver laluminosité globale de l’image initiale.

Avant de vous montrer différents exemples d’application, je vous présente ici la manièred’utiliser ce filtre en Actionscript :

1 var matrix:Array = new Array();2 // Définition de la matrice3 var convolution:ConvolutionFilter = new ConvolutionFilter ();4 convolution.matrixX = 3;5 convolution.matrixY = 3;6 convolution.matrix = matrix;

372

Page 396: Programmez en Actionscript 3

GLOSSAIRE DES FILTRES

Vous remarquerez alors que la matrice est également définie à l’aide d’un tableau detype Arraydont il est nécessaire de spécifier les dimensions à l’aide des propriétésmatrixX et matrixY.

Flou

L’application la plus simple est donc de générer un flou en « moyennant » la valeur dupixel central à celle des pixels voisins :1 var matrix:Array = new Array ();2 matrix.push(0, 0.2, 0);3 matrix.push(0.2, 0.2, 0.2),4 matrix.push(0, 0.2, 0);

Le résultat se trouve à la figure 18.14.

Figure 18.14 – L’image est floue

Il pourrait également être possible de prendre en compte la valeur des pixels en diago-nale pour la génération de ce flou.

Détection de contours

La convolution est principalement utile pour détecter les contours à l’intérieurd’une image. Le principe est alors de retrancher la valeur des pixels voisins et ainsi ré-véler les zones où les pixels proches n’ont pas une valeur identique. Voici donc commentdétecter des contours :1 var matrix:Array = new Array ();2 matrix.push(0, -1, 0);3 matrix.push(-1, 4, -1),4 matrix.push(0, -1, 0);

Le résultat se trouve à la figure 18.15.

Notez que cette opération peut également être effectuée uniquement en ho-rizontal ou en vertical, on même en diagonal !

373

Page 397: Programmez en Actionscript 3

CHAPITRE 18. FILTRES ET MODES DE FUSION

Figure 18.15 – Détection des contours

Accentuation de contours

Si vous avez bien regardé la matrice de détection de contours, vous noterez quela somme des valeurs est nulle. Nous avons alors perdu des informations concernantl’image. Ainsi, en rajoutant 1 au centre, il est possible de transformer cette détectionde contours en accentuation de contours. Voyez donc ce que cette nouvelle matriceprovoque :

1 var matrix:Array = new Array();2 matrix.push(0, -1, 0);3 matrix.push(-1, 5, -1),4 matrix.push(0, -1, 0);

Le résultat se trouve à la figure 18.16.

Figure 18.16 – Accentuation des contours

Estampage

Cette détection de contours permet également de créer un effet d’estampage pourfaire ressortir le « relief » de l’image. Voici comment procéder :

1 var matrix:Array = new Array();2 matrix.push(-2, -1, 0);3 matrix.push(-1, 1, 1),4 matrix.push(0, 1, 2);

374

Page 398: Programmez en Actionscript 3

GLOSSAIRE DES FILTRES

Le résultat se trouve à la figure 18.17.

Figure 18.17 – Estampage de l’image

Dans l’exemple précédent, nous avions des valeurs négatives dans le coin supérieurgauche et des valeurs positives dans le coin opposé, ce qui a pour effet de « creuser »l’image. En inversant ces valeurs, vous obtiendrez donc l’effet inverse.

Mappage de déplacement

Enfin, la classe DisplacementMapFilter est le dernier filtre en Flash. Celui-ci permetd’utiliser ce qu’on appelle une carte de déplacement pour déformer une image.Le déplacement est alors créé à partir des différents canaux de cette « carte ». Dansl’exemple que nous verrons par la suite, nous avons ainsi défini le canal de couleur bleuepour l’affectation de la position en x, et le canal de couleur rouge de celui en y. Voicidonc notre image de mappage du déplacement à la figure 18.18.

Figure 18.18 – Mappage du déplacement

Vous noterez que le déplacement se fait suivant la valeur du canal de couleurcorrespondant. C’est pourquoi, la valeur 127 n’affecte aucun déplacement,contrairement aux valeurs 255 et 0 qui provoquent un déplacement maximaldans des directions opposées.

Voici donc comment utiliser cette image de mappage du déplacement chargée grâce àla classe Class sous le nom de Deplacement :

1 var monDeplacement:Bitmap = new Deplacement ();2 // Définition de la carte de déplacement3 var map:BitmapData = new BitmapData(monDeplacement.width ,

monDeplacement.height);

375

Page 399: Programmez en Actionscript 3

CHAPITRE 18. FILTRES ET MODES DE FUSION

4 map.draw(monDeplacement);5 // Création du filtre6 var deplacement:DisplacementMapFilter = new

DisplacementMapFilter ();7 deplacement.mapBitmap = map;8 deplacement.componentX = BitmapDataChannel.BLUE;9 deplacement.componentY = BitmapDataChannel.RED;

10 deplacement.scaleX = 60;11 deplacement.scaleY = 60;12 deplacement.mode = DisplacementMapFilterMode.IGNORE;

Comme vous l’avez certainement deviné, les canaux de couleurs sont choisis grâce à laclasse BitmapDataChannel et l’échelle d’affectation est spécifiée à l’aide des proprié-tés scaleX et scaleY. Enfin, les constantes de la classe DisplacementMapFilterModepermettent de gérer l’affectation des pixels sur les bords de l’image.

Le résultat se trouve à la figure 18.19.

Figure 18.19 – Image modifiée

Les modes de fusion

Définition

Un autre moyen d’améliorer rapidement et facilement le rendu final de vos objetsvisuels est l’utilisation de modes de fusion ! Lorsqu’on parle de fusion, il s’agit enfait de « mixer » différents éléments graphiques ensemble. Le principe est alors de gérerla manière dont ces différents objets seront fusionnés dans le rendu final. Les modesde fusion sont donc également une manière rapide de transformer l’apparence de vosobjets d’affichage.

376

Page 400: Programmez en Actionscript 3

LES MODES DE FUSION

Fusion de calque

La première utilité de ces modes de fusion est de pouvoir combiner différents objetssuperposés, nommés communément calques, en fusionnant leurs couleurs. Voici à lafigure 18.20 un exemple de fusion entre deux calques.

Figure 18.20 – Fusion de deux images

Pour bien distinguer les filtres et les modes de fusions, retenez qu’un filtres’applique à un unique objet, contrairement aux modes de fusions qui né-cessitent au moins deux objets pour pouvoir être actifs.

Fusion de transparence

La seconde utilisation de ces modes de fusion est la fusion de transparence. Leprincipe est d’utiliser les niveaux de transparence d’un calque pour masquer certainesparties d’un second élément. Voici un exemple à la figure 18.21.

Figure 18.21 – Fusion de transparence

Une autre manière de gérer l’opacité de certaines zones d’un élément estl’utilisation de masques, comme nous le verrons dans le chapitre suivant.

377

Page 401: Programmez en Actionscript 3

CHAPITRE 18. FILTRES ET MODES DE FUSION

Mise en place

La fusion de calques peut être réalisée entre n’importe quels objets héritant de laclasse DisplayObject. Ceux-ci disposent alors d’une propriété nommée blendModepour définir le mode de fusion désiré. Cette définition est alors réalisée à l’aide desconstantes de la classe BlendMode.

La définition d’un mode de fusion se fait en réalité uniquement sur un seulcalque. Vous devez alors l’appliquer sur l’objet possédant l’index d’affichagele plus grand, autrement l’effet de sera pas visible.

Voici donc comment ajouter le mode de fusion nommée DARKEN à l’objet monCalque :1 monCalque.blendMode = BlendMode.DARKEN;

Toutefois, en ce qui concerne les fusions de transparence, vous aurez égalementbesoin d’imposer la création d’un groupe de transparences pour l’objet d’affichage.Cela consiste à appliquer un mode de fusion de type LAYER au conteneur :1 this.blendMode = BlendMode.LAYER;

Voilà, vous connaissez tout sur les modes de fusion à présent. Il ne nous reste plusqu’à faire un tour des treize modes de fusion disponibles. Pour vous aider, je vouspropose un petit glossaire.

Glossaire de modes de fusion

Le mode de fusion par défaut

Tout objet d’affichage possède obligatoirement un seul et unique mode de fusion.Ainsi, il existe un mode de fusion nommé NORMAL qui est appliqué par défaut à toutobjet. Voici donc comment redéfinir le mode de fusion :1 monCalque.blendMode = BlendMode.NORMAL;

Le résultat se trouve à la figure 18.22.

Ce mode n’a aucune utilité, si ce n’est de revenir au mode de fusion pardéfaut.

Les fusions de calques

Addition

Comme son nom l’indique, ce mode de fusion va additionner les différents canauxde couleurs du calque à ceux de l’arrière-plan. Pour utiliser celui-ci, vous disposez le la

378

Page 402: Programmez en Actionscript 3

GLOSSAIRE DE MODES DE FUSION

Figure 18.22 – Fusion par défaut

constante ADD :

1 monCalque.blendMode = BlendMode.ADD;

Le résultat se trouve à la figure 18.23.

Figure 18.23 – Fusion par addition

Ce mode de fusion aura donc tendance à éclaircir l’arrière-plan. Celui-ci peut êtreutilisé pour créer des transitions entre deux objets en utilisant un fondu d’éclaircisse-ment.

Obscurcir

Ce mode de fusion permet de sélectionner les valeurs les plus faibles des canaux decouleurs entre le calque et l’arrière-plan. Il est défini par la constante DARKEN :

1 monCalque.blendMode = BlendMode.DARKEN;

Le résultat se trouve à la figure 18.24.

Bien évidement, en l’utilisant vous allez obscurcir l’arrière plan. L’assombrissement esttoutefois moins intense qu’avec le mode de fusion MULTIPLY.

379

Page 403: Programmez en Actionscript 3

CHAPITRE 18. FILTRES ET MODES DE FUSION

Figure 18.24 – L’image est obscurcie

Différence

Le principe ici est de soustraire, pour chacun des canaux de couleurs, la valeur la plussombre des deux de la plus claire. Voici la constante concernée :

1 monCalque.blendMode = BlendMode.DIFFERENCE;

Le résultat se trouve à la figure 18.25.

Figure 18.25 – Fusion par différence de couleur

L’utilisation de ce mode de fusion n’est pas très courante car il est difficile de prévoirl’apparence finale. Utilisez donc celui-ci avec précaution !

Lumière crue

Le principe de cemode de fusion est relativement complexe. Néanmoins, vous pouvezretenir qu’il permet de faire ressortir et d’assombrir les ombrages d’une image. Le nomde la constante qui le définit est HARDLIGHT :

1 monCalque.blendMode = BlendMode.HARDLIGHT;

Le résultat se trouve à la figure 18.26.

Notez que celui-ci a tendance a masquer les couleurs claires de l’arrière-plan.

380

Page 404: Programmez en Actionscript 3

GLOSSAIRE DE MODES DE FUSION

Figure 18.26 – Les ombres sont mises en valeur

Négatif

Le principe de cet effet, que nous avons déjà vu auparavant, est d’inverser les valeurssur chacun des canaux de couleurs. Il est défini par la constante INVERT :

1 monCalque.blendMode = BlendMode.INVERT;

Le résultat se trouve à la figure 18.27.

Figure 18.27 – Inversion de la couleur de chaque pixel

La couleur d’origine du calque où le mode de fusion est appliqué n’a ici aucun effet surle rendu final. Il s’agit également d’un mode de fusion peu courant.

Éclaircir

Dans ce mode de fusion, les valeurs de canaux de couleurs de couleurs retenues sontcelles qui sont les plus claires entre le calque et l’arrière-plan. Il s’agit du mode defusion opposé à DARKEN. Voici sa constante :

1 monCalque.blendMode = BlendMode.LIGHTEN;

Le résultat se trouve à la figure 18.28.

Ce dernier est également moins éclaircissant que le mode de fusion ADD.

381

Page 405: Programmez en Actionscript 3

CHAPITRE 18. FILTRES ET MODES DE FUSION

Figure 18.28 – Éclaicissement de l’image

Produit

Dans ce mode de fusion, les valeurs des canaux de couleurs du calque et de l’arrière-plan sont multipliées entre elles puis sont « normalisées ». La constante correspondanteest MULTIPLY :

1 monCalque.blendMode = BlendMode.MULTIPLY;

Le résultat se trouve à la figure 18.29.

Figure 18.29 – Multiplication des couleurs

L’effet produit est un assombrissement de l’arrière-plan. Ce mode de fusion proche deDARKEN est toutefois plus radical dans l’obscurcissement.

Incrustation

Le principe de fonctionnement de cemode de fusion est plutôt complexe. La constanteutilisée est OVERLAY :

1 monCalque.blendMode = BlendMode.OVERLAY;

Le résultat se trouve à la figure 18.30.

Proche de HARDLIGHT, ce mode de fusion est généralement très utilisé. Le rendu finalest néanmoins légèrement différent de ce dernier dans les couleurs claires qui restentquasi-intactes.

382

Page 406: Programmez en Actionscript 3

GLOSSAIRE DE MODES DE FUSION

Figure 18.30 – Incrustation des couleurs

Écran

La particularité de ce mode de fusion est de supprimer toute nuance de noir ducalque. Il ne reste ensuite plus que la couleur « brute » de celui-ci. La constante qui ledéfinit est SCREEN :

1 monCalque.blendMode = BlendMode.SCREEN;

Le résultat se trouve à la figure 18.31.

Figure 18.31 – Mode de fusion écran

Ce mode de fusion a donc pour effet d’éclaircir l’arrière-plan.

Soustraction

Comme vous vous en doutez, ce mode de fusion va soustraire les différents ca-naux de couleurs du calque à ceux de l’arrière-plan. Celui-ci correspond à la constanteSUBTRACT :

1 monCalque.blendMode = BlendMode.SUBTRACT;

Le résultat se trouve à la figure 18.32.

Ce mode de fusion est donc l’opposé de ADD. Ainsi, il peut être utilisé pour créer destransitions en utilisant cette fois un fondu d’assombrissement.

383

Page 407: Programmez en Actionscript 3

CHAPITRE 18. FILTRES ET MODES DE FUSION

Figure 18.32 – Soustration des couleurs

Les fusions de transparence

Transparence

Ce mode de fusion permet d’appliquer les niveaux de transparence du calque àl’arrière-plan. Comme nous l’avons dit, ce type de fusion nécessite de modifier éga-lement le mode de fusion du conteneur. Voici donc comment réaliser cette opérationgrâce à la constante ALPHA :

1 this.blendMode = BlendMode.LAYER;2 monCalque.blendMode = BlendMode.ALPHA;

Le résultat se trouve à la figure 18.33.

Figure 18.33 – Transfert de la transparence

Je rappelle qu’il existe une autre méthode qui consiste à définir des masquesque nous introduirons dans le chapitre suivant. Personnellement, je vousconseillerai d’utiliser les masques plutôt que la fusion de transparence.

Suppression

Le principe ici est l’opposé de ALPHA. Ainsi, les niveaux de transparence du calque sontmaintenant soustraits de l’arrière-plan. Le nom de la constante correspondant est donc

384

Page 408: Programmez en Actionscript 3

GLOSSAIRE DE MODES DE FUSION

ERASE :

1 this.blendMode = BlendMode.LAYER;2 monCalque.blendMode = BlendMode.ERASE;

Le résultat se trouve à la figure 18.34.

Figure 18.34 – Suppression de l’opacité

Ce mode de fusion est également moins courant. Évitez de l’utiliser si vouspouvez contourner le problème en ajustant l’ordre d’affichage des différentséléments graphiques.

En résumé– Les filtres sont des effets qui sont applicables à tout objet graphique.– Il existe neuf filtres en Actionscript, regroupés dans le package flash.filters.– Chaque filtre est associé à une classe, dont les propriétés permettent de décrirel’effet correspondant.

– Ceux-ci sont ensuite ajoutés à la propriété filters de type Array de tout objetDisplayObject.

– Les modes de fusion permettent de définir la manière dont plusieurs élémentsdoivent être fusionner lors de l’affichage final.

– Chaque élément héritant de DisplayObject dispose d’un unique mode de fusiondéfini dans la propriété blendMode.

– Tous cesmodes de fusion sont définis à l’aide des constantes de la classe BlendMode.

385

Page 409: Programmez en Actionscript 3

CHAPITRE 18. FILTRES ET MODES DE FUSION

386

Page 410: Programmez en Actionscript 3

Chapitre 19Les masques

Difficulté :

Pour le dernier chapitre théorique de cette partie sur l’affichage, je vous propose de décou-vrir lesmasques ! Ce concept qui permet de cacher certaines zones d’un objet affichage, estspécifique à l’Actionscript et à la technologie Flash. Pour ceux qui utilisent des logicielsde 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 vraimenttrès pratique et très utilisée.

387

Page 411: Programmez en Actionscript 3

CHAPITRE 19. LES MASQUES

Un masque. . . qui ne masque pas

Le principe des masques

Lorsque vous créez des éléments graphiques, il est possible que vous ayez besoin d’isolerune certaine partie de l’objet d’affichage en question. C’est pourquoi vous aurez besoinde séparer la zone visible de la zone à cacher. Pour cela, nous utilisons ce qu’on appelledes masques !

Qu’est-ce qu’un masque ?

Un masque est un élément graphique comme un autre. On retrouve alors des masquesde type Shape, Sprite ou encore Bitmap. Celui-ci sert alors à délimiter la zone visibled’un autre objet d’affichage, définie par l’opacité du masque.

Pour bien comprendre cette notion, je vous propose à la figure 19.1 un petit schéma.

Figure 19.1 – Principe d’utilisation des masques

Comme vous pouvez le voir, nous avons donc défini un masque circulaire qui laisseapparaître la photo uniquement à l’intérieur de celui-ci. Bien évidemment, un masquepeut être extrêmement complexe et composé de différentes formes. Par exemple, nousaurions pu suivre les courbes du serpent pour pouvoir l’isoler du reste de l’image.

Dans l’exemple précédent, comme dans la suite du chapitre, j’utiliserai exclu-sivement des masques de couleur verte. Cela vous permettra de bien discernerles masques des objets d’affichage « classiques ».

Les masques en Flash

Définition du masque

Avant d’appliquer un masque à un objet visuel quelconque, il est nécessaire de définirces deux éléments. Pour commencer, je vous suggère un exemple relativement simple.Nous allons donc démarrer par deux objets Shape où nous dessinerons des formesbasiques.

388

Page 412: Programmez en Actionscript 3

UN MASQUE. . . QUI NE MASQUE PAS

Dans ce chapitre, nous nous contenterons de définir des masques dessinésgrâce aux méthodes de la classe Graphics. Toutefois, le principe avec desimages « bitmap » est strictement identique. Il faudra néanmoins prendre encompte le canal alpha, comme nous le verrons dans la suite du chapitre.

Voici donc nos deux éléments monObjet et masque contenant respectivement un rec-tangle orange et un cercle vert :

1 var monObjet:Shape = new Shape();2 var masque:Shape = new Shape ();3 this.addChild(monObjet);4 this.addChild(masque);56 monObjet.graphics.beginFill(0xFF8800);7 monObjet.graphics.drawRect(0, 0, 100 , 100);8 monObjet.graphics.endFill ();9

10 masque.graphics.beginFill(0x00FF00);11 masque.graphics.drawCircle(50, 50 , 50);12 masque.graphics.endFill ();

Nous avons ici placé l’objet masque au premier plan, ce qui donne la figure 19.2.

Figure 19.2 – L’objet et son masque

Lorsque vous définissez un masque avec les méthodes de la classe Graphics,seuls les remplissages sont utilisés pour définir le masque. Les lignes serontalors tout simplement ignorées.

L’objectif consiste donc maintenant à définir l’objet de couleur verte comme masquepour l’élément monObjet.

Une propriété mask

En fait, la notion de masque est liée à tout objet visuel, c’est-à-dire tout objet dela classe DisplayObject ou plutôt d’une de ses sous-classes. Nous avons déjà vuqu’une classe peut posséder un attribut d’elle-même ; la classe DisplayObject est jus-tement l’une d’elles. En effet, celle-ci possède une propriété nommée mask de typeDisplayObject !

Ainsi, avec les objets de type Shape déclarés précédemment, il est possible de fairececi :

389

Page 413: Programmez en Actionscript 3

CHAPITRE 19. LES MASQUES

1 monObjet.mask = masque;

Dans cette instruction, nous passons bien l’objet masque à la propriété mask de l’élémentmonObjet. Si vous relancez alors l’exécution du projet, vous verrez la magie s’opérer(voir figure 19.3).

Figure 19.3 – Effet du masque sur l’objet

Comme vous pouvez le constater, le masque n’est maintenant plus visible.C’est pourquoi, l’instruction this.addChild(masque) est en réalité faculta-tive. Toutefois, si vous n’ajoutez pas le masque à la liste d’affichage, celui-cine sera alors pas affecté par les éventuelles transformations du conteneur.Pour éviter tout problème, je vous conseille donc de l’ajouter à chaque fois àla liste d’affichage.

Pour finir, veuillez noter qu’il est possible de supprimer le masque d’un objet simple-ment en définissant sa propriété mask à null.

Niveaux de transparence multiples

Présentation du concept

Comme nous l’avons vu précédemment, nous pouvons définir la forme d’un masquepour isoler certaines zones d’un objet d’affichage. Toutefois, il est également possiblede définir la transparence de celui-ci en gérant l’opacité du masque. Rien ne nousempêche alors d’utiliser des niveaux de transparence multiples. Pour illustrercela, je vous propose à la figure 19.4 un exemple de masque à plusieurs niveaux detransparence.

Figure 19.4 – Principe des niveaux de transparence multiples

Comme le montre l’illustration précédente, l’objet d’affichage adapte donc sa transpa-rence à l’opacité du masque qui lui est associé. Nous verrons alors qu’il est possible

390

Page 414: Programmez en Actionscript 3

NIVEAUX DE TRANSPARENCE MULTIPLES

d’utiliser des dégradés pour définir un masque ou bien utiliser directement une image« bitmap » dont le format supporte la transparence.

Place au code

Création du masque

Pour définir différents niveaux de transparence, il est nécessaire de « jouer » avecl’opacité des remplissages. Je suggère alors que nous réalisions un masque composé detrois disques qui se superposent partiellement. Voici le code que je vous propose pourfaire cela :

1 // Objet à masquer2 monObjet.graphics.beginFill(0xFF00FF);3 monObjet.graphics.drawRect(0, 0, 160 , 150);4 monObjet.graphics.endFill ();5 // Masque6 masque.graphics.beginFill(0x00FF00 ,0.5);7 masque.graphics.drawCircle(80, 50 , 50);8 masque.graphics.endFill ();9 masque.graphics.beginFill(0x00FF00 ,0.5);

10 masque.graphics.drawCircle(50, 100 , 50);11 masque.graphics.endFill ();12 masque.graphics.beginFill(0x00FF00 ,0.5);13 masque.graphics.drawCircle(110 , 100 , 50);14 masque.graphics.endFill ();

Nous avons donc ici réalisé un masque composé de trois niveaux de transparence diffé-rents comme vous pouvez le voir à la figure 19.5.

Figure 19.5 – Un masque à plusieurs niveaux de transparence

Mise en place du masque

Redéfinissons maintenant la propriété mask de monObjet comme nous avons appris àle faire :

1 monObjet.mask = masque;

391

Page 415: Programmez en Actionscript 3

CHAPITRE 19. LES MASQUES

Vous serez alors surpris de découvrir que ce masque ne fonctionne pas comme nousl’avions prévu, mais réagit comme si nous avions laissé une opacité maximale pour nosremplissages. Regardez plutôt la figure 19.6.

Figure 19.6 – Mauvaise application d’un masque à plusieur niveaux de transparence

En réalité, pour pouvoir gérer la transparence d’un masque, nous devonsutiliser une mise en cache sous forme de bitmap. L’élément graphique estalors géré comme s’il s’agissait d’une image « bitmap » en tenant compte duniveau de transparence de chacun de ses pixels.

Le cache bitmap

Tout objet de type DisplayObject possède une propriété nommée cacheAsBitmap.Celle-ci permet d’activer la «mise en cache sous forme de bitmap », en la définis-sant tout simplement à true. Habituellement, les objets d’affichage sont manipuléspar le lecteur Flash comme s’il s’agissait d’objets vectoriels, ce qui donne de bonnesperformances la plupart du temps, mais implique quelques limitations, comme celleque nous venons de rencontrer. Lorsqu’un objet d’affichage est mis en cache sousforme de bitmap, il est d’abord rendu sous forme d’image contenant des pixels, puismanipulé par le lecteur Flash. Cela nous permet donc d’effectuer des opérations pluscomplexes (comme les masques à plusieurs niveaux de transparence). Ainsi, il nous fautactiver ce cache sur le masque, mais également sur l’objet auquel il est appliqué. Voicicomment procéder pour appliquer le masque à l’objet :

1 monObjet.cacheAsBitmap = true;2 masque.cacheAsBitmap = true;3 monObjet.mask = masque;

Cette fois, vous verrez apparaître les différents niveaux de transparence tels qu’ils ontété définis durant la création du masque. Nous obtenons la figure 19.7.

Cette mise cache est également nécessaire lorsqu’on travaille avec des objetsde type Bitmap. Le format d’image choisi doit néanmoins utiliser un canalalpha, comme c’est le cas des formats GIF ou PNG. La transparence estalors utilisée pour définir le masque à partir de cette image.

392

Page 416: Programmez en Actionscript 3

EXERCICE : UNE LAMPE TORCHE

Figure 19.7 – Application correcte d’un masque à plusieurs niveaux de tranparence

Mettre un objet d’affichage en cache bitmap a un impact sur les perfor-mances : ainsi, il est plus rapide de déplacer l’objet en cache bitmap, maisles transformations comme la rotation ou le redimensionnement ralentissentl’application de façon significative. Pour résumer, si vous voulez afficher ungrand nombre d’objets qui se déplacent, vous pouvez améliorer les perfor-mances de votre application en activant la mise en cache bitmap, à conditionde ne pas leur appliquer de transformations.

Exercice : une lampe torche

Pour terminer ce chapitre, nous allons réaliser un petit exercice ensemble. Nous allonscréer une lampe torche à partir de deux images et d’un masque. Cet exercice ne com-porte aucune difficulté, contentez-vous uniquement de suivre ces différentes étapes avecmoi.

Préparation des images

Rue de nuit

Pour commencer, je vous invite à créer un dossier nommé images où nous placeronsnos deux images. Dans un premier temps, nous aurons besoin de l’image d’une ruesombre qui servira de fond pour notre projet. Voici à la figure 19.8 l’image que j’ainommée « RueSombre.png ».

Cette image sera ainsi notre rue lorsqu’elle n’est pas éclairée par la lampe torche. Nousviendrons donc ajouter une partie lumineuse par dessus pour simuler l’effet d’une lampetorche.

Rue éclairée par la lampe

Lorsque notre lampe torche passera sur une zone, celle-ci sera éclairée presque comme enplein jour. Nous aurons alors besoin d’une seconde image de cette même rue, mais cettefois beaucoup plus lumineuse. Voici donc notre seconde image « RueEclairee.png »(figure 19.9).

393

Page 417: Programmez en Actionscript 3

CHAPITRE 19. LES MASQUES

Figure 19.8 – RueSombre.png

394

Page 418: Programmez en Actionscript 3

EXERCICE : UNE LAMPE TORCHE

Figure 19.9 – RueEclairee.png

395

Page 419: Programmez en Actionscript 3

CHAPITRE 19. LES MASQUES

La lampe torche n’agissant que sur une certaine partie de la rue, c’est cette image quisubira l’effet du masque que nous créerons juste après.

Chargement des images

En premier lieu, nous allons importer nos images dans notre animation Flash. Pourcela, nous créerons deux variables de type Class que nous appellerons RueSombre etRueEclairee comme vous avez appris à le faire. Voici toutefois le code correspondantpour ceux qui auraient déjà oublié :

1 // Chargement des images2 [Embed(source = 'images/RueSombre.png')]3 private var RueSombre:Class;4 [Embed(source = 'images/RueEclairee.png')]5 private var RueEclairee:Class;

N’oubliez pas d’ajouter les images dans le dossier de votre projet pour quecelui-ci puisse compiler. Si jamais vous n’avez pas placé les images dans undossier images, pensez alors à mettre à jour les liens ci-dessous.

Mise en place des images

Là encore, il n’y a aucune difficulté pour la mise en place des images. La seule chose àvérifier est de placer l’instance de la classe RueEclairee par dessus celle de la classeRueSombre. Sinon, vous ne verrez absolument rien dans le rendu final de l’animation.Voici ce que je vous propose de faire :

1 // Mise en place des images2 var maRueSombre:Bitmap = new RueSombre ();3 var maRueEclairee:Bitmap = new RueEclairee ();4 this.addChild(maRueSombre);5 this.addChild(maRueEclairee);

Mise en place du masque

À présent, nous allons nous occuper du masque que nous appliquerons à l’image dela rue éclairée. Cela devrait donc donner au final un effet de lampe torche, que vouspourrez déplacer pour éclairer la zone de la rue que vous souhaiterez.

Préparation du dégradé

La première étape est la préparation du dégradé qui nous servira à tracer notre masque.Voici donc le code suggéré :

396

Page 420: Programmez en Actionscript 3

EXERCICE : UNE LAMPE TORCHE

1 // Préparation du dégradé2 var couleurs:Array = [0x00FF00 , 0x00FF00 ];3 var alphas:Array = [1, 0];4 var ratios:Array = [192 , 255];5 var matrix:Matrix = new Matrix ();6 matrix.createGradientBox(200 , 200 , 0, -100 , -100);

Ce qu’il est important de noter, c’est que nous utiliserons une seule couleur où l’opacitédiminuera sur les bords pour donner un effet d’atténuation de la lumière. Nous voulonségalement un dégradé rapide sur l’extérieur de la forme, c’est pourquoi nous avonsaugmenté la première valeur du tableau ratios.

Création de la lampe

Nous pouvons maintenant dessiner la forme du masque dans un objet de type Sprite.Nous allons donc définir un remplissage dégradé, puis nous tracerons un cercle pourreprésenter la forme du faisceau de lumière sortant de la lampe. Voici comment réaliserceci :

1 // Création de la lampe2 var lampe:Sprite = new Sprite ();3 lampe.graphics.beginGradientFill(GradientType.RADIAL , couleurs ,

alphas , ratios , matrix);4 lampe.graphics.drawCircle(0, 0, 100);5 lampe.graphics.endFill ();6 this.addChild(lampe);

La figure 19.10 vous montre à quoi ressemble le masque nous allons utiliser.

Figure 19.10 – Aperçu du masque

Application du masque

Le masque réalisé précédemment va nous permettre d’afficher l’image de la rue éclairéeuniquement dans la zone où la lampe pointe. Pour faire cela, nous allons définir l’ins-tance lampe comme masque pour l’objet maRueEclairee. Nous allons donc procédercomme nous avons appris à le faire :

397

Page 421: Programmez en Actionscript 3

CHAPITRE 19. LES MASQUES

1 // Mise en place du masque2 maRueEclairee.cacheAsBitmap = true;3 lampe.cacheAsBitmap = true;4 maRueEclairee.mask = lampe;

Nous avons à présent réalisé l’effet souhaité. Pour donner un peu plus d’intérêt à ceprojet, nous allons animer celui-ci.

Animation de la lampe

Pour animer le masque, nous allons utiliser la méthode startDrag() de la classeSprite. En indiquant son paramètre à true, on impose à l’objet en question de « col-ler » à la position de la souris. Ainsi, notre lampe va suivre les mouvements de la souris,pour imiter les gestes du poignet. Voici donc comment procéder :

1 // Animation de la lampe2 lampe.startDrag(true);

Projet final

Le rendu

Nous avons maintenant terminé cet exercice sur les masques. Je vous propose à la figure19.11 un aperçu de l’animation finale.

Le code complet

Enfin, pour vous aider à avoir une vision d’ensemble de ce que nous venons de réaliserensemble, voici ci-dessous l’intégralité du code de ce projet :

1 package2 {3 import flash.display.Sprite;4 import flash.display.Shape;5 import flash.display.Bitmap;6 import flash.events.Event;7 import flash.geom.Matrix;8 import flash.display.GradientType;9

10 /**11 * ...12 * @author Guillaume13 */14 public class Main extends Sprite15 {16 // Chargement des images17 [Embed(source = 'images/RueSombre.png')]

398

Page 422: Programmez en Actionscript 3

EXERCICE : UNE LAMPE TORCHE

Figure 19.11 – Rendu final de l’exercice

399

Page 423: Programmez en Actionscript 3

CHAPITRE 19. LES MASQUES

18 private var RueSombre:Class;19 [Embed(source = 'images/RueEclairee.png')]20 private var RueEclairee:Class;2122 public function Main():void23 {24 if (stage) init();25 else addEventListener(Event.ADDED_TO_STAGE , init);26 }2728 private function init(e:Event = null):void29 {30 removeEventListener(Event.ADDED_TO_STAGE , init);3132 // Mise en place des images33 var maRueSombre:Bitmap = new RueSombre ();34 var maRueEclairee:Bitmap = new RueEclairee ();35 this.addChild(maRueSombre);36 this.addChild(maRueEclairee);3738 // Préparation du dégradé39 var couleurs:Array = [0x00FF00 , 0x00FF00 ];40 var alphas:Array = [1, 0];41 var ratios:Array = [192 , 255];42 var matrix:Matrix = new Matrix ();43 matrix.createGradientBox(200 , 200 , 0, -100 , -100);4445 // Création de la lampe46 var lampe:Sprite = new Sprite ();47 lampe.graphics.beginGradientFill(GradientType.

RADIAL , couleurs , alphas , ratios , matrix);48 lampe.graphics.drawCircle(0, 0, 100);49 lampe.graphics.endFill ();50 this.addChild(lampe);5152 // Mise en place du masque53 maRueEclairee.cacheAsBitmap = true;54 lampe.cacheAsBitmap = true;55 maRueEclairee.mask = lampe;5657 // Animation de la lampe58 lampe.startDrag(true);59 }6061 }6263 }

400

Page 424: Programmez en Actionscript 3

EXERCICE : UNE LAMPE TORCHE

En résumé– Un masque est un objet d’affichage qui sert à délimiter une zone visible d’unautre objet.

– Lorsqu’on utilise la classe Graphics, seuls les remplissages sont pris en compte dansles masques.

– Le masque d’un objet se définit par sa propriété mask.– Pour gérer les niveaux de transparence, la propriété cacheAsBitmap du masque

et de l’objet doit être passée à true.– Pour supprimer le masque d’un objet, sa propriété mask doit être redéfinie à lavaleur null.

401

Page 425: Programmez en Actionscript 3

CHAPITRE 19. LES MASQUES

402

Page 426: Programmez en Actionscript 3

Chapitre 20TP : Mauvais temps

Difficulté :

Après ces trois longues parties plutôt théoriques, il est temps de passer un peu à la pratique !Au cours de ce TP, vous aurez donc l’occasion de revenir sur l’ensemble des notions que vousavez vues jusqu’à présent. Étant donné la quantité de choses que vous avez dû assimilerjusqu’à maintenant, il est normal que vous ayez quelques difficultés. Ne soyez donc pasgênés d’aller relire un chapitre ou deux qui vous ont semblé flous à la première lecture.Toutefois, vous êtes parfaitement en mesure de réussir ce TP, c’est pourquoi, je vous invitefortement à essayer par vous-mêmes avant d’aller voir directement la correction.

403

Page 427: Programmez en Actionscript 3

CHAPITRE 20. TP : MAUVAIS TEMPS

Le cahier des charges

L’objectif du chapitre

Le projet

L’objectif du chapitre est de concevoir une animation représentant une chute de neige !Pour obtenir un rendu un peu plus réaliste, nous ajouterons également quelques petitsdétails que je vous présenterais dans la suite de ce TP. Avant de vous en dire plus, jevous propose à la figure 20.1 un petit aperçu de l’animation que nous obtiendrons à lafin de ce chapitre.

Figure 20.1 – Aperçu de l’animation « Mauvais temps ».

Comme vous pouvez le voir, nous allons créer un certain nombre de flocons que nousanimerons afin de donner l’illusion d’une chute de neige. Nous ajouterons égalementune image de fond ainsi qu’un masque pour cacher les flocons derrière la branche aupremier plan. Par ailleurs, vous avez peut être remarqué que les bords de l’image ontété assombris afin de mettre en valeur le centre de l’image.

Bien évidemment, votre but est d’obtenir un rendu le plus proche possibledu mien. Toutefois, il est impossible que vous obteniez exactement la mêmechose. L’objectif est de pratiquer et d’arriver à un résultat convenable et nonde reproduire exactement la même image. Ne passez donc pas des jours àtenter d’obtenir des flocons quasi identiques à ceux présentés juste au-dessus.

Sachez qu’il y a des dizaines de façons différentes de réaliser une telle animation. Je vousprésenterais donc ici la méthode que j’ai choisie, mais n’ayez pas peur si la votre estdifférente. Avant de vous lancer tête baissée, lisez bien toutes les consignes et pré-requis,sans quoi vous n’arriverez certainement pas au bout !

404

Page 428: Programmez en Actionscript 3

LE CAHIER DES CHARGES

Intérêt du projet

Ce projet a été choisi pour diverses raisons que voici :

– Tout d’abord, il s’agit d’une animation très répandu en Flash et que beaucoup dedébutants désirent réaliser.

– Dans ce projet, nous allons utiliser la quasi-totalité des connaissances acquises jusqu’àprésent à savoir : variables, conditions, boucles, fonctions, tableaux, classes ,Programmation Orientée Objet et quasiment tout ce qui est lié à l’affichage.

– Enfin, cette animation ne nécessite pas énormément de lignes de code, ce qui estplutôt favorable pour l’un de vos premiers TP.

Bien entendu, nous allons détailler davantage la manière de procéder pour concevoirce projet.

Le travail à réaliser

Pour réaliser cette animation, je vous invite à procéder pas à pas. C’est pourquoi, jevous ai présenté les différentes étapes de la conception de ce projet.

Création de l’aspect d’un flocon

La première étape va consister à dessiner un flocon. Vous avez déjà toutes les connais-sances pour parvenir à dessiner celui-ci, vous devriez donc y arriver sans problème. Ilest possible de réaliser des formes de flocons extrêmement complexes, néanmoins unsimple disque fera très bien l’affaire. Le fait qu’il y aura des milliers de flocons dansnotre future animation devrait faire naître des idées dans votre esprit quant à la ma-nière de les concevoir . Je n’en dis pas plus, à vous de réfléchir d’ores et déjà, à lameilleure façon de faire !

La génération des flocons

Ensuite, vous allez devoir générer l’ensemble de vos flocons que nous réutiliserons àl’infini. Une fois généré, chaque flocon devra être positionné aléatoirement à l’écran. Ilvous faudra également définir aléatoirement son aspect ainsi que sa vitesse de chute.Pensez également que vous pouvez donner de la profondeur à votre scène, sachant queles flocons les plus gros seront au premier plan et les plus rapides de notre point devue.

L’animation des flocons

Tout ce qui concerne l’animation sera regroupé à l’intérieur d’une méthode qui seraappelée à intervalles réguliers grâce à la fonction setInterval(). À l’intérieur de cetteméthode, vous ferez l’ensemble des modifications nécessaires à l’animation des flocons.Vous pourrez ainsi mettre à jour la position de chaque flocon, et éventuellement, réini-

405

Page 429: Programmez en Actionscript 3

CHAPITRE 20. TP : MAUVAIS TEMPS

tialiser un flocon sorti de la scène. Cette fonction sera donc appelée régulièrement et,à l’infini, se chargera ainsi de l’animation de la scène.

C’est un peu prématuré puisqu’il s’agit de l’objet du prochain chapitre, mais vousutiliserez pour cela ce qu’on appelle une fonction de rappel. Sans plus d’explications,voici comment utiliser cette fonction setInterval() :

1 var monInterval:uint = setInterval(maMethode , intervalle);

Dans l’instruction précédente, maMethode représente une méthode, donc de type Function,et intervalle correspond au temps espaçant deux exécutions consécutives de la fonc-tion précédente.

Association des différents éléments graphiques

Lorsque que toute la gestion des flocons aura été terminée, vous pourrez alors passerà la composition de la scène finale. Vous devrez donc ajouter l’image de fond et lemasque à la scène. Vous pourrez également tenter de créer cet effet d’assombrissementdes bords de la scène en étant imaginatif. Cette étape devrait normalement se déroulerrelativement bien si vous être parvenu jusque là !

Les images

Enfin, je vous suggère de télécharger les deux images dont vous aurez besoin pourréaliser ce TP (voir les figures 20.2 et 20.3). Il y a donc l’image de fond intitulée« Paysage.png » ainsi que le masque nommé « Masque.png ».

Figure 20.2 – Paysage.png

406

Page 430: Programmez en Actionscript 3

LA CORRECTION

Figure 20.3 – Masque.png

La correction

La structure du programme

Avant de nous lancer tête baissée dans les lignes de code, je vais vous présenter un peula manière dont j’ai conçu et organisé le code au sein du projet. Si vous avez réalisé ceprojet par vous-même, il est probable que vous n’ayez pas structuré votre projet de lamême façon. Je rappelle qu’il n’y a pas qu’une seule et unique manière de concevoirune telle animation.

La figure 20.4 vous montre comment j’ai procédé pour programmer ce TP.

Ainsi, dans l’organisation précédente, nous avons divisé le code en trois classes diffé-rentes :

– La classe Flocon est celle qui va principalement vous permettre de dessiner un flocon.Elle hérite donc de Shape pour avoir accès aux méthodes de la classe Graphics. Vouspouvez également associer à cette classe un attribut _vitesse qui correspond à lavitesse de chute du flocon et qui lui est donc propre.

– Ensuite, nous avons la classe Neige qui hérite de Sprite et est donc un conteneur.Elle va donc nous permettre de générer et d’animer l’ensemble des flocons.

– Enfin, notre classe principale va nous servir à composer la scène finale à l’aide del’image de fond, du masque et d’un dernier objet que nous créerons et qui servira àassombrir les bords de la scène.

Dans la suite de la correction de ce TP, nous allons donc détailler l’ensemble de sesclasses en partant de la classe Flocon pour aller vers la classe principale.

407

Page 431: Programmez en Actionscript 3

CHAPITRE 20. TP : MAUVAIS TEMPS

Figure 20.4 – La structure du projet telle qu’elle est définie dans la correction

La classe Flocon

Création de la classe

La première classe que nous allons créer est la classe Flocon ! Voici donc la structurede base de cette classe :

1 package2 {3 import flash.display.Shape;45 public class Flocon extends Shape6 {7 public function Flocon ()8 {9 super();

1011 }1213 }1415 }

Celle-ci permet tout d’abord de créer le « visuel » du flocon. Pour cela, nous utiliseronsles méthodes de la classe Graphics puisque notre classe hérite de Shape. Rien deplus facile maintenant pour vous, il suffit de tracer un disque blanc à l’intérieur duconstructeur de la manière suivante :

408

Page 432: Programmez en Actionscript 3

LA CORRECTION

1 this.graphics.beginFill(0xFFFFFF);2 this.graphics.drawCircle(0, 0, 1.5);

Sachant que nos flocons ne tomberont pas tous à la même vitesse, nous allons donccréer un attribut _vitesse pour retenir celle-ci :

1 private var _vitesse:Number;

Enfin, n’oubliez pas d’initialiser cet attribut et de lui associer des accesseurs, que nousne détaillerons pas ici. Jetez simplement un coup d’œil au code complet de cette classequi, soit dit entre nous, est plutôt succinct.

La classe Neige

Création de la classe

À présent, nous allons nous occuper de la classe Neige qui sera donc notre conteneurpour l’ensemble des flocons. Pour commencer, je vous invite donc à créer une nouvelleclasse si ce n’est déjà fait. À l’intérieur, nous aurons besoin des trois constantes que j’ainommé LARGEUR_SCENE, HAUTEUR_SCENE et NOMBRE_FLOCONS. Pour faciliter la suite,j’ai déjà fait l’intégralité des importations ainsi que la mise en place de la structureglobale de la classe. Voici donc notre classe Neige, prête à être remplie :

1 package2 {3 import flash.display.Sprite;4 import flash.filters.BlurFilter;5 import flash.filters.BitmapFilterQuality;6 import flash.utils .*;78 public class Neige extends Sprite9 {

10 private const LARGEUR_SCENE:int = 480;11 private const HAUTEUR_SCENE:int = 320;12 private const NOMBRE_FLOCONS:int = 3000;1314 public function Neige ()15 {16 super();17 // Génération des flocons18 }1920 public function animerFlocons ():void21 {22 // Animation des flocons23 }24 }2526 }

409

Page 433: Programmez en Actionscript 3

CHAPITRE 20. TP : MAUVAIS TEMPS

Génération des flocons

Nous allons ici nous intéresser à la création des flocons et à leur mise en place sur lascène au démarrage de l’animation. Pour commencer, nous allons créer nos flocons enutilisant un tableau de Flocon de type Array. Ce tableau devra être accessible depuisla fonction animerFlocons(), c’est pourquoi, j’ai décidé de créer un nouvel attributnommé MesFlocons :

1 // Tableau de Flocon2 private var mesFlocons:Array;

Dans ce paragraphe, nous nous occuperons de la génération des flocons. Plaçons-nousdonc à l’intérieur du constructeur de la classe Neige. Commençons tout de suite parinitialiser notre tableau Array en définissant sa taille à NOMBRE_FLOCONS défini justeavant :

1 mesFlocons = new Array();

À présent, nous devons instancier nos flocons et leur apporter quelques modificationsun par un. Il se trouve que les boucles sont justement très recommandées pour parcourirles éléments d’un tableau :

1 for (var i:uint = 0; i < NOMBRE_FLOCONS - 1; i++) {2 // Création et modification de chaque flocon3 }

Nous pouvons maintenant instancier nos flocons, les uns après les autres :

1 mesFlocons.push(new Flocon ());

Lors du démarrage de l’animation, il serait préférable que les flocons soient répartisaléatoirement sur l’écran. Nous allons donc modifier la position horizontale et la po-sition verticale en utilisant la méthode random() de la classe Math. Voici commentréaliser cette opération :

1 // Placement aléatoire des flocons sur l'écran2 mesFlocons[i].x = Math.random () * LARGEUR_SCENE;3 mesFlocons[i].y = Math.random () * HAUTEUR_SCENE;

Pour donner une impression de profondeur à notre scène, nous allons modifier l’aspectde nos flocons ainsi que leur vitesse. Pour cela, nous allons définir une variable aspectqui représentera la taille du flocon, mais également sa « distance » à l’écran, le zérocorrespondant à une distance infinie, c’est-à-dire loin de l’écran. Étant donné qu’avecla distance, la vitesse de chute des flocons semble diminuer également, nous réutilise-rons cette variable pour définir la vitesse du flocon. Voici le code correspondant à cesmanipulations :

1 // Définition d'un aspect aléatoire2 var aspect:Number = Math.random () * 1.5;3 // Modification de l'aspect du flocon4 mesFlocons[i]. scaleX = aspect;

410

Page 434: Programmez en Actionscript 3

LA CORRECTION

5 mesFlocons[i]. scaleY = aspect;6 mesFlocons[i].alpha = aspect;7 // Modification de la vitesse du flocon8 mesFlocons[i]. vitesse = 2 * (aspect + Math.random ());

Suivant la distance du flocon à l’écran, celui-ci sera également plus ou moins net. Nousallons donc réutiliser notre variable aspect pour créer un filtre de flou, simulant laprofondeur de champ de la caméra. Pour accentuer cet effet de profondeur, j’ai utiliséune formule mathématique avec des puissances. Je vous donne directement le codecorrespondant :

1 // Génération du filtre2 var flou:BlurFilter = new BlurFilter ();3 flou.blurX = Math.pow(10*aspect ,4)/10000;4 flou.blurY = Math.pow(10*aspect ,4)/10000;5 flou.quality = BitmapFilterQuality.MEDIUM;6 // Application du filtre au flocon7 mesFlocons[i]. filters = new Array(flou);

Enfin, il ne nous reste plus qu’à ajouter notre flocon à la liste d’affichage de la classeNeige :

1 this.addChild(mesFlocons[i]);

La génération des flocons est maintenant terminée et notre application est prête à êtreanimée ! Pour cela, n’oubliez pas de mettre l’instruction suivante à l’extérieur de laboucle :

1 var monInterval:uint = setInterval(animerFlocons , 40);

L’animation des flocons

Dans ce paragraphe, nous allons nous occuper de toute la partie « animation » du pro-gramme. Nous travaillerons donc à l’intérieur de la méthode animerFlocons() qui, jele rappelle, sera exécutée toutes les 40 millisecondes grâce à la fonction setInterval().Encore une fois, nous allons manipuler les flocons individuellement. Nous utiliseronsdonc à nouveau une boucle for :

1 for (var i:uint = 0; i < mesFlocons.length; i++) {2 // Mise à jour de chaque flocon3 }

Le principe de l’animation consiste à modifier la position de chaque flocon. Pour fairecela, nous utiliserons la propriété vitesse de la classe Flocon que nous viendronsajouter à la position verticale du flocon. Voici comment il faut procéder :

1 mesFlocons[i].y += mesFlocons[i]. vitesse;

Pour éviter de créer des flocons à l’infini, nous allons réutiliser les flocons qui sont sortisde la zone visible de l’écran pour les renvoyer en haut de celui-ci. Vous vous en doutez

411

Page 435: Programmez en Actionscript 3

CHAPITRE 20. TP : MAUVAIS TEMPS

peut-être, nous utiliserons une condition if en testant la valeur de la position verticaled’un flocon comme ceci :

1 if (mesFlocons[i].y > HAUTEUR_SCENE) {2 // Réinitialisation du flocon en haut de la scène.3 }

À l’intérieur, nous pouvons alors remettre la position verticale du flocon à zéro etéventuellement replacer aléatoirement le flocon horizontalement :

1 mesFlocons[i].x = Math.random () * LARGEUR_SCENE;2 mesFlocons[i].y = 0;

Aussi surprenant que cela puisse paraître, nous avons à présent terminé l’animationdes flocons !

La classe principale

Création des objets d’affichage

Nous voici de retour dans la classe principale ! Nous allons donc ici gérer la mise enplace des différents éléments à l’écran. Dans un premier temps, je vous propose d’im-porter les deux images externes, à savoir Paysage.png et Masque.png que vous avezdû normalement télécharger précédemment. Voici comment j’ai réalisé ceci :

1 // Préparation des images2 [Embed(source = 'images/Paysage.png')]3 private var Paysage:Class;4 [Embed(source = 'images/Masque.png')]5 private var Masque:Class;

J’ai donc utilisé quatre éléments différents pour composer la scène finale. J’ai toutd’abord pris deux occurrences monPaysage et monMasque des images précédentes. En-suite j’ai instancié notre classe Neige qui contient l’ensemble des flocons de l’animation.Enfin, j’ai créé une nouvelle variable nommée maVignette de type Shape. Celle-ci vanous permettre de créer un « effet de vignette », comme nous le verrons juste après.Voilà donc nos quatre objets :

1 // Création des objets d'affichage2 var monPaysage:Bitmap = new Paysage ();3 var monMasque:Bitmap = new Masque ();4 var maNeige:Neige = new Neige();5 var maVignette:Shape = new Shape();

Dans la suite, nous allons alors gérer l’« interconnexion » entre ces différents élémentspour aboutir au rendu final que vous avez vu en début de chapitre.

412

Page 436: Programmez en Actionscript 3

LA CORRECTION

Création d’un effet de vignette

Un « effet de vignette » est une technique qui permet de mettre en valeur ce qui setrouve au centre d’une image. En fait, cela consiste à assombrir les bords et les anglesde l’image. Pour faire cela, le plus simple est créer un dégradé elliptique, de couleurblanche au centre et sombre à l’extérieur. Ainsi, par application d’unmode de fusion,le centre de l’image se voit devenir plus lumineuse et ressort davantage. Voici donc àla figure 20.5 le vignettage que nous allons réaliser.

Figure 20.5 – Dégradé radial pour un « effet de vignette »

Pour réaliser cet effet, nous allons créer un dégradé de type radial à l’intérieur d’unremplissage de forme rectangulaire. Pour commencer, nous nous occuperons des ré-glages du dégradé en termes de couleurs. Nous aurons donc un dégradé du blanc aunoir, comme vous pouvez le voir ci-dessous :

1 // Paramètrage du dégradé2 var couleurs:Array = [0xFFFFFF , 0x000000 ];3 var alphas:Array = [1, 1];4 var ratios:Array = [96, 255];

Ensuite, il nous faut générer la matrice permettant de contrôler l’aspect général dudégradé. Pour cela, nous allons donc créer un dégradé radial plus large que la taillede la scène afin de ne pas avoir de noir absolu, puis nous recentrerons celui-ci. Voicicomment j’ai réalisé ceci :

1 // Création de la matrice de description2 var matrix:Matrix = new Matrix ();3 var largeur:Number = 2*LARGEUR_SCENE;4 var hauteur:Number = 2*HAUTEUR_SCENE;5 var rotation:Number = 0;6 var tx:Number = -0.5*LARGEUR_SCENE;7 var ty:Number = -0.5*HAUTEUR_SCENE;8 matrix.createGradientBox(largeur , hauteur , rotation , tx , ty);

413

Page 437: Programmez en Actionscript 3

CHAPITRE 20. TP : MAUVAIS TEMPS

L’étape suivante consiste alors à tracer le remplissage correspondant à la taille de lascène :

1 // Tracé du remplissage2 maVignette.graphics.beginGradientFill(GradientType.RADIAL ,

couleurs , alphas , ratios , matrix);3 maVignette.graphics.drawRect(0, 0, LARGEUR_SCENE , HAUTEUR_SCENE

);

Enfin, nous allons appliquer unmode de fusion de type «multiplier » qui va permettred’assombrir les bords de l’image en laissant le centre de celle-ci intact.

1 // Application du mode de fusion2 maVignette.blendMode = BlendMode.MULTIPLY;

Nous avons à présent l’intégralité de nos éléments graphiques qu’il va falloir agencerles uns avec les autres pour obtenir le rendu final désiré.

Mise en place des éléments à l’écran

Maintenant, nous devons ajouter chacun de nos éléments à la liste d’affichage. Misà part le masque qui ne sera pas visible, les objets d’affichage doivent être ajoutésdans un certain ordre. En arrière-plan, nous aurons donc l’image de fond présentedans la variable monPaysage. Ensuite, nous placerons l’objet maNeige par-dessus quisera masqué par monMasque. Enfin, nous placerons maVignette au premier plan pourque son mode de fusion s’applique à tous les objets derrière elle. Voilà donc l’ordre àrespecter :

1 // Ajout des éléments à la liste d'affichage2 this.addChild(monPaysage);3 this.addChild(monMasque);4 this.addChild(maNeige);5 this.addChild(maVignette);

Pour finir, appliquez le masque à l’objet maNeige :

1 // Application du masque2 maNeige.cacheAsBitmap = true;3 monMasque.cacheAsBitmap = true;4 maNeige.mask = monMasque;

Ça y est, c’est terminé ! Nous avons à présent fini l’intégralité de cette animation quidemandait quelques efforts, je vous l’accorde.

Le code source complet

La classe Flocon

Flocon.as

414

Page 438: Programmez en Actionscript 3

LE CODE SOURCE COMPLET

1 package2 {3 import flash.display.Shape;45 public class Flocon extends Shape6 {7 private var _vitesse:Number;89 public function Flocon ()

10 {11 super();12 _vitesse = 0;13 this.graphics.beginFill(0xFFFFFF);14 this.graphics.drawCircle(0, 0, 1.5);15 }1617 public function get vitesse ():Number18 {19 return _vitesse;20 }2122 public function set vitesse(value:Number):void23 {24 _vitesse = value;25 }2627 }2829 }

La classe Neige

Neige.as

1 package2 {3 import flash.display.Sprite;4 import flash.filters.BlurFilter;5 import flash.filters.BitmapFilterQuality;6 import flash.utils .*;78 public class Neige extends Sprite9 {

10 private const LARGEUR_SCENE:int = 480;11 private const HAUTEUR_SCENE:int = 320;12 private const NOMBRE_FLOCONS:int = 3000;13 // Tableau de Flocon14 private var mesFlocons:Array;15

415

Page 439: Programmez en Actionscript 3

CHAPITRE 20. TP : MAUVAIS TEMPS

16 public function Neige ()17 {18 super();19 mesFlocons = new Array();20 for (var i:uint = 0; i < NOMBRE_FLOCONS - 1; i++) {21 // Création et modification de chaque flocon22 mesFlocons.push(new Flocon ());23 // Placement aléatoire des flocons sur l'écran24 mesFlocons[i].x = Math.random () * LARGEUR_SCENE

;25 mesFlocons[i].y = Math.random () * HAUTEUR_SCENE

;26 // Définition d'un aspect aléatoire27 var aspect:Number = Math.random () * 1.5;28 // Modification de l'aspect du flocon29 mesFlocons[i]. scaleX = aspect;30 mesFlocons[i]. scaleY = aspect;31 mesFlocons[i].alpha = aspect;32 // Modification de la vitesse du flocon33 mesFlocons[i]. vitesse = 2 * (aspect + Math.

random ());34 // Génération du filtre35 var flou:BlurFilter = new BlurFilter ();36 flou.blurX = Math.pow(10*aspect ,4)/10000;37 flou.blurY = Math.pow(10*aspect ,4)/10000;38 flou.quality = BitmapFilterQuality.MEDIUM;39 // Application du filtre au flocon40 mesFlocons[i]. filters = new Array(flou);41 // Ajout du flocon à la liste d'affichage42 this.addChild(mesFlocons[i]);43 }4445 var monInterval:uint = setInterval(animerFlocons ,

25);46 }4748 public function animerFlocons ():void49 {50 for (var i:uint = 0; i < mesFlocons.length; i++) {51 // Mise à jour de chaque flocon52 mesFlocons[i].y += mesFlocons[i]. vitesse;53 if (mesFlocons[i].y > HAUTEUR_SCENE) {54 // Réinitialisation du flocon en haut de la

scène.55 mesFlocons[i].x = Math.random () *

LARGEUR_SCENE;56 mesFlocons[i].y = 0;57 }58 }59 }

416

Page 440: Programmez en Actionscript 3

LE CODE SOURCE COMPLET

60 }6162 }

La classe principale

Main.as

1 package2 {3 import flash.display.Shape;4 import flash.display.Sprite;5 import flash.events.Event;6 import flash.display.Bitmap;7 import flash.geom.Matrix;8 import flash.display.GradientType;9 import flash.display.BlendMode;

1011 [SWF(width="480", height="320")]12 public class Main extends Sprite13 {14 private const LARGEUR_SCENE:int = 480;15 private const HAUTEUR_SCENE:int = 320;16 // Préparation des images17 [Embed(source = 'images/Paysage.png')]18 private var Paysage:Class;19 [Embed(source = 'images/Masque.png')]20 private var Masque:Class;2122 public function Main():void23 {24 if (stage) init();25 else addEventListener(Event.ADDED_TO_STAGE , init);26 }2728 private function init(e:Event = null):void29 {30 removeEventListener(Event.ADDED_TO_STAGE , init);31 // Création des objets d'affichage32 var monPaysage:Bitmap = new Paysage ();33 var monMasque:Bitmap = new Masque ();34 var maNeige:Neige = new Neige();35 var maVignette:Shape = new Shape();36 // Paramétrage du dégradé37 var couleurs:Array = [0xFFFFFF , 0x000000 ];38 var alphas:Array = [1, 1];39 var ratios:Array = [96, 255];40 // Création de la matrice de description41 var matrix:Matrix = new Matrix ();

417

Page 441: Programmez en Actionscript 3

CHAPITRE 20. TP : MAUVAIS TEMPS

42 var largeur:Number = 2*LARGEUR_SCENE;43 var hauteur:Number = 2*HAUTEUR_SCENE;44 var rotation:Number = 0;45 var tx:Number = -0.5*LARGEUR_SCENE;46 var ty:Number = -0.5*HAUTEUR_SCENE;47 matrix.createGradientBox(largeur , hauteur , rotation

, tx , ty);48 // Tracé du remplissage49 maVignette.graphics.beginGradientFill(GradientType.

RADIAL , couleurs , alphas , ratios , matrix);50 maVignette.graphics.drawRect(0, 0, LARGEUR_SCENE ,

HAUTEUR_SCENE);51 Application du mode de fusion52 maVignette.blendMode = BlendMode.MULTIPLY;53 // Ajout des éléments à la liste d'affichage54 this.addChild(monPaysage);55 this.addChild(monMasque);56 this.addChild(maNeige);57 this.addChild(maVignette);58 // Application du masque59 maNeige.cacheAsBitmap = true;60 monMasque.cacheAsBitmap = true;61 maNeige.mask = monMasque;6263 }6465 }6667 }

418

Page 442: Programmez en Actionscript 3

Quatrième partie

Interaction et animation

419

Page 443: Programmez en Actionscript 3
Page 444: Programmez en Actionscript 3

Chapitre 21Les événements

Difficulté :

Nous voici dans une nouvelle partie portant sur l’interactivité et l’animation en Actions-cript. Ces deux concepts sont étroitement liés à la notion d’évènement qui est l’objet dece chapitre. Il sera malheureusement le plus théorique et le plus complexe de cette partie.Une fois que vous aurez acquis les bases de la programmation événementielle, les autreschapitres seront beaucoup plus pratiques et faciles à aborder.

421

Page 445: Programmez en Actionscript 3

CHAPITRE 21. LES ÉVÉNEMENTS

Qu’est ce qu’un évènement ?

Introduction

Dans ce chapitre, nous allons aborder la programmation événementielle. A l’instarde la POO, cette manière de programmer s’inspire d’éléments du quotidien, à savoir :les évènements.

Attention, j’en vois déjà certains penser aux festivals de cet été : il ne s’agit pas decela bien évidemment ! Les évènements, tels que nous allons les voir, sont définiscomme des éléments non prévisibles, généralement déclenché par un changement d’étatquelconque. Par exemple, dans la vie courante, nous pouvons citer :

– Un réveil qui sonne.– Un accident de voiture.– Une panne de courant.– La réception d’un fax.

Pour compléter la définition précédente, nous pourrions dire qu’il s’agit d’évènementssoudains qui surgissent lorsque l’on ne s’y attend pas. Dans l’exemple du réveil, il estvrai qu’on s’attend forcément à ce qu’il sonne, cependant, vous devez avouer que vousêtes toujours surpris lorsque ce dernier se met à sonner !

En programmation, le principe est le même. Dans le cas de l’ActionScript 3, nouspourrions citer comme événements :

– Un clic à l’aide de la souris.– Le déplacement du curseur de la souris.– L’enfoncement d’une touche du clavier.– La fin de chargement d’une image depuis un serveur.– Une erreur lors du chargement de cette image.

À l’apparition de l’un des évènements, il est alors possible d’exécuter des instructionsspécifiques, pour mettre à jour l’affichage par exemple. Étant donné que nous ne savonspas à l’avance quand ceux-ci se produiront, il serait possible, mais très fastidieux,d’inclure des instructions au milieu de votre programme qui bouclent indéfinimentpour détecter ces événements : c’était la méthode avant l’entrée en scène du conceptde gestion des évènements, qui facilite grandement ce processus.

Pour introduire ce concept, nous allons maintenant faire une analogie en prenant l’idéede la réception d’un fax.

Un jour au bureau. . .

Aujourd’hui, vous travaillez pour une grande entreprise de renommée internationale.Votre compagnie dispose ainsi de différentes agences réparties sur plusieurs continents.En tant que responsable produits, vous allez devoir prochainement présenter un nou-veau concept à l’ensemble du groupe. Il est donc prévu que vous assistiez à une réunionavec des collaborateurs de diverses agences. En revanche, les détails pratiques tels quel’heure et l’endroit de cette réunion ne sont pas encore fixés.

422

Page 446: Programmez en Actionscript 3

QU’EST CE QU’UN ÉVÈNEMENT?

Fonction d’écouteur

Monsieur Gumble, directeur d’une agence nord-américaine, a promis qu’il vous en-verrait les informations concernant la réunion d’aujourd’hui par fax. Comme à votrehabitude, ce matin-là vous arrivez au bureau légèrement en avance. Vous en profitezalors pour sortir une feuille et commencez à noter différentes choses dessus.

Machinalement, vous avez commencé à anticiper et vous avez noté les différentes tâchesà faire à la réception de ce fameux fax : cela ressemble à une fonction contenant une séried’instructions, non ? Cette « fonction » qui devra être appelée dès que vous recevrez lefax est désignée comme étant une fonction d’écouteur.

En ActionScript 3, elle sera donc une fonction quelconque ou une méthode de classeregroupant des instructions à exécuter lors de l’apparition d’un évènement. Généra-lement, les actions qui en découleront dépendent de paramètres liés à l’évènement. Parexemple, savoir quelle touche a été enfoncée permettrait d’exécuter des instructionsdifférentes suivant s’il s’agit d’un

�� ��A ou d’un�� ��S .

Écouter un événement

Ça y est ! Vous êtes prêts à recevoir votre fax. Vous jetez régulièrement un coup d’œilsur le télécopieur qui se trouve dans le coin.

Attendre qu’un événement survienne est appelé écouter un événement. On écoutetoujours sur un objet désigné comme étant la cible de l’événement. On dit égalementque cet objet déclenchera l’événement lorsque celui-ci surviendra. Ici, le télécopieurest la cible de l’événement qui se produira à la réception d’un fax.

En programmation, on écoute un événement particulier en renseignant une sorte de« signature », appelée type d’événement, décrite par une chaîne de caractères : ilest alors possible de distinguer un clic de souris du déplacement du curseur au-dessusd’un objet identique. Écouter un événement qu’un objet sera susceptible de déclencherconsiste donc à associer une fonction d’écouteur à un type d’évènements touten ciblant cet objet. Ainsi, à chaque fois que ledit objet déclenchera l’évènement cor-respondant au type en question, la ou les fonctions d’écouteur impliquées serontappelées.

Seul un objet peut faire apparaître un événement. Nous écouterons donctoujours des événements relatifs à des objets (ici, notre télécopieur).

Cependant, le fax n’arrive toujours pas et l’ennui pointe le bout de son nez. Vouslevez alors la tête et parcourez votre bureau du regard : vous apercevez un collègue etvous remarquez que ce dernier semble également attendre un fax devant la machine.Toutefois, il est peu probable qu’il provienne de Monsieur Gumble. De la même façon,votre voisin n’effectuera pas les mêmes tâches que vous après réception de son fax, safonction d’écouteur est donc probablement différente.

423

Page 447: Programmez en Actionscript 3

CHAPITRE 21. LES ÉVÉNEMENTS

Il est possible qu’un événement soit écouté par plusieurs fonctions d’écou-teur même si elles sont différentes. Elles seront toutes appelées lorsque l’évé-nement sera déclenché.

L’évènement

Après la pause déjeuner, vous revenez à votre poste pour poursuivre votre travail de lamatinée. Vous n’avez alors pas le temps de vous asseoir qu’un fax arrive ! Vous regardezcelui-ci de plus près, il s’agit bien du fax de monsieur Gumble. Vous le parcourez doncdes yeux et voyez que celui-ci regorge d’informations. Vous y trouvez le nom de toutesles personnes qui seront présentes, l’objet de la réunion, mais également la date, l’heureet le lieu de la réunion. Ça tombe bien, ce sont exactement les données qu’il vousmanquait !

Vous ressortez alors votre feuille puis commencez les réservations. Parmi les différentesinformations fournies dans le fax, vous en avez extrait celles qui vous étaient utiles pourpouvoir exécuter les tâches que vous vous étiez fixés. On dit que le fax représentel’événement sous la forme d’un objet qui contient différentes données sur ce qui s’estproduit.

En programmation événementielle , comme tout le reste en en Actionscript,les évènements sont donc représentés par des objets qui renferment également desinformations concernant l’évènement en question. De la même façon, il est possible« d’interroger » cette classe, pour pouvoir gérer et traiter correctement ce dernier enfonction de son type et de ses attributs. Ces objets sont tous issus de la classe Event,dont nous reparlerons plus loin.

Les écouteurs en POO

Nous allons à présent revenir et nous pencher plus sérieusement sur les écouteurset leur gestion. Comme nous l’avons dit plus haut, les écouteurs sont associés auxobjets. Ainsi, tout objet peut théoriquement utiliser les écouteurs pour répondreaux évènements, à une condition néanmoins : l’objet doit implémenter l’interfaceIEventDispatcher.

L’interface IEventDispatcher

L’interface IEventDispatcher définit donc le jeu de méthodes servant à la gestiondes écouteurs. Sans plus attendre, voici à la figure 21.1 l’ensemble des définitions deméthodes que propose cette interface.

Comme vous pouvez le voir, cette interface propose cinq définitions de méthodes pourla gestion des écouteurs. La méthode addEventListener() est celle que nous uti-liserons le plus, sa signature complète est la suivante :

424

Page 448: Programmez en Actionscript 3

LES ÉCOUTEURS EN POO

Figure 21.1 – L’interface IEventDispatcher

1 addEventListener(type:String , listener:Function , useCapture:Boolean = false , priority:int = 0, useWeakReference:Boolean= false):void

Néanmoins, dans un premier temps, nous allons laisser de côté les paramètres faculta-tifs. Ce qui nous donne donc :

1 addEventListener(type:String , listener:Function):void

Avant de vous montrer un exemple d’utilisation, nous allons revenir sur la notiond’écouteurs. Si vous êtes pointilleux, vous aurez alors remarqué la présence du mot an-glais « add » dans le nom cette méthode, qui signifie ajout. Ainsi, lorsque nous utilisonscette méthode nous ajoutons un nouvel écouteur à notre objet. En effet, il est possiblede définir plusieurs écouteurs pour un même objet et de pouvoir ainsi répondre à diversévènements. Grâce à cela, il est donc possible d’être à l’écoute à la fois d’évènementsprovenant de la souris et d’autres provenant du clavier.

Tout comme il est possible d’ajouter des écouteurs à un objet, il est possible d’enretrancher. C’est donc la méthode removeEventListener() qui s’en charge, et voicisa signature complète :

1 removeEventListener(type:String , listener:Function , useCapture:Boolean = false):void

Nous retiendrons pour l’instant cette méthode sous sa forme simplifié :

1 removeEventListener(type:String , listener:Function):void

Dans un premier temps, nous allons oublier les méthodes dispatchEvent() et willTrigger().En revanche, vous pouvez noter la présence de la méthode hasEventListener() quipermet de vérifier si un écouteur est enregistré auprès d’un objet pour un type d’évé-nement spécifique. Cette méthode renvoie donc un booléen.

La classe EventDispatcher

Comme nous l’avons dit plus haut, c’est l’interface IEventDispatcher qui définit lejeu de méthodes servant à la gestion des écouteurs. Néanmoins, c’est à l’intérieurde la classe EventDispatcher que le contenu de l’ensemble de ces méthodes est défini.Bien entendu, cette classe implémente l’interface IEventDispatcher, et c’est elle quiva réellement servir de classe de base pour toute classe voulant « distribuer » des

425

Page 449: Programmez en Actionscript 3

CHAPITRE 21. LES ÉVÉNEMENTS

évènements. Par héritage, cette classe permet donc à tout objet d’utiliser les méthodesde l’interface IEventDispatcher et d’être à l’écoute d’évènements ; on dit alors quel’objet devient une cible d’évènements.

Ainsi, toutes les classe filles de EventDispatcher héritent donc de ces méthodes liéesà la gestion des écouteurs. À l’instar de nombreux objets, nous retrouvons parmielles la classe DisplayObject que nous avons déjà vue. Donc, si vous vous souvenezbien, l’ensemble des classes d’affichage sont, par héritage, des sous-classes de la classeEventDispatcher (voir figure 21.2).

Figure 21.2 – Extrait de l’arbre d’héritage des classes d’affichage

Cela tombe bien, tous les éléments de notre liste d’affichage vont donc pouvoir répondreà divers évènements. Nous verrons que les objets appartenant à la liste d’affichagerépondent aux évènements d’une manière assez spécifique : on appelle cela le fluxd’évènements. Nous aborderons cette notion au cours de ce chapitre.

Mise en place d’un écouteur

Introduction aux fonctions de rappel

La théorie

En regardant la méthode addEventListener() de plus près, vous vous apercevrez quecelle-ci dispose d’un paramètre de type Function :

1 addEventListener(type:String , listener:Function):void

426

Page 450: Programmez en Actionscript 3

MISE EN PLACE D’UN ÉCOUTEUR

Dans ce cas, la fonction listener est ce qu’on appelle une fonction de rappel (oucallback en anglais). Il s’agit donc d’une fonction, ou d’une méthode, qui est passéeen paramètre à une autre fonction. Ainsi, à l’intérieur de cette dernière, il est possiblede faire appel à la fonction de rappel à sa guide.

Quel est l’intérêt de cette fonction de rappel ? N’est-il pas plus simple dedéfinir les instructions directement dans la seconde fonction ?

L’intérêt ici est justement de pouvoir se servir d’une fonction sachant qu’on ne laconnaît pas à l’avance. De cette manière, il est alors possible d’exécuter des instruc-tions dynamiquement sans avoir besoin de les définir directement. Le plus souvent, lesfonctions de rappel sont appelés suite à une condition, comme l’apparition d’unévènement par exemple. En utilisant ce concept, vous pouvez ainsi créer une classeet laisser à l’utilisateur la liberté d’exécuter les instructions qu’il souhaite sans qu’ilait accès à la classe elle-même. Cela est extrêmement pratique lorsqu’on conçoit sonprogramme par héritage ou lorsque l’on crée une bibliothèque de classes.

Une fonction de rappel est une fonction appelée à l’intérieur d’une autre. Son utili-sation et sa signature sont donc définies et figées lors de son appel. Ainsi, à la définitionde la fonction de rappel, il est nécessaire d’ajouter les points suivants :

– Le nombre et le type des paramètres.– Le type de la valeur renvoyée.

Vous pouvez donc tout à fait utiliser ce concept à l’intérieur de vos fonctions et ainsiaméliorer la ré-utilisabilité de votre code.

Un exemple

Pour mieux comprendre cette notion, voici un exemple basique de fonction utilisantune fonction de rappel suivant une condition :

1 function uneFonction(condition:Boolean , fonction:Function):void2 {3 if(condition){4 fonction.call();5 }6 }

Et voici la définition de la fonction de rappel :

1 function fonctionDeRappel ():void2 {3 trace("Ceci est une fonction de rappel.");4 }

427

Page 451: Programmez en Actionscript 3

CHAPITRE 21. LES ÉVÉNEMENTS

Pour utiliser au mieux ce concept, je vous conseille de vous rendre sur la docu-mentation officielle de la classe Function. Vous verrez notamment commentvous servir de la méthode call() suivant les paramètres définies pour votrefonction.

B

�Documentation Function

Code web : 171723Si vous souhaitez tester cet exemple, vous pouvez alors exécuter l’instruction suivanteaprès avoir défini les deux fonctions précédentes :

1 uneFonction(true , fonctionDeRappel);

Ce qui donne naturellement à l’exécution du code :

Ceci est une fonction de rappel.

Créer une fonction d’écouteur

Lorsqu’on parle de gestion d’évènements, les fonctions de rappel sont alors pluscommunément appelées fonction d’écouteur, comme nous l’avons évoqué plus haut.La gestion de cette fonction est alors du ressort de la superclasse EventDispatcher.Lors de la mise en place d’un écouteur, nous avons donc uniquement à nous préoccuperde la définition de la fonction d’écouteur.

Les fonctions d’écouteur doivent donc répondre aux exigences fixées par la classeEventDispatcher. Voici donc la signature type d’une fonction d’écouteur :

1 function uneFonction(event:Event):void2 {3 // Instructions à exécutées lors de l'apparition d'un évè

nement de type donné4 }

Le paramètre event à renseigner ici est de type Event, cependant, dans lapratique, il s’agira plus généralement d’une sous-classe de cette dernière. Laclasse utilisée pour ce paramètre dépendra directement du type d’évènementspécifié lors de la mise en place de l’écouteur.

Comme exemple, je vous propose cette fonction d’écouteur qui pourrait servir à lagestion d’évènements liés à la souris :

1 function monEcouteur(event:MouseEvent):void2 {3 trace("Vous avez cliqué sur la souris.");4 }

Comme vous pouvez le voir ici, le paramètre de cette fonction est de type MouseEvent,dont nous reparlerons dès le prochain chapitre. Il s’agit donc d’une sous-classe de la

428

Page 452: Programmez en Actionscript 3

MISE EN PLACE D’UN ÉCOUTEUR

classe Event spécifique aux évènements générés par votre souris. Bien évidemment,cette classe aurait été différente s’il s’agissait d’évènements provenant du clavier parexemple.

Gérer les écouteurs d’un objet

Ajouter un écouteur

Comme vous l’aurez compris, pour ajouter un écouteur à un objet, nous auronsbesoin de la méthode addEventListener(). Parce que mieux vaut deux fois qu’une, jevous rappelle l’allure de la signature de cette dernière :

1 addEventListener(type:String , listener:Function):void

À présent, vous savez donc comment définir la fonction à passer en paramètre de cetteméthode. Quant au type d’évènement, ici sous forme de String, celui-ci peut êtrerenseigné via les constantes définies à l’intérieur de la classe Event ou de l’une de sessous-classes.

Encore une fois, l’utilisation de ces constantes facilitent grandement la lisibilité et ledébogage du code. Par exemple, la chaîne de caractères "click" peut être rempla-cée par l’expression MouseEvent.CLICK. De cette manière, le code est plus clair. Parailleurs, le compilateur peut alors détecter une éventuelle faute de frappe, ce qui n’estpas le cas pour la chaîne en « brut ».

La constante MouseEvent.CLICK permet de faire référence aux évènements générés parle clic de votre souris. En outre, nous sommes capables de terminer la mise en placede notre écouteur. Voici donc comment enregistrer l’évènement monEcouteur() définieplus haut à l’objet stage :

1 stage.addEventListener(MouseEvent.CLICK , monEcouteur);

Si vous le désirez, vous pouvez à présent tester le code complet suivant :

1 function monEcouteur(event:MouseEvent):void2 {3 trace("Vous avez cliqué sur la scène principale.");4 }5 stage.addEventListener(MouseEvent.CLICK , monEcouteur);

Une fois l’application lancée et si vous cliquez à plusieurs reprise à l’intérieur de votrescène, vous verrez apparaître 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

Page 453: Programmez en Actionscript 3

CHAPITRE 21. LES ÉVÉNEMENTS

Dans cet exemple, nous avons enregistré l’écouteur auprès de l’objet stage,c’est-à-dire la scène principale. Nous aurions très bien pu le faire pour notreclasse Main de type Sprite. Cependant, si vous n’avez rien ajouté à celle-ci,ses dimensions sont nulles et il n’est pas possible d’y cliquer à l’intérieur.

Supprimer un écouteur

À tout moment, il est possible de retirer un écouteur enregistré auprès d’un objet. Pourcela, nous disposons de la méthode removeEventListener() définie par l’interfaceIEventDispatcher :1 removeEventListener(type:String , listener:Function):void

Une fois cette méthode appelée, l’objet ne répond alors plus aux évènements en ques-tion. Nous n’allons pas épiloguer plus longtemps sur cette méthode qui s’utilise de lamême façon que addEventListener().

Voici donc comment retirer l’écouteur ajouté plus haut :1 stage.removeEventListener(MouseEvent.CLICK , monEcouteur);

Le flux d’événements

Présentation du concept de flux d’évènements

Introduction

Lorsque survient un évènement, Flash Player distribue celui-ci directement à l’objetcible. Ce dernier peut alors gérer l’évènement comme il le souhaite, grâce à un éventuelécouteur. En revanche, ceci est plus complexe s’il s’agit d’un objet d’affichage. Pourvous en convaincre, nous allons reprendre nos histoires de voitures !

Souvenez-vous de notre voiture organisée comme à la figure 21.3 dans la liste d’affichage.

Il s’agit donc de la hiérarchie à l’intérieur de notre programme. Ceci dit, une fois quevous aurez lancé l’exécution du code, vous obtiendrez la fenêtre visible à la figure 21.4.

Dans l’image précédente, vous voyez que le curseur est positionné sur l’une des deuxroues. Au hasard, nous dirons qu’il s’agit de l’objet roue2. Si vous cliquez à l’aide devotre souris, un objet MouseEvent va donc être généré pour que l’évènement puisseêtre traité. Cependant, une petite question se pose alors !

À qui doit être distribué l’évènement généré par la souris ?

Certains diront qu’il semble plus logique de distribuer l’évènement auprès de l’objetroue2. En effet, c’est bien l’objet qui réellement la cible de l’évènement puisque c’est

430

Page 454: Programmez en Actionscript 3

LE FLUX D’ÉVÉNEMENTS

Figure 21.3 – L’arbre d’affichage de la voiture

Figure 21.4 – Les différents objets de la voiture à l’intérieur du Flash Player

431

Page 455: Programmez en Actionscript 3

CHAPITRE 21. LES ÉVÉNEMENTS

sur lui que le clic est effectué. À première vue, il est normal de faire de l’objet roue2la cible de l’évènement.

Toutefois, en y réfléchissant bien, ceci n’est finalement pas ce qu’il y a de plus pratique.Imaginons que dans notre application, nous voulions non pas détecter un clic sur l’unedes roues ou même sur la carrosserie, mais sur la voiture elle-même. Comment allons-nous pouvoir gérer cette situation au niveaux des évènements ? Allons nous devoirdéfinir un écouteur pour chacun des objets enfants de notre objet voiture ? Heureuse-ment, non ! Le Flash Player intègre ce qu’on appelle le flux d’évènements qui élargitgrandement les possibilités de la gestion des évènements.

Qu’est-ce que le flux d’évènements ?

Pour faciliter la gestion des évènements pour les objets d’affichage, le Flash Playerutilise une technique qui consiste à acheminer l’objet d’évènement dans toute la hié-rarchie de la liste d’affichage, depuis la scène principale jusqu’à l’objet cible. Pour êtreplus précis, l’objet évènement effectue en réalité un aller-retour sur le chemin décritprécédemment. Nous pouvons alors distinguer trois phases :

– La phase de capture : cette phase comprend la distribution de l’objet évènementdepuis la scène principale jusqu’à l’objet parent de la cible.

– La phase cible : il s’agit de la gestion de l’évènement par l’objet cible.– La phase de propagation : cette dernière phase est la « remontée » jusqu’à lascène principale, il s’agit donc du chemin inverse à la phase de capture.

Appliqué au cas d’un clic sur l’objet roue2 de notre voiture, le flux d’évènements peutalors être décomposé comme à la figure 21.5.

Figure 21.5 – La diffusion dans le flux d’évènements

Avec cette manière de procéder, il devient possible de gérer l’évènement à tous lesétages de la hiérarchie de notre liste d’affichage. Ainsi, nous pouvons alors enregistrerun écouteur pour cet évènement auprès du conteneur voiture. Pour mieux comprendre

432

Page 456: Programmez en Actionscript 3

LE FLUX D’ÉVÉNEMENTS

tous les mécanismes du flux d’évènements, nous allons maintenant réaliser quelquesmanipulations.

Bien comprendre le fonctionnement

Dans le flux d’évènements, l’objet d’évènements est distribué à chaque « nœud »ou objet de la liste d’affichage. Pour bien cerner comment cela fonctionne, nous allonstester quelques petits bouts de code. Nous allons donc reprendre notre voiture.

Commençons par définir nos éléments :1 // Définition des objets d'affichage2 var voiture:Sprite = new Sprite ();3 voiture.name = "voiture";4 var roue2:Sprite = new Sprite ();5 roue2.name = "roue2";6 voiture.addChild(roue2);7 addChild(voiture);

Pour simplifier l’exemple, nous limiterons le tracé de notre voiture à une unique roue.C’est un peu ridicule, je sais ! Mais cela ne nous empêchera pas de comprendre lesmécanismes liés au flux d’évènements.

Voici donc le code proposé pour dessiner cette roue :1 // Traçage de la roue2 roue2.graphics.lineStyle(2, 0x000000);3 roue2.graphics.beginFill(0xCCE5FF);4 roue2.graphics.drawCircle(0,0,25);5 roue2.graphics.endFill ();6 roue2.x = stage.stageWidth / 2;7 roue2.y = stage.stageHeight / 2;

En guise de fonction d’écouteur, nous nous contenterons de citer le nom de l’ob-jet d’affichage qui reçoit l’objet évènement. C’est pour cela que nous avons défini lapropriété name pour chacun de nos objets.

Pour rappel, le nom des variables est arbitraire et n’a de sens qu’à l’inté-rieur du code. Une fois le code compilé, Flash Player gère directement lesvariables en mémoire sans utiliser le nom que vous avez défini dans votrecode. C’est pourquoi la propriété name définie pour toutes les sous-classes deDisplayObject, permet facilement de distinguer nos objets d’affichage lorsde l’exécution du code.

Voici donc notre fonction d’écouteur :1 // Définition de la fonction d'écouteur2 function monEcouteur(event:MouseEvent):void3 {4 trace("Événement en cours de traitement par l'objet " +

event.currentTarget.name);

433

Page 457: Programmez en Actionscript 3

CHAPITRE 21. LES ÉVÉNEMENTS

5 }

Appliquons alors cette fonction d’écouteur à nos deux objets voiture et roue2, pourles évènements de type MouseEvent.CLICK :

1 // Mise en place des écouteurs2 voiture.addEventListener(MouseEvent.CLICK , monEcouteur);3 roue2.addEventListener(MouseEvent.CLICK , monEcouteur);

Je vous propose à présent de lancer l’exécution du code puis de cliquer sur votre roueà l’aide de votre souris. Vous verrez alors apparaître ceci dans la console :

Événement en cours de traitement par l’objet roue2Événement en cours de traitement par l’objet voiture

Attendez ! Pourquoi l’évènement est-il distribué à l’objet voiture après avoirété traité par l’objet roue2 ? Et sachant que le flux d’évènements représenteun aller-retour dans la liste d’affichage, ne devrait-il pas y avoir deux traite-ment de la fonction d’écouteur par l’objet stage ?

En toute rigueur, si ! Toutefois, lors de la mise en place d’un écouteur avec la méthodeaddEventListener(), nous définissons en réalité la phase durant laquelle l’écouteurest actif. Pour cela, il faut revenir sur la définition de cette fonction :

1 addEventListener(type:String , listener:Function , useCapture:Boolean = false , priority:int = 0, useWeakReference:Boolean= false):void

Dans cette méthode, le troisième paramètre nommé useCapture, de type Boolean,permet de définir les phases durant lesquelles l’écouteur est actif. Voilà donc commentce paramètre influe sur le flux d’évènements :

– true : l’écouteur est actif uniquement pendant la phase de capture.– false : l’écouteur est actif pendant les phases cible et de propagation.

Par défaut, ce paramètre vaut false. Dans le cas de notre objet voiture, l’écouteurest donc actif seulement pendant la phase de propagation.

Essayons maintenant de définir l’écouteur de notre objet voiture pendant la phase decapture :

1 voiture.addEventListener(MouseEvent.CLICK , monEcouteur , true);

Cette fois-ci, notre voiture voit bien l’évènement avant l’objet 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 d’évènements, vous aurez alors devinéque l’objet voiture peut intervenir à la fois durant la phase de capture et la phase de

434

Page 458: Programmez en Actionscript 3

L’OBJET EVENT

propagation. Cependant, cela nécessite d’enregistrer deux écouteurs différents auprèsde l’objet en question.

Même si cela semble superflu, voilà les instructions de définition des écouteurs :

1 voiture.addEventListener(MouseEvent.CLICK , monEcouteur , true);2 roue2.addEventListener(MouseEvent.CLICK , monEcouteur);3 voiture.addEventListener(MouseEvent.CLICK , monEcouteur);

À présent, nous pouvons donc agir à tous les niveaux, ou disons durant toutes les phasesdu flux d’évènements, 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 paramètre de la valeur true àla méthode addEventListener() de l’objet cible a pour effet de désactiver l’écouteurpendant la phase cible. Voici un exemple illustrant ces propos :

1 voiture.addEventListener(MouseEvent.CLICK , monEcouteur , true);2 roue2.addEventListener(MouseEvent.CLICK , monEcouteur , true);3 voiture.addEventListener(MouseEvent.CLICK , monEcouteur);

Ce qui donne évidemment dans la console de sortie :

Événement en cours de traitement par l’objet voitureÉvénement en cours de traitement par l’objet voiture

L’objet Event

Présentation de la classe Event

Avant de clôturer ce chapitre, nous allons brièvement parler de la classe Event. Nousavons déjà vu que cette dernière est la superclasse de tout objet évènement. Ainsi, lessous-classes hériteront de toutes ses propriétés. Ses accesseurs et méthodes servirontprincipalement à la gestion de l’évènement, nous allons donc rapidement les étudier.

Voici à la figure 21.6 l’heureuse élue que nous allons étudier.

Bien entendu, nous ne verrons et ne détaillerons pas toutes ces propriétés. Nous nousfocaliserons uniquement sur celles qui ont le plus d’intérêt pour nous pour l’instant.Parmi les attributs, certains sont plutôt d’ordre général, nous retiendrons donc lesdeux suivants :

– type : cet accesseur définit le type de l’évènement sous la forme d’une chaîne decaractères. Il s’agit de cette même chaîne qui est transmise en paramètre à laméthode addEventListener().

– target : cet attribut fait référence à l’objet cible de l’évènement.

435

Page 459: Programmez en Actionscript 3

CHAPITRE 21. LES ÉVÉNEMENTS

Figure 21.6 – La classe Event

Voici un petit code d’exemple d’utilisation de ces propriétés :

1 stage.addEventListener(MouseEvent.CLICK , monEcouteur);2 function monEcouteur(event:MouseEvent):void3 {4 trace("Événement de type " + event.type);5 trace("Cible de l'événement" + event.target);6 }

Ce qui donne :

Événement de type clickCible de l’événement[object Stage]

Les propriétés liés au flux d’évènements

Certaines propriétés de la classe Event sont en lien direct avec le flux d’évènements.Celles-ci permettent alors de situer et de contrôler l’objet Event tout au long du fluxd’évènements. Nous pouvons donc citer les deux attributs suivant :

– eventPhase : cette propriété indique la phase en cours dans le flux d’évènements.– currentTarget : cet attribut est une référence à l’objet cible « provisoire » qui peut

se situer n’importe où dans la hiérarchie de la liste d’affichage.

Afin de mieux comprendre ce dont il est question, nous allons reprendre nos objetsvoiture et roue2. Puis nous allons redéfinir la fonction d’écouteur pour faire ap-paraître les valeurs de ces attributs :

1 // Définition de la fonction d'écouteur2 function monEcouteur(event:MouseEvent):void3 {4 trace("Événement en cours de traitement par l'objet " +

event.currentTarget.name);5 trace("Phase du flux d'évènements en cours : " + event.

eventPhase);6 }

436

Page 460: Programmez en Actionscript 3

L’OBJET EVENT

Maintenant, enregistrons un écouteur pour chacune des phases du flux d’évènements :

1 // Mise en place des écouteurs2 voiture.addEventListener(MouseEvent.CLICK , monEcouteur , true);3 voiture.addEventListener(MouseEvent.CLICK , monEcouteur);4 roue2.addEventListener(MouseEvent.CLICK , monEcouteur);

À présent, il n’y a plus aucun doute sur la manière dont est géré l’objet évènement àtravers les différentes phases :

Événement en cours de traitement par l’objet voiturePhase du flux d’évènements en cours : 1Événement en cours de traitement par l’objet roue2Phase du flux d’évènements en cours : 2Événement en cours de traitement par l’objet voiturePhase du flux d’évènements en cours : 3

Comme vous le voyez, les phases sont représentés par un nombre entierallant de 1 à 3. Comme souvent en Actionscript, l’utilisation de ces va-leurs est simplifiée par la classe EventPhase et ses constantes respectivesCAPTURING_PHASE, AT_TARGET et BUBBLING_PHASE.

La classe Event dispose de deux méthodes stopImmediatePropagation() et stopPropagation()qui servent à stopper la diffusion de l’évènement dans le flux d’évènements, respec-tivement à partir du nœud actuel ou du nœud suivant. Ces méthodes permettent doncde gérer directement la propagation de l’objet évènement.

Pour visualiser ceci, je vous invite à remplacer la fonction d’écouteur monEcouteur()par la suivante :

1 function monEcouteur(event:MouseEvent):void2 {3 trace("Événement en cours de traitement par l'objet " +

event.currentTarget.name);4 if(event.eventPhase == EventPhase.AT_TARGET){5 event.stopPropagation ();6 }7 }

La propagation est alors stoppée à la fin de l’exécution de la fonction d’écouteur associéeà l’objet roue2 :

Événement en cours de traitement par l’objet voitureÉvénement en cours de traitement par l’objet roue2

437

Page 461: Programmez en Actionscript 3

CHAPITRE 21. LES ÉVÉNEMENTS

En résumé– Un évènement est généré de manière imprévisible, comme le clic d’une souris par

exemple.– Lesméthodes de gestion des écouteurs sont définies par l’interface IEventDispatcher

et la classe EventDispatcher.– La méthode addEventListener() sert à associer une fonction de rappel ou fonc-tion d’écouteur à un type d’évènements pour un objet donné.

– Le flux d’évènements définit le parcours effectué par un évènement dans la hié-rarchie de la liste d’affichage, entre la scène principale et l’objet cible.

– Le flux d’évènements est composé de la phase de capture, la phase cible et laphase de propagation.

– Les objets évènement sont représentés par la classe Event, ou l’une de ses classes-filles.

438

Page 462: Programmez en Actionscript 3

Chapitre 22Interagir avec l’utilisateur

Difficulté :

Maintenant que toutes les bases de la programmation événementielle sont posées, nousallons pouvoir mettre tout ceci en pratique au cours de ce chapitre. Nous apprendronscomment utiliser et manipuler des données saisies par l’utilisateur. Cela pourra être desdonnées issues de la souris ou du clavier.

439

Page 463: Programmez en Actionscript 3

CHAPITRE 22. INTERAGIR AVEC L’UTILISATEUR

La souris

L’objet MouseEvent

Introduction

Nous allons apprendre à gérer et manipuler des évènements provenant de lasouris. Lorsque qu’un tel évènement se produit, un objet de la classe MouseEvent estgénéré. Comme nous l’avons vu, tous les objets évènements héritent de la classeEvent et de ses propriétés (voir figure 22.1).

Figure 22.1 – La classe MouseEvent

Dans le chapitre précédent, j’avais mentionné le fait que les objets renfermaient desinformations liées à l’évènement. Ainsi, la classe MouseEvent dispose principalementde propriétés contenant des informations en lien avec la souris, notamment la positiondu curseur au moment de la génération de l’évènement. Étant donné que les interactionsavec la souris sont étroitement liées à l’interface graphique, cette classe sera évidemmentdistribuée dans le flux d’évènements.

Nous allons maintenant faire un tour des principales constantes et propriétés decette classe. Néanmoins, nous ne les verrons pas toutes, et je vous conseille donc devous rendre sur la page de la classe du guide de référence pour davantage d’informations.

B

�Documentation MouseEvent

Code web : 462867.

440

Page 464: Programmez en Actionscript 3

LA SOURIS

Les différents types d’évènements

Les types d’évènements liés à la souris sont définis sous forme de constantesstatiques de la classe MouseEvent. On les utilise ainsi :

1 MouseEvent.NOM_DE_LA_CONSTANTE23 // Par exemple :4 MouseEvent.CLICK

Voici ces constantes :

– CLICK : cette constante définit un clic avec le bouton gauche de la souris (il faut quele bouton soit successivement enfoncé puis relâché tout en étant au-dessus de la cibleà chaque fois).

– DOUBLE_CLICK : celle-ci définit un double-clic de la souris. Toutefois, la gestion de cetype d’évènements nécessite d’affecter la valeur true à la propriété doubleClickEnabledde l’objet en question.

– MOUSE_DOWN : cette constante décrit l’enfoncement du bouton gauche de la souris.– MOUSE_UP : à l’opposé de MOUSE_DOWN, MOUSE_UP est produit par le relâchement dubouton gauche de la souris.

– MIDDLE_CLICK : cette fois-ci, il s’agit d’un clic à l’aide du bouton du milieu de lasouris (qui est en général la molette de la souris).

– MIDDLE_MOUSE_DOWN : cette constante décrit l’enfoncement du bouton du milieu dela souris.

– MIDDLE_MOUSE_UP : comme pour MOUSE_UP, MIDDLE_MOUSE_UP est produit par lerelâchement du bouton du milieu de la souris, à l’opposé de MIDDLE_MOUSE_DOWN.

– RIGHT_CLICK : pour ce type d’événement, il s’agit d’un clic à l’aide du bouton droitde la souris.

– RIGHT_MOUSE_DOWN : cette constante décrit l’enfoncement du bouton droit de la sou-ris.

– RIGHT_MOUSE_UP : RIGHT_MOUSE_UP est produit par le relâchement du bouton droitde la souris, à l’opposé de RIGHT_MOUSE_DOWN.

– MOUSE_MOVE : un tel évènement se produit à chaque déplacement de la souris, mêmed’un seul et unique pixel !

– MOUSE_WHEEL : cette constante définit une action de défilement à l’aide de la molettede la souris. La direction de la molette est définie dans l’attribut delta de l’objet del’événement, qui est alors un entier positif ou négatif.

– ROLL_OVER : cette constante définit le survol de l’objet courant, ou de l’un de sesenfants, par la souris.

– ROLL_OUT : à l’inverse de MOUSE_OVER, cet évènement est généré lorsque la sourisquitte la « zone de tracé » d’un objet d’affichage et de l’ensemble de ses enfants.

Grâce à toutes ces constantes que vous pouvez combiner, il vous est maintenant possiblede prendre en compte les commande de l’utilisateur avec la souris.

441

Page 465: Programmez en Actionscript 3

CHAPITRE 22. INTERAGIR AVEC L’UTILISATEUR

Il existe également les constantes MOUSE_OVER et MOUSE_OUT, très semblablesau couple ROLL_OVER / ROLL_OUT. La différence se situe au niveau des objetsd’affichage enfants de la cible de l’événement : dans le cas de MOUSE_OVERet MOUSE_OUT, l’événement sera déclenché à chaque fois que la souris quittela surface d’un enfant pour aller sur un autre, même s’il n’y a pas d’espacevide entre eux. A l’inverse, pour ROLL_OVER et ROLL_OUT, la cible est sesenfants sont considérés comme étant une unique surface : l’événement n’estdéclenché qu’une seule fois. Il est donc fortement conseillé de toujours utiliserROLL_OVER et ROLL_OUT.

Imaginons que vous ayez créé un bouton constitué d’une image de fond assez grande etd’un champ de texte au milieu et que vous vouliez l’animer au passage de la souris. Enutilisant MOUSE_OVER et MOUSE_OUT, un événement de type MOUSE_OVER se déclencherad’abord lorsque la souris arrivera sur l’image de fond. Mais si la souris passe ensuitesur le champ de texte, un événement de type MOUSE_OUT apparaîtra (la souris a quittéla surface d’un enfant du bouton) puis, immédiatement après, un autre événement detype MOUSE_OVER sera déclenché (la souris arrive au-dessus du champ de texte) et vice-versa. Cela n’est pas vraiment optimal et cela peut provoquer des bugs d’animationpas très agréables sur le bouton lorsque la souris passe dessus.

Si vous utilisez ROLL_OVER et ROLL_OUT, un événement de type ROLL_OVER se déclen-chera une seule fois lorsque la souris entrera sur la surface de l’image de fond, mêmesi la souris passe de l’image au champ de texte. Enfin, un unique événement de typeROLL_OUT sera déclenché lorsque la souris quittera l’image de fond. En effet, les surfacesde chaque enfant ne sont pas considérées comme indépendantes : elles forment un tout(la surface totale du bouton).

Quelques propriétés utiles

La classe MouseEvent possède un certain nombre d’attributs ou de propriétés. Envoici quelques unes qui pourront vous êtes très utiles :

– stageX : contient la position horizontale globale où s’est produit l’évènement.– stageY : contient la position verticale globale où s’est produit l’évènement.– localX : contient la position horizontale locale par rapport au conteneur parent oùs’est produit l’évènement.

– localY : contient la position verticale locale par rapport au conteneur parent où s’estproduit l’évènement.

– buttonDown : indique si le bouton est enfoncé, principalement utile pour les évène-ments de type MOUSE_MOVE.

– altKey : indique si la touche�� ��Alt est enfoncée en parallèle de l’événement de la

souris.– ctrlKey : indique si la touche

�� ��Ctrl (ou�� ��Cmd pour les utilisateurs de Mac) est

enfoncée en parallèle de l’événement de la souris.– shiftKey : indique si la touche

�� ��Shift est enfoncée en parallèle de l’événement dela souris.

– delta (uniquement pour les événements de type MOUSE_WHEEL) : contient un entier

442

Page 466: Programmez en Actionscript 3

LA SOURIS

positif si la molette est défilée vers le haut, négatif dans le cas contraire.

Les trois propriétés altKey, ctrlKey et shiftKey sont uniquement des in-dicateurs permettant de déterminer si les touches correspondantes sont en-foncées lors de la génération de l’évènement. Des actions sur ces boutonsn’engendrent en aucun cas l’émission d’un objet MouseEvent.

Exemple : bouton simple

Pour illustrer ce que nous venons de voir, créons notre premier bouton ensemble ! Voicile code à écrire pour le bouton :

1 // Bouton2 var bouton:Sprite = new Sprite ();3 // Autorisation du double -clic4 bouton.doubleClickEnabled = true;5 // Curseur de bouton (généralement en forme de main)6 bouton.buttonMode = true;7 bouton.useHandCursor = true;8 // Les enfants ne sont pas gérés par la souris afin qu'ils n'

interfèrent pas avec le curseur de la souris9 // (sinon le champ de texte pourrait annuler le curseur de

bouton)10 bouton.mouseChildren = false;11 addChild(bouton);1213 // Texte14 var texte:TextField = new TextField ();15 // Pour éviter que le texte soit sélectionné16 texte.selectable = false;17 // Taille automatique18 texte.autoSize = TextFieldAutoSize.LEFT;19 // Format du texte20 texte.defaultTextFormat = new TextFormat('Arial', 32, 0xffffff)

;21 // Contenu22 texte.text = "Je suis un bouton";23 // Ajout du texte dans le bouton24 bouton.addChild(texte);2526 // Fond bleu27 var fond:Shape = new Shape ();28 // Ligne29 fond.graphics.lineStyle(2, 0x9999ff , 1, true);30 // Remplissage31 fond.graphics.beginFill(0x0000ff);32 // Dessin d'un rectangle à coins arrondis

443

Page 467: Programmez en Actionscript 3

CHAPITRE 22. INTERAGIR AVEC L’UTILISATEUR

33 fond.graphics.drawRoundRect(0, 0, texte.width , texte.height , 12);

34 // Ajout du fond bleu dans le bouton , en dessous du texte (cad ,à l'index 0)

35 bouton.addChildAt(fond , 0);3637 // Alignement du bouton au centre de la scène38 bouton.x = (stage.stageWidth - bouton.width) / 2;39 bouton.y = (stage.stageHeight - bouton.height) / 2;

Nous créons en premier lieu un sprite qui va représenter le bouton. On active le doubleclic à l’aide de l’attribut doubleClickEnabled, puis on active le curseur de bouton (gé-néralement en forme de main) en mettant les attributs buttonMode et useHandCursorà true.

Pourquoi désactiver la gestion de la souris sur les enfants du bouton ?

Si nous ne le faisons pas, le champ de texte aura le fâcheux comportement de malfaire fonctionner le curseur, qui sera remis en pointeur par défaut (au lieu du cur-seur de bouton en forme de main). Ainsi, par sécurité, il vaut mieux mettre l’attributmouseChildren à false pour les enfants soient plus directement gérés par la souris.Toutefois, ils comptent quand même dans la surface totale du bouton.

Puis nous créons le champ de texte qui affichera l’étiquette du bouton, suivie d’undessin de rectangle arrondi bleu pour embellir tout ceci.

Ensuite, écrivons les fonctions d’écouteur qui nous permettront de tester différentsévénements de la souris :1 // Fonctions d'écouteurs2 function onOver(e:MouseEvent):void3 {4 trace("La souris est entrée au-dessus du bouton.");5 }6 function onOut(e:MouseEvent):void7 {8 trace("La souris n'est plus au-dessus du bouton.");9 }

10 function onDown(e:MouseEvent):void11 {12 trace("Le bouton gauche de la souris est enfoncé au -dessus

du bouton.");13 }14 function onUp(e:MouseEvent):void15 {16 trace("Le bouton gauche de la souris est relâché au -dessus

du bouton.");17 }18 function onClick(e:MouseEvent):void

444

Page 468: Programmez en Actionscript 3

LA SOURIS

19 {20 trace("Le bouton a été cliqué.");21 }22 function onDoubleClick(e:MouseEvent):void23 {24 trace("Le bouton a été double -cliqué.");25 }26 function onMiddleClick(e:MouseEvent):void27 {28 trace("Le bouton a été cliqué milieu.");29 }30 function onRightClick(e:MouseEvent):void31 {32 trace("Le bouton a été cliqué droit.");33 }34 function onMove(e:MouseEvent):void35 {36 trace("La souris s'est déplacée au -dessus du bouton.");37 }

Enfin, nous écoutons les différents événements de la souris sur le bouton, qui en seraalors la cible :

1 // Evénements de la souris2 bouton.addEventListener(MouseEvent.ROLL_OVER , onOver);3 bouton.addEventListener(MouseEvent.ROLL_OUT , onOut);4 bouton.addEventListener(MouseEvent.MOUSE_DOWN , onDown);5 bouton.addEventListener(MouseEvent.MOUSE_UP , onUp);6 bouton.addEventListener(MouseEvent.CLICK , onClick);7 bouton.addEventListener(MouseEvent.DOUBLE_CLICK , onDoubleClick)

;8 bouton.addEventListener(MouseEvent.MIDDLE_CLICK , onMiddleClick)

;9 bouton.addEventListener(MouseEvent.RIGHT_CLICK , onRightClick);

10 bouton.addEventListener(MouseEvent.MOUSE_MOVE , onMove);

Nous avons à l’écran quelque chose comme la figure 22.2.

Figure 22.2 – Notre bouton bleu !

Si vous jouez un peu avec, vous obtiendrez des informations dans la console sur lesdifférents événements qui se déclenchent :

La souris est entrée au-dessus du bouton.La souris s’est déplacée au -dessus du bouton.La souris s’est déplacée au -dessus du bouton.

445

Page 469: Programmez en Actionscript 3

CHAPITRE 22. INTERAGIR AVEC L’UTILISATEUR

La souris s’est déplacée au -dessus du bouton.Le bouton gauche de la souris est enfoncé au -dessus du bouton.Le bouton gauche de la souris est relâché au -dessus du bouton.Le bouton a été cliqué.Le bouton a été cliqué milieu.Le bouton a été cliqué droit.La souris s’est déplacée au -dessus du bouton.La souris s’est déplacée au -dessus du bouton.La souris s’est déplacée au -dessus du bouton.La souris n’est plus au-dessus du bouton.

La technique du « glisser-déposer »

Le glisser-déposer (ou drag and drop en anglais) est une méthode qui consiste àdéplacer un élément graphique d’un endroit à un autre. Il s’agit du même principe quelorsque que vous déplacez une icône sur votre bureau. Pour cela, vous effectuez un clicque vous maintenez le temps du déplacement. Le déplacement s’arrête lorsque vousrelâchez le bouton de la souris.

EnActionscript, ce concept est beaucoup plus poussé et puissant puisqu’il est possiblede contrôler à souhaits ce fameux glisser-déposer. Une manière de réaliser ceci se-rait de combiner intelligemment les trois types d’évènements MOUSE_DOWN, MOUSE_MOVEet MOUVE_UP. Mais l’Actionscript facilite davantage la mise en place de cette tech-nique. C’est pourquoi la classe Sprite dispose des deux méthodes startDrag() etstopDrag() permettant respectivement d’activer ou de désactiver le glisser-déposersur cet objet.

Nous allons utiliser un exemple qui sera beaucoup plus parlant. Commençons par des-siner un carré violet dans notre scène :

1 var objet:Sprite = new Sprite ();2 addChild(objet);3 objet.graphics.beginFill(0x8800FF);4 objet.graphics.drawRect(0, 0, 50, 50);

En utilisant ces fameuses méthodes startDrag() et stopDrag(), il n’est maintenantplus nécessaire de se préoccuper des déplacements de la souris. Seuls le démarrage etl’arrêt du glisser-déposer doivent être contrôlés. Nous pouvons alors très facilementmettre ceci en place grâce aux deux écouteurs suivants :

1 objet.addEventListener(MouseEvent.MOUSE_DOWN , glisser);2 function glisser(event:MouseEvent):void3 {4 objet.startDrag ();5 }6 objet.addEventListener(MouseEvent.MOUSE_UP , deposer);7 function deposer(e:MouseEvent):void8 {9 objet.stopDrag ();

446

Page 470: Programmez en Actionscript 3

LA SOURIS

10 }

À l’intérieur du Flash Player, il est maintenant possible de déplacer notre objet àvolonté !

Exercice : Créer et animer un viseur

Dessiner le viseur

Dans cet exercice, nous allons voir comment dessiner et animer un viseur tel quenous pourrions en trouver dans un jeu de tir. Nous commencerons donc par tracerl’élément qui vous servira de viseur.

Voici à la figure 22.3 le viseur que je vous propose de dessiner.

Figure 22.3 – Le viseur

Créons donc un objet viseur de type Shape, et traçons les différents éléments quicompose celui-ci :1 var viseur:Shape = new Shape ();2 addChild(viseur);3 viseur.graphics.lineStyle(2, 0x000000);4 viseur.graphics.drawCircle(0, 0, 20);5 viseur.graphics.lineStyle(1, 0x550000);6 viseur.graphics.drawCircle(0, 0, 16);7 viseur.graphics.moveTo(-25, 0);8 viseur.graphics.lineTo(25, 0);9 viseur.graphics.moveTo(0, -25);

10 viseur.graphics.lineTo(0, 25);11 viseur.x = stage.stageWidth / 2;12 viseur.y = stage.stageHeight / 2;

Comme vous pouvez le voir, il n’y a rien de bien compliqué dans ce code. Nous avonsuniquement tracé deux cercles concentriques et deux segments perpendiculaires.

En réalité, pour cet exercice, nous n’allons pas réellement remplacer le curseur. Nousallons nous contenter de « suivre » la position de la souris et nous masquerons la souriselle-même. Cela donnera alors l’illusion que le curseur est un viseur.

Pour masquer la souris, utilisez l’instruction suivante :1 Mouse.hide();

La fonction hide() est une méthode statique de la classe Mouse. N’oubliezdonc pas d’importer cette classe dans votre projet. Pour faire réapparaîtrevotre curseur, vous pouvez utiliser la méthode statique inverse : show().

447

Page 471: Programmez en Actionscript 3

CHAPITRE 22. INTERAGIR AVEC L’UTILISATEUR

Gérer les évènements

À présent, occupons-nous de la gestion des évènements ! Nous allons procéder endeux temps. Premièrement, nous allons faire en sorte que le viseur suive le curseur enmettant à jour sa position. Ensuite, nous ajouterons un second écouteur pour simulerun tir. Bien sûr tout cela reste à un niveau basique, mais l’idée est là.

Pour mettre à jour la position du viseur, nous allons utiliser les évènements de typeMOUSE_MOVE. Les propriétés stageX et stageY de la classe MouseEvent nous servirontà replacer le viseur.

Voilà donc la mise en place de notre écouteur :

1 stage.addEventListener(MouseEvent.MOUSE_MOVE ,repositionnerViseur);

2 function repositionnerViseur(event:MouseEvent):void3 {4 viseur.x = event.stageX;5 viseur.y = event.stageY;6 }

Nous allons maintenant nous concentrer sur la gestion des évènements de type« tirs ». Je vous propose pour cela, d’utiliser le clic de la souris, ou plutôt l’enfoncementdu bouton de gauche. Il s’agit bien évidemment de l’évènement MOUSE_DOWN.

À l’intérieur de la fonction d’écouteur associée, nous créerons un petit rond rouge,grossièrement semblable à une tâche de sang, puis nous la positionnerons au niveau duviseur. Rien de bien complexe ici, voici le code correspondant :

1 stage.addEventListener(MouseEvent.MOUSE_DOWN , tirer);2 function tirer(event:MouseEvent):void3 {4 var impact:Shape = new Shape();5 impact.graphics.beginFill(0xFF0000);6 impact.graphics.drawCircle(0, 0, 4);7 impact.x = event.stageX;8 impact.y = event.stageY;9 addChildAt(impact , 0);

10 }

Nous avons utilisé un évènement de type MOUSE_DOWN, mais nous pourrions très bien pule faire à l’aide des évènements MOUSE_UP ou CLICK. Lorsque vous programmez votreinterface, c’est à vous de choisir le type d’évènements qui correspond le mieux à ce quevous souhaitez faire.

Le rendu

Pour admirer le magnifique rendu de cette application (voir figure 22.4), je ne peuxque vous inviter à exécuter le code et à tirer dans tous les sens !

448

Page 472: Programmez en Actionscript 3

LA SOURIS

Figure 22.4 – Les prémices d’un jeu de tir

Curseurs personnalisés

Il est possible de remplacer le curseur de la souris par une image ou une animation denotre choix, ce qui présente des avantages par rapport à la technique que nous venonsde voir pour le viseur : le curseur sera un curseur natif, c’est-à-dire qu’il sera direc-tement géré par le système d’exploitation de l’utilisateur. Cela implique de meilleuresperformances : moins de ressources seront consommées pour afficher le curseur et mêmesi votre application est victime de ralentissement, votre curseur personnalisé n’en serapas affecté, ce qui améliore grandement l’expérience utilisateur. De plus, le curseur nesera pas coupé aux bords de la zone d’affichage de votre application : il pourra dépasseren dehors de la fenêtre (par exemple, s’il se situe en bas de votre application, il conti-nuera d’être affiché, même en dehors de la scène). Il est donc très fortement conseilléd’utiliser les curseurs natifs personnalisés si vous voulez remplacer le curseur de lasouris, c’est la meilleure méthode.

Il est possible que le système sur lequel votre application est lancée ne supportepas les curseurs natifs (c’est par exemple le cas pour les smartphones) : vouspouvez le savoir avec l’attribut statique supportsNativeCursor de la classeMouse.

Ainsi, nous n’utiliserons de curseur natif que si cette fonctionnalité est supportée :

1 if(Mouse.supportsNativeCursor)2 {3 // Création du curseur natif personnalisé ici

449

Page 473: Programmez en Actionscript 3

CHAPITRE 22. INTERAGIR AVEC L’UTILISATEUR

4 }

Un curseur natif ne peut pas dépasser une taille de 32 pixels sur 32 pixels.

Préparer son curseur

Il faut savoir qu’un curseur personnalisé ne peut être qu’une image bitmap (ou unesérie d’images dans le cas des curseurs animés). Ce qui signifie qu’il nous est impossibled’utiliser directement un objet d’affichage comme le dessin (de la classe Shape) quenous avons créé pour afficher notre viseur. Toutefois, il existe un moyen de prendre unecapture de n’importe quel objet d’affichage pour obtenir une image bitmap !

Il est bien entendu également possible d’utiliser directement des images quevous aurez incorporées au préalable.

Reprenons le code que nous avons utilisé pour créer notre viseur sans l’ajouter à lascène :

1 var viseur:Shape = new Shape();2 viseur.graphics.lineStyle(2, 0x000000);3 viseur.graphics.drawCircle(0, 0, 20);4 viseur.graphics.lineStyle(1, 0x550000);5 viseur.graphics.drawCircle(0, 0, 16);6 viseur.graphics.moveTo(-25, 0);7 viseur.graphics.lineTo(25, 0);8 viseur.graphics.moveTo(0, -25);9 viseur.graphics.lineTo(0, 25);

Nous ne pouvons pas utiliser ce dessin pour en faire un curseur natif, mais nous pou-vons en prendre une capture (comme vous prendriez une capture d’écran). Pour cela,nous allons d’abord créer une image vide avec la classe BitmapData et utiliser sa mé-thode draw() (qui signifie ’dessiner’). Cette méthode prend en paramètre n’importequel objet qui implémente l’interface IBitmapDrawable. Comme nous pouvons le voirdans la documentation, il s’agit de tous les objets ayant pour classe (ou super-classe)BitmapData ou DisplayObject.

Pour créer l’image bitmap, il nous faut les bornes d’affichage de notre viseur : en effet,notre dessin est centré par rapport à son origine, donc si nous en faisons une capturesans en tenir compte, il sera coupé à partir de son origine (donc nous n’obtiendronsqu’un quart du viseur). Nous calculons les bornes d’affichage de notre dessin grâce à laméthode getBounds() de la classe DisplayObject, qui prend en paramètre un objetd’affichage servant de référence. Nous passons donc le viseur lui-même pour savoir decombien il dépasse par rapport à sa propre origine :

450

Page 474: Programmez en Actionscript 3

LA SOURIS

1 // Bornes d'affichage de l'objet2 var bornes:Rectangle = viseur.getBounds(viseur);3 trace("bornes:" + bornes);

Si vous testez votre code tout de suite, vous obtiendrez ceci dans la console :

bornes :(x=-25.5, y=-25.5, w=51, h=51)

Nous pouvons alors remarquer que notre dessin dépasse de 25 pixels et demi par rapportà son origine, verticalement et horizontalement. Sa taille totale est de 51 pixels sur 51pixels.

Créons notre image vide :

1 // Image vide de bonne taille2 var capture:BitmapData = new BitmapData(32, 32, true , 0);

Ensuite, pour prendre en compte le fait que notre dessin dépasse de son origine, nousallons « déplacer » la capture pour compenser à l’aide d’une matrice de transfor-mation :

1 // Déplacement de la capture en fonction des bornes d'affichage2 var transformation:Matrix = new Matrix ();3 transformation.translate( -bornes.x, -bornes.y);

Comme un curseur natif ne peut dépasser une taille de 32 pixels de côté, nous allonsréduire la taille du viseur :

1 // La taille maximale d'un curseur natif est de 32 pixels2 transformation.scale(32 / bornes.width , 32 / bornes.height);

Enfin, il ne nous reste plus qu’à prendre la capture de notre viseur :

1 // Capture2 capture.draw(viseur , transformation);

Désormais, notre image contient une capture bitmap de notre viseur, utilisable pourcréer un curseur personnalisé !

Pour vérifier que nous ne nous sommes pas trompés, affichons la capture avec un objetde la classe Bitmap :

1 // Affichage de la capture pour vérification2 var apercu:Bitmap = new Bitmap(capture);3 addChild(apercu);

Nous obtenons alors la figure 22.5.

Pour bien comprendre qu’il s’agit d’une capture bitmap, agrandissons l’aperçu quatrefois :

1 apercu.scaleX = 4;2 apercu.scaleY = apercu.scaleX;

451

Page 475: Programmez en Actionscript 3

CHAPITRE 22. INTERAGIR AVEC L’UTILISATEUR

Figure 22.5 – L’aperçu de la capture

Figure 22.6 – Il s’agit bien d’une image bitmap

Ce qui nous donne la figure 22.6.

Les gros pixels nous confirment que nous avons là une image bitmap et non plus undessin vectoriel.

Créer le curseur natif

Chaque curseur natif est créé à l’aide d’un objet de la classe MouseCursorData conte-nant les images et autres informations à propos du curseur. Commençons donc par encréer une instance :

1 // Données du curseur natif personnalisé2 var curseur:MouseCursorData = new MouseCursorData ();

Ensuite, il nous faut un vecteur contenant une ou plusieurs images (ici nous lui inséronsla capture du viseur) :

1 // Images du curseur (s'il y en a plusieurs , le curseur seraanimé)

2 var images:Vector.<BitmapData > = new Vector.<BitmapData >();3 images.push(capture);4 curseur.data = images;

Puis nous renseignons le point actif du curseur, c’est-à-dire la position qui représentele point où l’utilisateur va cliquer. Dans notre cas, nous voulons que le point actif soit

452

Page 476: Programmez en Actionscript 3

LA SOURIS

le centre du viseur :

1 // Point actif du curseur -> centre de notre viseur2 curseur.hotSpot = new Point(capture.width / 2, capture.height /

2);

Enfin, il faut enregistrer notre curseur natif en lui donnant un nom, grâce à laméthode statique registerCursor de la classe Mouse :

1 // Enregistrement du cuseur natif personnalisé2 Mouse.registerCursor("viseur", curseur);

Notre curseur est fin prêt à être utilisé !

Activer un curseur natif

Pour activer notre nouveau curseur natif, il faut affecter à l’attribut statiquecursor de la classe Mouse le nom de notre curseur :

1 // Activons notre cuseur2 Mouse.cursor = "viseur";

Et voilà que notre curseur de souris s’est transformé en viseur, comme le montre lafigure 22.7.

Figure 22.7 – Notre curseur natif personnalisé

Comme vous pouvez le remarquer, le curseur n’est plus coupé par les bords de notreapplication et il est très fluide quelque soit la fréquence de rafraîchissement de l’appli-cation.

Voici le code complet permettant de créer ce curseur natif :

1 if (Mouse.supportsNativeCursor)2 {3 // Dessin4 var viseur:Shape = new Shape ();5 viseur.graphics.lineStyle(2, 0x000000);6 viseur.graphics.drawCircle(0, 0, 20);7 viseur.graphics.lineStyle(1, 0x550000);

453

Page 477: Programmez en Actionscript 3

CHAPITRE 22. INTERAGIR AVEC L’UTILISATEUR

8 viseur.graphics.drawCircle(0, 0, 16);9 viseur.graphics.moveTo(-25, 0);

10 viseur.graphics.lineTo(25, 0);11 viseur.graphics.moveTo(0, -25);12 viseur.graphics.lineTo(0, 25);1314 // Bornes d'affichage de l'objet15 var bornes:Rectangle = viseur.getBounds(viseur);16 trace("bornes:" + bornes);1718 // Image vide de bonne taille19 var capture:BitmapData = new BitmapData(32, 32, true , 0);20 // Déplacement de la capture en fonction des bornes d'

affichage21 var transformation:Matrix = new Matrix ();22 transformation.translate( -bornes.x, -bornes.y);23 // La taille maximale d'un curseur natif est de 32 pixels24 transformation.scale(32 / bornes.width , 32 / bornes.height)

;25 // Capture26 capture.draw(viseur , transformation);2728 // Affichage de la capture pour vérification29 /*var apercu:Bitmap = new Bitmap(capture);30 addChild(apercu);31 apercu.scaleX = 4;32 apercu.scaleY = apercu.scaleX;*/333435 // Données du curseur natif personnalisé36 var curseur:MouseCursorData = new MouseCursorData ();37 // Images du curseur (s'il y en a plusieurs , le curseur

sera animé)38 var images:Vector.<BitmapData > = new Vector.<BitmapData >();39 images.push(capture);40 curseur.data = images;41 // Point actif du curseur -> centre de notre viseur42 curseur.hotSpot = new Point(capture.width / 2, capture.

height / 2);43 // Enregistrement du cuseur natif personnalisé44 Mouse.registerCursor("viseur", curseur);4546 // Activons notre cuseur47 Mouse.cursor = "viseur";4849 }

454

Page 478: Programmez en Actionscript 3

LE CLAVIER

Désactiver le curseur natif personnalisé

Si vous n’avez plus besoin de votre curseur natif en forme de viseur, vous pouvez trèssimplement revenir au curseur par défaut du système d’exploitation de l’utilisateur àl’aide de l’instruction suivante :

1 Mouse.cursor = MouseCursor.AUTO;

Le clavier

L’objet KeyboardEvent

Tout comme ceux qui proviennent de la souris, les évènements issus du claviergénèrent leur propre classe, à savoir KeyboardEvent. Celle-ci hérite évidemment de laclasse Event, en y ajoutant ses propres propriétés.

Voici à la figure 22.8 un schéma UML qui permet de résumer un peu toutes lespropriétés ou méthodes fournies par ces deux classes.

Figure 22.8 – La classe KeyboardEvent

Contrairement à la souris, les types d’évènements produits par le clavier sont beaucoupmoins nombreux, puisqu’ils ne sont que deux ! Voici donc les constantes de la classeKeyboardEvent qui les définissent :

– KEY_DOWN : cette constante décrit l’enfoncement de n’importe quelle touche du clavier.– KEY_UP : celle-ci représente le relâchement de n’importe quelle touche du clavier.

455

Page 479: Programmez en Actionscript 3

CHAPITRE 22. INTERAGIR AVEC L’UTILISATEUR

Même s’il est possible de trouver un grand nombre d’applications nécessitant la combi-naison de ces deux types d’évènements, vous n’en utiliserez qu’un la majorité du temps.Et comme cela semble souvent plus naturel, il s’agira de l’évènement KEY_DOWN.

Les attributs ou propriétés associées à la classe KeyboardEvent ne sont égalementpas très nombreuses, et les voici :

– charCode : cet attribut représente la lettre, ou plutôt le caractère de la touche concer-née par l’évènement. Ce caractère est définit par un code numérique.

– keyCode : cette propriété contient le code de la touche enfoncée ou relâchée.– keyLocation : indique l’emplacement de la touche sur le clavier.– altKey : indique si la touche

�� ��Alt est enfoncée en parallèle de l’événement de lasouris.

– ctrlKey : indique si la touche�� ��Ctrl (ou

�� ��Cmd pour les utilisateurs de Mac) estenfoncée en parallèle de l’événement de la souris.

– shiftKey : indique si la touche�� ��Shift est enfoncée en parallèle de l’événement de

la souris.

Pour savoir sur quelle touche l’utilisateur a appuyé, nous pouvons utiliser la classeKeyboard qui contient le code de chaque touche du clavier. Par exemple, pour effectuerune action sur l’utilisateur qui appuie sur la touche

�� ��A , nous procéderons ainsi :

1 if(event.keyCode == Keyboard.A)2 {3 trace("Appui sur la touche [A]");4 }

Il est important de bien distinguer les deux propriétés charCode et keyCode.La première désigne le code de la touche dans le jeu de caractères actuel.Chaque caractère est associé à une valeur numérique : on parle alors decodage de caractères ou encore encodage. Par défaut, il s’agit de l’UTF-8, qui prend en charge le célèbre code ASCII. En revanche, keyCode faitréférence à la touche en elle-même indépendamment du codage utilisé. Ainsiles lettres « a » et « A » sont associées à deux codes différent en UTF-8, maisla touche reste la même, et donc keyCode aussi. Inversement la touche 1 dupavé numérique est différente du 1 du clavier central, pourtant le caractèreest strictement le même.

Enfin, avant de basculer vers des exemples, nous allons revenir sur la propriété keyLocation.Si vous regardez votre clavier de plus près, vous verrez alors que celui-ci est composé dedeux touches

�� ��Ctrl distincts, ou encore de deux touches�� ��Shift différentes. Aussi sur-

prenant que cela puisse paraître, chaque couple possède exactement les mêmes attributscharCode et keyCode.

Mais comment les différencier alors ?

456

Page 480: Programmez en Actionscript 3

LE CLAVIER

C’est là qu’entre en scène cette fameuse propriété keyLocation. Sous forme de nombre,cette propriété permet de définir l’emplacement de la touche sur le clavier. Pour cela, laclasse KeyLocation propose un jeu de constantes relativement explicite. Jugez plutôt :STANDARD, LEFT, RIGHT et NUM_PAD.

Exercice : gérer l’affichage de l’animation

C’est l’heure de passer un peu à la pratique à travers un petit exemple, simple certes,mais très intéressant. L’objectif est donc de basculer l’animation en mode plein écranavec la combinaison

�� ��Shift +�� ��Entrée (et uniquement à l’aide la touche

�� ��Shift

de gauche). Pour revenir à l’affichage normal, un simple appui sur la touche�� ��Échap

devrait suffire.

Pour réaliser le basculement d’un mode d’affichage à un autre, nous aurons besoin d’uti-liser la propriété displayState défini par la classe Stage. Cette propriété peut alorsprendre les valeurs des constantes NORMAL, FULL_SCREEN et FULL_SCREEN_INTERACTIVEde la classe StageDisplayState.

Le mode FULL_SCREEN_INTERACTIVE permet le support complet du claviercontrairement au mode FULL_SCREEN qui se limite à quelques touches utiles(comme les touches fléchées). Seulement, le support complet du clavier peutintroduire des failles de sécurités (un site web imitant votre bureau en pleinécran pour vous demander et voler vos identifiants par exemple), c’est pour-quoi un message informatif et une demande de confirmation sont affichés àl’utilisateur si votre application est sur une page web dans un navigateur.Ce n’est pas le cas pour le mode FULL_SCREEN qui restreint l’utilisation duclavier.

Avant de nous lancer tête baissée, réfléchissons un peu et analysons ce que nous voulonsfaire. Grâce aux propriétés keyCode et shiftKey, il est possible de détecter la com-binaison des touches

�� ��Shift et�� ��Entrée . En revanche, dans ce cas là, la gestion de

l’évènement qui engendrera le basculement en plein écran sera faite lors de l’enfonce-ment de la touche

�� ��Entrée . C’est pourquoi, à ce moment, nous n’aurons pas accès à lapropriété keyLocation ni généré l’enfoncement de la touche

�� ��Shift . Pour pouvoir gé-rer correctement ce cas de figure, nous serons dans l’obligation de déclarer une variablechargée de conserver la valeur de la propriété keyLocation de l’évènement précédent.

Pour commencer, nous pouvons donc mettre en place l’écouteur suivant :

1 var lastKeyLocation:uint = 0;2 stage.addEventListener(KeyboardEvent.KEY_DOWN ,

changerDAffichage);3 function changerDAffichage(event:KeyboardEvent):void4 {5 // Gestion du changement du mode d'affichage6 lastKeyLocation = event.keyLocation;7 }

457

Page 481: Programmez en Actionscript 3

CHAPITRE 22. INTERAGIR AVEC L’UTILISATEUR

Ensuite, nous devons définir la condition de mise en plein écran. Pour cela, nous al-lons donc détecter l’enfoncement de la touche

�� ��Entrée par sa propriété keyCode quivaudra Keyboard.ENTER (équivalent à 13), en présence de la touche

�� ��Shift , et utiliserégalement notre variable lastKeyLocation, comme ceci :

1 if (event.keyCode == Keyboard.ENTER && event.shiftKey == true&& lastKeyLocation == KeyLocation.LEFT)

2 {3 // Mise en plein écran4 }

La remise en mode d’affichage normal sera beaucoup plus simple puisqu’il suffit dedétecter une valeur Keyboard.ESCAPE (équivalent à 27) de la propriété keyCode quicorrespond à la touche

�� ��Echap .

Au final, cela nous donne le code suivant :

1 var lastKeyLocation:uint = 0;2 stage.addEventListener(KeyboardEvent.KEY_DOWN ,

changerDAffichage);3 function changerDAffichage(event:KeyboardEvent):void4 {5 if (event.keyCode == Keyboard.ENTER && event.shiftKey ==

true && lastKeyLocation == KeyLocation.LEFT)6 {7 if (stage.allowsFullScreen)8 {9 // Plein écran supporté

10 if (stage.allowsFullScreenInteractive)11 {12 // Plein écran avec support complet du clavier13 stage.displayState = StageDisplayState.

FULL_SCREEN_INTERACTIVE;14 }15 else16 {17 // Plein écran restreint18 stage.displayState = StageDisplayState.

FULL_SCREEN;19 }20 }21 }22 if (event.keyCode == Keyboard.ESCAPE)23 {24 stage.displayState = StageDisplayState.NORMAL;25 }26 trace("Etat de l'écran : " + stage.displayState);2728 lastKeyLocation = event.keyLocation;29 }

458

Page 482: Programmez en Actionscript 3

CHAMPS DE SAISIE

Ne pas oublier de vérifier que les différents modes d’affichagesont disponibles à l’aide des attributs allowsFullScreen etallowsFullScreenInteractive de la classe Stage.

Si tout se passe bien, nous obtenons ceci dans la console en basculant entre l’affichagenormal et le plein écran :

Etat de l’écran : normalEtat de l’écran : fullScreenInteractiveEtat de l’écran : normal

Champs de saisie

Retour sur l’objet TextField

Introduction

Un champ de saisie est particulier : on y peut entrer du texte, le modifier ou l’effacer.Par exemple, vous pouvez demander le nom de l’utilisateur grâce à un champ de saisie.Il est possible de rendre un champ de texte éditable pour le transformer en champ desaisie. Pour cela, rien de plus simple ! Il suffit de mettre l’attribut type d’un objet dela classe TextField à TextFieldType.INPUT comme ceci :

1 monSuperTexte.type = TextFieldType.INPUT;

Comme d’habitude, ne pas oublier d’importer chaque classe que vous utilisez,ici TextFieldType.

Reprenons un code à base de TextField puis faisons en sorte de créer un champ desaisie :

1 // Création de l'objet TextField2 var monSuperTexte:TextField = new TextField ();34 // Formatage du texte5 var format:TextFormat = new TextFormat("Arial", 14 , 0x000000);6 monSuperTexte.defaultTextFormat = format;78 // Ajout d'une bordure9 monSuperTexte.border = true;

1011 // Taille12 monSuperTexte.width = 200;13 monSuperTexte.height = 20;14

459

Page 483: Programmez en Actionscript 3

CHAPITRE 22. INTERAGIR AVEC L’UTILISATEUR

15 // Centrage16 monSuperTexte.x = (stage.stageWidth - monSuperTexte.width) / 2;17 monSuperTexte.y = (stage.stageHeight - monSuperTexte.height) /

2;1819 // Ajout à l'affichage20 addChild(monSuperTexte);2122 // Il faut pouvoir sélectionner le texte (ligne falcutative)23 monSuperTexte.selectable = true;2425 // Type du champ de texte : saisie26 monSuperTexte.type = TextFieldType.INPUT;

Je peux maintenant écrire ce que je veux dans le champ de texte éditable, comme lemontre la figure 22.9.

Figure 22.9 – Un champ de saisie !

Bien entendu, il est tout à fait possible de rendre un champ de saisie multi-lignes. Celafonctionne exactement de la même façon que pour un champ de texte basique :

1 // Basculement en mode multi -lignes2 monSuperTexte.multiline = true;3 monSuperTexte.autoSize = TextFieldAutoSize.LEFT;

Ce qui nous donne la figure 22.10.

460

Page 484: Programmez en Actionscript 3

CHAMPS DE SAISIE

Figure 22.10 – Un champ de saisie multi-lignes

Restriction de la saisie

Lorsque nous définissons un objet TextField en tant que champ de saisie de texte,l’utilisateur peut écrire ce qu’il souhaite à l’intérieur. Dans certains cas, cela peuts’avérer inapproprié. Imaginons que nous voulions créer un formulaire dans lequel l’uti-lisateur peut renseigner des informations personnelles, telles que son nom, son prénom,sa date de naissance, etc. Il peut alors devenir gênant de se retrouver avec un nom defamille comportant des chiffres, ou encore avec une date de naissance contenant descaractères tels que « # », « @ » ou « & ».

En Actionscript, il est possible de restreindre la saisie du texte, c’est-à-diren’autoriser la saisie que certains caractères. Pour effectuer cela, nous devons nous servirde la propriété restrict de la classe TextField. Il suffit alors de renseigner la listedes caractères autorisés, comme ceci :

1 // Restriction de la saisie du texte2 monSuperTexte.restrict = "ABC";

Une fois le programme lancé, essayez de saisir divers caractères. Vous verrez alors qu’ilest possible de saisir uniquement les trois caractères que nous avons précisé au-dessus,comme le montre la figure 22.11.

Figure 22.11 – Restriction de la saisie aux trois caractères « A », « B » ou « C »

461

Page 485: Programmez en Actionscript 3

CHAPITRE 22. INTERAGIR AVEC L’UTILISATEUR

Je pense que certains s’imaginent déjà qu’autoriser la saisie d’un grand nombre decaractères va être une « galère » colossale ! Heureusement, il existe des raccourcis pourfaciliter la restriction à une plage de caractères. Par exemple, voici comment autoriserseulement la saisie de chiffres :

1 monSuperTexte.restrict = "0-9";

Ce qui nous donne la figure 22.12.

Figure 22.12 – Restriction de la saisie aux caractères numériques

Pour les lettres, cela fonctionne exactement de la même manière. Voici comment faire,avec en prime l’ajout de l’espace (drôlement pratique pour séparer les mots) :

1 monSuperTexte.restrict = "A-Z ";

Si vous entrez des caractères alphabétiques, ceux-ci sont alors automatiquement saisisen majuscule comme vous voir sur la figure 22.13.

Figure 22.13 – Restriction de la saisie aux majuscules

Pour restreindre la saisie à l’ensemble des caractères alpha-numériques, vousdevrez alors renseigner la chaîne de caractères suivante : "A-Za-z0-9 ".

Quelques autres propriétés utiles

Il arrive parfois que nous ayons besoin de masquer le contenu de la saisie d’untexte, à l’instar des mots de passe. Comme d’habitude, l’Actionscript a tout prévu :un attribut de la classe TextField, nommé displayAsPassword, permet de faire ceci.

Cette propriété est un booléen qu’il suffit donc de mettre à la valeur true :

1 // Définition de la saisie en mode « mot de passe »2 monSuperTexte.displayAsPassword = true;

À présent, si vous saisissez du texte, le contenu du champ de texte sera remplacé parune série de « * », comme sur la figure 22.14.

Figure 22.14 – La saisie de mot de passe

462

Page 486: Programmez en Actionscript 3

CHAMPS DE SAISIE

Contrairement à un champ de texte, disons traditionnel, seul l’affichage estdifférent. Vous pouvez ainsi utiliser la propriété text comme à son habitude.Cette dernière contient toujours le contenu de la saisie et non la série de« * ».

Enfin, vous pouvez également noter la présence de l’attribut maxChars permet de définirle nombre de caractères maximal à saisir. Une fois cette limite atteinte, plus aucuncaractère ne peut être ajouté.

Pour utilise cette fonction, il vous suffit de préciser simplement le nombre de caractèresautorisés pour la saisie :

1 monSuperTexte.maxChars = 10;

Évènements et TextField

Détecter une modification

Il est possible de détecter la moindre modification du texte contenu dans lechamp de saisie car ce dernier déclenche alors un événement de type Event.CHANGE.Cela se produit lorsque :

– Un caractère est entré.– Un caractère est supprimé.– Du texte est collé dans le champ de saisie.– Une partie du texte est supprimée.– Une partie du texte est coupée.

De manière générale, le type d’événement Event.CHANGE est utilisé sur lesobjets qui disposent d’une valeur importante susceptible d’être modifiée :champs de saisie, barre de défilement, compteur. . . Vous pouvez vous-mêmedéclencher des événements de ce type dans vos classes si besoin.

Ajoutons donc un écouteur d’événement à notre champ de saisie :

1 monSuperTexte.addEventListener(Event.CHANGE ,detecterModification);

2 function detecterModification(event:Event):void3 {4 trace(monSuperTexte.text);5 }

Si vous entrez du texte dans notre champ de saisie, vous obtiendrez une sortie similairedans la console :

CCeCecCeci

463

Page 487: Programmez en Actionscript 3

CHAPITRE 22. INTERAGIR AVEC L’UTILISATEUR

CeciCeci eCeci esCeci estCeci estCeci est mCeci est maCeci est maCeci est ma sCeci est ma saCeci est ma saiCeci est ma saisCeci est ma saisiCeci est ma saisieCeci est ma saisieCeci est ma saisie !

L’objet TextEvent

En Actionscript, il existe un objet évènement particulièrement bien adapté auxchamps de texte : il s’agit de la classe TextEvent ! Cet évènement sera donc étroi-tement lié à ce qui ce passe au niveau du clavier, mais pas uniquement. Toutefois, lorsde la saisie d’un texte dans un champ à l’aide du clavier, cet évènement sera distri-bué, disons, en « doublon » de l’objet KeyboardEvent. Vous aurez alors la possibilitéd’utiliser l’un ou l’autre de ces évènements, mais aussi pourquoi pas les deux !

La figure 22.15 reprend l’ensemble des propriétés de cette classe et de sa super-classeEvent.

Figure 22.15 – La classe TextEvent

464

Page 488: Programmez en Actionscript 3

CHAMPS DE SAISIE

Cette classe d’évènements ajoute donc un unique attribut nommé text par rapport àsa super-classe. Il vous sera donc sûrement utile !

Pour comprendre l’utilité de cet évènement, je vous propose maintenant de découvrirles deux manières dont peut être généré celui-ci. Les constantes qui servent à définir letype de ce dernier sont les suivantes :

– LINK : est distribué lorsque que vous cliquez sur un lien présent dans un objetTextField.

– TEXT_INPUT : est généré avant chaque modification d’un champ de saisie, donc àchaque enfoncement d’une touche, mais également lors de la répétition d’un caractèresi celle-ci reste enfoncée.

L’évènement LINK est relativement simple à mettre en place. Comme nous l’avonsdit plus haut, ce type d’évènements est généré lorsque vous cliquez sur un lien à l’inté-rieur d’un champ de texte. Souvenez-vous, pour créer un lien dans un champ de texte,nous utilisons du texte sous forme HTML. Un lien s’écrit alors de la façon suivante :

1 <a href="adresse">lien </a>

Pour utiliser l’évènement FOCUS, nous devons néanmoins spécifier dans le code HTMLauquel nous souhaitons faire appel pour cet évènement. Pour cela, il est nécessaire derajouter la chaîne de caractères « event : » en en-tête du lien, comme cela :

1 monSuperTexte.htmlText = "<a href='event:adresse '>lien </a>";

Ensuite, nous pouvons définir notre fonction d’écouteur, comme vous savez maintenantle faire :

1 monSuperTexte.addEventListener(TextEvent.LINK , capterLien);2 function capterLien(event:TextEvent):void3 {4 trace(event.text);5 }

En cliquant sur le lien dans Flash Player, vous pourrez alors voir apparaître ceci dansla console de sortie :

adresse

Le second évènement proposé par la classe TextEvent est donc TEXT_INPUT ! Pourcommencer, je vous invite à tester l’écouteur suivant, afin de bien voir comment FlashPlayer réagit à cet évènement :

1 monSuperTexte.addEventListener(TextEvent.TEXT_INPUT ,detecterSaisie);

2 function detecterSaisie(event:TextEvent):void3 {4 trace(event.text);5 }

Essayez alors de saisir quelques caractères au clavier :

465

Page 489: Programmez en Actionscript 3

CHAPITRE 22. INTERAGIR AVEC L’UTILISATEUR

Ceci

est

ma

saisie

!

Quel est l’intérêt de cet évènement ? Ne pouvons-nous pas faire la mêmechose avec KeyboardEvent.Key_DOWN ?

Il est vrai que vu d’ici, ce type d’évènements n’apporte rien de plus par rapport à unévènement issu de la classe KeyboardEvent. Néanmoins, pour juger de son utilité, il estnécessaire de bien comprendre la différence de génération de ces deux évènements. Lepremier est généré dès lors qu’une touche est enfoncée, quelle que soit cette touche. Enrevanche, le second est distribué uniquement dans le cas d’une entrée de texte. Dans cedernier cas, nous pouvons donc exclure l’appui sur les touches suivantes :

�� ��Alt ,�� ��Ctrl ,�� ��Shift ,

�� ��Tab , ou encore�� ��Entrée . Par ailleurs, la classe TextEvent facilite énormé-

ment la gestion du texte. Par exemple, dans le cas présent, pas question d’encodage !La propriété text contient directement le caractère et non son code numérique.

Enfin, une dernière petite subtilité rend l’utilisation de cet évènement très pratique. Ilfaut savoir que ce n’est qu’une fois que l’évènement TextEvent.TEXT_INPUT a terminéson aller-retour dans le flux d’évènements que le champ de saisie est mis à jour. Ceci vadonc nous permettre de revenir sur des propriétés de la super-classe Event. Rappelez-vous, cette classe disposait d’un attribut nommé cancelable. Soyez bien attentif à cequi va suivre ! Cet attribut indique si le comportement associé à l’événement peut êtreévité. Dans notre cas, il s’agit de la mise à jour du contenu du champ de texte actif.Si ce comportement par défaut peut être évité, la méthode preventDefault() permetquant à elle de l’annuler.

Essayez donc le code suivant :

1 monSuperTexte.addEventListener(TextEvent.TEXT_INPUT ,

466

Page 490: Programmez en Actionscript 3

CHAMPS DE SAISIE

detecterSaisie);2 function detecterSaisie(event:TextEvent):void3 {4 if (event.cancelable == true) {5 trace(event.text);6 event.preventDefault ();7 }8 }

Voyez plutôt le résultat, plus aucun caractère n’est affiché à l’intérieur du champ desaisie de texte.

La gestion du focus

Dans une interface graphique complexe, composée par exemple de plusieurs champs desaisie, un seul objet peut être actif à la fois. Je veux dire par là qu’un seul champ detexte doit être rempli lorsque vous tapez au clavier. Cela introduit donc la notion defocus, qui désigne alors l’objet cible actif. Pour repérer cet objet d’affichage au sein del’ensemble de la liste d’affichage, une référence à ce dernier est stocké dans l’attributfocus de stage. Nous avons accès à cet attribut par un getter et un setter. Il estdonc tout à fait possible de définir nous-mêmes l’objet qui a le focus.

Lorsque le focus est modifié, un évènement de type FocusEvent est alors distribué.Pour un objet donné, deux types d’évènements sont distincts :

– FOCUS_IN : généré lorsque que l’objet interactif prend le focus.– FOCUS_OUT : généré lorsque que l’objet interactif perd le focus.

Sachant que l’exercice qui suit utilise ces types d’évènements, nous nous passeronsd’exemples ici.

Exercice : un mini formulaire

Pour conclure ce chapitre, je vais vous présenter un petit exercice consistant à réaliserun formulaire. Ce sera l’occasion de revenir sur certains points importants tout enutilisant les évènements fournis par Flash Player.

Pour réaliser ce « mini » formulaire, nous utiliserons quatre champs de saisie de texteafin de pouvoir renseigner les informations suivantes pour un quelconque traitement :

– Nom.– Prénom.– Date de naissance.– Lieu de naissance.

Une particularité de notre formulaire sera de présenter les intitulés, ou étiquettes,à l’intérieur des champs de saisie eux-mêmes. Pour être plus précis, le concept est depré-remplir les champs de texte par leur étiquette. Puis nous utiliserons les évènementsFOCUS_IN et FOCUS_OUT pour effacer ou remettre en place ces intitulés.

467

Page 491: Programmez en Actionscript 3

CHAPITRE 22. INTERAGIR AVEC L’UTILISATEUR

Pour mieux visualiser la chose, voici, à la figure 22.16, un aperçu de ce que nousobtiendrons à la fin de l’exercice.

Figure 22.16 – Un formulaire avec libellé intégré

Étant donné que nous serons amenés à utiliser plusieurs champs de saisie similaires, ilpeut être intéressant de définir une nouvelle classe. Je suggère donc de créer un objetd’affichage personnalisé à partir d’un TextField.

Dans un premier temps, je vous propose de découvrir cette classe que j’ai nomméeEditableTextField, puis nous l’analyserons ensuite :

1 package2 {3 import flash.text.TextField;4 import flash.text.TextFormat;5 import flash.text.TextFieldType;6 import flash.events.FocusEvent;78 public class EditableTextField extends TextField9 {

10 // Attributs11 private var _etiquette:String;12 private var _formatEtiquette:TextFormat;13 private var _formatEdition:TextFormat;1415 public function EditableTextField(etiquette:String)16 {17 _etiquette = etiquette;18 _formatEtiquette = new TextFormat("Arial", 14,

0x999999);19 _formatEdition = new TextFormat("Arial", 14,

0x000000);20 defaultTextFormat = _formatEtiquette;21 type = TextFieldType.INPUT;22 selectable = true;23 border = true;24 text = _etiquette;

468

Page 492: Programmez en Actionscript 3

CHAMPS DE SAISIE

25 addEventListener(FocusEvent.FOCUS_IN ,effacerEtiquette);

26 addEventListener(FocusEvent.FOCUS_OUT ,remettreEtiquette);

27 }2829 // Méthodes d'écouteurs30 private function effacerEtiquette(event:FocusEvent):

void31 {32 if (text == _etiquette)33 {34 defaultTextFormat = _formatEdition;35 text = "";36 }37 }3839 private function remettreEtiquette(event:FocusEvent):

void40 {41 if (text == "")42 {43 defaultTextFormat = _formatEtiquette;44 text = _etiquette;45 }4647 }4849 }5051 }

Pour analyser cette classe, prenons les choses telles qu’elle viennent. En premier, j’aidéclaré les trois attributs suivants :

– _etiquette : contient l’intitulé ou l’étiquette du champ de texte.– _formatEtiquette : définit le formatage à utiliser lors de l’affichage de l’intitulé.– _formatEdition : définit le formatage à adopter lors de l’édition du champ de texte.

À l’intérieur du constructeur de la classe, il n’y a rien de bien compliqué. Nous ini-tialisons l’ensemble des attributs et en profitons pour regrouper les différentes instruc-tions communes, touchant aux propriétés de la super-classe TextField. Pour clôturerce constructeur, deux écouteurs sont mis en place afin de gérer la transition entrel’affichage de l’étiquette et son effacement avant l’édition du champ de saisie. Je ne vaispas entrer plus avant dans les détails car je juge que vous êtes à présent suffisammentdoués pour comprendre le fonctionnement de cette classe tout seuls.

469

Page 493: Programmez en Actionscript 3

CHAPITRE 22. INTERAGIR AVEC L’UTILISATEUR

En définissant les écouteurs de cette manière, à l’intérieur d’une classe, vouspouvez facilement simplifier et alléger le code. Effectivement, si vous aviezdû le faire depuis l’extérieur de la classe, vous auriez très certainement définideux fonctions d’écouteurs pour chacun des champs de saisie de l’interfacegraphique. N’hésitez pas à utiliser cette technique pour simplifier et organiserau mieux votre code.

Maintenant, il ne reste plus qu’à disposer les champs de texte à l’écran et à ajuster lesderniers détails :

1 // Champ de saisie du nom de famille2 var nom:EditableTextField = new EditableTextField("Nom");3 nom.restrict = "A-Za -z\\- ";4 nom.width = 185;5 nom.height = 20;6 nom.x = 10;7 nom.y = 10;8 addChild(nom);9

10 // Champ de saisie du prénom11 var prenom:EditableTextField = new EditableTextField("Prénom");12 prenom.restrict = "A-Za-z\\- ";13 prenom.width = 185;14 prenom.height = 20;15 prenom.x = 205;16 prenom.y = 10;17 addChild(prenom);1819 // Champ de saisie de la date de naissance20 var dateDeNaissance:EditableTextField = new EditableTextField("

JJ/MM/AAAA");21 dateDeNaissance.restrict = "0-9/";22 dateDeNaissance.maxChars = 10;23 dateDeNaissance.width = 100;24 dateDeNaissance.height = 20;25 dateDeNaissance.x = 10;26 dateDeNaissance.y = 40;27 addChild(dateDeNaissance);2829 // Champ de saisie du lieu de naissance30 var lieuDeNaissance:EditableTextField = new EditableTextField("

Lieu de naissance");31 lieuDeNaissance.restrict = "A-Za-z0-9\\- ";32 lieuDeNaissance.width = 270;33 lieuDeNaissance.height = 20;34 lieuDeNaissance.x = 120;35 lieuDeNaissance.y = 40;36 addChild(lieuDeNaissance);

470

Page 494: Programmez en Actionscript 3

CHAMPS DE SAISIE

Vous remarquerez, à travers cet exemple, que la définition de la propriétérestrict n’affecte que la saisie de texte depuis l’extérieur du programme.Cela explique pourquoi l’affichage de l’intitulé de l’objet dateDeNaissancene pose aucun problème.

En résumé– Les actions produites par l’utilisateur sur la souris génèrent des objets de la classeMouseEvent.

– L’affichage de la souris peut être géré via les méthodes de la classe Mouse.– Le glisser-déposer est une technique qui peut être contrôlé par les méthodes startDrag()et stopdrag().

– Un objet KeyboardEvent est généré après toute action produite sur le clavier.– Un objet TextField est transformable en champ de saisie, en redéfinissant la valeur

de la propriété type à l’aide les constantes de la classe TextFieldType.– Différentes propriétés de la classe TextField servent à paramétrer la saisie d’untexte, telles que restrict, displayAsPassword ou maxChars.

– Les évènements issus des classes TextEvent et FocusEvent augmentent les possibi-lités de la gestion d’évènements provenant de la souris ou du clavier.

471

Page 495: Programmez en Actionscript 3

CHAPITRE 22. INTERAGIR AVEC L’UTILISATEUR

472

Page 496: Programmez en Actionscript 3

Chapitre 23Animer des objets

Difficulté :

Dans le chapitre précédent, nous avons commencé à donner vie à nos applications en inter-agissant avec l’utilisateur au moyen du clavier et de la souris. Grâce à cela, les programmespeuvent agir suivant les décisions prises par l’utilisateur. Néanmoins, il n’est pas toujoursnécessaire d’attendre une action de la part de l’utilisateur avant de devoir mettre à jourl’affichage.

Comme vous l’aurez deviné, nous allons ici apprendre à créer des animations. Cela vouspermettra d’améliorer la jouabilité de vos jeux ou la fluidité de votre site web. Dans cechapitre, nous allons donc voir comment animer des objets en utilisant différentes tech-niques.

473

Page 497: Programmez en Actionscript 3

CHAPITRE 23. ANIMER DES OBJETS

L’animation par images-clés

L’évènement Event.ENTER_FRAME

Pour bien comprendre ce qui va suivre, nous allons faire un petit point sur les ani-mations Flash et leur fonctionnement. Une application Flash est une animationcadencée à un nombre d’images par seconde constant. Toute modification liée à unobjet présent sur l’écran entraîne donc une mise à jour de l’affichage à l’image suivantetout en générant un nouveau rendu.

À l’origine, ce système d’animation par images successives permettait de réaliser desanimations complexes à l’aide de Flash Professionnal. En utilisant les MovieClip, ilétait alors possible d’animer des objets à l’aide d’images-clés. Comme nous l’avons déjàdit précédemment dans ce cours, cette classe, dérivée de la classe Sprite, ajoute uneligne de temps (ou timeline en anglais). Voici, à la figure 23.1, un exemple d’éditiond’un MovieClip à l’intérieur du logiciel Adobe Flash Professionnal.

Figure 23.1 – Une ligne de temps d’un MovieClip

Revenons maintenant à nos moutons, ou plutôt à l’Actionscript ! Le principe est lemême que dans Flash Professionnal, l’affichage est mis à jour automatiquementà partir des événements qui se produisent et d’éventuelles modifications réalisées àl’intérieur du code. Les rendus sont donc créés à fréquence constante, définie par lenombre d’images par seconde paramétré pour le projet. Bien entendu, tout ceci estgéré directement par Flash Player !

Pour définir le cadencement de l’animation, nous pouvons paramétrer la propriétéframeRate lié au fichier SWF, comme dans la ligne suivante :

1 [SWF(width="400",height="200",backgroundColor="#ffffff",frameRate="25")]

Il est possible de procéder autrement pour modifier la cadence d’animation du pro-gramme, il suffit de changer la valeur de la propriété frameRate de l’objet stagecomme ceci :

1 stage.frameRate = 30;

Créer une animation basique

Animer un objet consiste à faire évoluer au moins l’une de ses propriétés au coursdu temps. Par exemple, lors d’un mouvement, la position d’un objet est décomposée

474

Page 498: Programmez en Actionscript 3

L’ANIMATION PAR IMAGES-CLÉS

en petits incréments répartis tout au long de sa trajectoire au fil du temps. Une bonneidée serait alors de synchroniser l’exécution du code avec la cadence du fichier SWF.En effet, il est inutile de modifier la position d’un objet toutes les millisecondes si unrendu est généré seulement toutes les 40 millisecondes.

Lors de l’exécution du programme, un événement de type Event.ENTER_FRAME estgénéré avant chaque nouveau rendu. Il est ainsi possible de réaliser des modificationsavant chaque mise à jour de l’affichage. Je vous propose donc de réaliser une petiteanimation utilisant ce principe.

Dans un premier temps, nous allons créer un petit carré au centre de notre application :

1 var objet:Shape = new Shape ();2 objet.graphics.beginFill(0xAA00FF);3 objet.graphics.drawRect( -25 , -25, 50 , 50);4 objet.x = stage.stageWidth / 2;5 objet.y = stage.stageHeight / 2;6 addChild(objet);

Pour suivre la cadence de l’animation, nous pouvons alors ajouter un écouteur àl’événement Event.ENTER_FRAME en associant une fonction d’écouteur qui servira àanimer notre objet. Voici notre instruction :

1 objet.addEventListener(Event.ENTER_FRAME , animerObjet);

À l’intérieur de notre fonction, nous pouvons ensuite animer notre carré. Par exemple,en incrémentant la propriété rotation, nous forçons l’objet à tourner à chaque nouveaurendu, comme ceci :

1 function animerObjet(event:Event):void2 {3 objet.rotation ++;4 }

Au final, nous obtenu un objet en perpétuelle rotation comme illustré sur l’image 23.2.

Figure 23.2 – Un objet en rotation

475

Page 499: Programmez en Actionscript 3

CHAPITRE 23. ANIMER DES OBJETS

Ce type de manipulation est bien évidemment réalisable avec n’importe quelattribut ou méthode d’un objet. Il est alors possible de modifier sa position,son orientation, sa taille, ou encore les filtres associés à cet objet. La seulelimite est votre imagination !

Je vous propose maintenant d’aller un peu plus loin et d’animer un flou sur notreobjet. Nous allons également en profiter pour apprendre à stopper une animationgrâce à la méthode removeEventListener().

Dans un premier temps, plaçons un filtre de type BlurFilter sans effet apparent :

1 var flou:BlurFilter = new BlurFilter(0, 0, BitmapFilterQuality.HIGH);

2 objet.filters = new Array(flou);

Puis, nous allons retravailler notre fonction animer(), afin d’incrémenter le flou hori-zontal avant chaque nouveau rendu de notre application. Il nous faudra aussi mettre àjour la propriété filters de notre objet, pour que le filtre prenne effet. Pour finir, noussupprimerons notre écouteur à l’événement Event.ENTER_FRAME pour stopper l’ani-mation. Dans notre exemple, nous arrêterons d’augmenter le flou horinzontal lorsquecelui-ci aura atteint la valeur 50.

Voyez plutôt :

1 function animerObjet(event:Event):void2 {3 flou.blurX ++;4 objet.filters = new Array(flou);5 if(flou.blurX > 50){6 objet.removeEventListener(Event.ENTER_FRAME ,

animerObjet);7 }8 }

En lançant l’animation, vous verrez alors notre carré se flouter progressivement puis sefiger au bout d’un certain temps, comme sur l’image 23.3.

Figure 23.3 – Animation d’un filtre d’un objet

476

Page 500: Programmez en Actionscript 3

L’UTILISATION DE TIMER

L’utilisation de Timer

La classe Timer

Lorsqu’une animation Flash est lancée, les instructions du programme sont exécutéesà une vitesse qui est définie par votre machine. Ainsi, quand vous passerez d’une ma-chine à une autre, les instructions ne seront pas exécutées au même rythme. Il est doncimpossible à l’intérieur du code de synchroniser correctement les instructions avec letemps. Théoriquement, il serait possible d’utiliser les événements Event.ENTER_FRAMEpour réaliser cela, mais je vous recommande très fortement d’utiliser plutôt les Timer !

Comme vous n’êtes pas obligés de me croire sur parole, je vais essayer de vous donner di-verses raisons qui justifient ce choix. Tout d’abord, les événements Event.ENTER_FRAMEne sont pas générés de manière extrêmement précise. En effet, un rendu trop chargéou un calcul un peu complexe pourrait ralentir légèrement la cadence de votre ani-mation. Par ailleurs, une modification de la cadence de votre fichier SWF suffirait àdérégler l’intégralité de votre programme. Vous seriez alors dans l’obligation d’effectuerde lourdes modifications à l’intérieur de votre code source, même si l’impact peut êtrelimité en utilisant des constantes. Enfin, il est probable que vous ayez besoin d’exécuterdes instructions à une cadence élevée, cela ne justifie pas l’accélération du rythme derendu de l’affichage pour autant.

Ainsi, lorsque l’on souhaite gérer le temps de manière significative, il est préférabled’utiliser la classe Timer. Le contrôle sur les intervalles temporels en sera amélioré etvous facilitera la vie pour la création de moteurs physiques par exemple.

Comme nous l’avons dit précédemment, l’utilisation de l’événementEvent.ENTER_FRAME est le meilleur moyen de synchroniser vos actions àl’intérieur du code avec la cadence d’animation du fichier SWF. Néan-moins, l’événement Event.ENTER_FRAME doit être utilisé uniquement à desfins d’animation et non pour gérer le temps en tant que tel. Préférez alorsl’utilisation de Timer.

La figure 23.4 décrit cette classe Timer.

Sans surprise, l’utilisation d’un Timer se base sur le concept des événements. Sonprincipe de fonctionnement consiste donc à générer des événements à intervalles tem-porels réguliers. Ces événements sont alors de type TimerEvent et sont produits àintervalles spécifiés par la propriété delay de la classe Timer. La propriété repeatCountpermet de définir le nombre total d’événements qui doivent être créés.

L’instruction suivante est un exemple qui définit un Timer paramétré à 5 événementsgénérés toutes les secondes :

1 var minuteur:Timer = new Timer(1000 , 5);

La propriété delay représente un intervalle de temps en millisecondes. Parailleurs, la valeur 0 pour repeatCount sert à répéter la création d’événementsun nombre infini de fois.

477

Page 501: Programmez en Actionscript 3

CHAPITRE 23. ANIMER DES OBJETS

Figure 23.4 – La classe Timer héritant de EventDispatcher

Lors de l’instanciation d’un objet de la classe Timer, le décompte du temps n’est toute-fois pas encore lancé. Pour contrôler cela, nous disposons des trois méthodes start(),stop() et reset(). Enfin, sachant que la classe Timer hérite de EventDispatcher,nous pouvons assigner un écouteur à notre objet de type Timer.

Voici donc le code complet permettant de lancer la génération d’événements TimerEvent.

1 var minuteur:Timer = new Timer(1000 , 5);2 minuteur.addEventListener(TimerEvent.TIMER , maFonction);3 minuteur.start();4 function maFonction(event:TimerEvent):void5 {6 // Instructions7 }

Comme vous l’aurez compris, l’évenement TIMER de TimerEvent est le type d’événe-ments générés à chaque intervalle de temps décompté. Mais il existe également le typeCOMPLETE qui est produit lorsque le nombre d’itérations repeatCount est atteint et quele Timer arrive à terme.

Exercice : une horloge

Présentation des graphismes

Comme le titre l’indique, nous allons réaliser une horloge analogique. Cet exercice vanous permettre de mettre en pratique tout ce que nous avons vu sur les classes Timeret TimerEvent. Mais avant d’en dire plus sur le fonctionnement et la gestion desécouteurs, je vous présente le résultat de l’exercice sur la figure 23.5.

478

Page 502: Programmez en Actionscript 3

L’UTILISATION DE TIMER

Figure 23.5 – Une horloge analogique

Sachant que l’objectif n’est pas la partie visuelle, mais plutôt la gestion du temps,j’ai décidé de placer une bonne partie du code lié à l’affichage à l’intérieur de deuxclasses Cadran et Aiguille. La première permet de dessiner le cadran de l’horloge enspécifiant le rayon de celui-ci dans le constructeur. La seconde classe sert à tracer uneaiguille en fonction de son type : HEURE, MINUTE ou SECONDE.

Je vous laisse découvrir ces deux classes. Voici la première nommée Cadran :

1 package2 {3 import flash.display.Sprite;4 import flash.display.Shape;56 public class Cadran extends Sprite7 {89 public function Cadran(rayon:Number)

10 {11 super();12 for (var i:int = 0; i < 60; i++) {13 var point:Shape = new Shape ();14 point.graphics.beginFill(0x888888);15 if((i%5) == 0){16 point.graphics.drawCircle(0, 50, 2);17 }else {18 point.graphics.drawCircle(0, 50, 1);19 }20 point.rotation = i * 6;21 addChild(point);22 }23 }2425 }26 }

Et voici la classe Aiguille :

1 package2 {3 import flash.display.Shape;45 public class Aiguille extends Shape6 {

479

Page 503: Programmez en Actionscript 3

CHAPITRE 23. ANIMER DES OBJETS

7 // Constantes8 public static const HEURE:String = "heure";9 public static const MINUTE:String = "minute";

10 public static const SECONDE:String = "seconde";1112 // Constructeur13 public function Aiguille(type:String)14 {15 super();16 var longueur:Number;17 if (type == HEURE) {18 longueur = 30;19 }else {20 longueur = 45;21 }22 if (type == SECONDE) {23 graphics.beginFill(0x880000);24 }else {25 graphics.beginFill(0x000000);26 }27 graphics.moveTo(-1.5, 0);28 graphics.lineTo(-0.5, longueur / 4);29 graphics.lineTo(0.5, longueur / 4);30 graphics.lineTo(1.5, 0);31 graphics.lineTo(0.5, -longueur);32 graphics.lineTo(-0.5, -longueur);33 graphics.endFill ();34 }3536 }3738 }

Si vous souhaitez tester le code de cette horloge, je vous invite alors à créer deuxnouvelles classes et y insérer les lignes de code que je viens de vous fournir.

Mise en place des éléments à l’écran

Maintenant, il est temps de placer les différents éléments qui composent l’horloge surla scène principale. Nous aurons donc besoin d’un cadran, ainsi que trois aiguilles, unede chaque type. Enfin, nous centrerons le tout pour avoir l’horloge au milieu de l’écran.

Il n’y a rien de compliqué pour faire cela, c’est pourquoi je vous expose le code direc-tement :

1 // Mise en place des objets d'affichage à l'écran2 x = stage.stageWidth / 2;3 y = stage.stageHeight / 2;4 var cadran:Cadran = new Cadran(50);5 var aiguilleHeures:Aiguille = new Aiguille(Aiguille.HEURE);

480

Page 504: Programmez en Actionscript 3

L’UTILISATION DE TIMER

6 var aiguilleMinutes:Aiguille = new Aiguille(Aiguille.MINUTE);7 var aiguilleSecondes:Aiguille = new Aiguille(Aiguille.SECONDE);8 addChild(cadran);9 addChild(aiguilleHeures);

10 addChild(aiguilleMinutes);11 addChild(aiguilleSecondes);

À ce stade, nous avons alors notre horloge entièrement dessinée avec les aiguilles enposition initiale, c’est-à-dire indiquant l’instant « 00 :00 :00 ».

Mettre l’horloge à l’heure

Il serait grand temps de mettre à jour l’heure affichée sur notre horloge. Pour cela,nous allons faire une brève introduction à la gestion des dates et des heures.

Pour pouvoir manipuler les dates et les heures, nous avons à notre disposition la classeDate. Cette dernière intègre tout un tas de propriétés et méthodes servant notammentà récupérer des informations sur la date en question.

Voilà comment instancier un objet Date, en référence au jour et à l’heure actuels :

1 var maDate:Date = new Date();

Parmi l’ensemble des méthodes fournies par cette classe, nous allons avoir recoursaux trois suivantes : getHours(), getMinutes() et getSeconds(), dont les noms sontrelativement explicites.

Si vous voulez en apprendre davantage sur l’objet Date, je vous conseilled’aller visiter sa page officielle.

B

�Documentation Date

Code web : 496063Pour en revenir à notre horloge, voici comment nous pouvons récupérer l’heure actuellepour mettre celle-ci à jour :

1 // Mise à l'heure des aiguilles2 var heureActuelle:Date = new Date();3 aiguilleSecondes.rotation = 360 * heureActuelle.getSeconds () /

60;4 aiguilleMinutes.rotation = 360 * heureActuelle.getMinutes () /

60;5 aiguilleHeures.rotation = 360 * heureActuelle.getHours () / 12;

Animer l’horloge

C’est maintenant que nous allons utiliser la classe Timer afin de générer un évé-nement à intervalle régulier. Dans notre cas, nous voulons pouvoir mettre à jour

481

Page 505: Programmez en Actionscript 3

CHAPITRE 23. ANIMER DES OBJETS

nos aiguilles à chaque seconde. Nous devrons également faire en sorte que nos aiguillestournent indéfiniment.

Si vous avez bien suivi ce qui a été dit auparavant, vous êtes alors capables de trouverce code tout seul :

1 // Mise en place du Timer2 var minuteur:Timer = new Timer(1000 , 0);3 minuteur.addEventListener(TimerEvent.TIMER , bougerAiguilles);4 minuteur.start();

Pour animer notre horloge, nous devrons donc mettre à jour l’orientation de chacunedes aiguilles toutes les secondes. La seule difficulté est de ne pas se tromper sur lavaleur des angles à appliquer pour chaque aiguille.

Notre fonction d’écouteur ressemble alors à ceci :

1 // Fonction d'écouteur2 function bougerAiguilles(event:TimerEvent):void3 {4 aiguilleSecondes.rotation += 360 / 60;5 aiguilleMinutes.rotation += 360 / (60 * 60);6 aiguilleHeures.rotation += 360 / (60 * 60 * 24);7 }

Voilà qui est fait !

Les interpolations avec TweenMax

Enfin, il est possible d’utiliser ce que l’on appelle des interpolations (ou tweensen anglais) pour animer des objets. Il n’est dans ce cas pas nécessaire de répéter desinstructions, les interpolations vont faire tout le travail à notre place !

Une interpolation est un calcul effectué à l’avance de l’animation d’un ou plusieursobjets, sur un ou plusieurs de leurs attributs. On spécifie la durée de l’animation etles valeurs finales des attributs. Une fois l’animation de l’interpolation lancée,ces attributs varieront selon ces paramètres pour créer une animation fluide. Pour nous,tout ceci tient en une ligne de code !

La librairie TweenMax

Présentation et installation

Nous allons utiliser une librairie d’interpolation créée par Greensock qui s’appelleTweenMax ou GSAP (GreenSock Animation Platform) et qui est très connueet utilisée dans le milieu, car elle présente de nombreux avantages en plus d’être faciled’utilisation. Le seul inconvénient de cette librairie est qu’elle est payante pour certainsprojets commerciaux.

482

Page 506: Programmez en Actionscript 3

LES INTERPOLATIONS AVEC TWEENMAX

Il existe d’autres librairies d’interpolations très différentes auxquelles vouspouvez également jeter un coup d’œil si vous êtes curieux. Je citerais enexemple Actuate, GTween, Tweener, et bien d’autres. . .

Commençons par télécharger la librairie sur le site de GreenSock. Cliquez sur le bouton« Get GSAP » à gauche puis sur le bouton « Download AS3 » et enfin sur le bouton« Download zip » (voir figure 23.6).

B

�GreenSock

Code web : 797993

Figure 23.6 – Page de téléchargement de GSAP

Une fois l’archive récupérée, ouvrez-là et extrayez le dossier com dans le dossier dessources de votre projet,par exemple, src (voir figure 23.7).

Voilà ! La librairie est prête à être utilisée !

Importation dans les classes

Pour pouvoir utiliser TweenMax dans une de vos classes, il faut ajouter ces deuxlignes en haut du package de la classe :

1 import com.greensock .*;2 import com.greensock.easing .*;

La première ligne importe toutes les classes de base de TweenMax, tandis que laseconde importe les classes des courbes d’animation permettant de modifier les inter-polations. Nous les détaillerons un peu plus loin.

483

Page 507: Programmez en Actionscript 3

CHAPITRE 23. ANIMER DES OBJETS

Figure 23.7 – Contenu de l’archive de GSAP

Les bases de l’animation avec TweenMax

Mise en place

Avant de réellement utiliser TweenMax, nous allons préparer un peu le terrain : ilnous faut bien quelque chose à animer ! Commençons par créer un beau carré :

1 var carre:Sprite = new Sprite ();2 carre.graphics.beginFill(0xAA00FF);3 carre.graphics.drawRect(-25 , -25, 50, 50);4 carre.x = stage.stageWidth / 2;5 carre.y = stage.stageHeight / 2;6 addChild(carre);

Pour l’instant, nous obtenons la figure 23.8.

Notre objectif est d’animer le carré au passage de la souris. Ajoutons des écouteursd’événement comme nous l’avons vu dans les chapitres précédents :

1 carre.addEventListener(MouseEvent.ROLL_OVER , onOver);2 carre.addEventListener(MouseEvent.ROLL_OUT , onOut);34 function onOver(e:MouseEvent):void5 {6

484

Page 508: Programmez en Actionscript 3

LES INTERPOLATIONS AVEC TWEENMAX

Figure 23.8 – Un beau petit carré !

485

Page 509: Programmez en Actionscript 3

CHAPITRE 23. ANIMER DES OBJETS

7 }89 function onOut(e:MouseEvent):void

10 {1112 }

Utilisation de TweenMax

La librairie Tweenmax s’utilise principalement avec la classe TweenMax (du packagecom.greensock). Il y a également des versions allégées de cette classe pour réduirela taille de votre application : TweenLite et TweenNano. Nous ne les détaillerons pasici car elles fonctionnent exactement de la même manière, certaines fonctionnalités enmoins. Les méthodes de la classe TweenMax que nous allons manipuler sont statiques :il n’est donc pas nécessaire d’instancier la classe à l’aide du mot-clé new.

La première (et sans doute la plus utilisée) est la méthode statique TweenMax.to (l’an-glais to signifie vers en français). Voici sa signature :

1 TweenMax.to(cible:Object , duree:Number , parametres:Object):TweenMax

Cette méthode anime les attributs spécifiés de la ou les cibles pendant une certainedurée, vers les valeurs que l’on a spécifiées. Le premier paramètre que l’on doit passerest l’objet à animer ; il est également possible de passer un tableau d’objets pour enanimer plusieurs en même temps. Le second spécifie la durée en secondes de l’animation.Enfin, on passe en troisième paramètre un objet anonyme (de classe Object) contenantla configuration de l’animation, avec notamment les attributs à animer et leurs valeursfinales.

Notez que vous n’êtes pas obligés de passer un objet d’affichage : tout objetest accepté. Par exemple, vous pouvez « animer » l’attribut pv d’un objetde classe Personnage pour le faire varier pendant 10 secondes si cela vouschante, même si ce n’est pas un objet d’affichage.

L’objet de configuration

Le dernier paramètre est donc un objet anonyme (pas besoin de classe spécifique) quiva contenir les attributs à animer et leur valeur finale. Par exemple, si nous voulonsanimer l’opacité de notre carré pour qu’elle passe à 0.5 en 1 seconde :

1 var parametrages:Object = new Object ();2 parametrages.alpha = 0.5;3 TweenMax.to(carre , 1, parametrages);

Nous pouvons aussi écrire l’objet sous forme abrégée avec des accolades :

486

Page 510: Programmez en Actionscript 3

LES INTERPOLATIONS AVEC TWEENMAX

1 var parametrages:Object = { alpha:0.5 };2 TweenMax.to(carre , 1, parametrages);

Ou en se passant de variable intermédiaire :

1 TweenMax.to(carre , 1, { alpha:0.5 });

Animons notre carré

Maintenant que notre carré est prêt, nous pouvons l’animer au passage de la souris àl’aide de la méthode statique to de la classe TweenMax comme nous venons de le voir :

1 // Anime l'opacité vers 50%2 TweenMax.to(carre , 1, { alpha:0.5 } );

Lorsque la souris sortira du carré, on animera son opacité vers sa valeur initiale de 1(pleinement opaque) :

1 // Anime l'opacité vers 100%2 TweenMax.to(carre , 1, { alpha:1 } );

Il ne nous reste plus qu’à placer ces lignes dans les écouteurs correspondants :

1 function onOver(e:MouseEvent):void2 {3 TweenMax.to(carre , 1, { alpha:0.5 } );4 }56 function onOut(e:MouseEvent):void7 {8 TweenMax.to(carre , 1, { alpha:1 } );9 }

Ainsi, notre carré va devenir à demi transparent au passage de la souris !

Animer plusieurs objets en même temps

Il est possible d’animer plusieurs objets en même temps en passant un tableaud’objet dans le paramètre cible. Ces objets seront animés de la même façon sur lesmêmes attributs de manière synchronisée.

Il faut bien faire attention à ce que les attributs que l’on veut animer soientprésents et accessibles sur tous les objets animés.

Par exemple, si nous disposions d’un deuxième carré, nous pourrions les animer de lamême manière à l’aide d’un tableau :

487

Page 511: Programmez en Actionscript 3

CHAPITRE 23. ANIMER DES OBJETS

1 var cibles:Array = new Array();2 // On ajoute les carrés à animer3 cibles.push(carre);4 cibles.push(carre2);56 // Anime l'opacité des objets contenus dans le tableau vers 50%7 TweenMax.to(cibles , 1, { alpha:0.5 } );

On peut, bien entendu, utiliser la forme abrégée des tableaux pour rendre le code plusfacile à écrire et à lire :

1 // Anime l'opacité des deux objets vers 50%2 TweenMax.to([carre , carre2], 1, { alpha:0.5 } );

Animation avec initialisation

La deuxième méthode statique très utile est TweenMax.fromTo, elle permet d’initialiserles valeurs d’attributs avant l’animation. Voici sa signature :

1 TweenMax.fromTo(cible:Object , duree:Number , initialisation:Object , parametres:Object):TweenMax

Un nouveau paramètre est demandé après la durée de l’animation : il s’agit d’un autreobjet anonyme contenant les attributs à initialiser sur l’objet cible au début de l’ani-mation. Par exemple, on peut initialiser les attributs scaleX et scaleY à 0 pour quel’objet soit minuscule, puis animer ces mêmes attributs vers 1 (taille normale) :

1 // Les attribus scaleX et scaleY vont varier de 0 à 1 en uneseconde

2 TweenMax.fromTo(carre , 1, {scaleX:0, scaleY:0}, {scaleX:1,scaleY:1} );

Avec cette instruction, notre carré apparaîtra en grossissant progressivement.

Utilisation avancée de TweenMax

Les propriétés des animations

En plus des attributs de l’objet cible (ou des objets cibles), on peut ajouter quelquespropriétés relatives à l’animation dans l’objet de paramétrage. Par exemple, on peutdéfinir un nombre de répétition de l’animation à l’aide de l’attribut repeat (en mettant-1, on répète l’animation infiniment) :

1 // L'animation se répètera infiniment2 TweenMax.to(carre , 1, { alpha:0.5, repeat:-1 });

On peut également retarder le début de l’animation avec delay (durée exprimée ensecondes) :

488

Page 512: Programmez en Actionscript 3

LES INTERPOLATIONS AVEC TWEENMAX

1 // L'animation se lancera dans 3 secondes2 TweenMax.to(carre , 1, { alpha:0.5, delay:3});

Bien sûr, il est possible de combiner plusieurs de ces paramètres :1 // L'animation se répètera infiniment avec 3 secondes de délai

entre chaque répétition2 TweenMax.to(carre , 1, { alpha:0.5, repeat:-1, delay:3});

Il existe d’autres paramètres disponibles comme la documentation de la librairie ledécrit (en anglais).

Utiliser les évènements

Certaines propriétés pouvant être spécifiées dans l’objet de configuration de l’animationsont des fonctions qui peuvent être appellées automatiquement par l’animation lorsde certains événements. Nous allons voir les deux plus importantes. Tout d’abord, lapropriété onStart qui est une fonction appellée lorsque l’animation commence :1 TweenMax.to(carre , 1, { x: 0, y: 0, onStart: debutAnimation });2 function debutAnimation ():void3 {4 trace("Début de l'animation");5 }

La fonction debutAnimation sera appellée dès que l’animation commencera ou serarelancée, hors répétitions.

L’autre propriété est onComplete, représentant une fonction appellée une fois l’anima-tion terminée (après répétitions) :1 TweenMax.to(carre , 1, { x: 0, y: 0, onComplete: finAnimation });2 function finAnimation ():void3 {4 trace("Fin de l'animation");5 }

Valeurs relatives

Il est possible d’animer des attributs numériques de manière relative en passantl’opération d’incrémentation ou de décrémentation entre guillemets. Par exemple, sil’on veut animer la position horizontale du carré pour qu’il avance de 100 pixels, nouspouvons écrire ceci :1 TweenMax.to(carre , 1, { x:"+=100" } );

Ainsi, nous n’avons pas besoin de savoir quelle est la valeur initiale de sa position pourcalculer la nouvelle, TweenMax se charge de le faire à notre place. Nous pouvonségalement réduire la position horizontale comme ceci :1 TweenMax.to(carre , 1, { x:"-=100" } );

489

Page 513: Programmez en Actionscript 3

CHAPITRE 23. ANIMER DES OBJETS

Easing

On peut faire varier la vitesse de l’animation à l’aide de fonctions mathématiques,appelées fonctions de easing. L’animation suit alors cette fonction pour modifier lesdifférentes valeurs successives. Ces fonctions peuvent intervenir en entrée d’animation,en sortie ou les deux. Par exemple, avec la fonction x2 en début d’animation, la vitessesera au départ nulle puis va augmenter petit à petit (suivant la fonction mathématiquede la puissance deux).

Pour illustrer cette notion de fonction de easing, voici quatre exemples où l’on adessiné les différentes positions d’un point animé. Dans le premier, nous utilison lafonction x, également appelée fonction linéaire (figure 23.9).

Figure 23.9 – Fontion de easing linéaire : vitesse constante

Les différentes positions sont calculées avec la fonction linéaire, donc l’animation estlinéaire.

Maintenant, nous utilisons la fonction x3 (ou fonction cubique) en début d’animation(voir figure 23.10).

Figure 23.10 – Fonction de easing Cubique en entrée

Les différentes position sont calculées avec la fonction cubique en entrée ce qui donneun effet d’accélération.

Cette fois-ci, nous utilisons la fonction cubique en sortie, comme à la figure 23.11.

Figure 23.11 – Fonction de easing Cubique en sortie

Cela nous donne alors un effet de décélération.

Enfin, nous utilisons la fonction cubique en entrée et en sortie (voir figure 23.12).

Figure 23.12 – Fonction de easing Cubique en entrée et en sortie

On a alors un effet d’accélération puis de décélération.

Pour utiliser ces différentes fonctions easing, nous devons spécifier la propriété easedans la configuration de l’animation, en utilisant comme valeur les attributs statiques

490

Page 514: Programmez en Actionscript 3

LES INTERPOLATIONS AVEC TWEENMAX

des classes contenues dans le package com.greensock.easing que nous avons ajoutéen haut de notre classe :

1 import com.greensock .*;2 // On inclut les différentes fonctions de easing grâce à l'é

toile3 import com.greensock.easing .*;

Dans ce package, une classe par fonction de easing est définie, avec une méthodestatique correspondant à l’entrée, la sortie ou les deux, à passer dans la propriétéease :

1 var choixEasing:Function;23 // Animation linéaire4 choixEasing = Linear.easeNone;56 // Animation cubique en entrée7 choixEasing = Cubic.easeIn;8 // Animation cubique en sortie9 choixEasing = Cubic.easeOut;

10 // Animation cubique en entrée et en sortie11 choixEasing = Cubic.easeInOut;1213 // Animation avec le paramètre ease14 TweenMax.to(carre , 1, { x:"+=100", ease:choixEasing } );

Nous pouvons, bien sûr, abréger ce code en se passant de variable intermédiaire :

1 // Animation linéaire2 TweenMax.to(carre , 1, { x:"+=100", ease:Linear.easeNone } );

Par défaut, la fonction de easing utilisée pour toutes les animations est lafonction x^2 (ou fonction Carré) en sortie, c’est-à-dire Quad.easeOut. Il ya donc une légère décélération par défaut.

Il est possible d’utiliser des fonctions de easing plus exotiques comme la fonctionBounce qui fait rebondir les valeurs des attributs animés. Essayons cette fonction ensortie :

1 TweenMax.fromTo(carre , 1, {scaleX:5, scaleY:5}, {scaleX:1,scaleY:1, ease:Bounce.easeOut} );

Ici, on anime la taille relative de notre carré de cinq fois plus grand à sa taille normaleavec un effet de rebondissement intéressant.

Vous pouvez consulter la liste de toutes les fonctions de easing disponibles sur ladocumentation de la librairie.

491

Page 515: Programmez en Actionscript 3

CHAPITRE 23. ANIMER DES OBJETS

Contrôle d’une animation

Lorsque nous utilisons les méthodes statiques de la classe TweenMax pour animer des ob-jets, nous pouvons récupérer une instance de cette classe représentant l’animation. Eneffet, les méthodes TweenMax.to et TweenMax.fromTo que nous avons vues retournentun objet de classe TweenMax :

1 // Animation de rotation de notre carré, affectée à unevariable

2 var animation:TweenMax = TweenMax.to(carre , 5, {rotation:360 ,repeat:-1, ease:Linear.easeNone });

A partir de là, nous pouvons accéder aux propriétés des instances de la classe TweenMaxpour contrôler l’animation. Nous pouvons ainsi la mettre en pause à l’aide de sa mé-thode pause comme ceci :

1 animation.pause ();

Il est possible de reprendre la lecture de l’animation à l’aide de la méthode resume :

1 animation.resume ();

La méthode restart, quant à elle, permet de recommencer l’animation depuis le dé-but :

1 animation.restart ();

Enfin, la méthode kill permet d’arrêter complètement l’animation qui est alors sup-primée :

1 animation.kill();

Animer une animation

Vous souvenez-vous que les animations prenaient en paramètre n’importe quel objet ?Y compris d’autres animations ? En effet, il est tout à fait possible d’animer despropriétés d’une animation à l’aide d’une nouvelle animation. L’attribut qui nousintéresse alors est le nombre flottant timeScale, qui permet d’accélérer ou de ralentirune animation de manière arbitraire. A zéro, l’animation est en pause, à un, l’animationavance à la vitesse normale, à deux, elle se déroule deux fois plus vite, etc.

1 animation.timeScale = 0.5; // On ralentit l'animation de moitié

Ainsi, il nous est possible d’animer cet attribut à l’aide d’une nouvelle animation :

1 // On anime l'attribut timeScale de notre animation de rotation2 TweenMax.fromTo(animation , 5, {timeScale:0}, {timeScale:1});

Grâce à cette instruction, l’animation de rotation de notre cube sera initialement enpause puis va s’accélérer jusqu’à atteindre la vitesse normale. Cela signifie que le carréva progressivement se mettre à tourner sur lui-même !

492

Page 516: Programmez en Actionscript 3

LES INTERPOLATIONS AVEC TWEENMAX

En résumé– Animer un objet consiste à modifier au moins l’une de ses propriétés à intervalles

réguliers.– L’événement Event.ENTER_FRAME est généré avant que chaque image ne soit rendue.– La propriété frameRate de l’objet Stage permet de gérer le cadencement des imagesau sein de l’animation.

– La classe Timer offre un moyen de contrôler le temps de manière précise, contraire-ment à l’événement Event.ENTER_FRAME.

– TweenMax est une célèbre librairie d’interpolation qui permet de simplifier aumaximum l’animation de vos objets.

493

Page 517: Programmez en Actionscript 3

CHAPITRE 23. ANIMER DES OBJETS

494

Page 518: Programmez en Actionscript 3

Chapitre 24Les collisions

Difficulté :

Un jour, si êtes amené à programmer des jeux vidéo, vous allez devoir vous intéresser àla notion de collisions. Vous souhaiterez alors savoir si votre voiture quitte la route, si unobjet sort du cadre de la scène, si deux billes se touchent ou encore si votre personnage ales pieds sur terre. . .

Au cours de ce chapitre, nous découvrirons ensemble les prémices de la théorie des colli-sions. Ainsi, nous serons capables de détecter une collision entre des objets de différentestailles et différentes formes. Nous verrons également comment affiner, plus ou moins, cettedétection de collisions, en fonction de la forme des objets, afin d’optimiser au maximumles performances du programme.

À la fin de ce chapitre, vous serez enfin en mesure de réaliser vos propres jeux vidéo !

495

Page 519: Programmez en Actionscript 3

CHAPITRE 24. LES COLLISIONS

Préambule

Définition d’une collision

Comme cela a été annoncé en introduction, nous parlerons de collisions tout au longde ce chapitre. Aussi, pour mieux comprendre tout ce qui va suivre, nous allons d’aborddéfinir le terme « collision ».

Dans la vie de tous les jours, nous attribuons ce terme à toutes sortes d’impact ou dechoc entre deux objets. Nous pouvons citer l’exemple d’un verre qui se brise au contactdu sol, d’une balle qui atteint sa cible ou encore d’une voiture qui percute un mur.

Dans un programme, nous pourrons parler de collision lorsque deux objets « se touchent »ou se chevauchent. De la même manière, nous pourrons savoir si un objet verre est encontact avec un autre objet sol ou si notre objet voiture percute l’objet mur.

En principe, rien n’empêche votre objet voiture de continuer sa course à travers l’objetmur. Cela ne posera absolument aucun problème à votre application pour continuer às’exécuter. Il faut avouer que c’est tout de même fâcheux ! Il nous incombe donc degérer les collisions à l’intérieur de notre programme afin de pouvoir exécuter des tâchesappropriées.

À la figure 24.1, vous pouvez voir que les objets voiture et mur se chevauchent légè-rement, et sont, par conséquent, en collision.

Figure 24.1 – Collision entre les objets voiture et mur

Détecter des collisions

Des fonctions booléennes

Le principal objectif pour un programmeur sera donc de détecter l’existence d’unecollision entre deux objets.

Mais alors, comment savoir s’il y a collision entre deux objets ?

C’est justement toute la difficulté de la chose, mais également la raison d’être de cechapitre. Nous verrons qu’il existe différents moyens d’y arriver, qui dépendent princi-

496

Page 520: Programmez en Actionscript 3

PRÉAMBULE

palement de la forme des objets et de la précision souhaitée.

Quoi qu’il en soit, nous détecterons les collisions toujours de la même manière : nousutiliserons diverses fonctions ou méthodes, prenant en paramètres les objets à tester,et renvoyant un booléen, qui sera vrai si il y a collision entre les objets transmis oufaux dans le cas inverse.

Effets produits par une collision

Les effets engendrés par une éventuelle collision ne sont pas pris en compte dans cesfonctions de détection de collisions. Ce n’est qu’une fois la collision confirméequ’il est possible de gérer l’impact généré par celle-ci.

Prenons l’exemple d’un choc entre deux boules quelconques, comme sur la figure 25.21.

Figure 24.2 – Choc élastique entre deux boules

Dans l’exemple précédent, nous voyons que nos boules sont en collision à la troisièmeposition. À la suite de ce choc, les boules sont alors déviées et leur vitesse modifiée.Dans ce cas précis, nous pourrions nous appuyer sur la théorie des chocs élastiquespour mettre à jour le mouvement de chacune des boules. Néanmoins, l’effet produitpar la collision aurait été traité différemment s’il s’agissait d’un choc entre un objetvoiture et un objet mur ou encore entre les objets verre et sol.

Les instructions qui découlent d’une collision sont donc directement liés aux typesd’objets que vous manipulez, ou plutôt à ce qu’ils représentent. Par ailleurs, cela dépendégalement de ce que vous, en tant que programmeur, souhaitez faire. Par exemple,l’impact de l’objet voiture sur le mur pourrait stopper net cette dernière en déformantson capot, mais pourrait tout aussi bien la faire « rebondir » et laisser celle-ci intacte.De plus, suivant la vue utilisée (vue de face, de dessus, de côté, etc.) et la manière dontvos classes sont construites, les instructions ne seront pas tout les mêmes.

Les manipulations post-collision sont spécifiques à chaque programme et nesont pas forcément transposables à tous vos projets. Dans ce chapitre, nousnous donc concentrerons uniquement sur les méthodes de détection decollisions entre objets.

497

Page 521: Programmez en Actionscript 3

CHAPITRE 24. LES COLLISIONS

La théorie des collisions

Collisions rectangulaires

La méthode hitTestObject()

Par défaut, tout objet héritant de DisplayObject dispose de deux méthodes ser-vant à détecter des collisions entre objets d’affichage. La première, nomméehitTestObject() est celle dont nous allons parler maintenant. Pour cela, nous auronsbesoin de deux objets. Traçons deux rectangles qui se superposent, au moins partielle-ment :

1 var obj1:Shape = new Shape ();2 obj1.graphics.beginFill(0x000000);3 obj1.graphics.drawRect(0, 0, 100 , 100);4 var obj2:Shape = new Shape ();5 obj2.graphics.beginFill(0x880088);6 obj2.graphics.drawRect(50, 50, 100 , 100);7 addChild(obj1);8 addChild(obj2);

La figure 24.3 nous confirme que les objets obj1 et obj2 se chevauchent bien.

Figure 24.3 – Collision entre deux rectangles

À présent, testons la collision entre ces deux objets.

Pour cela, nous allons donc nous servir de la méthode hitTestObject() qui prend enparamètre simplement l’objet d’affichage avec lequel tester la collision. Sachant que laméthode hitTestObject() appartient à la classe DisplayObject, nous pouvons aussibien l’utiliser à partir de l’objet d’affichage obj1 comme obj2.

Pour s’assurer de son bon fonctionnement, affichons le résultat de cette fonction dansla console, comme ceci :

1 trace(obj1.hitTestObject(obj2)); // Affiche : true

Comme vous n’êtes pas dupes, confirmons le bon fonctionnement de la méthodehitTestObject() en déplaçant un de des rectangles et en ré-affichant le résultat :

1 obj2.y = 100;2 trace(obj1.hitTestObject(obj2)); // Affiche : false

498

Page 522: Programmez en Actionscript 3

LA THÉORIE DES COLLISIONS

La méthode hitTestObject() possède néanmoins un énorme défaut lorsqu’il s’agitd’étudier une collision entre deux objets non rectangulaires. En effet, la détection decollision réalisée à l’intérieur de cette méthode est effectuée non pas sur les objetsd’affichages eux-mêmes, mais sur leur cadre de sélection que nous allons à présentévoquer.

Les cadres de sélection

Un cadre de sélection (ou bounding box en anglais) peut être défini comma la pluspetite zone rectangulaire incluant intégralement un objet d’affichage.

Étant donné qu’un dessin est toujours plus parlant, reprenons l’exemple de la collisionentre nos objets d’affichage voiture et mur. La figure 24.4 nous montre alors ces deuxobjets délimités par leur cadre de sélection respectif.

Figure 24.4 – Les objets d’affichage et leur cadre de sélection

La classe DisplayObject dispose des deux méthodes getBounds() etgetRect() pour récupérer les coordonnées du cadre de sélection d’un ob-jet d’affichage. La différence entre celles-ci est que la méthode getRect()définit le cadre de sélection sans tenir compte des lignes contenues dans l’objetd’affichage. Pour plus d’informations, je vous invite à aller voir la documen-tation.

B

��

Documentation getBounds()et getRect()Code web : 719404

Pour revenir aux collisions rectangulaires, la méthode hitTestObject() réalise doncun test de collision entre les cadres de sélection de deux objets d’affichage et non surleurs formes réelles.

Ce type de collisions peut être donc être utile pour tout objet de forme rectan-gulaire, bien entendu, mais pas seulement ! La méthode hitTestObject()peut aussi vous servir lorsque vous n’avez pas besoin d’une précision extrême.Et enfin, les détections de collisions rectangulaires peuvent égalementêtre suffisantes lorsque vos objets non rectangulaires sont de tailles minimes.En effet, pour des objets très petits, le cadre de sélection est quasimentconfondu avec l’objet lui-même.

499

Page 523: Programmez en Actionscript 3

CHAPITRE 24. LES COLLISIONS

Collisions avec la scène principale

Jusqu’à présent, nous avons vu uniquement comment détecter des collisions rec-tangulaires correspondant, plus ou moins, à deux objets qui se percutent. Toutefois,dans d’autres cas, il peut être utile de détecter si un objet sort d’une certainezone délimitée.

Par exemple, ce type de collisions peut être utilisé pour détecter si un objet sort de lascène principale. Nous allons donc voir maintenant comment gérer ce genre de cas.

Sur la figure 24.5, j’ai rappelé les coordonnées limites de la scène principale de votreanimation.

Figure 24.5 – Limites de la scène principale

Pour apprendre à gérer les collisions avec la scène principale, je vous proposeun petit exemple. Nous allons ainsi réaliser une animation où un rectangle suivra lesmouvements de souris, mais sans sortir du cadre de la scène principale.

Commençons par dessiner un rectangle et faisons-le suivre la souris. Vous devriez main-tenant savoir coder tout ça, mais je vais quand même vous donner un petit coup depouce pour ceux qui auraient oublié comment procéder :

1 var rectangle:Shape = new Shape();2 rectangle.graphics.beginFill(0x00BB00);3 rectangle.graphics.drawRect(-50 , -50, 100 , 100);4 addChild(rectangle);5 stage.addEventListener(MouseEvent.MOUSE_MOVE , deplacer);6 function deplacer(event:MouseEvent):void7 {

500

Page 524: Programmez en Actionscript 3

LA THÉORIE DES COLLISIONS

8 rectangle.x = event.stageX;9 rectangle.y = event.stageY;

10 }

Pour tester si notre objet sort de la scène principale, nous devons tester les limitesde notre rectangle par rapport aux dimensions de l’animation. Étant donné que notrerectangle est centré sur son origine locale, nous pouvons détecter les dépassements decette manière :

1 function deplacer(event:MouseEvent):void2 {3 rectangle.x = event.stageX;4 rectangle.y = event.stageY;56 // Bord gauche7 if (rectangle.x - rectangle.width / 2 < 0)8 {9 trace("Trop à gauche");

10 }11 // Bord droit12 if (rectangle.x + rectangle.width / 2 > stage.stageWidth)13 {14 trace("Trop à droite");15 }16 // Bord haut17 if (rectangle.y - rectangle.height / 2 < 0)18 {19 trace("Trop haut");20 }21 // Bord bas22 if (rectangle.y + rectangle.height / 2 > stage.stageHeight)23 {24 trace("Trop bas");25 }26 }

Certains d’entre vous pourraient se dire que dans le cas présent, nous n’avonspas de fonction booléenne pour la détection de collisions. Toutefois, dois-je vous rappeler qu’une condition renvoie une valeur booléenne ? Nouspouvons ainsi considérer chaque condition comme un détecteur de colli-sion avec une bordure. Dans cet exemple, nous avons donc quatre tests decollisions différents ; évidemment, un rectangle compte quatre côtés !

Enfin, pour empêcher le rectangle de sortir de la scène principale, il suffit de réinitialisersa position pour que celui-ci reste adjacent à la bordure éventuellement franchie.

Voilà comment nous pourrions faire :

1 function deplacer(event:MouseEvent):void2 {

501

Page 525: Programmez en Actionscript 3

CHAPITRE 24. LES COLLISIONS

3 rectangle.x = event.stageX;4 rectangle.y = event.stageY;5 if (rectangle.x - rectangle.width / 2 < 0)6 {7 rectangle.x = rectangle.width / 2;8 }9 if (rectangle.y - rectangle.height / 2 < 0)

10 {11 rectangle.y = rectangle.height / 2;12 }13 if (rectangle.x + rectangle.width / 2 > stage.stageWidth)14 {15 rectangle.x = stage.stageWidth - rectangle.width / 2;16 }17 if (rectangle.y + rectangle.height / 2 > stage.stageHeight)18 {19 rectangle.y = stage.stageHeight - rectangle.height / 2;20 }21 }

Ici, nous avons travaillé avec la scène principale, néanmoins, il est tout à faitpossible de travailler avec un conteneur enfant de type Sprite. Il faudraitalors utiliser l’espace de coordonnées local à ce conteneur, ainsi que ses di-mensions décrites par les attributs width et height. Pour généraliser ceci,quelque soit la position du rectangle par rapport à sa propre origine, il estpossible d’utiliser la méthode getBounds() de l’objet en question.

Collisions circulaires

Le théorème de Pythagore

Pour détecter des collisions entre deux objets de forme circulaire, nous au-rons besoin de calculer la distance qui sépare leurs centres. Pour cela, nous utiliseronsle théorème de Pythagore ! Certains d’entre vous auront peut-être l’impression de re-tourner sur les bancs de l’école, mais il est important de faire un petit rappel de cethéorème. Je passerai néanmoins relativement vite sur ce point, ne vous inquiétez pas !

Pour rappel, le théorème de Pythagore définit une relation entre les trois côtés d’untriangle rectangle, tel que celui sur la figure 24.6.

En utilisant la notation de l’image précédente, le théorème de Pythagore définit larelation suivante :

a2 = b2 + c2

D’un point de vue littéraire, ce théorème est défini de la manière suivante :« Si un triangle est rectangle, alors le carré de l’hypoténuse est égale à lasomme des carrés des deux autres côtés. »

502

Page 526: Programmez en Actionscript 3

LA THÉORIE DES COLLISIONS

Figure 24.6 – Un triangle rectangle

Calcul des distances

Maintenant, nous allons voir comment calculer la distance entre deux objets. Dansle cas présent, nous nous focaliserons sur les cercles. Néanmoins, ceci peut facilementêtre transposable à d’autres types d’objets.

Lorsque nous utilisons le terme « distance » entre deux objets, nous parlons de cellequi sépare les centres de nos objets. Ainsi, à la figure 24.7, nous pouvons voir commentelle est définie dans le cas des cercles.

Figure 24.7 – Distance entre deux cercles

D’après le théorème de Pythagore, nous avons donc la relation suivante :

d2 = (∆ x)2 + (∆ y)2

Dans l’expression précédente, ∆ x représente la différence d’abscisse entre les deuxobjets, c’est-à-dire

x2 − x1

. Bien entendu, c’est la même chose pour y.

Nous supposerons ici que les objets d’affichage correspondant aux cercles possèdentleur origine d’affichage au centre des cercles. Nous pouvons alors calculer la distanceentre deux cercles de cette manière :

1 var d:Number = Math.sqrt(Math.pow(objet2.x - objet1.x, 2) +Math.pow(objet2.y - objet1.y, 2));

503

Page 527: Programmez en Actionscript 3

CHAPITRE 24. LES COLLISIONS

Toutefois, en considérant le temps nécessaire pour réaliser cette opération, il seraitpréférable d’utiliser quelque chose de plus optimisé. En effet, l’utilisation de la multi-plication est plus rapide que le passage par la méthode pow() de la classe Math. Enfait, il serait plus intéressant, du point de vue des performances, de ne pas utiliser cetteclasse. C’est pourquoi, il est préférable de travailler avec des distances au carré, ce quinous évite d’avoir recours à la méthode sqrt().

Voici donc comment redéfinir cette même instruction sans utiliser la classe Math et enrestant en distance au carré :

1 var d:Number = (objet2.x - objet1.x)*( objet2.x - objet1.x) + (objet2.y - objet1.y)*( objet2.y - objet1.y);

Je rappelle qu’un carré est une valeur toujours positive. Quel que soit lesobjets et le sens avec lesquels vous les utilisez, le résultat sera toujours lemême.

Détecter une collision

À présent, vous savez calculer la distance entre deux cercles. Cela tombe bien,nous allons justement en avoir besoin pour détecter les collisions entre objets de formecirculaire. Quelle que soit la position et l’orientation de chacun des deux cercles, ceux-ciseront en collision si la distance entre leurs centres est inférieure à une certaine valeur.Voyez plutôt la figure 24.8.

Figure 24.8 – Distance maximale de collision

En regardant l’image précédente de plus près, nous pouvons en déduire que la distancemaximale de collision entre deux cercles est r1 + r2, soit 2r dans le cas de deuxcercles de rayons identiques. Par ailleurs, nous pouvons également utiliser le fait que lerayon d’un objet correspond exactement à la moitié de sa largeur ou de sa hauteur.

Pour détecter une collision entre deux objets d’affichage obj1 et obj2 de forme circu-laire, nous pouvons définir une fonction de ce style :

1 function testerCollision(obj1:DisplayObject , obj2:DisplayObject):Boolean

2 {

504

Page 528: Programmez en Actionscript 3

LA THÉORIE DES COLLISIONS

3 var collision:Boolean = false;4 var d:Number = (obj2.x - obj1.x)*(obj2.x - obj1.x) + (obj2.

y - obj1.y)*(obj2.y - obj1.y);5 if(d < (obj1.width/2 + obj2.height/2)*(obj1.width/2 + obj2.

height/2))6 {7 collision = true;8 }9 return collision;

10 }

Encore une fois, ce code se base sur le fait que les objets d’affichage sontcentrés sur leur origine. Si ce n’est pas le cas, il sera nécessaire de l’adapterlégèrement.

Collisions ponctuelles

La méthode hitTestPoint()

Nous allons maintenant nous pencher sur le cas des collisions ponctuelles, c’est-à-dire entre un objet d’affichage et un point. Ce dernier sera alors uniquement caractérisépar ses coordonnées x et y.

Nous n’allons pas entrer dans la théorie, je vais plutôt vous présenter une méthodefaisant le travail à votre place. Il s’agit de la méthode hitTestPoint() présente danstoute classe héritant de DisplayObject. En voici sa signature :

1 hitTestPoint(x:Number , y:Number , shapeFlag:Boolean = false):Boolean

Comme vous le voyez, l’utilisation de cette méthode nécessite de renseigner les coordon-nées du point avec lequel tester la collision ainsi qu’un troisième paramètre facultatifnommée shapeFlag. Ce dernier paramètre, de type Boolean, sert à spécifier si la détec-tion de collision doit être faite sur l’objet lui-même en tant que forme complexe (true)ou uniquement d’après son cadre de sélection (false).

Ce type de détection de collisions peut être extrêmement utile dans certains cas.Par exemple, vous pourriez réaliser un jeu de tir et détecter la collision entre la positionde votre curseur et un ennemi quelconque comme l’illustre bien la figure 24.9.

Pour vous donner un exemple de code, voici comment il serait possible de réaliser cettedétection à partir de la méthode hitTestPoint() :

1 stage.addEventListener(MouseEvent.MOUSE_DOWN , tir);2 function tir(event:MouseEvent):void3 {4 if (maCible.hitTestPoint(event.stageX , event.stageY , true))

{5 trace("Cible atteinte");

505

Page 529: Programmez en Actionscript 3

CHAPITRE 24. LES COLLISIONS

Figure 24.9 – Un jeu de tir utilisant les collisions ponctuelles

6 }7 }

Si vous souhaitez tester ce code, il vous suffit d’instancier un objet d’affichage maCibleet de l’ajouter à la liste d’affichage. Le code précédent vous servira alors à détecter lescollisions entre votre curseur et cet objet lors d’un clic avec votre souris.

Exercice : Un mini-jeu de tir

Le principe du jeu va être relativement simple. Nous allons tout d’abord dessiner uneballe qui se baladera à l’intérieur de la scène principale. Puis, lorsque vous cliquerezdessus, votre score de points augmentera.

Démarrons tout de suite en dessinant un disque représentant notre balle que nousplacerons initialement au centre de l’écran :

1 var cible:Shape = new Shape ();2 cible.graphics.beginFill(0x880088);3 cible.graphics.drawCircle(0, 0, 50);4 cible.x = stage.stageWidth / 2;5 cible.y = stage.stageHeight / 2;6 addChild(cible);7 var score:int = 0;

Pour gérer les mouvements de notre balle, nous allons avoir besoin d’utiliser deux va-riables vitesseX et vitesseY qui représenteront donc sa vitesse de déplacement hori-zontale et verticale. Pour détecter les collisions avec la scène principale, nous utiliseronsle principe des collisions rectangulaires, qui, dans ce cas, sera plus que suffisant. Àla suite d’une collision, nous pourrons mettre à jour la position de l’objet ainsi que savitesse, qui sera inversée suivant le côté de la scène que la balle aura percuté.

Tout ceci peut sans doute vous paraître compliqué, pourtant, regardez le code corres-pondant qui n’est pas si terrible :

1 // On initialise des vitesses horizontales et verticales aléatoirement

506

Page 530: Programmez en Actionscript 3

LA THÉORIE DES COLLISIONS

2 var vitesseX:int = 1 + Math.random () * 10;3 var vitesseY:int = 1 + Math.random () * 10;45 // Pour chaque frame6 addEventListener(Event.ENTER_FRAME , deplacer);7 function deplacer(event:Event):void8 {9 // On déplace la balle

10 cible.x += vitesseX;11 cible.y += vitesseY;1213 // On détecte les collisions de la balle avec la scène1415 // Bord gauche16 if (cible.x - cible.width / 2 < 0)17 {18 cible.x = cible.width / 2;19 vitesseX = - vitesseX;20 }21 // Bord droit22 else if (cible.x + cible.width / 2 > stage.stageWidth)23 {24 cible.x = stage.stageWidth - cible.width / 2;25 vitesseX = - vitesseX;26 }2728 // Bord haut29 if (cible.y - cible.height / 2 < 0)30 {31 cible.y = cible.height / 2;32 vitesseY = - vitesseY;33 }34 // Bord bas35 else if (cible.y + cible.height / 2 > stage.stageHeight)36 {37 cible.y = stage.stageHeight - cible.height / 2;38 vitesseY = - vitesseY;39 }40 }

Utiliser le mot-clé else nous permet ici d’économiser des tests. En effet, sil’objet entre en collision avec le bord gauche, il est inutile de tester le borddroit ; de même avec le bord haut et bas.

Enfin, la gestion des tirs peut se faire à l’aide la méthode hitTestpoint() comme celaa été décrit précédemment :

1 stage.addEventListener(MouseEvent.CLICK , tir);2 function tir(event:MouseEvent):void

507

Page 531: Programmez en Actionscript 3

CHAPITRE 24. LES COLLISIONS

3 {4 if (cible.hitTestPoint(event.stageX , event.stageY , true))5 {6 score += 10;7 trace("Score : " + score);8 }9 }

L’exercice que nous venons de réaliser est un préambule à un jeu de tir plus complexe.Pour vous exercer, je vous invite donc grandement à essayer de réaliser un vrai jeu detir suivant vos envies.

Les collisions de pixels

Utiliser l’opacité

Les masques

Une autre manière d’appréhender les collisions est d’utiliser les objets d’affichage sousforme d’images bitmap. Comme vous le savez maintenant, ces images sont décritespar une série de pixels. Et rappelez-vous, les pixels sont caractérisés par des nombresde la forme 0xAARRVVBB, où AA représentent l’opacité du pixel.

L’opacité d’un objet d’affichage permet justement de décrire les contours de la partievisible de celui-ci. C’est pourquoi, l’opacité est grandement utile pour effectuer destests de collisions. Mais nous reviendrons là-dessus plus tard.

En attendant, la figure 24.10 vous montre à quoi peut ressembler le canal alpha del’image voiture, appelé généralement masque de l’image.

Figure 24.10 – Masque (ou opacité) de l’objet voiture

Bien entendu, il serait tout à fait possible de réaliser des tests de collisionsen utilisant les canaux rouge, vert ou bleu. Cependant, cela n’est pas trèscourant, aussi, nous n’en parlerons pas.

508

Page 532: Programmez en Actionscript 3

LES COLLISIONS DE PIXELS

Une manière de détecter des collisions

Ici, nous allons voir comment nous pourrions procéder pour détecter une collisionentre deux images bitmap. Toutefois, nous verrons que la classe BitmapData intègreune méthode hitTest(). Malheureusement, je ne suis pas certain de son fonctionne-ment interne. Mais, quoi qu’il en soit, cela ne nous empêche pas d’imaginer la manièredont cela pourrait être fait.

La technique dont je vais vous parler est simplement tirée de mon imagination. Il estdonc fort probable qu’il y ait d’autres façons d’y parvenir et de manière plus optimisée.Néanmoins, je cherche ici simplement à vous faire découvrir une méthode que vouspourriez vous-mêmes transcrire en code. Vous pourrez ensuite très facilement adaptercelle-ci ou une autre à vos projets pour des applications diverses.

La technique que je vais vous présenter maintenant tire parti du fait qu’une transpa-rence totale est représentée par une valeur correspondante nulle. Je ferais égalementl’hypothèse que l’opacité est représentée par une valeur décimale comprise entre 0 et1. Ainsi, en multipliant simplement les valeurs des opacités des deux pixels devant sesuperposer, nous obtenons un nouveau masque contenant simplement l’intersection desdeux images.

Je vous propose un exemple utilisant des matrices pour illustrer ceci. Pour cela, nousutiliserons le produit d’Hadamard ou produit composante par composante.N’ayez pas peur, cela n’est pas aussi compliqué que ça en a l’air.

Voyez plutôt :

1 1 0 01 1 0 01 1 0 01 1 0 0

1 1 1 11 1 1 10 0 0 00 0 0 0

=

1 1 0 01 1 0 00 0 0 00 0 0 0

Grâce à ce calcul, toute valeur non-nulle correspond donc à un pixel étant en collisionentre les deux objets. Il pourrait même être envisageable d’utiliser un seuil pour lesvaleurs intermédiaires entre 0 et 1 pour considérer s’il y a collision ou non.

Dans l’encadré rouge de la figure 24.11, je vous laisse apprécier ce que cette méthodepourrait donner localement pour notre problème de collision entre les objets voitureet mur.

Une fois cette multiplication faite, nous n’allons plus qu’à parcourir l’ensemble despixels pour détecter si les pixels dépassent le seuil d’opacité définit (ou son carré sivous souhaitez prendre en compte la multiplication appliquée aux valeurs de base). Unseul pixel dépassant le seuil d’opacité est alors synonyme de collision.

509

Page 533: Programmez en Actionscript 3

CHAPITRE 24. LES COLLISIONS

Figure 24.11 – Résultat d’une multiplication entre les masques de deux images

Application en code

Une méthode prête à l’emploi

Vous ayant déjà détaillé le principe, je vais simplement ici vous exposer le code d’uneclasse intégrant une méthode statique réalisant ce travail à partir d’objets d’affichagequelconques.

1 package2 {3 import flash.display.DisplayObject;4 import flash.display.BitmapData;5 import flash.geom.Matrix;6 import flash.geom.Point;7 import flash.geom.Rectangle;89 public class Collision

10 {1112 public function Collision ()13 {14 throw new Error('Classe abstraite ');15 }1617 static public function tester(obj1:DisplayObject , obj2:

DisplayObject , seuil:uint):Boolean18 {19 var collision:Boolean = false;20 if (obj1.hitTestObject(obj2) == true)21 {22 var img1:BitmapData = creerBitmapData(obj1);

510

Page 534: Programmez en Actionscript 3

LES COLLISIONS DE PIXELS

23 var img2:BitmapData = creerBitmapData(obj2);24 var rect1:Rectangle = obj1.getBounds(obj1);25 var rect2:Rectangle = obj2.getBounds(obj2);26 var pos1:Point = new Point(obj1.x + rect1.x,

obj1.y + rect1.y);27 var pos2:Point = new Point(obj2.x + rect2.x,

obj2.y + rect2.y);28 collision = img1.hitTest(pos1 , seuil , img2 ,

pos2 , seuil);29 }30 return collision;31 }3233 static private function creerBitmapData(objet:

DisplayObject):BitmapData34 {35 var image:BitmapData = new BitmapData(objet.width ,

objet.height , true , 0x00000000);36 var rect:Rectangle = objet.getBounds(objet);37 var transformation:Matrix = new Matrix ();38 transformation.translate(-rect.x, -rect.y);39 image.draw(objet , transformation);40 return image;41 }4243 }4445 }

Comme je l’ai dit plus haut, tout repose sur la méthode hitTest() de la classeBitmapData. Le reste est uniquement la mise en place des éléments à transmettreà cette méthode.

La méthode proposée ci-dessus possède néanmoins un petit défaut. En effet,les diverses transformations appliquées à l’objet ne sont pas prises en compteet généreront des bugs. Les objets d’affichage utilisés doivent ne doivent doncsubir aucune transformation. Néanmoins, ceci peut être corrigé en les prenanten compte lors du tracé des BitmapData.

Un exemple d’utilisation

Pour tous ceux qui souhaiteraient voir l’efficacité de la méthode statique donnée pré-cédemment, je vous propose ci-dessous un petit code d’exemple. Regardez alors lasimplicité d’utilisation de cette méthode. Encore une fois, un grand merci à la POO.

1 var obj1:Shape = new Shape ();2 obj1.graphics.lineStyle(20, 0x000000);3 obj1.graphics.drawCircle(200 , 200 , 100);

511

Page 535: Programmez en Actionscript 3

CHAPITRE 24. LES COLLISIONS

4 var obj2:Shape = new Shape ();5 obj2.graphics.beginFill(0x880088);6 obj2.graphics.drawCircle(0, 0, 15);7 obj28 addChild(obj1);9 addChild(obj2);

10 addEventListener(Event.ENTER_FRAME , maFonction);11 function maFonction ():void12 {13 obj2.x = mouseX;14 obj2.y = mouseY;15 if (Collision.tester(obj1 , obj2 , 0x11)) {16 obj1.filters = new Array(new GlowFilter ());17 }else{18 obj1.filters = new Array ();19 }20 }

Ce chapitre n’était qu’une introduction à la théorie des collisions. Même si voussavez désormais répondre à la plupart de vos besoins en termes de collisions, n’hésitezpas à vous perfectionner, notamment grâce au tutoriel sur la théorie des collisions deFvirtman.

En résumé– La détection d’une collision entre deux objets d’affichage se fait à l’aide d’unefonction booléenne.

– Suivants la forme des objets d’affichage et la précision de détection souhaitée, cesfonctions de tests de collisions doivent être différentes.

– Pour tout DisplayObject, la méthode hitTestObject() permet de détecter descollisions entre deux objets à partir de leur cadre de sélection.

– La méthode hitTestPoint() de la classe DisplayObject sert à tester une éven-tuelle collision entre un objet quelconque et un point.

– Pour affiner au mieux les collisions entre deux objets aux formes complexes, laméthode hitTest() de la classe BitmapData effectue des tests au niveau des pixels.

– Les effets engendrées par une collision doivent être traités en dehors des fonctionsbooléennes de détection des collisions.

512

Page 536: Programmez en Actionscript 3

Chapitre 25TP : Jeu de billard

Difficulté :

La fin du cours approche à grand pas et, après tous ces chapitres théoriques, il est tempsde passer de nouveau à la pratique ! Cette partie consiste en un gros TP : en effet, nousallons créer un jeu de billard américain ! Une grande partie des notions que nous avons vuesjusqu’ici seront utiles pour écrire votre jeu de billard, alors n’hésitez pas à revenir sur lespassages sur lesquels vous ne vous sentez pas à l’aide avant d’entamer le TP.

C’est parti pour le grand TP final !

513

Page 537: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

Objectifs

Les règles de notre billard

L’objectif de ce TP est de créer un jeu video reprenant le jeu du billard américain.

Le billard est un jeu en deux équipes se déroulant sur une table de billard, avec plusieursbilles numérotées et de différentes couleurs. Chaque joueur manipule une sorte de bâtonappelé la « queue » et a le droit de taper seulement dans la bille blanche. La table debillard (avec ou sans bandes) dispose de six trous dans lesquels il faut envoyer les billesde notre équipe.

Nous n’allons pas implémenter toutes les autres règles du billard américainpour simplifier le TP, nous laisserons le soin au joueur de décider comment ilveut jouer. Toutefois, rien ne vous empêche de les implémenter vous-mêmepar la suite pour vous entraîner !

Vous verrez à la figure 25.1 ce à quoi devrait ressembler notre jeu, à peu de choses près.

Figure 25.1 – En pleine partie de billard !

514

Page 538: Programmez en Actionscript 3

OBJECTIFS

Le déroulement d’une partie

Phase 1 : Préparation de la partie

Cette phase est lancée lorsqu’une nouvelle partie démarre. Dans un premier temps, ilfaut placer le triangle des billes à droite de la table comme à la figure 25.2.

Figure 25.2 – Disposition initiale des billes

La bille 8 est toujours au centre de la troisième rangée, tandis que les autres billespeuvent être placées dans l’ordre que vous voulez.

La bille blanche peut être placée n’importe où (en général, soit sur le premierpoint blanc de la table, soit sur le deuxième au début de la partie). Nouspouvons alors laisser le choix de l’emplacement de cette bille au joueur lorsde la phase suivante.

Phase 2 : Placement de la bille blanche

La bille blanche suit le curseur de la souris tout en ne pouvant sortir de la zone de jeu(en vert clair sur la table). Lorsque le joueur clique sur le bouton gauche de la souris,il faut placer la bille (voir figure 25.3) et passer à la phase suivante (phase 3).

Figure 25.3 – On placera la bille blanche à la souris

515

Page 539: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

Phase 3 : Visée avec la queue

La queue est alignée sur la bille blanche et le joueur peut viser la bille blanche enfaisant bouger la souris (voir figure 25.4). La distance entre le bout de la queue et labille blanche détermine la puissance du coup porté. Au clic de la souris, on tape dansla bille blanche et c’est au tour de la phase 4.

Figure 25.4 – On visera avec la queue de billard

Il serait préférable de limiter la distance maximum de la queue avec la billeblanche afin d’éviter que la puissance du coup soit trop élevée. On peutégalement envisager de poser une limite de distance minimum pour que lejoueur ne puisse pas faire de coup sans puissance du tout.

Phase 4 : Simulation des billes

Durant cette phase, il faut calculer le déplacement des billes à chaque avancée d’image.Si deux billes entrent en collision, un calcul de choc élastique permet de déterminer leurnouvelle direction et vitesse de déplacement. Si une bille entre en collision de bordureavec un trou, la bille est retirée du jeu jusqu’à la prochaine partie. S’il s’agit de la billeblanche, il faut la replacer : nous retournons donc à la phase 2. Une fois les billes toutesrentrées (hors bille blanche), nous pouvons recommencer une partie et donc retournerà la phase 1.

Pendant qu’elle se déplace, chaque bille doit tourner sur elle-même en fonction de savitesse de déplacement, afin de donner un minimum d’impression de mouvement.

516

Page 540: Programmez en Actionscript 3

PRÉPARATION ET CONSEILS

Comme le calcul des chocs élastiques est un peu mathématique et techniqueet que cela n’est pas l’objet du cours, le code correspondant vous sera fourni,je vous rassure.

Consigne supplémentaire

Afin que notre jeu soit utilisable sur un petit écran, il serait préférable de pouvoirdéplacer le billard à l’aide du bouton droit de la souris.

Préparation et conseils

Préparation du projet

Dossier et ressources

Avant de commencer le TP, il nous faut préparer un peu le terrain. Commencez par créerun nouveau dossier (ou projet Flashdevelop) appellé Billard. Copiez le dossier comde la librairie GSAP (que nous avons découverte dans le chapitre sur l’animation)dans le dossier src où se trouve votre classe principale Main.

Nous allons également utiliser une image et des polices de caractères à placer dans undossier lib qui seront embarquées dans notre application. Pour cela, je vous ai préparéune archive à extraire directement dans le dossier de votre projet.

B

�Téléchargez les ressources

Code web : 166391Ces ressources comprennent un dossier img contenant la texture de fond de notreapplication et un dossier fonts contenant les fichiers de police de caractères à inclure àl’aide d’une classe EmbedFonts à créer sur le modèle de celle que nous avons vue dansle chapitre sur le texte.

Premières classes utiles

Vous pouvez déjà créer ces deux classes contenant des valeurs utiles pour notre projet.Tout d’abord, les constantes des unités de mesure dans un fichier Unite.as :

1 package2 {3 public class Unite4 {5 public static const METRE:Number = 400;6 public static const GRAMME:Number = 1;7 }8 }

517

Page 541: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

Puis, les constantes mathématiques dont nous aurons besoin pour certains calculs dansun fichier Constantes.as :

1 package2 {3 public class Constantes4 {5 public static var restitution:Number = 0.85;6 public static var frottement:Number = 0.007;7 }8 }

Il pourrait être utile de pouvoir modifier ces « constantes » mathématiquependant le jeu (par exemple, dans un écran d’options), afin de permettreau joueur d’affiner ses préférences au niveau du comportement des billes.Nous ne le ferons pas dans le cadre de ce TP, mais cela peut être une idéed’amélioration.

Enfin, voici quelques fonctions mathématiques rassemblées au sien de cette classe quipourront vous être utiles :

1 package2 {3 import flash.display.DisplayObject;4 /**5 * Quelques fonctions utiles.6 * @author Guillaume CHAU7 */8 public class Outils9 {

10 /**11 * Calcule et renvoie la distance (en pixels) entre

deux objets.12 * @param obj113 * @param obj214 * @return Distance en pixels15 */16 static public function distance(obj1:DisplayObject ,

obj2:DisplayObject):Number17 {18 return distanceNombres(obj1.x, obj1.y, obj2.x, obj2

.y);19 }2021 /**22 * Calcule et renvoie la distance (en pixels) entre les

deux points formés par les coordonnées parssées enparamètre.

23 * @param x124 * @param y1

518

Page 542: Programmez en Actionscript 3

PRÉPARATION ET CONSEILS

25 * @param x226 * @param y227 * @return Distance en pixels28 */29 static public function distanceNombres(x1:Number , y1:

Number , x2:Number , y2:Number):Number30 {31 var X:Number = x2 - x1;32 var Y:Number = y2 - y1;33 return Math.sqrt(X * X + Y * Y);34 }3536 /**37 * Calcule et renvoie l'angle (en radians) entre les

deux objets.38 * @param obj139 * @param obj240 * @return Angle en radians41 */42 static public function angle(obj1:DisplayObject , obj2:

DisplayObject):Number43 {44 return angleNombres(obj1.x, obj1.y, obj2.x, obj2.y)

;45 }4647 /**48 * Calcule et renvoie l'angle (en radians) entre les

deux points formés par les coordonnées passées enparamètre.

49 * @param x150 * @param y151 * @param x252 * @param y253 * @return Angle en radians54 */55 static public function angleNombres(x1:Number , y1:

Number , x2:Number , y2:Number):Number56 {57 return Math.atan2(y2 - y1, x2 - x1);58 }59 }6061 }

A quoi servent ces commentaires un peu étranges devant les propriétés pu-bliques ?

519

Page 543: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

1 /**2 * Calcule et renvoie la distance (en pixels) entre deux objets

.3 * @param obj14 * @param obj25 * @return Distance en pixels6 */

Ces commentaires sont des commentaires de documentation. Il permettent dedécrire, dans un format standardisé, le fonctionnement de la propriété. Si vous voulezen savoir plus, je vous invite à consulter le chapitre correspondant dans les annexes.

Les différents éléments du jeu

Voici les différents éléments qui composerons notre jeu du billard. Il peut être judicieuxde définir nos classes à partir de ces éléments.

La table

La table peut être représentée par un rectangle arrondi marron contenant un autrerectangle arrondi vert avec quelques marques blanches transparentes pour aider à placerla bille blanche. La zone jouable en vert clair mesure 2,34 m de largeur et 1,17 m dehauteur ; la marge de la partie vert foncée fait 0,08 m (8 cm). Nous pouvons par exempledéfinir les différentes tailles ainsi en utilisant notre classe Unite :

1 var tableLargeur:Number = 2.34 * Unite.METRE;2 var tableHauteur:Number = 1.17 * Unite.METRE;3 var margeFond:Number = 0.08 * Unite.METRE;

Vous verrez ce à quoi la table doit ressembler à la figure 25.9.

Pour obtenir ce résultat, il faut dessiner en plusieurs étapes.

Tout d’abord, dessinons un rectangle de couleur 0x0c351e (vert foncé) avec une bordurede taille 5, de couleur 0x432e0e (marron) et arrondie de 32 pixels (figure 25.6).

Ajoutons un dessin (par exemple avec la classe Shape) dans notre table qui représenterala zone de jeu, avec un rectangle de couleur 0x006029 (vert clair) avec bords arrondisde 10 pixels, sans bordure (figure 25.7).

Nous pouvons ajouter un filtre d’ombre portée interne de couleur noire à la zonede jeu pour donner un peu de relief.

Ensuite, ajoutons trois lignes blanches transparentes (alpha à 15%) avec un petit disqueau centre (alpha à 30%), à voir à la figure 25.8.

Enfin, nous pouvons ajouter un filtre d’ombre portée pour simuler le volume de la table,comme à la figure 25.9.

520

Page 544: Programmez en Actionscript 3

PRÉPARATION ET CONSEILS

Figure 25.5 – Le rendu final de la table

Figure 25.6 – Première étape : le fond

521

Page 545: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

Figure 25.7 – Etape 2 : zone de jeu

Figure 25.8 – Etape 3 : marquage blanc

522

Page 546: Programmez en Actionscript 3

PRÉPARATION ET CONSEILS

Figure 25.9 – Le rendu final de la table

Les trous

Chaque trou fait 0.069 m (ou 6,9 cm) de diamètre. Il sera constitué d’un simple disquede couleur noire (voir figure 25.10).

Figure 25.10 – Un trou de billard

Il y en a six à disposer autour de la zone de jeu de cette manière, comme à la figure25.11.

Les billes

Chaque bille sera représentée par un disque de couleur, avec un numéro au centre.Une bille sur deux aura des bandes blanches (sauf la bille blanche et la bille 8) pourdifférencier les deux équipes. Leur diamètre est de 0.07 m (ou 7 cm), et leur masse vaut172 g :

1 var diametre:Number = 0.05 * Unite.METRE;2 var masse:Number = 172 * Unite.GRAMME;

Voici les 16 couleurs réglementaires des billes dans l’ordre (la bille numéro zéro est labille blanche) :

1 var couleurs:Array = [

523

Page 547: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

Figure 25.11 – La position de chaque trou

2 0xffffff , // Bille blanche3 0xfac92e ,4 0x1744c1 ,5 0xee372e ,6 0x271d53 ,7 0xff8d59 ,8 0x189e66 ,9 0x931422 ,

10 0x000000 , // Bille 811 0xf7af1d ,12 0x2059e8 ,13 0xde291d ,14 0x2f2665 ,15 0xfb8351 ,16 0x0d955c ,17 0x92121d18 ];

Il est temps de mettre en forme ces billes ! Prenons le cas de la bille 13 et commençonspar dessiner un disque (centré sur l’origine) de la couleur de la bille (figure 25.12).

Si le numéro de la bille est supérieur ou égal à 9, il faut ajouter des bandes blanchescomme à la figure 25.13.

Pensez à utiliser un masque circulaire pour faire prendre aux deux bandes laforme circulaire de la bille.

524

Page 548: Programmez en Actionscript 3

PRÉPARATION ET CONSEILS

Figure 25.12 – Etape 1 : disque de couleur

Figure 25.13 – Etape 2 : éventuelles bandes blanches

Ensuite, si le numéro est supérieur à zéro (donc si ce n’est pas la bille blanche), onajoute un champ de texte noir contenant le numéro avec un disque planc dessiné endessous (figure 25.14).

Figure 25.14 – Etape 3 : étiquette du numéro

Souvenez-vous : il faut utiliser des polices de caractères embarquées dansnotre application, sinon on ne pourra pas faire tourner les billes sans que letexte ne disparaisse !

Enfin, pour donner un peu de volume à nos billes, nous pouvons ajouter quelques filtressur chacune :

1 filters = [2 // Ombre3 new DropShadowFilter(3, 45, 0, 0.3, 6, 6, 1, 2),4 // Volume (ombre intérieure)5 new DropShadowFilter( -10, 45, 0, 0.3, 6, 6, 1, 2, true)6 ];

Ce qui nous donne la figure 25.15.

525

Page 549: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

Figure 25.15 – Etape 4 : filtres d’ombrage

La queue

La queue est un bâton de bois équipé d’un 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 rectanglede couleur noire pour le manche et un autre rectangle légèrement plus fin de couleur0x3e2317 (marron) pour le bâton (figure 25.16).

Figure 25.16 – Queue de billard

Je vous recommande de dessiner la queue de telle sorte que son origine soitau bout, comme sur la figure ci-dessus.

Ce dessin doit être placé dans un objet de dessin (Shape) dans notre classe qui re-présentera la queue afin de pouvoir la centrer sur la bille blanche et bouger le dessinuniquement 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 précisant la puissance du coup qui sera porté en fonction de la distance parrapport à la bille blanche et quelques effets d’ombre (figure 25.18).

526

Page 550: Programmez en Actionscript 3

PRÉPARATION ET CONSEILS

Figure 25.18 – Quelques ajouts sur la queue de billard

Encore une fois, il faut utiliser des polices de caractères embarquées pouréviter que le texte ne disparaisse à la rotation de la queue de billard.

Le fond

Le fond de notre scène sera un dessin couvrant la taille de la fenêtre rempli avec cettetexture (figure 25.19).

Figure 25.19 – Texture de fond

Il faut donc ajouter un écouteur sur l’événement Event.RESIZE sur la scène principalepour détecter le changement de taille. Pour remplir avec une image, nous utiliserons laméthode beginBitmapFill() de la classe Graphics.

Un peu de Maths

Voici quelques portions de code permettant d’effectuer les calculs sortants un peu ducadre du cours.

Vecteur géométrique

En premier lieu, nous aurons besoin de vecteurs géométriques à deux dimensions, dotésde quatre attributs pour nos calculs : x, y, module et angle (figure 25.20).

Voici la classe Vecteur2D représentant un vecteur géométrique à deux dimensions :

1 package2 {

527

Page 551: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

Figure 25.20 – Un vecteur géométrique à deux dimensions

3 /**4 * Un vecteur x;y, pour les calculs5 * @author Guillaume CHAU6 */7 public class Vecteur2D8 {9 private var _x:Number;

10 private var _y:Number;1112 private var _module:Number = 0;13 private var _angle:Number = 0;1415 public function Vecteur2D(x:Number = 0, y:Number = 0)16 {17 _x = x;18 _y = y;1920 _calculAngleModule ();21 }2223 public function toString ():String24 {25 return "[Vecteur2D x=" + x + " y=" + y + " module="

+ module + " angle=" + angle + "]";26 }2728 /**29 * Revoie une copie du vecteur.30 * @return31 */32 public function clone ():Vecteur2D33 {34 var c:Vecteur2D = new Vecteur2D ();35 c.x = _x;

528

Page 552: Programmez en Actionscript 3

PRÉPARATION ET CONSEILS

36 c.y = _y;37 return c;38 }3940 /**41 * Ajoute le vecteur passé en paramètre au vecteur

courant.42 * @param vecteur Vecteur à ajouter.43 * @param apply Si vrai , modifie directement le

vecteur courant. Sinon , renvoie un nouveau vecteur.44 * @return Le vecteur représentant la somme

des deux premiers vecteurs.45 */46 public function ajouter(vecteur:Vecteur2D , apply:

Boolean = false):Vecteur2D47 {48 var cible:Vecteur2D;49 if (apply)50 {51 cible = this;52 }53 else54 {55 cible = clone ();56 }57 cible.x += vecteur.x;58 cible.y += vecteur.y;59 return cible;60 }6162 /**63 * Soustrait le vecteur passé en paramètre au vecteur

courant.64 * @param vecteur Vecteur à soustraire.65 * @param apply Si vrai , modifie directement le

vecteur courant. Sinon , renvoie un nouveau vecteur.66 * @return Le vecteur représentant la

soustraction des deux premiers vecteurs.67 */68 public function soustraire(vecteur:Vecteur2D , apply:

Boolean = false):Vecteur2D69 {70 var cible:Vecteur2D;71 if (apply)72 {73 cible = this;74 }75 else76 {77 cible = clone ();

529

Page 553: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

78 }79 cible.x -= vecteur.x;80 cible.y -= vecteur.y;81 return cible;82 }8384 /**85 * Multiplie le vecteur par un coefficient numérique.86 * @param coef Coefficient numérique.87 * @param apply Si vrai , modifie directement le

vecteur courant. Sinon , renvoie un nouveau vecteur.88 * @return Le vecteur ayant reçu la

multiplication.89 */90 public function multiplier(coef:Number , apply:Boolean =

false):Vecteur2D91 {92 var cible:Vecteur2D;93 if (apply)94 {95 cible = this;96 }97 else98 {99 cible = clone ();

100 }101 cible.x *= coef;102 cible.y *= coef;103 return cible;104 }105106 /**107 * Normalise le vecteur (c'est -à-dire modifie ses

coordonnées x et y telles que son module vaille 1).108 * @param apply Si vrai , modifie directement le

vecteur courant. Sinon , renvoie un nouveau vecteur.109 * @return Le vecteur normalisé.110 */111 public function normaliser(apply:Boolean = false):

Vecteur2D112 {113 var cible:Vecteur2D;114 if (apply)115 {116 cible = this;117 }118 else119 {120 cible = clone ();121 }

530

Page 554: Programmez en Actionscript 3

PRÉPARATION ET CONSEILS

122 var m:Number = cible.module;123 if (m != 0)124 {125 cible.x /= m;126 cible.y /= m;127 }128 else129 {130 cible.x = 0;131 cible.y = 0;132 }133 return cible;134 }135136 /**137 * Calcule le produit du vecteur courant avec le

vecteur passé en paramètre.138 * @param vecteur Le vecteur à multiplier avec le

vecteur courant.139 * @return Nombre résultant de la

multiplication des deux vecteurs.140 */141 public function produit(vecteur:Vecteur2D):Number142 {143 return this.x * vecteur.x + this.y + vecteur.y;144 }145146 /* PRIVE */147148 private function _calculCoord ():void149 {150 if (_module == 0)151 {152 _x = 0;153 _y = 0;154 }155 else156 {157 _x = Math.cos(angle) * _module;158 _y = Math.sin(angle) * _module;159 }160 }161162 private function _calculAngleModule ():void163 {164 if (_x == 0 && _y == 0)165 {166 _angle = 0;167 _module = 0;168 }

531

Page 555: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

169 else170 {171 _module = Outils.distanceNombres(0, 0, _x, _y);172 _angle = Outils.angleNombres(0, 0, _x, _y);173 }174 }175176 /* GETTERS */177178 /**179 * Coordonnée horizontale.180 */181 public function get x():Number182 {183 return _x;184 }185186 public function set x(value:Number):void187 {188 _x = value;189190 _calculAngleModule ();191 }192193 /**194 * Coordonnée verticale.195 */196 public function get y():Number197 {198 return _y;199 }200201 public function set y(value:Number):void202 {203 _y = value;204205 _calculAngleModule ();206 }207208 /**209 * Module (longeur du vecteur).210 */211 public function get module ():Number212 {213 return _module;214 }215216 public function set module(value:Number):void217 {218 _module = value;

532

Page 556: Programmez en Actionscript 3

PRÉPARATION ET CONSEILS

219220 _calculCoord ();221 }222223 /**224 * Angle du vecteur par rapport à l'horizontale.225 */226 public function get angle():Number227 {228 return _angle;229 }230231 public function set angle(value:Number):void232 {233 _angle = value;234235 _calculCoord ();236 }237238 }239240 }

Vous pouvez l’afficher pour la copier en utilisant le code web ci-dessous.

B

�Classe Vecteur2D

Code web : 933976Cette classe sera notamment utile pour calculer les changements de trajectoires entreles billes ou, pourquoi pas, représenter le déplacement de chaque bille.

Il peut souvent être intéressant de représenter des concepts abstraits (commeles vecteurs géométriques) en classes à par entière afin de faciliter les calculspar 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 trajec-toire et la vitesse des deux billes est alors modifiée comme on peut le remarquer dansla figure 25.21.

Pour le projet, partons du principe que chaque bille possède un attribut velocite declasse Vecteur2D qui représente son déplacement (horizontal et vertical) dans la zonede jeu. Pour la phase de simulation du jeu de billard, il faut alors déplacer chaque billeen fonction de la valeur des coordonnées du vecteur (velocite.x pour le déplacementhorizontal et velocite.y pour le déplacement vertical), et ceci régulièrement pourdonner l’illusion du déplacement (par exemple, à chaque changement de frame grâce àl’événement Event.ENTER_FRAME).

On peut calculer les nouvelles trajectoires de deux billes entrant en collision à l’aide de

533

Page 557: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

Figure 25.21 – Choc élastique entre deux billes

ce calcul un peu complexe que je vous ai préparé :

1 var taille:Number = (this.taille + bille.taille) / 2;23 // Repositionnement au point de contact4 // Vecteur distance entre les boules5 var delta:Vecteur2D = new Vecteur2D(this.x - bille.x, this.y -

bille.y);6 var d:Number = delta.module;7 // Distance de translation minimum pour pousser les boules8 if (d == 0)9 {

10 d = (this.taille + bille.taille) * 0.5 - 1;11 delta = new Vecteur2D ((this.taille + bille.taille) * 0.5, 0

);12 }13 var mtd:Vecteur2D = delta.multiplier ((( this.taille + bille.

taille) * 0.5 - d) / d);1415 // Masse inverse16 var im1:Number = 1 / this.masse;17 var im2:Number = 1 / bille.masse;1819 // Repousser les balles pour éviter qu'elles se chevauchent20 var correction:Vecteur2D = mtd.multiplier(im1 / (im1 + im2));21 this.x += correction.x;22 this.y += correction.y;23 bille.x -= correction.x;24 bille.y -= correction.y;2526 // Calcul de la base orthonormée (n,g)27 // n est perpendiculaire au plan de collision , g est tangent28 var nx:Number = (bille.x - this.x) / taille;29 var ny:Number = (bille.y - this.y) / taille;30 var gx:Number = -ny;31 var gy:Number = nx;3233 // Calcul des vitesses dans cette base

534

Page 558: Programmez en Actionscript 3

ORGANISATION DE L’APPLICATION

34 var v1n:Number = nx * this.velocite.x + ny * this.velocite.y;35 var v1g:Number = gx * this.velocite.x + gy * this.velocite.y;36 var v2n:Number = nx * bille.velocite.x + ny * bille.velocite.y;37 var v2g:Number = gx * bille.velocite.x + gy * bille.velocite.y;3839 // Permute les coordonnées n et conserve la vitesse

tangentielle40 // Exécute la transformation inverse (base orthonormée =>

matrice transposée)41 this.velocite.x = nx * v2n + gx * v1g;42 this.velocite.y = ny * v2n + gy * v1g;43 bille.velocite.x = nx * v1n + gx * v2g;44 bille.velocite.y = ny * v1n + gy * v2g;

L’objet courant de ce calcul (c’est-à-dire l’objet pointé par le mot-clé this)est la bille qui est entrée en collision avec la deuxième bille, contenue dans lavariable bille.

Après ce calcul, l’objet velocite de chaque bille contient le nouveau déplacementhorizontal (velocite.x) et le nouveau déplacement vertical (velocite.y) de la bille.

Organiser son projet

Maintenant que vous avez toutes les clés en mains, il faut organiser votre projet. Posez-vous plusieurs questions avant de commencer à coder quoi que ce soit ! Commencez pardessiner sur une feuille les classes que vous allez créer, réfléchissez à la façon dont ellesvont interagir entre elles, si il y aura des classes mères, etc. Pour vous donner un ordred’idée, mon projet compte au total 12 classes (hors librairie GSAP), mais vous pouveztout à fait en créer plus ou moins que moi. Ensuite, représentez le déroulement d’unepartie de billard pour l’avoir bien en tête lorsque vous implémenterez la logique dece jeu de billard. Et surtout, n’hésitez par à parcourir à nouveau certaines sections ducours. Essayez de produire quelque chose, même si cela n’a pas autant de fonctionnalitésque vous l’espériez, avant de regarder la correction : on apprend le mieux en pratiquantsoi-même !

A vos stylos et claviers !

Organisation de l’application

La structure de l’application

Avant de commencer à programmer tête baissée, il faut réfléchir à la structure duprojet. Avec quelques feuilles et un crayon, vous pouvez commencer à organiser votreapplication, ce travail est très important pour que votre projet soit clair et lisible (ycompris pour vous-même). Je vais vous présenter la structure que j’ai choisie, qui peut

535

Page 559: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

tout à fait différer de la vôtre, il n’y a pas une seule solution à ce problème, ne l’oubliezpas !

J’ai donc articulé mon application autour d’une classe nommée Billard qui représentele jeu de billard que nous concevons. Cette classe utilise d’autres classes pour composerles différents éléments du jeu : la table, les trous, les billes et la queue, qui sont lesdifférents objets visuels. La logique du jeu de billard est également contenue dans laclasse Billard. A côté de cette classe, nous retrouvons la classe Vecteur2D servant àfaire plusieurs calculs (comme les déplacements des billes et les chocs élastiques). Enfin,la classe Main représente le programme principal qui va créer un jeu de billard à l’aidede la classe Billard.

Vous verre à la figure 25.22 le diagramme des classes principales de l’application.

Figure 25.22 – Diagramme des classes

Les autres classes annexes (comme les classes Unite et Constantes) ne sontpas représentées sur ce diagramme pour des raisons de lisibilité.

536

Page 560: Programmez en Actionscript 3

CRÉATION DES CLASSES

Description des différents classes

Nous avons donc huit classes principales :

– Classe Main : programme principal, chargé de gérer la création du jeu du Billard etla texture de fond de l’application.

– Classe Billard : représente le jeu du billard, c’est-à-dire sa logique (avec les quatrephases de jeu) et ses différents éléments.

– Classe Visuel : classe mère des éléments composants le jeu.– Classe Table : consiste principalement en un dessin de la table de billard et gestiondes collisions entre les billes et les bords de la zone de jeu.

– Classe Trou : dessin d’un trou de la table de billard avec la gestion des collisions desbilles avec ce trou .

– Classe Bille : dessin d’une bille de billard (avec un numéro), ainsi que la gestion dudéplacement de la bille et des collisions entre deux billes.

– Classe Queue : dessin de la queue de billard (avec les indicateurs visuels).– Classe Vecteur2D : représente un vecteur géométrique à deux dimensions pour lescalculs.

Création des classes

Dans cette partie, nous allons détailler les différentes classes du projet, une à une.Toutefois, essayez quand même d’aboutir à un résultat par vos propres moyens avantde vous jeter sur cette correction, cela vous aidera à progresser !

Visuel

Commençons par créer la classe de base de nos objets graphiques, la classe Visuel.Cette classe va gérer la taille des objets visuels et va faire en sorte de les dessinerà chaque modification de taille en partant de la classe d’affichage Sprite. Grâce aupolymorphisme, nous pouvons redéfinir les accesseurs width et height de la classeSprite de telle sorte que la méthode protégée _dessiner soit appellée automatique-ment dès qu’un changement de taille intervient : ainsi, nos objets graphiques serontredessinés dès qu’il sera nécessaire !

1 package2 {3 import flash.display.Sprite;45 /**6 * Classe de base des objets graphiques.7 * @author Guillaume CHAU8 */9 public class Visuel extends Sprite

10 {11 // Taille "virtuelle"

537

Page 561: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

12 private var _width:Number = 0;13 private var _height:Number = 0;1415 private var _taille:Number = 0;1617 public function Visuel ()18 {1920 }2122 /* PRIVE */2324 protected function _dessiner ():void25 {26 // A implémenter dans les sous -classes27 }2829 /* GETTERS */3031 override public function get width ():Number32 {33 return _width;34 }3536 override public function set width(value:Number):void37 {38 _width = value;3940 _dessiner ();41 }4243 override public function get height ():Number44 {45 return _height;46 }4748 override public function set height(value:Number):void49 {50 _height = value;5152 _dessiner ();53 }5455 /**56 * Taille de l'objet visuel au cas où il n'a besoin que

d'un nombre (exemple : diamètre).57 */58 public function get taille ():Number59 {60 return _taille;

538

Page 562: Programmez en Actionscript 3

CRÉATION DES CLASSES

61 }6263 public function set taille(value:Number):void64 {65 _taille = value;6667 _dessiner ();68 }69 }7071 }

Vous pouvez l’afficher pour la copier en utilisant le code web ci-dessous.

B

�Classe Visuel

Code web : 930063

J’ai ajouté un attribut taille pour les objets n’ayant besoin que d’un nombrepour leur taille (comme les billes et les trous de la table).

Au lieu de laisser la classe Sprite redimensionner (étirer) l’objet comme d’habitude,nous stockons les nouvelles informations de taille (que j’ai appellées les informationsde taille virtuelle), puis nous utiliserons ses informations dans la méthode _dessiner(redéfinie 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-classede la classe Visuel. Commençons donc par lui faire hériter la classe Visuel :

1 package2 {3 /**4 * Bille de billard.5 * @author Guillaume CHAU6 */7 public class Bille extends Visuel8 {9

10 }11 }

Si vous utilisez Flashdevelop, il est possible de spécifier la classe mère lorsque vouscréez une classe pour que l’IDE écrive le code correspondant automatiquement (avecles imports). Il suffit de la renseigner dans le champ Base Class de la fenêtre de créationde classe. Cliquez d’abord sur le bouton Browse en face du champ Base Class, commeà la figure 25.23.

Puis tapez le nom de la classe mère et sélectionnez-la (voir figure 25.24).

539

Page 563: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

Figure 25.23 – Fenêtre de création de classe

Figure 25.24 – Sélection de la classe mère

540

Page 564: Programmez en Actionscript 3

CRÉATION DES CLASSES

Une fois la classe créée, ajoutons-lui les attributs des billes :

1 // Infos de bases2 private var _couleur:uint;3 private var _numero:int;4 private var _masse:Number;56 // Vraie si la bille est tombée dans un trou7 private var _horsJeu:Boolean = false;89 // Eléments visuels

10 private var _masque:Shape;11 private var _etiquette:TextField;1213 // Vecteur de déplacement14 private var _velocite:Vecteur2D;

Sans oublier les accesseurs correspondants :

1 /**2 * Couleur de la bille (exemple: 0xFF0055).3 */4 public function get couleur ():uint5 {6 return _couleur;7 }89 /**

10 * 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 billea des bandes blanches.

11 */12 public function get numero ():int13 {14 return _numero;15 }1617 /**18 * Masse de la bille. Utiliser Unite.GRAMME.19 */20 public function get masse():Number21 {22 return _masse;23 }2425 public function set masse(value:Number):void26 {27 _masse = value;28 }2930 /**

541

Page 565: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

31 * Vecteur géométrique représentant le déplacement de la billepar frame.

32 */33 public function get velocite ():Vecteur2D34 {35 return _velocite;36 }3738 public function set velocite(value:Vecteur2D):void39 {40 _velocite = value;41 }4243 /**44 * Indique si la bille est hors -jeu (ex: tombée dans un trou).45 */46 public function get horsJeu ():Boolean47 {48 return _horsJeu;49 }5051 public function set horsJeu(value:Boolean):void52 {53 _horsJeu = value;54 }

Constructeur

Le constructeur de la bille créé les différents objets contenus dans la bille : l’étiquette dunuméro et le vecteur de déplacement. De plus, il reçoit en paramètre les informationsde bases sur la bille (couleur, numéro, taille et masse).

1 public function Bille(couleur:uint , numero:int , taille:Number ,masse:Number)

2 {3 // Etiquette affichant le numéro de la bille4 _etiquette = new TextField ();5 _etiquette.selectable = false;6 _etiquette.autoSize = TextFieldAutoSize.LEFT;7 _etiquette.defaultTextFormat = new TextFormat('arial', 10,

0x000000);8 _etiquette.embedFonts = true;9 addChild(_etiquette);

1011 // Effets spéciaux12 filters = [13 // Ombre14 new DropShadowFilter(3, 45, 0, 0.3, 6, 6, 1, 2),15 // Volume (ombre intérieure)

542

Page 566: Programmez en Actionscript 3

CRÉATION DES CLASSES

16 new DropShadowFilter( -10, 45, 0, 0.3, 6, 6, 1, 2, true)

17 ];1819 // Vecteur géométrique à deux dimensions représentant le dé

placement de la bille pour chaque frame20 _velocite = new Vecteur2D ();2122 // Autres attributs23 _couleur = couleur;24 _numero = numero;25 this.taille = taille;26 _masse = masse;27 }

Dessin de la bille

Nous avons à notre disposition une méthode _dessiner héritée de la classe mère Visuelqui, pour rappel, sera appelée dès qu’il faudra redessiner l’objet graphique. Nous allonsdonc redéfinir cette méthode pour dessiner notre bille :

1 override protected function _dessiner ():void2 {3 super._dessiner ();45 // Bille6 graphics.clear();7 graphics.lineStyle(1, _couleur);8 graphics.beginFill(_couleur);9 graphics.drawCircle(0, 0, taille * 0.5 - 1);

1011 // Bandes12 if (_numero >= 9)13 {14 // Rectangles blancs15 graphics.lineStyle ();16 graphics.beginFill(0xffffff);17 graphics.drawRect( -taille / 2, -taille / 2 , taille , 3

);18 graphics.drawRect( -taille / 2, taille / 2 - 3, taille ,

3);19 graphics.endFill ();2021 // Masque circulaire22 _masque = new Shape ();23 _masque.graphics.beginFill(0);24 _masque.graphics.drawCircle(0, 0, taille * 0.5 - 1);25 addChild(_masque);26 mask = _masque;

543

Page 567: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

27 }2829 // Numéro30 _etiquette.visible = (_numero > 0);3132 if (_etiquette.visible)33 {34 _etiquette.text = _numero.toString ();35 _etiquette.x = -_etiquette.width * 0.5;36 _etiquette.y = -_etiquette.height * 0.5;3738 graphics.beginFill(0xffffff);39 graphics.drawCircle(0, 0, _etiquette.height * 0.4);40 }41 }

Les bandes ne sont dessinées que si le numéro de la bille est supérieur ou égal à 9 :on utilise alors un masque circulaire et deux rectangles blancs. Puis, nous cachonsl’étiquette si le numéro vaut zéro (correspondant alors à la bille blanche). Dans le cascontraire, nous mettons à jour l’étiquette, la centrons au milieu de la bille et dessinonsun disque blanc supplémentaire.

Collision avec une autre bille

La gestion des collisions avec les autres billes s’effectue en deux étapes :

– On teste d’abord la collision entre les deux billes.– Si les deux billes sont entrées en collision, on calcule leur nouveau vecteur de dépla-cement suite au choc élastique.

Commençons donc par créer une méthode testant la collision de la bille avec une autre :

1 private function _dectecterCollision(bille:Bille):Boolean2 {3 var dX:Number = this.x - bille.x;4 var dY:Number = this.y - bille.y;56 var racineRayons:Number = (this.taille + bille.taille) * 0.

5;7 racineRayons = racineRayons * racineRayons;89 var racineDistance:Number = (dX * dX) + (dY * dY);

1011 return racineDistance <= racineRayons;12 }

Pour savoir si deux billes sont entrées en collision, nous calculons la distance entre lesdeux au carré, puis nous la comparons au carré de la somme de leur rayon, comme nousl’avons vu dans le chapitre sur la théorie des collisions (et plus précisément la partiesur les collisions circulaires).

544

Page 568: Programmez en Actionscript 3

CRÉATION DES CLASSES

Ensuite, il faut créer une méthode qui va calculer les changements des vecteurs dedéplacement lors d’un choc élastique entre deux billes :

1 private function _calculerChocElastique(bille:Bille):void2 {3 var taille:Number = (this.taille + bille.taille) / 2;45 // Repositionnement au point de contact6 // Vecteur distance entre les boules7 var delta:Vecteur2D = new Vecteur2D(this.x - bille.x, this.

y - bille.y);8 var d:Number = delta.module;9 // Distance de translation minimum pour pousser les boules

10 if (d == 0)11 {12 d = (this.taille + bille.taille) * 0.5 - 1;13 delta = new Vecteur2D ((this.taille + bille.taille) * 0.

5, 0);14 }15 var mtd:Vecteur2D = delta.multiplier ((( this.taille + bille.

taille) * 0.5 - d) / d);1617 // Masse inverse18 var im1:Number = 1 / this.masse;19 var im2:Number = 1 / bille.masse;2021 // Repousser les balles pour éviter qu'elles se chevauchent22 var correction:Vecteur2D = mtd.multiplier(im1 / (im1 + im2)

);23 this.x += correction.x;24 this.y += correction.y;25 bille.x -= correction.x;26 bille.y -= correction.y;2728 // Calcul de la base orthonormée (n,g)29 // n est perpendiculaire au plan de collision , g est

tangent30 var nx:Number = (bille.x - this.x) / taille;31 var ny:Number = (bille.y - this.y) / taille;32 var gx:Number = -ny;33 var gy:Number = nx;3435 // Calcul des vitesses dans cette base36 var v1n:Number = nx * this.velocite.x + ny * this.velocite.

y;37 var v1g:Number = gx * this.velocite.x + gy * this.velocite.

y;38 var v2n:Number = nx * bille.velocite.x + ny * bille.

velocite.y;39 var v2g:Number = gx * bille.velocite.x + gy * bille.

velocite.y;

545

Page 569: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

4041 // Permute les coordonnées n et conserve la vitesse

tangentielle42 // Exécute la transformation inverse (base orthonormée =>

matrice transposée)43 this.velocite.x = nx * v2n + gx * v1g;44 this.velocite.y = ny * v2n + gy * v1g;45 bille.velocite.x = nx * v1n + gx * v2g;46 bille.velocite.y = ny * v1n + gy * v2g;47 }

Il s’agit du calcul que je vous avais donné à la préparation du TP qui permet de définirde nouveaux vecteurs géométriques de déplacement pour la bille courante et la billetestée à l’aide de la théorie des chocs élastiques.

Maintenant que nous avons ces deux méthodes de prêtes, nous pouvons créer la méthodepublique gérant la collision de la bille avec une autre bille :

1 /**2 * Teste la collision avec une autre bille , et applique le choc

élastique le cas échéant.3 * @param bille4 */5 public function testerCollision(bille:Bille):void6 {7 if (_dectecterCollision(bille))8 {9 _calculerChocElastique(bille);

10 }11 }

Il est important de bien séparer chaque fonctionnalité dans des fonctionsdifférentes : ici, nous avons créé deux méthodes privées qui serons utiliséesdans la méthode principale au lieu de tout mélanger dans une seule méthode :le test de collision puis le calcul du choc élastique. Cela permet de rendrele code plus clair, mais cela permet aussi au développeur de tester chaquefonctionnalité plus finement et donc de cerner les problèmes plus facilement.

Déplacement

Enfin, il nous faut une méthode pour déplacer la bille d’une frame. J’ai ajouté unparamètre multiplicateur qui permet de faire varier la vitesse de la simulation : il nousest alors possible de faire un magnifique ralenti ou au contraire, d’accélérer le jeu !

1 /**2 * Déplace la bille d'une frame avec application de la décélé

ration.3 * @param multiplieur

546

Page 570: Programmez en Actionscript 3

CRÉATION DES CLASSES

4 */5 public function deplacer(multiplicateur:Number = 1):void6 {7 x += _velocite.x * multiplicateur;8 y += _velocite.y * multiplicateur;9

10 rotation += _velocite.module * 3 * multiplicateur;1112 if (_velocite.module > 0.03)13 {14 _velocite.module -= (_velocite.module * Constantes.

frottement + 0.03) * multiplicateur;15 }16 else17 {18 _velocite.module = 0;19 }20 }

Nous commençons par déplacer la bille en fonction de son vecteur de déplacementvelocite, puis nous la faisons tourner sur elle-même plus ou moins rapidement enfonction de sa vitesse de déplacement (c’est-à-dire le module du vecteur de déplace-ment). Ensuite, nous diminuons la vitesse de la bille d’au moins 0.03 pixels par frame(fois le multiplicateur) en fonction de la constante de frottement que nous avons définiau début. Ceci nous permet de simuler la décélération de la bille sur la table.

Le minimum de 0.03 permet d’éviter des comportements bizarres de la billelors de la décélération en imposant une diminution minimale et un arrêt si lavitesse est trop petite (inférieure à 0.03).

Table

La table contient deux dessins (table et zone de jeu) et gère la collision des billes avecles bords de la zone de jeu. Ajoutons d’abord les deux attributs de la table (l’image defond et le dessin de la zone de jeu) :

1 // Eléments visuels2 private var _fond:Shape;3 private var _dessin:Shape;

Constructeur

Le constructeur sert une fois de plus à créer les objets d’affichages qui composentnotre objet. Il s’agit ici du dessin de la table et du dessin de la zone de jeu :

1 public function Table ()2 {

547

Page 571: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

3 _fond = new Shape();4 // Ombre portée5 _fond.filters = [new DropShadowFilter(10 , 45, 0, 0.6, 10 ,

10 , 1, 2)];6 addChild(_fond);78 _dessin = new Shape();9 // Ombre intérieure

10 _dessin.filters = [new DropShadowFilter(4, 45, 0, 0.3, 20,20 , 1, 2, true)];

11 addChild(_dessin);12 }

Dessin de la table

Comme pour la classe Bille, nous redéfinissions la méthode _dessiner de la classemère Visuel pour dessiner la table :

1 override protected function _dessiner ():void2 {3 super._dessiner ();45 // Fond6 var margeFond:Number = 0.08 * Unite.METRE;7 _fond.graphics.clear ();8 _fond.graphics.lineStyle(5, 0x432e0e , 1, true);9 _fond.graphics.beginFill(0x0c351e);

10 _fond.graphics.drawRoundRect( -margeFond , -margeFond , width+ 2 * margeFond , height + 2 * margeFond , 32);

1112 // Zone de jeu13 _dessin.graphics.clear();14 _dessin.graphics.beginFill(0x006029);15 _dessin.graphics.drawRoundRect(0, 0, width , height , 10);16 _dessin.graphics.endFill ();1718 // Lignes et points centraux19 for (var i:int = 1; i <= 3; i++)20 {21 // Ligne22 _dessin.graphics.lineStyle(4, 0xffffff , 0.15);23 _dessin.graphics.moveTo(width * 0.25 * i, 0);24 _dessin.graphics.lineTo(width * 0.25 * i, height);2526 // Point27 _dessin.graphics.lineStyle ();28 _dessin.graphics.beginFill(0xffffff , 0.3);29 _dessin.graphics.drawCircle(width * 0.25 * i, height *

0.5, 3);

548

Page 572: Programmez en Actionscript 3

CRÉATION DES CLASSES

30 }31 }

La taille définie grâce à width et height correspond à la taille de la zone dejeu pour faciliter l’écriture du code. La taille totale de la table (en comptantles bordures) est donc plus grande.

Collision avec les billes

Intéressons nous maintenant à la collision des billes avec les bords de la table. Il s’agitd’un cas dont nous avons parlé dans le chapitre sur la théorie des collisions à traversde l’exemple de la collision avec la scène principale. Cette-fois, il s’agit d’une zone plusréduite représentée par la zone de jeu.

1 /**2 * Teste la collision de la bille avec les bords de la zone de

jeu et applique la collision le cas échéant.3 * @param bille4 */5 public function testerCollision(bille:Bille):void6 {7 var taille:Number = bille.taille * 0.5;8 // Bord gauche9 if (bille.x - taille <= 0)

10 {11 bille.x = taille;12 bille.velocite.x *= -1;13 }14 // Bord droit15 else if (bille.x + taille >= width)16 {17 bille.x = width - taille;18 bille.velocite.x *= -1;19 }2021 // Bord haut22 if (bille.y - taille <= 0)23 {24 bille.y = taille;25 bille.velocite.y *= -1;26 }27 // Bord bas28 else if (bille.y + taille >= height)29 {30 bille.y = height - taille;31 bille.velocite.y *= -1;32 }33 }

549

Page 573: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

Trous

Chaque trou contient un dessin très simple et permet de gérer la collision avec les billes.Ce n’était pas demandé, mais j’ai ajouté en plus une poche pour afficher les billes quisont tombées dans chaque trou (voir figure 25.25).

Figure 25.25 – Poche contenant les billes tombées dans le trou

C’est quand-même plus agréable, non ? Mais ne vous inquiètez pas si vous n’avez pasfait quelque chose de similaire, il s’agit d’un bonus.

Attributs

Au niveau des attributs, nous avons le numéro du trou, la liste des billes tombéesdans le trou, le dessin du trou et enfin le dessin de la poche :

1 // Infos de base2 private var _numero:int;34 // Billes tombées dans le trou5 private var _billes:Vector.<Bille >;67 // Eléments visuels8 private var _dessin:Shape;9 private var _poche:Shape;

À la figure 25.26, les numéros de nos trous.

Les trous dont le numéro est inférieur ou égal à 3 sont en haut et les autres sont enbas. Cette information sera utile pour dessiner les poches des billes.

Vous pouvez ajouter des accesseurs pour chaque attribut si vous jugez cela nécessaire.

Constructeur

Le constructeur sert encore à initialiser les objets de la classe. Ici, nous créons la listedes billes, puis ajoutons les différents objets d’affichage (dessin du trou et de la poche),et enfin affectons le paramètre numero :

1 public function Trou(numero:int)

550

Page 574: Programmez en Actionscript 3

CRÉATION DES CLASSES

Figure 25.26 – Numéro des trous

2 {3 super();45 _billes = new Vector.<Bille >();67 _dessin = new Shape ();8 addChild(_dessin);9

10 _poche = new Shape ();11 _poche.alpha = 0;12 // Ombre intérieure de la poche13 _poche.filters = [new GlowFilter(0x000000 , 0.5, 6, 6, 2, 2,

true)];14 addChild(_poche);1516 _numero = numero;17 }

Dessin du trou

Encore une fois, nous redéfinissons la méthode _dessiner :

1 override protected function _dessiner ():void2 {3 super._dessiner ();45 // Trou6 _dessin.graphics.clear();

551

Page 575: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

7 _dessin.graphics.beginFill(0);8 _dessin.graphics.drawCircle(0, 0, taille * 0.5);9 }

Test de la collision des billes avec le trou

Pour la gestion des collisions avec les billes, nous avons besoin que d’une méthodetestant la collision d’une bille avec le trou :

1 /**2 * Teste la collision de la bille avec le trou courant.3 * @param bille4 * @return Vrai si la bille est entrée en collision avec

le trou.5 */6 public function testerCollision(bille:Bille):Boolean7 {8 return _dessin.hitTestObject(bille);9 }

Cette méthode permettra au billard de savoir si une bille est tombée dans un trou.

Ajout d’une bille tombée dans le trou

Dans le cas d’une collision, la bille sera ajouté au trou par le jeu de billard pour êtreaffichée dans la poche. Il nous faut alors cette méthode qui ajoute une bille :

1 /**2 * Ajoute une bille dans le trou. Elle sera affichée dans une

poche.3 * @param bille4 */5 public function ajouterBille(bille:Bille):void6 {7 // Index de la bille dans la liste des billes tombées dans

le trou8 var index:int = _billes.length;9

10 // Bille11 bille.alpha = 1;12 bille.rotation = 0;13 bille.x = x + (( index % 5) - 2) * bille.taille;14 bille.y = y + Math.floor(index / 5) * bille.taille;15 _billes.push(bille);1617 // Ajustement de la position de la bille en fonction de l'

enplacement de la poche18 if (numero <= 3)19 {

552

Page 576: Programmez en Actionscript 3

CRÉATION DES CLASSES

20 // Poche au dessus du trou21 bille.y -= bille.taille * 6;22 }23 else24 {25 // Poche en dessous du trou26 bille.y += bille.taille * 4;27 }2829 // Animation bille30 TweenMax.fromTo(bille , 0.8, { scaleX:0, scaleY:0 }, {

scaleX:1, scaleY:1, ease:Bounce.easeOut , delay:0.3 } );3132 // Poche33 _poche.graphics.clear();34 _poche.graphics.beginFill(0x888888 , 1);35 _poche.graphics.drawRoundRect(0, 0, 5 * bille.taille + 20,

3 * bille.taille + 20 , 20);36 _poche.x = -_poche.width * 0.5;37 _poche.y = -_poche.height;3839 // Dessin du triangle de la poche (façon bulle de BD)40 if (numero <= 3)41 {42 // Triangle en bas de la bulle43 _poche.y -= bille.taille * 3;44 _poche.graphics.moveTo(_poche.width * 0.5 - bille.

taille , _poche.height);45 _poche.graphics.lineTo(_poche.width * 0.5 + bille.

taille , _poche.height);46 _poche.graphics.lineTo(_poche.width * 0.5, _poche.

height + bille.taille);47 _poche.graphics.endFill ();48 }49 else50 {51 // Tirangle en haut de la bulle52 _poche.y += bille.taille * 3 + _poche.height;53 _poche.graphics.moveTo(_poche.width * 0.5 - bille.

taille , 0);54 _poche.graphics.lineTo(_poche.width * 0.5 + bille.

taille , 0);55 _poche.graphics.lineTo(_poche.width * 0.5, - bille.

taille);56 _poche.graphics.endFill ();57 }5859 // Animation poche60 TweenMax.to(_poche , 0.25 , { alpha:1 } );61 }

553

Page 577: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

Vous remarquerez que je dessine la poche ici au lieu de la dessiner dans laméthode _dessiner : en effet, nous avons besoin de la taille des billes pourfaire une bulle pouvant contenir au moins 15 billes. La poche doit faire doncune taille supérieure à 5 billes en largeur et 3 billes en hauteur.

Retrait des billes tombées dans le trou

Lorsque l’on recommence la partie, il nous faut enlever les billes dans chaque trou,grâce à cette méthode :

1 /**2 * Retire les billes du trou.3 */4 public function enleverBilles ():void5 {6 _billes = new Vector.<Bille >();78 // On cache la poche9 TweenMax.to(_poche , 0.25, { alpha:0, onComplete:_poche.

graphics.clear } );10 }

Queue

La classe de la queue de billard est plustôt simple a créer par rapport aux autres classes,on n’a pas de collision à gérer. Ici, il ne s’agit que d’affichage.

Commençons par les attributs de la classe :

1 // Infos de base2 private var _distance:Number;3 private var _puissance:Number;45 // Indique si les indicateurs visuels sont actifs6 private var _indicateursActifs:Boolean = true;78 // Eléments visuels9 private var _etiquette:TextField;

10 private var _dessin:Shape;

Constructeur

Cette fois encore, le constructeur créé les objets d’affichage contenus dans l’objet cou-rant :

1 public function Queue ()2 {

554

Page 578: Programmez en Actionscript 3

CRÉATION DES CLASSES

3 super();45 // Dessin de la queue de billard6 _dessin = new Shape ();7 _dessin.filters = [new DropShadowFilter(12, 45, 0, 0.3, 6,

6, 1, 2)];8 addChild(_dessin);9

10 // Etiquette indiquant la puissance du coup11 _etiquette = new TextField ();12 _etiquette.autoSize = TextFieldAutoSize.LEFT;13 _etiquette.embedFonts = true;14 _etiquette.selectable = false;15 _etiquette.defaultTextFormat = new TextFormat('arial', 22,

0xffffff , true);16 _etiquette.filters = [new GlowFilter(0x000000 , 0.5, 2, 2, 2

, 1), new DropShadowFilter(12, 45, 0, 0.3, 6, 6, 1, 2)];17 addChild(_etiquette);18 }

Dessin de la queue de billard

Surprise ! Nous redéfinissons encore la méthode _dessiner pour le dessin de notrequeue de billard ! L’étiquette indiquant la puissance du coup ne sera pas modifiée ici,mais plutôt dans une autre méthode. En effet, il est inutile (voire non-recommandé)de lier les deux opérations : la queue serait alors redessinée à chaque fois que le joueurbougera la souris pour modifier la puissance du coup. Nous nous contenterons ici decacher l’étiquette si les indicateurs visuels sont désactivés.

1 override protected function _dessiner ():void2 {3 super._dessiner ();45 // Queue6 _dessin.graphics.clear();7 _dessin.graphics.beginFill(0x000000);8 _dessin.graphics.drawRect(-width , -height * 0.5, width * 0.

4, height);9 _dessin.graphics.beginFill(0x3e2317);

10 _dessin.graphics.drawRect( -width * 0.6, -height * 0.6 * 0.5, width * 0.6, height * 0.6);

1112 // Viseur13 if (_indicateursActifs)14 {15 graphics.clear();16 graphics.lineStyle(3, 0xffffff , 0.5);17 graphics.moveTo(25, 0);18 graphics.lineTo(45, 0);

555

Page 579: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

19 }2021 // Etiquette de puissance22 _etiquette.visible = _indicateursActifs;23 }

Créons donc une autre méthode pour mettre à jour l’étiquette indiquant la puissancedu coup :

1 private function _majEtiquette ():void2 {3 _etiquette.text = Math.round(_puissance * 100) + '%';45 if (rotation < - 90 || rotation > 90)6 {7 _etiquette.rotation = 180;8 _etiquette.x = - _distance;9 _etiquette.y = _etiquette.height;

10 }11 else12 {13 _etiquette.rotation = 0;14 _etiquette.x = - _distance - _etiquette.width;15 _etiquette.y = - _etiquette.height;16 }17 }

Pourquoi distinger ici deux cas de rotation ?

Cela permet d’éviter que l’étiquette soit retournée si l’on tourne la queue dans l’autresens. Lorsque la queue est à gauche de la bille de tir, tout va bien. L’étiquette est affichédans le bon sens pour l’utilisateur (figure 25.27).

Mais si on tourne la queue du côté droit vis-à-vis de la bille, notre étiquette vas ceretrouver à l’envers ! Et ce n’est pas très confortable à lire, comme à la figure 25.28.

Il faut alors inverser l’étiquette si la queue est à droite de la bille de tir, c’est-à-diresi la rotation de la queue est inférieure à -90 degrés ou supérieure à 90 degrés, commeaux figures 25.29 et 25.30.

Nous avons alors un résultat satisfaisant (voir figure 25.31) !

Accesseurs

Enfin, ajoutons quelques accesseurs pour permettre la modification des données de laqueue de billard :

1 /**

556

Page 580: Programmez en Actionscript 3

CRÉATION DES CLASSES

Figure 25.27 – Queue à gauche de la bille de tir

Figure 25.28 – A droite, l’étiquette est à l’envers.

557

Page 581: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

Figure 25.29 – Rotation à 0˚ de la queue

Figure 25.30 – Rotation à 135˚ de la queue

558

Page 582: Programmez en Actionscript 3

CRÉATION DES CLASSES

Figure 25.31 – L’étiquette est dans le bon sens !

2 * Distance du bout de la queue par rapport à la bille de tir.3 */4 public function get distance ():Number5 {6 return _distance;7 }89 public function set distance(value:Number):void

10 {11 _distance = value;1213 // On déplace le dessin de la queue en fonction de la

distance par rapport à la bille de tir14 _dessin.x = -_distance;15 }1617 /**18 * Puissance du tir délivré par la queue.19 */20 public function get puissance ():Number21 {22 return _puissance;23 }2425 public function set puissance(value:Number):void26 {27 _puissance = value;2829 _majEtiquette ();30 }3132 /**33 * Indique si les indicateurs visuels sont visibles ou non.34 */

559

Page 583: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

35 public function get indicateursActifs ():Boolean36 {37 return _indicateursActifs;38 }3940 public function set indicateursActifs(value:Boolean):void41 {42 _indicateursActifs = value;4344 _dessiner ();45 }

Billard

Cette classe est la plus complexe de l’animation : c’est le coeur de notre jeu de billard.

Commençons par écrire les différents attributs de la classe :

1 // Eléments visuels2 private var _table:Table;3 private var _billes:Vector.<Bille >;4 private var _billeDeTir:Bille;5 private var _queue:Queue;6 private var _trous:Vector.<Trou >;78 // Configuration de la queue de billard9 private var _distanceMinimum:Number = 25;

10 private var _distanceMaximum:Number = 250;11 private var _puissanceMinimum:Number = 1;12 private var _puissanceMaximum:Number = 35;13 // Distance de la souris par rapport à la pointe de la queue14 private var _distanceSouris:Number = 200;1516 // Vitesse actuelle de l'animation (1 = vitesse normale)17 private var _vitesseAnimation:Number = 1;1819 // Indicateurs20 private var _simulationEnCours:Boolean = false;21 private var _phaseDeTir:Boolean = false;2223 // Indique si le billard est en train d'être déplacé24 private var _tableDrag:Boolean = false;

Constructeur

Le constructeur de la classe va une fois de plus nous servir à crééer les objets néces-saires au bon fonctionnement de l’objet courant (ici, le jeu de billard).

Commençons par ajouter la table de billard :

560

Page 584: Programmez en Actionscript 3

CRÉATION DES CLASSES

1 // Table2 _table = new Table ();3 // Taille standard4 _table.width = 2.34 * Unite.METRE;5 _table.height = 1.17 * Unite.METRE;6 addChild(_table);

Puis, continuons sur les six trous de la table :1 // Trous2 _trous = new Vector.<Trou >();3 // Marge entre les trous et les bords de la table4 var margeTrou:Number = 0.015 * Unite.METRE;5 var i:int;6 for (i = 0; i < 6; i++)7 {8 var trou:Trou = new Trou(i + 1);9 trou.taille = 0.069 * Unite.METRE;

10 // Lignes de trois colonnes de trous11 trou.x = (i % 3) * (_table.width + 2 * margeTrou) / 2 -

margeTrou;12 trou.y = Math.floor(i / 3) * (_table.height + 2 * margeTrou

) - margeTrou;13 _table.addChild(trou);14 _trous.push(trou);15 }

Attaquons-nous maintenant aux billes. D’abord, spécifions les différents couleurs pos-sibles :1 // Billes2 // Couleurs réglementaires3 var couleurs:Array = [4 0xffffff , // Bille blanche5 0xfac92e ,6 0x1744c1 ,7 0xee372e ,8 0x271d53 ,9 0xff8d59 ,

10 0x189e66 ,11 0x931422 ,12 0x000000 , // Bille 813 0xf7af1d ,14 0x2059e8 ,15 0xde291d ,16 0x2f2665 ,17 0xfb8351 ,18 0x0d955c ,19 0x92121d20 ];

Puis, créons les 16 billes dont nous avons besoin pour notre billard :

561

Page 585: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

1 // Liste des billes2 _billes = new Vector.<Bille >();3 // Création des 15 billes4 for (i = 0; i <= 15; i++)5 {6 var bille:Bille = new Bille(couleurs[i], i, 0.05 * Unite.

METRE , 172 * Unite.GRAMME);7 _table.addChild(bille);8 _billes.push(bille);9

10 if (i == 0)11 {12 _billeDeTir = bille;13 }14 }

Etant donné que nous allons déplacer la première bille (bille de tir) lors de la phase1 du déroulement du jeu, il est bon de la remettre au premier plan afin qu’elle ne seretrouve pas affichée derrière les autres billes :

1 // On remet la bille de tir au premier plan2 _table.setChildIndex(_billeDeTir , _table.numChildren - 1);

Occupons-nous maintenant de la queue de billard :

1 // Queue2 _queue = new Queue ();3 _queue.width = 1.5 * Unite.METRE;4 _queue.height = 0.025 * Unite.METRE;5 _table.addChild(_queue);

Puis, ajoutons un écouteur d’événement qui nous permet d’attendre que l’objet soitajouté à la scène principale afin d’avoir accès à la propriété stage :

1 // Lorsque le billard est ajouté à la scène , nous ajoutons lesautres écouteurs d'événements

2 addEventListener(Event.ADDED_TO_STAGE , onAddedToStage);

L’écouteur de cet événement ajoute des écouteurs pour gérer la souris :

1 private function onAddedToStage(event:Event):void2 {3 // Déplacement de la table de billard4 stage.addEventListener(MouseEvent.RIGHT_MOUSE_DOWN ,

onMouseRightDown);5 stage.addEventListener(MouseEvent.RIGHT_MOUSE_UP ,

onMouseRightUp);67 // Ralenti8 stage.addEventListener(MouseEvent.MIDDLE_CLICK ,

onMiddleClick);9 }

562

Page 586: Programmez en Actionscript 3

CRÉATION DES CLASSES

Ainsi, lorsque le bouton droit de la souris est enfoncé, il faut déplacer le billard. Parcontre, il faut le faire uniquement si l’on n’est pas en train de placer la bille de tir,c’est-à-dire si on est en phase de tir ou que la simulation est en cours.

1 /* Déplacement de la table de billard */23 private function onMouseRightDown(event:MouseEvent):void4 {5 if (_phaseDeTir || _simulationEnCours)6 {7 _table.startDrag ();8 _tableDrag = true;9 }

10 }

Une fois relaché, on arrête le déplacement de la table de billard si elle est en cours dedéplacement :

1 private function onMouseRightUp(event:MouseEvent):void2 {3 if (_tableDrag)4 {5 _table.stopDrag ();6 }7 }

Enfin, si on appuie sur la molette de la souris, on active ou désactive le ralenti (quin’était pas demandé) :

1 /* Ralenti */23 private function onMiddleClick(event:MouseEvent):void4 {5 ralenti ();6 }

Avec une méthode publique permettant d’activer ou désactiver le ralenti en modifiantl’attribut _vitesseAnimation :

1 /**2 * Active ou désactive le ralenti.3 */4 public function ralenti ():void5 {6 if (_vitesseAnimation != 0.15)7 {8 _vitesseAnimation = 0.15; // Ralenti à 15% !9 }

10 else11 {12 _vitesseAnimation = 1;13 }

563

Page 587: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

14 }

Phase 1 : Préparation

Il est tant d’implémenter les quatres phases du déroulement d’une partie. Commençonspar la première : la préparation de la partie. Dans un premier temps, il faut vider lestrous au cas où des billes seraient tombées dedans. Ensuite, nous plaçons les billes pourformer le triangle initial :

1 private function _placerBilles ():void2 {3 // Vider les trous4 for each(var trou:Trou in _trous)5 {6 trou.enleverBilles ();7 }89 // Triangle

10 var bille:Bille;11 var l:int = _billes.length;12 var triangleLignes:int = 1;13 var triangleLigne:int = 0;14 var triangleX:Number = _table.width * 0.75 - _billeDeTir.

taille * 2.5;15 var order:Array = [0, 9, 7, 12 , 15, 8, 1, 6, 10, 3, 14 , 11 ,

2, 13, 4, 5];16 for (var i:int = 0; i < l; i++)17 {18 bille = _billes[order[i]];1920 // Initialisation des billes21 bille.alpha = 1;22 bille.scaleX = 1;23 bille.scaleY = 1;24 bille.velocite.x = 0;25 bille.velocite.y = 0;2627 bille.horsJeu = false;28 if (i > 0)29 {30 bille.x = triangleX;31 bille.y = _table.height * 0.5 + (triangleLigne -

triangleLignes * 0.5 ) * _billeDeTir.taille +_billeDeTir.taille * 0.5;

3233 triangleLigne ++;34 if (triangleLigne == triangleLignes)35 {36 triangleLigne = 0;

564

Page 588: Programmez en Actionscript 3

CRÉATION DES CLASSES

37 triangleLignes ++;38 triangleX += _billeDeTir.taille;39 }40 }41 }42 }

Phase 2 : Placement de la bille de tir

Pour la phase suivante, il faut laisser au choix du joueur le placement de la bille de tir,mais uniquement dans la zone de jeu. Pour cela, nous utilisons la méthode startDragqui nous permet de coller la bille de tir à la souris tout en la restreignant à une zonebien précise :

1 private function _lancerPhaseBilleDeTir ():void2 {3 _arreterPhaseDeTir ();4 _arreterPhaseSimulation ();56 _table.stopDrag ();7 _tableDrag = false;89 // On annule d'éventuelles animations sur les propriétés de

la bille de tir pour éviter les conflits avec le "drag"10 TweenMax.killTweensOf(_billeDeTir);1112 // Réinitialisation de la bille13 _billeDeTir.horsJeu = false;14 _billeDeTir.scaleX = 1;15 _billeDeTir.scaleY = 1;16 _billeDeTir.velocite.x = 0;17 _billeDeTir.velocite.y = 0;1819 // On fait réapparaître la bille de tir20 TweenMax.to(_billeDeTir , 0.2, { alpha:1 } );2122 // On active le "drag" :23 // Lorsque la souris du joueur va se déplacer , la bille de

tir se positionnera en dessous , dans les limites de lazone de jeu.

24 _billeDeTir.startDrag(true , new Rectangle(_billeDeTir.taille * 0.5, _billeDeTir.taille * 0.5, _table.width -_billeDeTir.taille , _table.height - _billeDeTir.taille));

2526 addEventListener(MouseEvent.MOUSE_UP ,

onPhaseBilleDeTirClick);27 }

565

Page 589: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

La zone de jeu est définie par la taille de la table.

Lorsque l’utilisateur effectue un clic de souris, nous passons à la phase suivante (phasede tir) dans un écouteur d’événement de souris :

1 private function onPhaseBilleDeTirClick(event:MouseEvent):void2 {3 // On empêche la propagation de l'événement pour éviter que

le tir ne se déclenche tout de suite4 event.stopImmediatePropagation ();56 _lancerPhaseDeTir ();7 }

Il faut empêcher l’événement du clic de se propager dans les éléments gra-phiques parents (voir le flux d’événement dans le chapitre sur les événe-ments) : car effectivement, la méthode _lancerPhaseDeTir va ajouter unécouteur sur le même événement MouseEvent.MOUSE_UP, ce qui va le dé-clencher également et tirer sur la bille blanche tout de suite. A l’aide de laméthode stopImmediatePropagation de l’objet event, nous nous assuronsque d’autres écouteurs ne seront pas appellés par la suite.

Enfin, il nous faut une méthode pour terminer la phase de placement de la bille blanche,qui se charge de lâcher la bille et de supprimer l’écouteur de souris que nous avons créépour cette phase :

1 private function _arreterPhaseBilleDeTir ():void2 {3 _billeDeTir.stopDrag ();45 removeEventListener(MouseEvent.MOUSE_UP ,

onPhaseBilleDeTirClick);6 }

Phase 3 : Tir avec la queue de billard

Nous arrivons à cette phase de jeu après la phase deux ou si les billes ne bougent plus.

Créons une méthode pour lancer la phase :

1 private function _lancerPhaseDeTir ():void2 {3 _arreterPhaseBilleDeTir ();4 _arreterPhaseSimulation ();56 // Gestion de la souris

566

Page 590: Programmez en Actionscript 3

CRÉATION DES CLASSES

7 stage.addEventListener(MouseEvent.MOUSE_MOVE ,onPhaseDeTirMouseMove);

8 stage.addEventListener(MouseEvent.MOUSE_UP ,onPhaseDeTirClick);

910 _phaseDeTir = true;11 _queue.indicateursActifs = true;12 _queue.visible = true;1314 _deplacerQueue ();15 }

Dans un premier temps, nous arrêtons les autres phases, puis nous ajoutons les écou-teurs dont nous avons besoin. Enfin, nous préparons la queue de billard à être affichée.

Voici les fonctions écouteurs que nous allons utiliser pour cette phase de jeu :

1 private function onPhaseDeTirMouseMove(event:MouseEvent):void2 {3 _deplacerQueue ();4 }56 private function onPhaseDeTirClick(event:MouseEvent):void7 {8 _tirer ();9 }

Lorsque l’utilisateur déplace la souris, il faut mettre à jour la queue de billard, et,lorsque qu’il clique, il faut tirer sur la bille blanche.

Comme pour la deuxième phase, il nous faut une méthode pour arrêter la phase de tirqui se charge de supprimer les écouteurs d’événements :

1 private function _arreterPhaseDeTir ():void2 {3 // Fin de la gestion de la souris4 stage.removeEventListener(MouseEvent.MOUSE_MOVE ,

onPhaseDeTirMouseMove);5 stage.removeEventListener(MouseEvent.MOUSE_UP ,

onPhaseDeTirClick);67 _phaseDeTir = false;8 _queue.visible = false;9 }

Lorsque nous bougeons la souris, la queue doit tourner autour de la bille blanche etchanger la puissance du tir en fonction de la distance entre la souris et la bille. Pourcela, nous créons cette méthode :

1 private function _deplacerQueue ():void2 {3 // On centre la queue sur la bille de tir

567

Page 591: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

4 _queue.x = _billeDeTir.x;5 _queue.y = _billeDeTir.y;67 // Distance entre la souris et la bille de tir8 var distance:Number = Outils.distanceNombres(_table.mouseX ,

_table.mouseY , _billeDeTir.x, _billeDeTir.y) -_distanceSouris;

9 if (distance > _distanceMaximum)10 {11 distance = _distanceMaximum;12 }13 else if (distance < _distanceMinimum)14 {15 distance = _distanceMinimum;16 }1718 // Angle entre la souris et la bille de tir (radians)19 var angle:Number = Outils.angleNombres(_table.mouseX ,

_table.mouseY , _billeDeTir.x, _billeDeTir.y);2021 // Aplication des modifications sur la queue de billard22 _queue.rotation = angle / Math.PI * 180;23 _queue.distance = distance - 10;24 _queue.puissance = (distance - _distanceMinimum) / (

_distanceMaximum - _distanceMinimum);25 }

Il est intéressant de limiter la puissance du coup pour éviter que le tir soittrop fort, en limitant la distance entre la queue et la bille de tir à l’aide desattributs _distanceMinimum et _distanceMaximum.

Décortiquons un peu la méthode : nous commençons par placer la queue sur la billede tir, puis nous calculons la distance entre la pointe de la queue et la bille (distancedéterminée par la position de la souris de l’utilisateur). Nous vérifions que cette distanceest bien dans les limites autorisées, puis nous calculons l’angle entre la souris et la billede tir pour faire tourner la queue de billard dans la direction appropriée. Enfin, nousmettons à jour les attributs de la queue de billard avec les résultats de nos calculs.

Enfin, la dernière méthode de cette phase de jeu sert à tirer dans la bille blanche :1 private function _tirer ():void2 {3 // On arrête la phase de tir4 _arreterPhaseDeTir ();5 _queue.indicateursActifs = false;6 _queue.visible = true;78 // Distance entre la souris et la bille de tir9 var distance:Number = Outils.distanceNombres(_table.mouseX ,

_table.mouseY , _billeDeTir.x, _billeDeTir.y) -

568

Page 592: Programmez en Actionscript 3

CRÉATION DES CLASSES

_distanceSouris;10 if (distance > _distanceMaximum)11 {12 distance = _distanceMaximum;13 }14 else if (distance < _distanceMinimum)15 {16 distance = _distanceMinimum;17 }1819 // Angle entre la souris et la bille de tir (radians)20 var angle:Number = Outils.angleNombres(_table.mouseX ,

_table.mouseY , _billeDeTir.x, _billeDeTir.y);21 var module:Number = (distance - _distanceMinimum) / (

_distanceMaximum - _distanceMinimum) * (_puissanceMaximum - _puissanceMinimum) +_puissanceMinimum;

2223 // Coup sur la bille24 _billeDeTir.velocite.angle = angle;25 _billeDeTir.velocite.module = module;2627 // Animation de la queue28 TweenMax.to(_queue , 0.1, { distance:10, onComplete:

_lancerPhaseSimulation } );29 }

On arrête d’abord la phase actuelle (phase de tir), puis on calcule la puissance et l’angledu coup qui est porté. Ensuite, on modifie le vecteur de déplacement de la bille blanchepour la faire partir dans la direction et la vitesse souhaitées. Enfin, on anime rapidementla queue de billard pour donner la sensation qu’elle tape dans la bille blanche (ne pasoublier de la rendre visible, car la méthode _arreterPhaseDeTir la cache).

Phase 4 : Simulation des billes

La dernière phase de jeu est la simulation des billes, où l’on doit les déplacer tout engérant les différentes collisions des billes avec les autres billes, les trous et les bords dela zone de jeu.

Encore une fois, créons une méthode pour démarrer la phase de jeu :

1 private function _lancerPhaseSimulation ():void2 {3 _table.stopDrag ();4 _arreterPhaseBilleDeTir ();5 _arreterPhaseDeTir ();67 addEventListener(Event.ENTER_FRAME ,

onPhaseSimulationEnterFrame);8

569

Page 593: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

9 _simulationEnCours = true;10 }

On ajoute un écouteur qui va se déclencher pour chaque nouvelle image (par exemple,30 fois par seconde) et appeler cette méthode :

1 private function onPhaseSimulationEnterFrame(event:Event):void2 {3 _deplacerBilles ();4 }

Ajoutons tout de suite la méthode pour stopper cette phase de jeu (qui supprimel’écouteur d’événement) :

1 private function _arreterPhaseSimulation ():void2 {3 removeEventListener(Event.ENTER_FRAME ,

onPhaseSimulationEnterFrame);45 _simulationEnCours = false;6 }

A chaque nouvelle image, il faut donc déplacer toutes les billes encore en jeu en fonctionde leur vecteur vitesse et tester toutes les collisions possibles avec les autres billes, lestrous et les bords de la table. Créons une méthode pour gérer tout cela :

1 private function _deplacerBilles ():void2 {3 var toutesLesBillesSontImmobiles:Boolean = true;45 // Détection des collisions entre les billes6 var l:int = _billes.length;7 var bille1:Bille , bille2:Bille;8 for (var i:int = 0; i < l; i++)9 {

10 bille1 = _billes[i];1112 // Si la bille courante est hors -jeu , on passe à la

suivante13 if (bille1.horsJeu)14 {15 continue;16 }1718 // Si la bille courante se déplace19 if (bille1.velocite.module > 0)20 {21 toutesLesBillesSontImmobiles = false;22 }2324 // Tests des collisions de la bille courante avec les

autres billes

570

Page 594: Programmez en Actionscript 3

CRÉATION DES CLASSES

25 for (var j:int = i + 1; j < l; j++)26 {27 bille2 = _billes[j];2829 // Bille hors -jeu : on passe à la suivante30 if (bille2.horsJeu)31 {32 continue;33 }3435 // Test de collition36 bille1.testerCollision(bille2);37 }3839 // Déplacement de la bille courante40 _deplacerBille(bille1);41 }4243 // Toutes les billes sont immobiles et la bille de tir n'

est pas dans un trou , il faut relancer la phase de tir44 if (toutesLesBillesSontImmobiles)45 {46 if (_billeDeTir.horsJeu)47 {48 setTimeout(_lancerPhaseBilleDeTir , 400); // Laisse

du temps pour l'animation de chute de la billedans le trou

49 }50 else51 {52 _lancerPhaseDeTir ();53 }54 }55 }

A l’aide du booléen toutesLesBillesSontImmobiles, nous déterminons si les billes nebougent plus : il faut alors soit retourner à la phase 2 (placement de la bille blanche)si la bille blanche est tombée dans un trou, soit retourner à la phase 3 (phase de tir)pour taper à nouveau dans la bille blanche.

Pour déplacer chaque bille, j’ai créé une autre méthode pour séparer un petit peu lecode :

1 private function _deplacerBille(bille:Bille):void2 {3 // Mouvement de la bille (avec multiplicateur pour le

ralenti)4 bille.deplacer(_vitesseAnimation);56 // Détection des collisions de la bille avec les trous de

la table de billard

571

Page 595: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

7 _detecterCollisionTrou(bille);89 // Détextion des collisions de la bille avec les bords de

la table10 if (!bille.horsJeu)11 {12 _table.testerCollision(bille);13 }14 }

Comme nous pouvons le voir, elle se charge de déplacer la bille d’un cran, puis teste lescollisions entre la bille et les trous. Si la bille n’est pas tombée dans un trou, on testealors les collisions entre la bille et les bords de la table.

La gestion des collisions avec les trous est implémentée dans une autre méthode (encoredans une optique de séparation du code) :

1 private function _detecterCollisionTrou(bille:Bille):void2 {3 // On teste la collision de la bille avec chaque trou4 for each(var trou:Trou in _trous)5 {6 if (trou.testerCollision(bille))7 {8 // La bille est sortie -> hors -jeu9 bille.horsJeu = true;

1011 // Paramètres de l'animation12 var params:Object = { x: trou.x, y: trou.y, scaleX:

0.7, scaleY:0.7, alpha:0 };1314 if (bille != _billeDeTir)15 {16 // Si la bille n'est pas la bille de tir , on l'

ajoute à la réserve du trou à la fin de l'animation

17 params.onComplete = trou.ajouterBille;18 params.onCompleteParams = [bille];19 }2021 // Animation de chute dans le trou22 TweenMax.to(bille , 0.4, params);23 }24 }25 }

Pour chaque trou, on teste s’il y a collision avec la bille. Le cas échéant, la bille estmise hors jeu et est animée pour donner l’impression qu’elle chute dans le trou.

572

Page 596: Programmez en Actionscript 3

CRÉATION DES CLASSES

Nouvelle partie

Pour lancer une nouvelle partie, créons une méthode publique nouvellePartie qui secharge d’arrêter les différentes phases de jeu et relance le jeu de billard :

1 /**2 * Remet le billard à zéro et lance une nouvelle partie.3 */4 public function nouvellePartie ():void5 {6 // Arrêt de l'éventuelle partie ne cours7 _arreterPhaseBilleDeTir ();8 _arreterPhaseSimulation ();9 _arreterPhaseDeTir ();

1011 // Triangle des billes12 _placerBilles ();1314 // Bille de tir15 _lancerPhaseBilleDeTir ();16 }

Accesseurs

Enfin, ajoutons deux définitions des accesseurs de taille du billard afin de ne prendreen compte que la taille de la table (sans la queue de billard). Cela sera notammentutile pour centrer le billard au milieu de l’écran.

1 /* On remplace le fonctionnement habituel des accesseurs de lataille du billard pour ne prendre en compte que la taille dela table. */

23 override public function get width ():Number4 {5 return _table.width;6 }78 override public function get height ():Number9 {

10 return _table.height;11 }

Main

Dans notre classe principale, nous allons gérer la création du jeu de billard et l’affichagede la texture de fond de notre application.

573

Page 597: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

Préparatifs

Commençons par configurer la scène pour qu’elle soit alignée en haut à gauche, sanszoom automatique, tout en initialisant nos polices de caractères embarquées :

1 // Configuration de la scène2 stage.align = StageAlign.TOP_LEFT;3 stage.scaleMode = StageScaleMode.NO_SCALE;45 // Polices embarquées6 EmbedFonts.init();

Voici alors le code minimal notre classe Main :

1 package2 {3 import flash.display.Sprite;4 import flash.display.StageAlign;5 import flash.display.StageDisplayState;6 import flash.display.StageQuality;7 import flash.display.StageScaleMode;8 import flash.events.Event;9

10 /**11 * Classe principale12 * @author Guillaume CHAU13 */14 public class Main extends Sprite15 {16 public function Main():void17 {18 if (stage) init();19 else addEventListener(Event.ADDED_TO_STAGE , init);20 }2122 private function init(e:Event = null):void23 {24 removeEventListener(Event.ADDED_TO_STAGE , init);25 // entry point2627 // Configuration de la scène28 stage.align = StageAlign.TOP_LEFT;29 stage.scaleMode = StageScaleMode.NO_SCALE;30 stage.quality = StageQuality.BEST;3132 // Polices embarquées33 EmbedFonts.init();3435 // Commencer à coder ici36 }37 }

574

Page 598: Programmez en Actionscript 3

CRÉATION DES CLASSES

3839 }

Création de la texture de fond

Attaquons avec la texture tapissant le fond de l’application. Tout d’abord, embarquonsl’image dont nous avons besoin et déclarons les attributs nécessaires dans la classe (endehors de la méthode init) :

1 [Embed(source = "../lib/img/fond.png")]2 private var Fond:Class;34 private var _fond:Sprite;5 private var _texture:BitmapData;

Puis, créons le dessin de fond et la texture :

1 // Fond2 _fond = new Sprite ();3 addChild(_fond);45 // Texture du fond6 var bmp:Bitmap = new Fond();7 _texture = bmp.bitmapData;

J’utilise un objet de classe Sprite et non de classe Shape pour qu’il puisserecevoir les clics de souris afin que nous puissions écouter les événements desouris partout sur la scène principale (par exemple, pour déplacer la tableavec le clic droit).

Création du billard

Puis, occupons-nous du billard, avec en premier l’ajout d’un attribut dans la classe :

1 private var _billard:Billard;

Ensuite, créons le billard, ajoutons-le à la scène et lançons une nouvelle partie auto-matiquement :

1 // Billard2 _billard = new Billard ();3 addChild(_billard);4 _billard.nouvellePartie ();

575

Page 599: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

Position du billard et dessin de la texture de fond

Une fois nos objets créés, il faut s’occuper de leur position et taille sur la scène. Pourcela, ajoutons cette méthode :

1 private function _rafraichir ():void2 {3 // Fond4 _fond.graphics.clear ();5 _fond.graphics.beginBitmapFill(_texture);6 _fond.graphics.drawRect(0, 0, stage.stageWidth , stage.

stageHeight);78 // Billard9 _billard.x = (stage.stageWidth - _billard.width) * 0.5;

10 _billard.y = (stage.stageHeight - _billard.height) * 0.5;11 }

La méthode se charge de dessiner le fond de l’application avec un remplissage de l’imagede la texture grâce à la méthode beginBitmapFill de la classe Graphics (voir lechapitre sur le dessin avec l’Actionscript 3). Elle centre également le billard au milieude la scène pour des raisons de confort de l’utilisateur.

Cette méthode rafraichir doit être appelée une fois au lancement de notre applicationafin de mettre le fond et le billard en place, puis à chaque fois que la fenêtre del’application est redimensionnée.

Ainsi, dans le code principal (méthode init), ajoutons un premier appel à cette fonc-tion :

1 // On met à jour la position du billard et la texture de fondpour la première fois

2 _rafraichir ();

Gestion du redimensionnement de l’application

Comme nous l’avons vu, il faut écouter le changement de taille de la scène de l’appli-cation, afin de redessiner le fond texturé et de recentrer le billard. Créons la fonctionqui écoutera l’événement de redimensionnement :

1 private function onStageResize(event:Event):void2 {3 _rafraichir ();4 }

Puis, ajoutons dans le code principal l’écouteur à la scène principale pour se déclencherau redimensionnement (événement Event.RESIZE) :

1 // Lorsque la scène est redimensionnée2 stage.addEventListener(Event.RESIZE , onStageResize);

576

Page 600: Programmez en Actionscript 3

CONCLUSION ET AMÉLIORATIONS POSSIBLES

Maintenant, si l’utilisateur met l’application en plein écran par exemple, la texture defond recouvrera correctement la surface de l’écran et le billard sera bien centré.

Raccourci clavier

Enfin, ajoutons un raccourci clavier pour lancer une nouvelle partie à tout moment avecla touche espace. Ajoutons un écouteur d’événement clavier sur la scène principale :

1 // Gestion du clavier2 stage.addEventListener(KeyboardEvent.KEY_UP , onKeyUp);

Puis, écrivons cette fonction écouteur qui lance une nouvelle partie si le code de latouche relâchée par l’utilisateur correspond au code de la touche espace :

1 private function onKeyUp(event:KeyboardEvent):void2 {3 if (event.keyCode == Keyboard.SPACE)4 {5 _billard.nouvellePartie ();6 }7 }

Et voilà ! Nous avons fait le tour de toutes les classes du projet : vous avez pu comparervotre code avec le mien, si vous avez des différences, ne vous inquiétez pas, c’est toutà fait normal ! Il n’existe pas une seule solution pour implémenter notre billard.

Conclusion et améliorations possibles

Sources du Billard

J’ai préparé une archive contenant l’ensemble du dossier du projet de Billard afin quevous puissiez le télécharger, l’explorer et le compiler par vous-même. Vous aurez alorsune bonne vision globale de l’architecture de l’application.

B

��

Télécharger le dossier du pro-jetCode web : 865950

Idées d’amélioration

Notre billard américain fonctionne, mais il lui manque sûrement quelques fonctionna-lités pour constituer un jeu complet.

– Afficher un menu : la plupart des jeux disposent d’un menu pour effectuer diversesopérations. Ici, nous pourrions imaginer un menu permettant de lancer une nouvellepartie, afficher les règles du jeu de billard américain, une liste des raccourcis clavieret souris, etc.

577

Page 601: Programmez en Actionscript 3

CHAPITRE 25. TP : JEU DE BILLARD

– Appliquer plus de règles : le billard américain comporte davantage de règles quenous n’avons pas implémentées dans notre jeu. Par exemple, dès qu’un joueur metla bille 8 dans un trou, il perd et la partie s’arrête !

– Améliorer l’interface : il serait intéressant d’afficher plus d’interface pour lesjoueurs comme des compteurs de score, un indicateur de tour, un message indiquantquel joueur doit jouer, etc.

– Afficher le début de la trajectoire potentielle : pour aider le joueur à visersur la table de billard, ce qui n’est pas forcément évident sur un ordinateur, nouspourrions afficher des points blancs représentant la trajectoire possible de la billeblanche après le coup.

– Afficher différentes options : les joueurs aiment bien personnaliser leur jeu enchoisissant parmi plusieurs thèmes visuels par exemple ou en jouant en un tempslimité.

– Proposer du billard français : le billard français dispose de ses propres règles caril n’y a pas de trou dans la table et on ne dispose que de trois billes ! On pourraitalors créer une autre classe BillardFrancais et proposer le choix du type de billardau joueur.

N’hésitez pas à améliorer votre billard car comme je l’ai déjà répété : pratiquer, c’estprogresser !

578

Page 602: Programmez en Actionscript 3

Chapitre 26La gestion des erreurs

Difficulté :

Avant de clôturer cette partie, nous allons aborder un des sujets les plus fâcheux pour unprogrammeur : la gestion des erreurs. Vous verrez que cela pourra s’avérer extrêmementutile lorsque vous travaillerez avec des données externes à l’application. Ce sera notammentle cas si vous êtes amenés à charger du contenu multimédia à l’intérieur de l’applicationou si vous souhaitez échanger des données en réseau. Aussi, essayez d’être particulièrementattentif à ce qui va suivre, ce chapitre est important.

579

Page 603: Programmez en Actionscript 3

CHAPITRE 26. LA GESTION DES ERREURS

Les principes de base

Introduction à la gestion des erreurs

Lorsque nous prononçons le mot « erreurs », il est fréquent de voir des sourcils se froncer.Il s’agit en effet d’un sujet délicat, souvent synonyme de complications. Néanmoins,nous devons en passer par là pour s’assurer qu’un code s’exécute correctement. Ence qui nous concerne, nous pouvons distinguer deux principaux types d’erreurs : leserreurs de compilation et les erreurs d’exécution.

Sans grande surprise, les erreurs de compilation sont des erreurs qui se produisentlors de la compilation. Elles sont généralement facile à déceler puisque que le com-pilateur nous informe de leur existence. Par ailleurs, lors de l’apparition d’une erreurde ce genre, la compilation est stoppée et la génération du fichier SWF n’est pasachevée. Il nous est alors nécessaire de corriger cette erreur afin de pouvoir finaliserla compilation. Ce ne sont pas ces erreurs qui nous intéressent dans ce chapitre, nousallons plutôt nous concentrer sur les erreurs d’exécution.

Les erreurs d’exécution surviennent, comme leur nom l’indique, durant l’exécutiondu code. Contrairement aux erreurs de compilation, les erreurs d’exécution nebloquent pas la compilation d’un programme, mais se produisent lors de l’exécutiond’une instruction ou d’un code erroné. Suivant la complexité du programme, ces erreurspeuvent être difficiles à détecter, et donc à corriger.

La gestion des erreurs consiste alors à ajouter ou modifier du code dans un pro-gramme spécialement conçu pour traiter une ou plusieurs erreurs. Cela revient à détec-ter les éventuelles erreurs d’exécution et à les contourner afin de pouvoir reprendre,si possible, une exécution « normale » du programme. Le cas échéant, il peut êtreintéressant d’en informer tout simplement l’utilisateur.

Les différents types d’erreurs d’exécution

Les erreurs synchrones

Les erreurs d’exécution dites « synchrones » se produisent lors de l’exécution d’uneinstruction renvoyant un résultat immédiat. Nous pouvons également parler d’exceptions.Pour vous donner un exemple, voici un code qui ajoute un objet de type Sprite à laliste d’affichage sans l’avoir instancier au préalable :

1 var objet:Sprite;2 addChild(objet);

Comme vous pouvez le voir, la compilation du code ne pose absolument aucun pro-blème : le fichier SWF est donc bien généré. Toutefois, lors de l’exécution du code,vous allez voir apparaître ceci dans la console de sortie :

[Fault] exception , information=TypeError: Error #2007: Le paramètre child ne doit pas être nul.

580

Page 604: Programmez en Actionscript 3

LES ERREURS SYNCHRONES

Un tel message s’affichera à chaque fois qu’une erreur n’aura pas été traitée ; on ditalors que l’exception n’a pas été interceptée. Ce message permet au développeur decibler l’erreur afin de la réparer ou de la corriger. Comme vous avez peut-être pu leconstater, l’exécution du code s’est stoppée lors de l’apparition de l’erreur. En revanche,ceci n’est valable que dans la version de débogage du Flash Player. En effet, dans laversion commerciale, le Flash Player va tenter de passer outre l’erreur et de continuerl’exécution du code si possible.

Pour en revenir à la gestion des exceptions, rappelez-vous que celles-ci sont généréesdès lors que l’instruction en question est exécutée. Il est alors possible de traiter l’erreurimmédiatement dans le même bloc que l’instruction incriminée. Pour cela, nous verronscomment isoler le code erroné à l’intérieur d’une instruction try...catch afin de réagirtout de suite et de pouvoir reprendre l’exécution de la suite du programme.

Les erreurs asynchrones

Lors d’une opération quelconque, il peut arriver qu’une erreur ne puisse pas être re-tournée immédiatement. Ceci pourrait être le cas, par exemple, lors de la lecture ou del’écriture de données. En effet, l’accès à des données externes à l’application ne se faitpas de façon immédiate. Dans cette situation, une instruction try...catch serait alorsinutile. La réponse aux erreurs liées à ces opérations est donc gérée par événements.

Lorsque la génération d’une erreur n’est pas directe mais différée, l’erreur d’exécutionest dite « asynchrone ». Celle-ci est représentée par la classe ErrorEvent ou l’une deses sous-classes. La réponse à cette dernière se fait grâce à une fonction d’écouteurcomme d’ordinaire.

Les erreurs synchrones

L’intruction throw

Présentation

Avant d’entamer la gestion (ou interception) des exceptions en elle-même, nousallons parler de l’instruction throw. Ce mot-clé, que nous avons déjà vaguement évoqué,sert en réalité à renvoyer une exception. Cette exception se présente alors sous laforme d’une instance de la classe Error ou de l’une de ses sous-classes.

Pour vous donner un exemple, voici comment renvoyer une exception :

1 var monErreur:Error = new Error();2 throw monErreur;

En exécutant ce code, la console de sortie laisse alors apparaître ceci :

[Fault] exception , information=Error

581

Page 605: Programmez en Actionscript 3

CHAPITRE 26. LA GESTION DES ERREURS

Il faut avouer que dans le cas précédent, les informations concernant l’erreur étaientrelativement minces. Pour remédier à ce problème, il est possible de renseigner desinformations sur l’erreur dans le constructeur de la classe Error. Vous pouvez doncrenseigner un message qui s’affichera dans la console de sortie ou qui pourra être utilisélors de l’interception de l’erreur. Un second paramètre id peut également servir àidentifier l’erreur avec précision.

Cet identificateur sert généralement à rechercher les causes de l’erreur, princi-palement si vous n’êtes pas l’auteur de la classe l’ayant générée. Vous pouveznotamment trouver des informations précieuses par une recherche sur Inter-net.

Une erreur bien renseignée serait par exemple :

1 var monErreur:Error = new Error("Le paramètre child ne doit pasêtre nul.", 2007);

Exemple

À présent, nous allons réaliser une petite fonction renvoyant diverses erreurs que nousutiliserons dans la suite avec le bloc try...catch.

Voilà donc la fonction que je vous propose :

1 function testerErreur(objet:Object):void2 {3 if (objet == null)4 throw new TypeError("Le paramètre objet ne doit pas ê

tre nul.", 4000);5 if (objet == stage)6 throw new Error("Le paramètre objet ne doit pas être la

scène principale.", 4001);7 }

En l’analysant, vous constaterez que celle-ci renvoie des exceptions différentes suivantla nature de l’objet passé en paramètre. Cela pourrait correspondre par exemple auxvérifications nécessaires en début d’une méthode quelconque. Vérifions tout de mêmele bon fonctionnement de cette fonction. En premier lieu, passons la scène principaleen paramètre et voyons comment la version de débogage du Flash Player réagit.

L’instruction correspondante est la suivante :

1 testerErreur(stage);

Aucun souci, l’exception non interceptée est bien affichée dans la console :

[Fault] exception , information=Error: Le paramètre objet ne doitpas être la scène principale.

582

Page 606: Programmez en Actionscript 3

LES ERREURS SYNCHRONES

La seconde erreur renvoyée par la fonction définie plus haut, correspond au passage enparamètre d’un objet quelconque non instancié :

1 var monObjet:Object;2 testerErreur(monObjet);

L’erreur est également bien renvoyée et affichée dans la console de sortie :

[Fault] exception , information=TypeError: Le paramètre objet nedoit pas être nul.

L’instruction try...catch

Utilisation basique

Entrons maintenant dans le vif du sujet et découvrons le fonctionnement de l’ins-truction try...catch. Cette instruction permet d’isoler le code pouvant renvoyer uneexception : cela se fait alors à l’intérieur du bloc try. Ce bloc ne peut être utiliséindépendamment du bloc catch qui sert à intercepter les exceptions renvoyées.

1 try2 {3 // Instructions à isolées4 }5 catch(e:Error)6 {7 // Gestion de l'exception8 }

Par exemple, utilisons notre fonction testerErreur() pour comprendre comment l’en-semble try...catch fonctionne. En l’absence d’erreur, seul le bloc try est exécuté.Voyons cependant ce que cela donne lorsqu’une erreur apparaît. Tentons de renvoyerune exception de type Error :

1 try2 {3 testerErreur(stage);4 trace("Aucune exception renvoyée");5 }6 catch(e:Error)7 {8 trace("Exception interceptée : #" + e.errorID);9 }

Le résultat dans la console de sortie est le suivant :

Exception interceptée : #4001

583

Page 607: Programmez en Actionscript 3

CHAPITRE 26. LA GESTION DES ERREURS

Grâce à cet exemple, nous pouvons constater un certain nombre de choses. Toutd’abord, nous voyons que l’exception a bien été interceptée puisque qu’aucun mes-sage d’erreur n’est apparu dans la console de sortie. Ensuite, vous remarquerez quel’exécution du bloc try s’est stoppée lors de l’apparition de l’erreur. Enfin, le bloccatch a été exécuté intégralement et il possible de récupérer des informations

Utilisation avancée

Précédemment, nous avons vu comment mettre en place un bloc try...catch, per-mettant de gérer de façon basique les erreurs synchrones. Toutefois, il est possiblede gérer de manière plus poussée les exceptions renvoyées à l’intérieur du bloc try.D’une part, nous pouvons ajouter plusieurs blocs catch permettant d’identifier plusspécifiquement différents types d’erreurs. Chaque instruction catch est alors vérifiéedans l’ordre et est associée un type d’exception. Seul le premier bloc catch, corres-pondant au type d’exception renvoyée, est exécuté. D’autre part, le mot-clé facultatiffinally permet d’instroduire des instructions supplémentaires, exécutées au terme dela gestion de l’erreur, quel que soit le chemin parcouru à travers les différents blocs tryou catch.

Pour illustrer tout ce qui vient d’être dit, voici un exemple de code contenant un certainnombre de blocs :

1 try2 {3 testerErreur(null);4 }5 catch (e:TypeError)6 {7 trace("Exception interceptée de type TypeError");8 }9 catch(e:Error)

10 {11 trace("Exception interceptée de type Error");12 }13 finally14 {15 trace("Gestion terminée");16 }

Après exécution du code, la console laisse apparaître ceci :

Exception interceptée de type TypeErrorGestion terminée

Comme prévu, les blocs try et finally ont été exécutés et le seul bloc catch associéau type TypeError a été exécuté.

584

Page 608: Programmez en Actionscript 3

LES ERREURS ASYNCHRONES

Dans le cas de blocs catch associés à plusieurs types d’exceptions, ceux-cidoivent être ordonnés du type le plus spécifique au moins spécifique. Ainsi,la classe Error, super-classe de toutes les autres, doit être traitée en dernier.Dans l’exemple précédent, une exception de type ArgumentError aurait étéinterceptée par le dernier bloc catch.

Les erreurs asynchrones

Distribuer un objet ErrorEvent

Nous allons maintenant nous intéresser aux erreurs asynchrones et à leur gestion.Comme je vous l’ai introduit plus tôt, ce type d’erreurs est représenté par des événe-ments héritant de la classe ErrorEvent. Pour générer une erreur asynchrone, nouspouvons donc nous servir de la méthode dispatchEvent() de la classe EventDispatcher.

Pour la suite, je vous propose donc de renvoyer des erreurs via la fonction suivante :

1 function testerErreur(objet:Object):void2 {3 if (objet == null)4 dispatchEvent(new ErrorEvent(ErrorEvent.ERROR));5 }

Ensuite, voici comment générer ladite erreur :

1 testerErreur(null);

Sans gestion directe de l’erreur, la version de débogage du Flash Player arrête l’exé-cution du code et renvoie l’erreur à l’intérieur de la console de sortie. Voilà le messageaffiché :

Error #2044: error non pris en charge : text=

Bien évidemment, il est préférable d’étendre la classe ErrorEvent afin depersonnaliser l’erreur à son utilisation. Par exemple, la classe IOErrorEventest spécifique aux erreurs générées par l’interaction avec des données externesau programme.

Gérer des événements d’erreurs

Aussi surprenant que cela puisse paraître, vous n’allez rien apprendre ici. Effective-ment, la gestion des événements est strictement identique quel que soit le typed’événements. Seul la classe d’événement devra être ajustée pour pouvoir répondreaux erreurs asynchrones.

585

Page 609: Programmez en Actionscript 3

CHAPITRE 26. LA GESTION DES ERREURS

Nous pouvons donc très facilement définir une fonction de rappel pour un objet detype ErrorEvent et enregistrer l’écouteur auprès de l’objet courant. D’ailleurs en voicil’écriture :

1 function traiterErreur(error:ErrorEvent):void2 {3 trace("Erreur traitée");4 }5 addEventListener(ErrorEvent.ERROR , traiterErreur);

Testons la gestion de l’erreur comme tout à l’heure :

1 testerErreur(null);

Aucune surprise, la fonction d’écouteur est exécutée lors de l’apparition de l’événement :

Erreur traitée

Bien comprendre les deux approches

Une classe utilisant les deux approches

Précédemment, nous avons vu comment gérer des erreurs d’exécution, qu’ellessoient synchrones ou asynchrones. Cependant, il est fort probable que certainsd’entre vous n’arrivent pas encore à bien distinguer les différences d’utilisation quiexistent entre les deux types d’erreurs. Je vous propose ici une classe permettant d’illus-trer ceci.

Présentation

Dans un premier temps, je vous laisse découvrir et vous familiariser avec le code decette classe donné ci-dessous :

1 package2 {3 import flash.display.DisplayObject;4 import flash.events.ErrorEvent;5 import flash.events.Event;67 public class Animation8 {9 private var _objet:DisplayObject;

10 private var _vars:Object;1112 public function Animation(objet:DisplayObject = null)13 {14 _objet = objet;

586

Page 610: Programmez en Actionscript 3

BIEN COMPRENDRE LES DEUX APPROCHES

15 _vars = null;16 }1718 public function incrementer(vars:Object):void19 {20 if (_objet == null) {21 throw new TypeError("Objet nul");22 }else {23 _vars = vars;24 _objet.addEventListener(Event.ENTER_FRAME ,

animer);25 }26 }2728 private function animer(event:Event):void29 {30 for (var p:String in _vars) {31 try {32 _objet[p]++;33 if (_objet[p] >= _vars[p]) {34 _objet.removeEventListener(Event.

ENTER_FRAME , animer);35 }36 }catch (e:Error) {37 _objet.dispatchEvent(new ErrorEvent("

AnimErrorEvent"));38 }39 }40 }4142 }4344 }

Fonctionnement

Rassurez-vous, si vous n’avez pas entièrement cerné le fonctionnement de la classeAnimation, c’est normal ! C’est pourquoi, je vous propose maintenant quelques ex-plications. Tout d’abord, et j’espère que vous l’aurez compris, cette classe va nouspermettre d’animer un objet de type DisplayObject. Pour être plus précis, la mé-thode incrementer() va servir à lancer une animation visant à augmenter la valeur decertaines des propriétés de l’objet d’affichage jusqu’à une certaine valeur. Les propriétésà prendre en compte doivent être renseignées à travers le paramètre vars.

Revenons sur la définition de la méthode incrementer() :

1 public function incrementer(vars:Object):void2 {3 if (_objet == null) {

587

Page 611: Programmez en Actionscript 3

CHAPITRE 26. LA GESTION DES ERREURS

4 // Résultat immédiat permettant de générer une erreursynchrone

5 throw new TypeError("Objet nul");6 }else {7 _vars = vars;8 _objet.addEventListener(Event.ENTER_FRAME , animer);9 }

10 }

Nous pouvons constater qu’un test est réalisé afin de vérifier que l’élément _objetest bien instancié, et donc différent de la valeur null. Si ce n’est pas le cas, nousne pouvons pas démarrer l’animation et choisissons de renvoyer une exception. Danscette situation, l’erreur est détectée immédiatement et est bien de type synchrone.Dans la classe parente, une instruction try...catch permettra de gérer l’erreur. Siaucune erreur n’est détectée, l’animation peut être lancée en enregistrant un écouteursur l’événement Event.ENTER_FRAME.

Je vous invite à présent à tester le bon fonctionnement de la classe Animation. Essayonspar exemple d’animer la position d’un objet jusqu’à la position (100,100) :

1 var animation:Animation = new Animation(unObjet);2 animation.incrementer( { x: 100 , y:100 } );

Nous voyons ici que le programme ne pose aucun problème lors de l’exécution.

Vous remarquerez le passage de la valeur null en paramètre de la méthodeincrementer() génère bien une exception.

Penchons-nous maintenant sur l’animation en elle-même, traitée à l’intérieur de lafonction de rappel animer(). Voici le contenu de cette méthode :

1 private function animer(event:Event):void2 {3 for (var p:String in _vars) {4 try {5 _objet[p]++;6 if (_objet[p] >= _vars[p]) {7 _objet.removeEventListener(Event.ENTER_FRAME ,

animer);8 }9 }catch (e:Error) {

10 _objet.dispatchEvent(new ErrorEvent("AnimErrorEvent"));

11 }12 }13 }

Concernant le fonctionnement, la boucle for...in permet de récupérer chacune despropriétés de l’objet _vars sous forme de chaînes de caractères. À l’aide de ces

588

Page 612: Programmez en Actionscript 3

BIEN COMPRENDRE LES DEUX APPROCHES

dernières, nous avons alors accès aux propriétés correspondantes de l’objet d’affichageafin de pouvoir les incrémenter. Toutefois, il pourrait arriver que les propriétés ren-seignées ne soient pas de type numérique ou n’existent tout simplement pas. Il seraitalors avisé de renvoyer une erreur informant l’utilisateur qu’il tente d’accéder à unepropriété inexistante ou ne pouvant être incrémentée.

Pour réaliser ceci, commençons par isoler le code d’accès à la propriété en question.En effet, c’est cette instruction qui pourrait renvoyer une erreur et qui permettra dedéterminer si une erreur doit être renvoyée. Si l’erreur est avérée, celle-ci doit êtrerenvoyée à l’utilisateur sous forme d’erreur asynchrone.

Il s’agit bien d’une exception qui est renvoyée en tant qu’erreur asynchroneà la classe de niveau supérieur. En effet, si cette erreur est synchrone àl’intérieur de la méthode animer(), celle-ci est néanmoins asynchrone parrapport à l’appel de la méthode incrementer() réalisée par l’utilisateur.Dites-vous bien qu’entre l’appel de cette dernière et l’apparition de l’erreur, ils’est écoulé un certain temps puisque nous sommes dans la fonction d’écou-teur de l’événement Event.ENTER_FRAME.

Prenons l’exemple suivant afin de provoquer l’apparition d’une erreur :

1 var animation:Animation = new Animation(objet);2 animation.incrementer( { a:100 , b:100 } );

L’apparition de l’erreur asynchrone a bien lieu :

Error #2044: AnimErrorEvent non pris en charge : text=

Vous remarquerez qu’en diminuant la cadence d’animation du projet, il estpossible de percevoir très nettement le retard de génération de l’erreur asyn-chrone. Essayez par exemple de donner la valeur 1 à la propriété frameRatede l’objet stage. Vous verrez alors l’erreur apparaître au bout d’une secondeseulement dans la console de sortie.

Intérêts des erreurs

Les erreurs d’exécution ont principalement deux utilités. D’une part, une erreur peutservir à informer le programmeur ou utilisateur d’une classe qu’il en fait un usageerroné. C’est notamment le cas lors de la conception de classes abstraites, commenous l’avons vu, ou encore lorsque l’on souhaite avertir que l’un des paramètres d’uneméthode n’est pas valide. Dans ce cas, le programmeur va revoir presque systémati-quement son code afin de réparer l’erreur en question. D’autre part, l’erreur peut êtrepersistante et non réparable par le programmeur. Ce dernier peut alors contournerle problème afin de pouvoir poursuivre au mieux l’exécution du programme. C’est legenre de situation que vous pourrez rencontrer lorsque vous tenterez d’accéder à desdonnées externes à l’application.

589

Page 613: Programmez en Actionscript 3

CHAPITRE 26. LA GESTION DES ERREURS

Dans tous les cas, la meilleure chose à faire est de ne pas traiter l’erreur vous-mêmes,mais de laisser la possibilité à l’utilisateur de la classe de gérer les erreurs comme ill’entend.

En résumé– La gestion des erreurs consiste à ajouter du code spécifique au traitement deserreurs d’exécution.

– Les erreurs synchrones sont renvoyées immédiatement lors de l’exécution de l’ins-truction erronée.

– Les erreurs asynchrones correspondent aux erreurs ne pouvant pas être généréesdans l’immédiat.

– L’instruction try...catch permet d’isoler un code erroné renvoyant une erreursynchrone ou exception.

– Une erreur asynchrone est représentée par la classe ErrorEvent ou une de sessous-classes et peut être gérée comme n’importe quel type d’événements.

590

Page 614: Programmez en Actionscript 3

Cinquième partie

Annexes

591

Page 615: Programmez en Actionscript 3
Page 616: Programmez en Actionscript 3

Chapitre 27Bonnes pratiques

Difficulté :

Pour clôturer ce cours, je vous propose un petit chapitre d’annexe où nous allons parler de« bonnes pratiques ». Grâce à ce chapitre, vous pourrez prendre de bonnes habitudes dèsmaintenant. Ce n’est pas après cinq ans de programmation qu’il faudra commencer à sepréoccuper de coder et documenter proprement vos projets. Dans un premier temps, noustraiterons donc de la gestion de la mémoire dans Flash, puis nous enchaînerons sur lescommentaires de documentation et la documentation avec ASDoc.

593

Page 617: Programmez en Actionscript 3

CHAPITRE 27. BONNES PRATIQUES

La mémoire dans Flash

Flash et la mémoire vive

Tout d’abord, vous devez savoir que tout programme qui se lance doit d’abord secharger en mémoire, et éventuellement charger d’autres fichiers (comme des images).Je parle bien entendu de la mémoire vive de votre ordinateur où sont chargés tousles fichiers nécessaires au fonctionnement de votre système d’exploitation et de tous leslogiciels qui fonctionnent sur votre machine.

Le lecteur Flash dispose d’une machine virtuelle qui exécute un langage interprétéde haut niveau, ce qui implique que l’ActionScript ne vous permet pas de gérerdirectement la mémoire mise à la disposition de vos programmes et animations. Eneffet, c’est le lecteur Flash qui va s’occuper d’allouer de la mémoire et de la vider àvotre place (sauf pour quelques exceptions). Bien sûr, il faut respecter certaines règlesque nous allons voir plus bas, pour que la mémoire soit libérée correctement, règles quisont quelquefois bafouées par certains développeurs (d’où certains problèmes récurrentsde consommation de mémoire).

Le ramasse-miettes

Flash utilise donc une technique propre aux plateformes d’exécution (comme Java)pour vider le plus efficacement possible la mémoire de l’ordinateur qui n’est plus utiliséepar votre animation : le ramasse-miettes (ou garbage collector). C’est un petit pro-gramme qui va se charger de trouver tout ce qui est devenu inutile dans le programmepuis d’effacer la mémoire correspondante et ceci régulièrement lors de l’exécution. Iln’est pas possible de l’appeler manuellement car l’opération peut être complexe et doncrelativement lente : ainsi, seul le lecteur a le droit de lancer le ramasse-miettes quandil juge que cela est nécessaire.

Il sera néanmoins possible de l’appeler pendant que vous ferez des testsde débogage lors de l’écriture de vos programmes : il suffit d’entrer cetteligne : System.gc(); Cette commande sera tout simplement ignorée lors del’exécution réelle du programme (par exemple sur une page web).

Préparer un objet pour la suppression

Un objet doit remplir un certains nombre de conditions avant de pouvoir être suppriméde la mémoire par le ramasse-miette. On dit alors qu’il est éligible au nettoyage.Cet objet doit donc :

– Ne pas être présent dans l’arbre d’affichage de la scène principale.– Ne pas avoir de références (variables) pointant sur lui dans d’autres objets.– Ne pas avoir d’écouteurs d’événement enregistrés auprès de l’objet en question.

594

Page 618: Programmez en Actionscript 3

LA MÉMOIRE DANS FLASH

Exemple

Pour illustrer tout ceci, je vous propose à présent un petit exemple. Nous allons réa-liser un bouton qui pourrait servir d’accueil pour un site web ou pour un jeu. Unefois le bouton cliqué, celui-ci disparaît pour laisser place à l’application en elle-même.L’objectif est donc de préparer l’objet a sa suppression de la mémoire vive.

Dans un premier temps, créez une classe Button pour définir le graphisme de notrebouton. Celui-ci sera alors composé d’un fond en dégradé, avec un texte par dessus.Voici le code de cette classe :

1 package2 {3 import flash.display.Sprite;4 import flash.geom.Matrix;5 import flash.display.Shape;6 import flash.display.GradientType;7 import flash.text.TextField;8 import flash.text.TextFieldAutoSize;9 import flash.text.TextFormat;

1011 public class Button extends Sprite12 {13 private static const LARGEUR_SCENE:int = 320;14 private static const HAUTEUR_SCENE:int = 240;1516 public function Button ()17 {18 super();1920 // Dégradé de base21 var couleurs:Array = [0xEEBBBB , 0xDD0000 ];22 var alphas:Array = [1, 1];23 var ratios:Array = [0, 255];2425 // Matrice de description26 var matrix:Matrix = new Matrix ();27 var largeur:Number = 100;28 var hauteur:Number = 15;29 var rotation:Number = Math.PI / 2;30 var tx:Number = 0;31 var ty:Number = 0;32 matrix.createGradientBox(largeur , hauteur , rotation

, tx , ty);3334 // Tracé du bouton35 var fond:Shape = new Shape;36 fond.graphics.lineStyle(1, 0x880000);37 fond.graphics.beginGradientFill(GradientType.LINEAR

, couleurs , alphas , ratios , matrix);38 fond.graphics.drawRoundRect(0, 0, 100 , 25, 10);

595

Page 619: Programmez en Actionscript 3

CHAPITRE 27. BONNES PRATIQUES

39 fond.x = (LARGEUR_SCENE - fond.width) / 2;40 fond.y = (HAUTEUR_SCENE - fond.height) / 2;41 addChild(fond);4243 // Création du Texte44 var texte:TextField = new TextField ();45 texte.autoSize = TextFieldAutoSize.LEFT;46 var format:TextFormat = new TextFormat ();47 format.font = "Calibri";48 format.color = 0xFFFFFF;49 texte.defaultTextFormat = format;50 texte.text = "ENTRER";51 texte.selectable = false;52 texte.x = (LARGEUR_SCENE - texte.width) / 2;53 texte.y = (HAUTEUR_SCENE - texte.height) / 2;54 addChild(texte);55 }5657 }5859 }

Vous pouvez l’afficher pour la copier en utilisant le code web ci-dessous.

B

�Classe Button

Code web : 988840Aucun problème pour la mise en place du bouton ! Néanmoins, pour illustrer les troispoints vus plus haut, nous allons déclarer notre bouton en tant qu’attribut de la classeprincipale :

1 private var _monBouton:Button;

Nous l’instancions donc, lui ajoutons un écouteur pour l’événement MouseEvent.CLICK,et enfin l’ajoutons à la liste d’affichage, comme ceci :

1 _monBouton = new Button ();2 _monBouton.addEventListener(MouseEvent.CLICK , maFonction);3 addChild(_monBouton);

Une fois l’application lancée dans le Flash Player, cela donne la figure 27.1.

Une fois le bouton cliqué, nous devons le préparer à sa suppression de lamémoire vive.Dans le cas présent, nous aurons besoin de supprimer l’écouteur enregistré auprès del’objet, de supprimer celui-ci de la liste d’affichage, mais aussi de supprimer la référenceà l’objet définit pour l’attribut. Tout cela sera fait à l’intérieur de la fonction d’écouteurmaFonction(). Voilà comment réaliser tout ceci :

1 function maFonction(e:MouseEvent):void2 {3 _monBouton.removeEventListener(MouseEvent.CLICK , maFonction

);4 removeChild(_monBouton);

596

Page 620: Programmez en Actionscript 3

LES COMMENTAIRES DE DOCUMENTATION

Figure 27.1 – L’objet monBouton devant être supprimé

5 _monBouton = null;6 // L'objet "monBouton" est à présent éligible au nettoyage7 }

Voilà ! Ce n’est pas bien compliqué, mais il est vraiment essentiel de réaliser ces opéra-tions pour libérer la mémoire au fil de l’exécution de votre programme. Beaucoup tropde développeurs ont un gros problème de formation à la gestion de la mémoire, ce quiconduit après à des internautes qui pestent parce que « Flash Player prend toute laRAM ».

Les commentaires de documentation

Ecrire un commentaire de documentation

Nous avons rencontré dans le TP ce commentaire devant certaines propriétés dans laclasse Vecteur2D :

1 /**2 * Ajoute le vecteur passé en paramètre au vecteur courant.3 * @param vecteur Vecteur à ajouter.4 * @param apply Si vrai , modifie directement le vecteur

courant. Sinon , renvoie un nouveau vecteur.5 * @return Le vecteur représentant la somme des deux

premiers vecteurs.6 */

Ces commentaires sont des commentaires de documentation. Il permettent à votreIDE d’afficher des informations à propos de ces propriétés lors de l’autocomplétion ousi vous passez la souris dessus. Il sert également à générer une documentation devotre classe à l’aide de l’outil asdoc (voir figure 27.2).

597

Page 621: Programmez en Actionscript 3

CHAPITRE 27. BONNES PRATIQUES

Figure 27.2 – Une infobulle de Flashdevelop tirant des informations du commentairede documentation

Pour créer un commentaire de documentation, placez votre curseur de saisie surla ligne précédent une propriété publique et entrez /** avec deux étoiles. Si vousêtes sur un IDE comme Flashdevelop, il vous sera proposé de générer automatique-ment le squelette du commentaire de documentation associé à votre propriété. Parexemple :

1 /**2 *3 * @param vecteur4 * @param apply5 * @return6 */7 public function ajouter(vecteur:Vecteur2D , apply:Boolean =

false):Vecteur2D8 {9 // ...

10 }

A vous ensuite de remplir le commentaire à partir de la deuxième ligne en décrivantl’utilité de la propriété de manière à ce que quelqu’un d’autre que vous puisse com-prendre à quoi elle sert.

Voici quelques uns des tags utiliser pour concevoir un commentaire de documentation :

– @auteur : permet de spécifier l’auteur du code source.– @param : permet de faire la description du paramètre spécifié.– @return : permet de spécifier la valeur de retour pour la méthode.– @default : permet de spécifier la valeur par défaut.– @private : permet d’exclure l’élément de la documentation.– @see : permet de créer un lien interne ou externe à la documentation.

Bien évidemment, il en existe d’autres, je vous laisserai les découvrir par vous-mêmes !

Générer la documentation de vos classes

À présent, je vais vous montrer comment générer une belle documentation. Pour cela,nous allons avoir besoin d’un projet contenant des classes documentées. Nous pourrionspar exemple imaginer une collection de classes permettant de manipuler des élémentsmathématiques, tels que des points, des matrices, des vecteurs, . . .

Voici, à la figure 27.3, un exemple de projet contenant un certain nombre de classes.

598

Page 622: Programmez en Actionscript 3

LES COMMENTAIRES DE DOCUMENTATION

Figure 27.3 – Un exemple de projet contenant diverses classes

Pour l’exemple, vous remarquerez que j’ai repris les deux classes Outils etVecteur2D conçues spécialement pour le jeu de billard. Cela nous éviterade perdre du temps dans l’écriture de nouvelles classes, et puis les les com-mentaires de documentation y sont déjà tout prêts. Je vous invite à en faireautant !

Pour générer la documentation, nous allons utiliser l’outil inclus dans FlashDevelop,tout prêt à être utilisé. Pour le lancer, allez dans le menu Tools, puis cliquez surDocumentation Generator..., comme illustrer sur l’image 27.4.

Figure 27.4 – Menu Outils

Une fois la fenêtre ActionScript Documentation Generator ouverte, vous devez alorsrenseigner un certain nombre de champs. Au minimum, vous devez remplir les champssuivants :

599

Page 623: Programmez en Actionscript 3

CHAPITRE 27. BONNES PRATIQUES

– Page title : il s’agit du titre de la documentation. En général, vous renseignerezsimplement le nom de votre projet ou de votre bibliothèque de classes.

– Output directory : ceci correspond au répertoire qui contiendra l’ensemble desfichiers de votre documentation.

– Classpaths : vous devez renseigner ici l’ensemble des répertoires où se situe le codesource de vos classes.

– Compiler : étant donné que nous travaillons depuis le départ en Actionscript 3,utilisez plutôt l’option ASDOC (AS3) que celle donnée par défaut.

Voici les données spécifiées pour l’exemple en cours, à la figure 27.5.

Figure 27.5 – Interface pour le générateur de documentation

Lorsque tout est prêt, lancer le générateur simplement en appuyant sur le boutonGenerate!. Si des erreurs se produisent durant la génération des fichiers, on vous lefera savoir via la console de sortie spécifique à l’outil, présent sous l’onglet Output dela fenêtre. Si tout s’est bien déroulé, vous devriez trouver dans le répertoire de sortie,toute une panoplie de fichiers générés automatiquement. Pour visualiser le rendu, vousdevez utilisez le fichier index.hmtl, présent à la racine du répertoire.

Voilà ce que cela donne pour le projet ASDocExample, et plus particulièrement pour laclasse Vecteur2D : voir la figure 27.6.

Les documents générés avec ASDoc sont très populaires au sein de la commu-nauté des développeurs Actionscript. Elles accompagnent très généralementles bibliothèque de classes, telle que l’API Documentation pour la librairied’interpolation TweenMax, librairie d’interpolation créée par Greensock etque nous avons découvert lors de la dernière partie.

600

Page 624: Programmez en Actionscript 3

LES COMMENTAIRES DE DOCUMENTATION

Figure 27.6 – La documentation du projet ASDocExample

601

Page 625: Programmez en Actionscript 3

CHAPITRE 27. BONNES PRATIQUES

B

�L’API Documentation

Code web : 353359

En résumé– Afin de ne pas saturer la mémoire vive de l’utilisateur de votre application, il estnécessaire de libérer la mémoire au fur et à mesure de l’exécution de celle-ci.

– Pour être éligible au nettoyage, un objet doit répondre à un certain nombre decritères.

– Les commentaires de documentation permettent à votre IDE d’afficher desinformations concernant les propriétés lors de l’autocomplétion ou lors d’un survolavec la souris.

– Les commentaires de documentation débutent par la série de caractères /** etutilisent un certain nombre de tags commençant par @.

– L’ASDoc est un outil permettant de générer automatiquement une documentation,et il est disponible via la fenêtre Documentation Generator dans FlashDevelop.

602

Page 626: Programmez en Actionscript 3

Index

Aaccesseur . . . . . . . . . . . . . . . . . . . 133, 142, 159affectation. . . . . . . . . . . . . . . . . . . . . . . .53, 149affichage . . . . . . . . . . . . . . . 221, 225, 233, 359animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 473

Flash . . . . . . . . . . . . . . . . . . . . . . . . . . 4, 13Apache Flex . . . . . . . . . . . . . . . . . . . . . . . 14, 15Array . . . . . . . . . . . . . . . . . . . . . . . 98, 331, 373ASDoc . . . . . . . . . . . . . . . . . . . . . . . . . . 593, 600attribut . . . . . . . . . . . . . . . . . . . . 126, 128, 141

statique . . . . . . . . . . . . . . . . . . . . . . . . . 146

Bbinaire . . . . . . . . . . . . . . . . . . . . . . . . . . . 12, 219Bitmap . . . . . . . . . . . . . . . . . . . . . . . . . . 226, 344BitmapData . . . . . . . . . . . . . . . . 349, 359, 509Boolean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74boucle . . . . . . . . . . . . . . . . . . . . . . . 79, 105, 107

Cchaîne de caractères . . . . . . . . . . . . . . . 60, 69Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125

abstraite . . . . . . . . . . . . . . . . . . . . . . . . 200dynamique . . . . . . . . . . . . . . . . . . . . . . 190

clavier . . . . . . . . . . . . . . . . . . . . . . . 31, 455, 577collision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495commentaire . . . . . . . . . . . . . . . . . .30, 54, 519

de documentation . . . . . . . . . . . . . . . 597condition. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .67const . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148constructeur. . . . . . . . . . . . . . . . . . . . . .29, 129curseur . . . . . . . . . . . . . . . . 256, 308, 444, 449

Ddéclaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52dessin . . . . . . . . . . . . . . . . . . . . . . . . . . . 303, 351DisplayObject . . . . . . . . . . . . . . . . . . . . . . 238do...while . . . . . . . . . . . . . . . . . . . . . . . . . . . 82droit d’accès . . . . . . . . . . . . . . . . . . . . . . . . . 185

Eécouteur . . . . . . . . . . . . . . . . . . . . . . . . 423, 424else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72encapsulation . . . . . . . . . . . . . . . . . . . 115, 132erreur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 579Error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581événement . . . . . . . . . . . . . . . . . . . . . . 421, 585Event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 435EventDispatcher . . . . . . . . . . . . . . . . . . . . 425exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581extends . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176

Ffiltre . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362, 364final . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186Flash Player . . . . . . . . . . . . . . . . . . . . . . . . 8, 13FlashDevelop . . . . . . . . . . . . . . . . 36, 137, 259fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84, 105function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

Gget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308

Hhéritage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175

603

Page 627: Programmez en Actionscript 3

INDEX

Iif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72if...else . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72image . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341implements . . . . . . . . . . . . . . . . . . . . . . . . . . 196import . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .27instance. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .123int . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192internal . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133interpolation . . . . . . . . . . . . . . . . . . . . . . . . . 482

KKeyboardEvent . . . . . . . . . . . . . . . . . . . . . . 455

Mmasque . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387Math . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58matrice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327

Matrix . . . . . . . . . . . . . . . . . . . . . . . . . . 328mémoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 594méthode . . . . . . . . . . . . . . . . . . . . . . . . 128, 130mode de fusion . . . . . . . . . . . . . . . . . . 376, 378Mouse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447MouseEvent . . . . . . . . . . . . . . . . . . . . . . . . . . 440mutateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133

Nnew . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120null . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53Number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .55

Oobjet. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .112

Object . . . . . . . . . . . . . . . . . . . . . . . . . . 209opacité. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .244opérateur

arithmétique. . . . . . . . . . . . . . . . . . . . . .56logique . . . . . . . . . . . . . . . . . . . . . . . . . . . 70relationnel . . . . . . . . . . . . . . . . . . . . . . . . 68

origine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239override . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184

Ppackage . . . . . . . . . . . . . . . . . . . . . . . . . . 25, 127paramètre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

facultatif . . . . . . . . . . . . . . . . . . . . . . . . 130

pointeur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121police de caractères . . . . . . . . . . . . . 269, 287polymorphisme . . . . . . . . . . . . . . . . . . . . . . 183private . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132protected . . . . . . . . . . . . . . . . . . . . . . . . . . . 178public . . . . . . . . . . . . . . . . . . . . . . . . . . 133, 185

Rramasse-miettes . . . . . . . . . . . . . . . . . . . . . . 594return . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .91

Sscène . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133Shape . . . . . . . . . . . . . . . . . . . . . . . . . . . 226, 304souris . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440Sprite . . . . . . . . . . . . . . . . . . . . . . . . . . 227, 229Stage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227static . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146String . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .61super . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .76

Ttableau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .249

TextField . . . . . . . . . . . . . . . . . . . . . . 250this . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142, 231throw . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 581Timer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477trace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31transparence . . . . . . . . . . . . . . . . . . . . 244, 390try...catch . . . . . . . . . . . . . . . . . . . . . . . . .583TweenMax . . . . . . . . . . . . . . . . . . . . . . . . . . . . 482typage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

Uuint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55undefined . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

Vvar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

statique . . . . . . . . . . . . . . . . . . . . . . . . . 146Vector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100void . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

604

Page 628: Programmez en Actionscript 3

INDEX

WWhile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

605