Débuter la programmation avec ActionScript 3 pas à pas


Télécharger Débuter la programmation avec ActionScript 3 pas à pas

★★★★★★★★★★3.5 étoiles sur 5 basé sur 1 votes.
Votez ce document:

Télécharger aussi :


Pratique

d’ActionScript 3

 

Thibault Imbert

Relecture technique : Mathieu Anthoine Jérôme Decoster

 

 

2

 

Langage et  API

Le langage ActionScript 3 intègre de nombreuses nouveautés que nous allons traiter tout au long de cet ouvrage. Ce chapitre va nous permettre de découvrir les nouvelles fonctionnalités et comportements du langage, points essentiels pour tout développeur ActionScript 3.

Le langage  ActionScript 3

Avant de détailler les nouveautés liées au langage ActionScript 3, il convient de défi nir tout d’abord ce que nous entendons par le terme ActionScript. De manière générale, ce terme englobe deux composantes importantes :

?Le cœur du langage. Il s’agit du langage ActionScript basé sur la spécifi cation ECMAScript (ECMA-262). Ce dernier intègre partiellement certaines fonctionnalités issues de la spécifi cation ECMAScript 4.

?L’API du lecteur Flash. Il s’agit des fonctionnalités du lecteur Flash. Toutes les classes demandant à être importées font partie de l’API du lecteur et non du cœur du langage ActionScript.

Ainsi, l’interface de programmation du lecteur ou le langage peuvent être mis à jour indépendamment.

Le lecteur Flash 10 intègre une gestion partielle de la 3D, ainsi qu’une implémentation plus complète de la spécifi cation ECMAScript 4. La gestion de la 3D concerne ici uniquement l’interface de programmation du lecteur Flash ; à l’inverse les nouveaux objets comme la classe Vector, défi nis par la spécifi cation ECMAScript 4, sont directement liés au cœur du langage ActionScript. D’un côté réside le langage ActionScript 3, de l’autre, l’API du lecteur, appelée généralement interface de programmation (voir Figure 2.1).

Contrairement aux précédentes versions d’ActionScript, nous remarquons qu’en ActionScript 3, les différentes fonctionnalités du lecteur Flash sont désormais stockées dans des paquetages spécifi ques.

 

ActionScript 3

 

Cœur du langage                   Interface de

programmation

Spécification ECMAScript

Objets natifs, boucles               Interface de programmation et mots-clés                 API du lecteur Flash

Objets natifs ECMAScript :                 Paquetages Flash :

• Array              • flash.accessibility

• Boolean         • flash.display

• date               • flash.errors

• Error               • flash.events

• Function        • flash.external

• Infinity           • flash.filters

• int                  •

• Math              • flash.media

• NaN               •

• Number          • flash.printing

• Object            • flash.profiler

• RegExp         • flash.system

• String             •

• uint                •

• undefined      • flash.utils

• XML               •

Figure 2.1

Le langage ActionScript 3.

Afi n d’affi cher une vidéo, nous utiliserons les objets issus du paquetage fl ash.media. À l’inverse, pour les comportements de cinématique inverse, nous emploierons les classes ActionScript 3 issues du paquetage fl .ik. Flash CS4 étant confi guré pour importer automatiquement toutes les classes issues de l’API du lecteur Flash, il est inutile d’importer manuellement les classes lorsque nous codons au sein de l’environnement auteur.

Un fi chier est situé au sein du répertoire d’installation de Flash CS4. En lisant son contenu, nous découvrons toutes les classes importées automatiquement pour le compilateur :

<implicitImportsList>

     <implicitImport name = "adobe.utils.*"/>

     <implicitImport name = "flash.accessibility.*"/>

     <implicitImport name = "flash.desktop.*" swfVersion = "10"/>

     <implicitImport name = "flash.display.*"/>

     <implicitImport name = "flash.errors.*"/>

     <implicitImport name = "flash.events.*"/>

     <implicitImport name = "flash.external.*"/>

     <implicitImport name = "flash.filters.*"/>

     <implicitImport name = ".*"/>

     <implicitImport name = "flash.media.*"/>

     <implicitImport name = ".*"/>

     <implicitImport name = "flash.printing.*"/>

     <implicitImport name = "flash.profiler.*" swfVersion = “10”/>

     <implicitImport name = “flash.sampler.*” swfVersion = “10”/>

     <implicitImport name = “flash.system.*”/>

     <implicitImport name = “.*”/>

     <implicitImport name = “.engine.*” swfVersion = “10”/>

     <implicitImport name = “.*”/>

     <implicitImport name = “flash.utils.*”/>

     <implicitImport name = “.*”/>

</implicitImportsList>

Voici les différents emplacements de ce dernier selon les systèmes d’exploitations :

?PC. C:\Program Files\Adobe\Adobe Flash CS4\Common\Confi guration\ActionScript 3.0.

?Mac. /Applications/Adobe Flash CS4/Common/Confi guration/ActionScript 3.0.


Langage et API    

Nous pouvons remarquer la présence d’un attribut swfVersion permettant à l’environnement auteur de Flash CS4 de différencier les classes réservées au lecteur Flash 10.

Afi n de créer un clip dynamiquement, nous pouvons écrire directement sur une image du scénario :

var monClip:MovieClip = new MovieClip();

Si nous plaçons notre code à l’extérieur de Flash au sein de classes, nous devons explicitement importer les classes nécessaires :

import flash.display.MovieClip; var monClip:MovieClip = new MovieClip();

Dans cet ouvrage, nous n’importerons pas les classes du lecteur lorsque nous programmerons dans l’environnement auteur de Flash. À l’inverse, dès l’introduction des classes au Chapitre 11, Programmation orientée objet, nous importerons explicitement les classes utilisées.

 

 

?

Le langage ActionScript 3 englobe deux composantes : le cœur du langage ActionScript et l’interface de programmation du lecteur Flash.

?

Le cœur du langage est défi ni par la spécifi cation ECMAScript.

Machines virtuelles

Le code ActionScript est interprété par une partie du lecteur Flash appelée machine virtuelle.  Elle se charge de retranscrire en langage machine le code binaire (ActionScript byte code) généré par le compilateur.

Les lecteurs inférieurs à la version 9 intégraient une seule machine virtuelle, nommée AVM1, afi n d’interpréter le code ActionScript 1 et 2. En réalité, le code binaire généré par le compilateur en ActionScript 1 et 2 était le même, c’est la raison pour laquelle nous pouvions faire cohabiter au sein d’un même SWF ces deux versions du langage ActionScript. La Figure 2.2 illustre la machine virtuelle 1 (AVM1) présente dans le lecteur Flash 8.

Lecteur Flash 8

AVM1

Machine virtuelle 1

(ActionScript 1 et 2)

Figure 2.2

AVM1 au sein du lecteur Flash 8.

Le langage ActionScript 3 n’est pas compatible avec cette première machine virtuelle. Pour des raisons évidentes de rétrocompatibilité, les lecteurs Flash 9 et 10 embarquent donc deux machines virtuelles. Lors de la lecture d’un SWF, le lecteur sélectionne automatiquement la machine virtuelle appropriée afi n d’interpréter le code ActionScript présent au sein du SWF.

Ainsi, une application ActionScript 1 et 2 sera interprétée au sein des lecteurs Flash 9 et 10 par la machine virtuelle 1 (AVM1) et ne bénéfi ciera donc d’aucune optimisation des performances. La Figure 2.3 présente les deux machines virtuelles au sein des lecteurs Flash 9 et 10.

Lecteur Flash 9 et 10

AVM1

Machine virtuelle 1

(ActionScript 1 et 2)

 

AVM2

Machine virtuelle 2

(ActionScript 3)

Figure 2.3

Les lecteurs Flash 9 et 10 intègrent les deux machines virtuelles AVM1 et AVM2.

Seules les animations compilées en ActionScript 3 pourront bénéfi cier des optimisations réalisées par la nouvelle machine virtuelle (AVM2). Afi n d’en savoir plus sur le fonctionnement interne de la machine virtuelle ActionScript 3 (AVM2) et les différentes instructions défi nies par le bloc abc (ActionScript byte code) rendezvous à l’adresse suivante : .

Intéressons-nous à présent à la notion de traduction dynamique.

?

Les lecteurs Flash 8 et inférieurs intégraient une seule machine virtuelle afi n d’interpréter le code ActionScript 1 et 2.

?

La machine virtuelle 1 (AVM1) interprète le code ActionScript 1 et 2.

?

La machine virtuelle 2 ( AVM2) interprète seulement le code ActionScript 3.

?

Les lecteurs Flash 9 et 10 intègrent les deux machines virtuelles (AVM1 et AVM2).

?

Lors de la compilation, le langage ActionScript 3 ne peut pas cohabiter avec les précédentes versions d’ActionS cript au sein d’un même SWF.

Traduction dynamique

Afi n d’optimiser les performances, la machine virtuelle 2 (AVM2) des lecteurs Flash 9 et 10 intègre un mécanisme innovant de compilation du code à la volée. Bien que le terme puisse paraître étonnant, ce principe, appelé généralement traduction dynamique , permet d’obtenir de meilleures performances d’exécution du code en compilant ce dernier à l’exécution.

Dans les précédentes versions du lecteur Flash, le code présent au sein du SWF était directement retranscrit par la machine virtuelle en langage machine, sans aucune optimisation liée à la plateforme en cours.

En ActionScript 3, la machine virtuelle retranscrit le code binaire (ActionScript byte code) en langage machine à l’aide d’un compilateur à la volée (Just-in-time compiler). Ce dernier permet de compiler uniquement le code utilisé et de manière optimisée selon la plateforme en cours. La machine virtuelle peut donc optimiser les instructions pour un processeur spécifi que tout en prenant en considération les différentes contraintes de la plate forme. Pour plus d’informations liées à la compilation à l’exécution, rendez-vous aux adresses suivantes :

? ; ?à_la_volée.

Intéressons-nous à présent à la notion de typage en ActionScript.

Langage et API    

Gérer les types à l’exécution

Depuis toujours ActionScript est un langage dynamique. Un langage est dit dynamique lorsqu’il est capable de déterminer le type d’une variable non typée à l’exécution. Dans l’exemple suivant, nous défi nissons une variable distance en lui associant une valeur de 150 :

var distance = 150;

Si nous compilons le code précédent avec le compilateur de Flash CS4, il ne générera aucun avertissement et le code sera exécuté sans problème, notre variable distante sera alors de type int. Afi n d’aider le développeur lors de la compilation de son code, la notion de typage statique fut introduite en ActionScript 2 au sein de Flash MX 2004. Le concept consistait à associer un type de données à une variable à l’aide de la syntaxe suivante :

var maVariable:Type

Dans le code suivant, nous tentions d’affecter une chaîne à une variable de type Number :

var distance:Number = "150";

L’un des principaux avantages du typage statique résidait dans la possibilité de détecter les erreurs de type le plus tôt possible, c’est-à-dire avant l’exécution de l’application. En utilisant le code précédent en ActionScript 2, l’erreur suivante était générée à la compilation :

Incompatibilité de types dans l’instruction d’affectation : String détecté au lieu de Number.

En ActionScript 3, nous bénéfi cions toujours du même mécanisme de vérifi cation des types à la compilation, mais il devient optionnel. En compilant le même code en ActionScript 3, l’erreur suivante est générée :

1067: Contrainte implicite d’une valeur du type String vers un type sans rapport Number.

Nous remarquons qu’un code d’erreur est associé au message généré par le compilateur. Cela nous permet de mieux retrouver l’erreur correspondante au sein de la documentation.

Le typage statique est appelé Mode précis dans Flash CS4 et peut être désactivé par l’intermédiaire du panneau Paramètres d’ActionScript 3.0.À travers le panneau Paramètres de publication, puis de l’onglet Flash, nous cliquons sur le bouton Paramètres. Nous obtenons un panneau Paramètres d’ActionScript 3 contenant deux options liées aux erreurs (voir Figure 2.4).

Figure 2.4

Options du compilateur ActionScript 3.

Nous remarquons que par défaut, le Mode précis est activé. En décochant cette case, nous désactivons la vérifi cation des types à la compilation, dans le but de découvrir un comportement extrêmement important apporté par ActionScript 3. En testant le code précédent en mode non précis, nous remarquons qu’aucune erreur de compilation n’est générée. Il s’agit du comportement attendu car nous venons de désactiver la vérifi cation des types à la compilation. En revanche, à l’exécution, la machine virtuelle 2 (AVM2) convertit automatiquement la chaîne de caractères 150 en un nombre entier de type int. Afi n de vérifi er cette conversion automatique, nous pouvons utiliser la fonction describeType offrant des nombreuses informations :

var distance:Number = "150";

/* affiche :

<type name="int” base=”Object” isDynamic=”false” isFinal=”true” isStatic=”false”>

  <extendsClass type=”Object”/>

  <constructor>

    <parameter index=”1” type=”*” optional=”true”/>

  </constructor>

</type>

*/ trace( describeType ( distance ) );

La fonction describeType renvoie un objet XML décrivant le type de la variable. Nous remarquons que l’attribut name du nœud type renvoie int. Nous pouvons ainsi facilement extraire le type de l’objet à l’aide de la syntaxe E4X, sur laquelle nous reviendrons au Chapitre 17 dédié au XML :

var distance:Number = "150";

// affiche : int trace( describeType ( distance ).@name );

En modifi ant la chaîne de caractères nous obtenons une conversion automatique vers le type Number :

var distance:Number = "150.5";

// affiche : Number trace( describeType ( distance ).@name );

Si nous tentons d’affecter un autre type de données à celle-ci, la machine virtuelle 2 tend vers le type Number et convertit implicitement les données à l’exécution.

 

Nous pourrions ainsi en conclure de toujours conserver le Mode précis afi n de ne pas être surpris par ce comportement, mais certaines erreurs de types ne peuvent être détectées par le compilateur car elles n’interviennent qu’à l’exécution. Dans le cas du code suivant, le compilateur ne détecte aucune erreur :

var tableauDonnees:Array = [ "150", "250" ];

// l’entrée du tableau est automatiquement convertie en int var distance:Number = tableauDonnees[0];

À l’exécution, la chaîne de caractères présente à l’index 0 est automatiquement convertie en int. Cette conversion reste silencieuse tant que celle-ci réussit, le cas échéant une erreur à l’exécution est levée.  Dans le code suivant, nous tentons de stocker une chaîne de caractères au sein d’une variable de type MovieClip :

var tableauDonnees:Array = [ "clip", "250" ];

// lève une erreur à l’exécution var clip:MovieClip = tableauDonnees[0];


À l’exécution, la machine virtuelle 2 (AVM2) tente de convertir la chaîne en MovieClip et échoue, l’erreur à l’exécution suivante est levée :

TypeError: Error #1034: Echec de la contrainte de type : conversion de "clip" en flash.display.MovieClip impossible.

Nous pouvons alors nous interroger sur l’intérêt d’un tel comportement. Pourquoi la machine virtuelle s’évertue-t-elle à conserver les types à l’exécution et convertit automatiquement les données ? Afi n de garantir des performances optimales, la machine virtuelle 2 (AVM2) s’appuie sur les types défi nis par le développeur. Ainsi, lorsque nous typons une variable, l’occupation mémoire est optimisée spécifi quement pour ce type, ainsi que les instructions processeur.

 

Ce comportement diffère d’ActionScript 2, où la machine virtuelle 1 évaluait dynamiquement tous les types à l’exécution ; aucune optimisation n’était réalisée. Le typage des variables n’était qu’une aide à la compilation. La grande nouveauté liée à ActionScript 3 réside donc dans l’intérêt du typage à la compilation comme à l’exécution. En associant un type à une variable en ActionScript 3, nous bénéfi cions d’une vérifi cation des types à la compilation et d’une optimisation des calculs réalisés par le processeur et d’une meilleure optimisation mémoire.

ATTENTION

Il est donc primordial de toujours typer nos variables en ActionScript 3, les performances en dépendent très nettement. Nous typerons systématiquement nos variables durant l’ensemble de l’ouvrage.

Voici un exemple permettant de justifi er cette décision. Une simple boucle utilise une variable d’incrémentation i de type int :

var debut:Number = getTimer(); for ( var i:int = 0; i< 500000; i++ )

{

}

// affiche : 5 trace( getTimer() - debut );

La boucle nécessite 5 millisecondes pour effectuer 500 000 itérations. Sans typage de la variable i, la boucle suivante demande 14 fois plus de temps pour s’exécuter :

var debut:Number = getTimer() for ( var i = 0; i< 500000; i++ )

{

}

// affiche : 72 trace( getTimer() - debut );

Dans le code suivant, la variable prenom ne possède pas de type spécifi que, la machine virtuelle doit évaluer elle-même le type, ce qui ralentit le temps d’exécution :

var debut:Number = getTimer(); var prenom = "Bobby"; var prenomRaccourci:String;

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

{

 prenomRaccourci = prenom.substr ( 0, 3 ); }

// affiche : 430 trace( getTimer() - debut );

// affiche : Bob trace ( prenomRaccourci );

En typant simplement la variable prenom, nous divisons le temps d’exécution de presque deux fois :

var debut:Number = getTimer();

var prenom:String = “Bobby”; var prenomRaccourci:String;

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

{

 prenomRaccourci = prenom.substr ( 0, 3 ); }

// affiche : 232 trace( getTimer() - debut );

// affiche : Bob trace ( prenomRaccourci );

Au sein du panneau Paramètres ActionScript 3, nous apercevons un deuxième mode de compilation appeléMode avertissements. Il permet d’indiquer plusieurs types d’erreurs comme, par exemple, les erreurs liées à la migration de code. Supposons que nous tentions d’utiliser la méthode attachMovie dans un projet ActionScript 3 :

var ref:MovieClip = this.attachMovie ("clip", "monClip", 0);

Au lieu d’indiquer un simple message d’erreur, le compilateur nous renseigne que notre code n’est pas compatible avec ActionScript 3 et nous propose son équivalent. Le code précédent génère donc le message d’erreur suivant à la compilation :

Warning: 1060: Problème de migration : la méthode ‘attachMovie’ n’est plus prise en charge.  Si le nom de la sous-classe de MovieClip est A, utilisez var mc= new A(); addChild(mc). Pour plus d’informations, consultez la classe DisplayObjectContainer.

Le Mode avertissements permet d’avertir le développeur de certains comportements à l’exécution risquant de le prendre au dépourvu.

 

Comme nous l’avons vu précédemment, les avertissements n’empêchent ni la compilation du code ni son exécution. Ils indiquent simplement que le résultat de l’exécution risque de ne pas être celui attendu par le développeur.

 

Dans le code suivant, un développeur tente de stocker une chaîne de caractère au sein d’une variable de type Boolean :

var prenom:Boolean = "Bobby";

À la compilation, l’avertissement suivant est affi ché :

Warning: 3590: String utilisée alors qu’une valeur booléenne est attendue.

L’expression va être transtypée comme booléenne.

Il est donc fortement conseillé de conserver les mode précis et avertissements afi n d’intercepter un maximum d’erreurs à la compilation.

Comme nous l’avons vu précédemment, les lecteurs Flash 9 et 10 n’échouent plus en silence et lèvent des erreurs à l’exécution. Nous allons nous intéresser à ce nouveau comportement dans la partie suivante.

?

Il est possible de désactiver la vérifi cation de type à la compilation.

?

Il est impossible de désactiver la vérifi cation et la conversion de type à l’exécution.

?

Le typage en ActionScript 2 se limitait à une aide à la compilation.

?

Le typage en ActionScript 3 aide à la compilation et à l’exécution.

?

Dans un souci d’optimisation des performances, il est fortement recommandé de typer les variables en ActionScript 3.

?

Il est fortement conseillé de conserver les modes précis et avertissements afi n d’intercepter un maximum d’erreurs à la compilation.

Erreurs à l’exécution

Nous avons traité précédemment des erreurs de compilation à l’aide du Mode précis et abordé la notion d’erreurs à l’exécution. L’une des grandes nouveautés des lecteurs Flash 9 et 10 réside dans la gestion des erreurs.  Souvenez-vous, les précédentes versions du lecteur Flash ne levaient aucune erreur à l’exécution et échouaient en silence.

En ActionScript 3, lorsque l’exécution du programme est interrompue de manière anormale, on dit qu’une erreur d’exécution est levée. Afi n de générer une erreur à l’exécution, nous pouvons tester le code suivant :

// définition d’une variable de type MovieClip

// sa valeur par défaut est null var monClip:MovieClip;

// nous tentons de récupérer le nombre d’images du scénario du clip

// il vaut null, une erreur d’exécution est levée var nbImages:int = monClip.totalFrames;

La fenêtre de sortie affi che l’erreur suivante :

TypeError: Error #1009: Il est impossible d’accéder à la propriété ou à la méthode d’une référence d’objet nul.

Afi n de gérer cette erreur, nous pouvons utiliser un bloc try catch :

// définition d’une variable de type MovieClip

// sa valeur par défaut est null var monClip:MovieClip; var nbImages:int;

// grâce au bloc try catch nous pouvons gérer l’erreur try {

 nbImages = monClip.totalFrames;

} catch ( pErreur:Error )

{

 trace ( “une erreur d’exécution a été levée !”); }

Bien entendu, nous n’utiliserons pas systématiquement les blocs try catch pour éviter d’affi cher les erreurs à l’exécution. Certains tests simples, que nous découvrirons au cours de l’ouvrage, nous permettront quelquefois de ne pas recourir à ces blocs. Nous reviendrons sur cette notion à la section intitulée Bonnes pratiques.

Dans un contexte d’erreurs à l’exécution, il convient de défi nir les deux déclinaisons existantes du lecteur Flash :

?Version de débogage (Player Debug). Cette version du lecteur est destinée au développement et affi che les erreurs à l’exécution en ouvrant une fenêtre spécifi que indiquant l’erreur en cours. Ce lecteur est installé automatiquement lors de l’installation de l’environnement de développement Flash CS4 ou Flex Builder 3.

?Version production (Player Release). Cette version du lecteur est disponible depuis le site d’Adobe. Les personnes n’ayant pas d’environnement de développement installé utilisent cette version du lecteur. Ce dernier n’affi che pas les erreurs à l’exécution afi n de ne pas interrompre brutalement l’expérience utilisateur.

Avec le lecteur de débogage, les erreurs non gérées par un bloc try catch ouvrent un panneau d’erreur au sein du navigateur (voir Figure 2.5). Lorsqu’une erreur est levée, l’exécution du code est alors mise en pause. Nous pouvons alors décider soit de continuer l’exécution du code, bien qu’une erreur vienne d’être levée, soit de stopper totalement l’exécution de l’application.

Figure 2.5

Exemple d’erreur à l’exécution.

?

Les lecteurs Flash 9 et 10 lèvent des erreurs à l’exécution.

?

Ces erreurs ouvrent avec le lecteur de débogage une fenêtre indiquant l’erreur au sein du navigateur.

?

Toutes les méthodes de l’API du lecteur en ActionScript 3 peuvent lever des erreurs à l’exécution.

?

Les lecteurs Flash 9 et 10 n’échouent plus en silence, le débogage est donc facilité.

Nouveaux types primitifs

En ActionScript 2, seul le type Number existait afi n de défi nir un nombre. Ainsi, pour stocker un nombre entier ou décimal, le type Number était utilisé :

var age:Number = 20; var vitesse:Number = 12.8;

Aucune distinction n’était faite entre les nombres entiers, décimaux et non négatifs. ActionScript 3 intègre désormais trois types pour représenter les  nombres :

?

int. Représente un nombre entier 32 bits ( signed integer).

?

uint. Représente un nombre entier non signé de 32 bits. ( unsigned integer).

?

Number. Représente un nombre décimal de 64 bits (64-bit IEEE 754 double-precision fl oating-point num-

ber).

Notons que les deux nouveaux types int et uint ne prennent pas de majuscule, contrairement au type Number déjà présent au sein d’ActionScript 2. Une variable de type int peut contenir un nombre oscillant entre –2 147 483 648 et 2 147 483 648 :

// affiche : -2147483648 trace( int.MIN_VALUE );

// affiche : 2147483648 trace( int.MAX_VALUE );

Une variable de type uint peut contenir un nombre entier oscillant entre 0 et 4 294 967 295 :

// affiche : 0 trace( uint.MIN_VALUE );

// affiche : 4294967295 trace( uint.MAX_VALUE );

Souvenez-vous, la machine virtuelle 2 en ActionScript 3 conserve les types à l’exécution. Si nous tentons de stocker un nombre à virgule fl ottante au sein d’une variable de type int ou uint, le nombre est automatiquement converti en entier par la machine virtuelle :

var age:int = 22.2;

// affiche : 22 trace ( age );

Notons que la machine virtuelle arrondit à l’entier inférieur :

var age:int = 22.8; // affiche : 22 trace ( age );

Cette conversion automatique assurée par la machine virtuelle s’avère beaucoup plus rapide que la méthode fl oor de la classe Math. Dans le code suivant, nous arrondissons l’entier au sein d’une boucle à l’aide de la méthode fl oor, la boucle nécessite 111 millisecondes :

var distance:Number = 45.2; var arrondi:Number; var debut:Number = getTimer();

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

{

 arrondi = Math.floor ( distance ); }

// affiche : 111 trace( getTimer() - debut );

// affiche : 45 trace( arrondi );

À présent, nous laissons la machine virtuelle gérer pour nous l’arrondi du nombre :

var distance:Number = 45.2; var arrondi:int; var debut:Number = getTimer();

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

arrondi = distance;

}

// affiche : 8 trace( getTimer() - debut );

// affiche : 45 trace( arrondi );

Nous obtenons le même résultat en 8 millisecondes, soit un temps d’exécution presque 14 fois plus rapide.

 

Dans le code suivant, nous remarquons que la méthode fl oor de la classe Math ne renvoie pas la même valeur que la conversion en int par la machine virtuelle :

var distance:int = -3.2;

// affiche : -3 trace(distance); var profondeur:Number = Math.floor (-3.2);

// affiche : -4 trace( profondeur );

Partant du principe qu’une distance est toujours positive, nous pouvons utiliser le type uint qui offre, dans ce cas précis, des performances similaires au type int :

var arrondi:uint; 

Malheureusement, le type uint s’avère généralement beaucoup plus lent, dès lors qu’une opération mathématique est effectuée. En revanche, le type Number est, lui, plus rapide que le type int lors de division. Lors de la défi nition d’une boucle, il convient de toujours préférer une variable d’incrémentation de type int :

var debut:Number = getTimer();

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

{

}

// affiche : 61 trace( getTimer() - debut );

À l’inverse, avec un type uint les performances chutent de presque 400 % :

var debut:Number = getTimer();

for ( var i:uint = 0; i< 5000000; i++ )

{

}

// affiche : 238 trace( getTimer() - debut );

Gardez à l’esprit, qu’en cas d’hésitation, il est préférable d’employer le type Number :

var debut:Number = getTimer();

for ( var i:Number = 0; i< 5000000; i++ )

{

}

// affiche : 102 trace( getTimer() - debut );

Nous obtenons ainsi un compromis en termes de performances entre le type int et uint.

 

La même optimisation peut être obtenue pour calculer l’arrondi supérieur. Nous préférons laisser la machine virtuelle convertir à l’entier inférieur, puis nous ajoutons 1 :

var distance:Number = 45.2; var arrondi:int;

var debut:Number = getTimer();

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

{  arrondi = distance + 1;

}

// affiche : 12

trace( getTimer() - debut );

// affiche : 46 trace( arrondi );

En utilisant la méthode ceil de la classe Math, la boucle nécessite 22 fois plus de temps pour s’exécuter :

var distance:Number = 45.2; var arrondi:Number; var debut:Number = getTimer();

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

{  arrondi = ( distance ); }

// affiche : 264 trace( getTimer() - debut );

// affiche : 46 trace( arrondi );

Pour plus d’astuces liées à l’optimisation, rendez-vous aux adresses suivantes :

? ; ? .

Nous reviendrons sur quelques méthodes d’optimisation à la section Bonnes pratiques.



?

Le type int  permet de représenter un nombre entier de 32 bits.

?

Le type uint  permet de représenter un nombre entier de 32 bits non négatifs.

?

Le type Number  permet de représenter un nombre décimal 64 bits. Il est conseillé d’utiliser le type int pour les nombres entiers car il permet d’optimiser les performances.

?

Il est déconseillé d’employer le type uint.

?

En cas d’hésitation, il convient d’utiliser le type Number.

?

Il n’existe pas à ce jour de type fl oat, byte ou decimal en ActionScript 3.

Nouveaux opérateurs

De nouveaux opérateurs, tels is ou as, ont aussi fait leur apparition en ActionScript 3 . Au début du chapitre nous avons utilisé la fonction describeType afi n de décrire de manière détaillée un type spécifi que. Même si cette fonction s’avère très pratique, un développeur voudra plus généralement savoir si une variable est bien du type attendu.

Pour cela, certains développeurs en ActionScript 1 et 2 employaient l’opérateur typeof :

var prenom:String = "Bobby";

// affiche : true trace( typeof prenom == "string" );

Malheureusement cet opérateur posait déjà à l’époque deux problèmes. Le premier concernait le risque d’erreur du fait de la comparaison du retour de l’opérateur typeof à une simple chaîne de caractères. Cela augmentait fortement le risque d’erreurs, car nous ne bénéfi cions d’aucune vérifi cation du type à la compilation. Notez que l’opérateur typeof renvoie des types ne contenant pas de majuscule ce qui s’avère peu courant. L’erreur la plus classique était donc l’utilisation d’une majuscule dans le nom du type à tester :

var prenom:String = "Bobby";

// affiche : false trace( typeof prenom == “String” );

La seconde limitation concernait le nombre réduit de types que l’opérateur typeof renvoie. Seules six valeurs pouvaient être renvoyées. Elles sont décrites au Tableau 2.1.

Tableau 2.1 : Valeurs retournées par l’opérateur typeof

Type réel

Valeurs retournées par typeof

Array

object

Boolean

boolean

Function

function

int

number

Number

number

Object

object

String

string

uint

number

XML

xml

XMLList

xml

En cas d’utilisation de l’opérateur typeof sur un objet de type Array, nous obtenions la valeur object peu précise :

var distances:Array = [150, 300, 800];

// affiche : object trace( typeof distances );

Beaucoup de développeurs tombaient alors dans le piège suivant :

var distances:Array = [150, 300, 800];

// affiche : false

trace( typeof distances == “array” );

Si le développeur a bien utilisé une minuscule pour le type Array, il ne s’est pas souvenu que l’opérateur typeof est incapable de renvoyer le type Array, mais que dans ce cas, il renvoie simplement object. Certains développeurs au courant de cette limitation de l’opérateur typeof préféreaient l’opérateur instanceof plus adapté :

var distances:Array = [150, 300, 800];

// affiche : true trace( distances instanceof Array );

Avec ActionScript 3, en compilant le code suivant et en ayant activé le Mode avertissements, nous obtenons le message suivant :

Warning: 3555: L’opérateur instanceof est déprécié, utilisez plutôt l’opérateur is.

Nous préférerons ainsi l’utilisation de l’opérateur is, apparu en ActionScript 3, qui permet de tester si une variable est d’un type spécifi que :

var distances:Array = [150, 300, 800];

// affiche : true trace( distances is Array );

La différence subtile entre l’opérateur instanceof et is réside dans le support des interfaces. L’opérateur instanceof s’avère incompatible avec les interfaces et renvoie toujours false lorsque nous tentons de savoir si un objet les implémente ou non :

// création d’une clip

var monClip:MovieClip = new MovieClip();

// affiche : true trace(monClip is MovieClip);

// affiche : true

trace(monClip is IEventDispatcher);

// affiche : false trace(monClip instanceof IEventDispatcher);

Nous utiliserons tout au long de l’ouvrage le mot-clé is qui ne souffre pas de ces limitations :

var tableauDonnees:Array = [5654, 95, 54, 687968, 97851];

// affiche : true

trace( tableauDonnees is Array );

// affiche : true

trace( tableauDonnees is Object );

// affiche : false trace( tableauDonnees is MovieClip );

Nous reviendrons vite sur la notion d’interfaces, concept lié à la programmation orientée objet. Dans tous les cas, sachez que l’utilisation de l’opérateur is est préférée aux opérateurs instanceof et typeof.

 

Un autre opérateur nommé as fait également son apparition. Ce dernier permet de transtyper un objet vers un type spécifi que. Dans le code suivant, nous défi nissons une variable de type DisplayObject, mais celle-ci contient en réalité une instance de MovieClip :

var monObjetGraphique:DisplayObject = new MovieClip();

Si nous tentons d’appeler une méthode de la classe MovieClip sur la variable monClip, une erreur à la compilation est générée. Afi n de pouvoir appeler la méthode, sans que le compilateur ne nous bloque, nous pouvons transtyper vers le type MovieClip :

// transtypage en MovieClip

(monObjetGraphique as MovieClip).gotoAndStop(2);

En cas d’échec du transtypage, le résultat renvoie null. Nous pouvons donc tester si le transtypage réussit de la manière suivante :

var monObjetGraphique:DisplayObject = new MovieClip();

// affiche : true trace(monObjetGraphique as MovieClip != null );

Nous aurions pu transtyper avec l’écriture traditionnelle suivante :

var monObjetGraphique:DisplayObject = new MovieClip();

// transtypage en MovieClip

MovieClip(monObjetGraphique).gotoAndStop(2);

En termes de performances, le mot-clé as s’avère être presque deux fois plus rapide car il n’offre aucun contrôle d’erreur à l’exécution. En cas d’échec lors du transtypage, l’écriture précédente ne renvoie pas null, mais lève une erreur à l’exécution. Au cours de l’ouvrage, nous préférerons l’approche qui consiste à tester si le type de l’objet est compatible avant de procéder au transtypage :

var monObjetGraphique:DisplayObject = new MovieClip();

if ( monObjetGraphique is MovieClip )

{

 (monObjetGraphique as MovieClip).gotoAndStop(2); }

Peut-être vous demandez-vous déjà l’intérêt du transtypage ? Nous reviendrons à plusieurs reprises sur ce point au cours de différents cas concrets.

?

Les opérateurs typeof  et instanceof  s’avèrent limités et dépréciés.

?

L’opérateur is  est préféré en ActionScript 3.

?

La différence entre l’opérateur is et instanceof réside dans le support des interfaces.

?

Un nouvel opérateur as  fait son apparition afi n d’assurer le transtypage.

Valeurs par défaut

Il est important de noter que les valeurs undefi ned  et null  ont un comportement différent en ActionScript 3. Désormais, une variable renvoie undefi ned uniquement lorsque celle-ci n’existe pas ou lorsque nous ne la typons pas :

var prenom;

// affiche : undefined trace( prenom );

Lorsqu’une variable est typée, mais ne possède aucune valeur, une valeur par défaut lui est attribuée par la machine virtuelle :

var condition:Boolean; var total:int; var couleur:uint; var resultat:Number; var personnage:Object; var prenom:String; var donnees:*;

// affiche : false trace( condition );

// affiche : 0 trace( total );

// affiche : 0 trace( couleur );

// affiche : NaN trace( resultat );

// affiche : null trace( personnage );

// affiche : null trace( prenom );

// affiche : undefined trace( donnees );

Le Tableau 2.2 illustre les différentes valeurs attribuées par défaut aux types de données.

Tableau 2.2 : Valeurs par défaut associées aux types de données

 

Type de données                                            Valeur par défaut

 

Boolean                                                             false

int                                                                      0

uint                                                                    0

Number                                                           NaN

Object                                                                null

Tableau 2.2 : Valeurs par défaut associées aux types de données (suite)

Type de données

Valeur par défaut

Vector

null

String

null

Non typée (équivalent au type *)

undefi ned

Autres types

null

De la même manière, si nous tentons d’accéder à une propriété inexistante au sein d’une instance de classe non dynamique, telle String, nous obtenons une erreur à la compilation :

var prenom:String = "Bob";

// génère une erreur à la compilation trace( prenom.proprieteInexistante );

Si nous tentons d’accéder à une propriété inexistante au sein d’une instance de classe dynamique, le compilateur ne procède à aucune vérifi cation et nous obtenons la valeur undefi ned pour la propriété ciblée :

var objet:Object = new Object();

// affiche : undefined trace( objet.proprieteInexistante );

Attention, une exception demeure pour les nombres qui ne peuvent être null ou undefi ned. Si nous typons une variable avec le type Number, la valeur par défaut est NaN :

var distance:Number;

// affiche : NaN trace( distance );

En utilisant le type int ou uint, les variables sont automatiquement initialisées à 0 :

var distance:int; var autreDistance:uint;

// affiche : 0 trace( distance );

// affiche : 0 trace( autreDistance );

Afi n de déterminer si un nombre n’est pas initialisé, nous utiliserons donc la fonction isNaN :

var distance:Number;

// NaN trace( distance );

// true

trace( isNaN ( distance ) );

Attardons-nous à présent aux nouveaux types de données composites introduits par ActionScript 3.

?

Une variable renvoie undefi ned uniquement lorsque celle-ci n’existe pas ou n’est pas typée.

?

Lorsqu’une variable est typée, mais ne possède aucune valeur, la machine virtuelle attribue automatiquement une valeur par défaut.

Nouveaux types composites

Plusieurs nouveaux types composites font leur apparition en ActionScript 3. Voici une liste regroupant les principaux :

?

RegExp. Les expressions régulières permettent d’effectuer des recherches complexes sur des chaînes de caractères. Nous reviendrons sur les expressions régulières au cours de certains exercices.

?

XML. La spécifi cation ECMAScript 4 intègre un objet XML. Nous reviendrons sur le format XML et la spécifi cation E4X au Chapitre 17. Notons qu’en ActionScript 2, la classe XML était liée à l’API du lecteur Flash et non au langage ActionScript 3.

?

Class. Le type Class permet de défi nir une défi nition de classe. Nous découvrirons un premier cas d’utilisation du type Class au Chapitre 5, Symboles prédéfi nis.

?

Vector. La classe Vector représente un tableau contenant des objets de même type. Nous étudierons son fonctionnement en détail à la section La classe Vector.

Fonctions et paramètres facultatifs

ActionScript 3 intègre de nouvelles fonctionnalités liées à la défi nition de fonctions. Nous pouvons désormais défi nir des paramètres par défaut pour celles-ci. Prenons le cas d’une fonction affi chant un message personnalisé :

function alerte ( pMessage:String ):void

{

 trace( pMessage ); }

La fonction alerte accepte un paramètre accueillant le message à affi cher. Si nous souhaitons l’exécuter, nous devons obligatoirement passer un message :

alerte ("voici un message d’alerte !");

Si nous omettons le paramètre :

// génère une erreur à la compilation alerte ();

l’erreur à la compilation suivante est générée :

1136: Nombre d’arguments incorrect.  1 attendus.

ActionScript 3 permet de défi nir une valeur par défaut pour le paramètre :

function alerte ( pMessage:String="message par défaut" ):void

{

 trace( pMessage );

}

Une fois défi nie, nous pouvons appeler la fonction alerte sans passer de paramètre :

function alerte ( pMessage:String="message par défaut" ):void

{

 trace( pMessage ); }

// affiche : message par défaut alerte ();

Lorsque nous passons un paramètre spécifi que, il écrase la valeur par défaut :

function alerte ( pMessage:String="message par défaut" ):void

{

 trace( pMessage ); }

// affiche : un message personnalisé ! alerte ( "un message personnalisé !" );

De plus, ActionScript 3 intègre un nouveau mécanisme lié aux paramètres aléatoires. Imaginons que nous devions créer une fonction pouvant accueillir un nombre aléatoire de paramètres. En ActionScript 1 et 2, nous ne pouvions l’indiquer au sein de la signature de la fonction. Nous défi nissions donc une fonction sans paramètre, puis nous utilisions le tableau arguments regroupant l’ensemble des paramètres passés :

function calculMoyenne ():Number

{

 var lng:Number = arguments.length; var total:Number = 0;

 for (var i:Number = 0; i< lng; i++)

 {

                                        total += arguments[i];

 }

 return total / lng;

} var moyenne:Number = calculMoyenne ( 50, 48, 78, 20, 90 );

// affiche : 57.2 trace( moyenne );

Bien que cette écriture puisse paraître très souple, elle posait néanmoins un problème de relecture du code. En relisant la signature de la fonction, un développeur pouvait penser que la fonction calculMoyenne n’acceptait aucun paramètre, alors que ce n’était pas le cas.

Afi n de résoudre cette ambiguïté, ActionScript 3 introduit un mot-clé permettant de spécifi er dans les paramètres que la fonction en cours reçoit un nombre variable de paramètres. Dans ce but, nous ajoutons trois points de suspensions en tant que paramètre de la fonction, suivi d’un nom de variable de notre choix. En Action Script 3, le même code s’écrit donc de la manière suivante :

function calculMoyenne ( parametres ):Number

{

 var lng:int = parametres.length; var total:Number = 0;

 for (var i:Number = 0; i< lng; i++)

 {                total += parametres[i];

 }

 return total / lng;

} var moyenne:Number = calculMoyenne ( 50, 48, 78, 20, 90 );

// affiche : 57.2 trace( moyenne );

En relisant le code précédent, le développeur ActionScript 3 peut facilement détecter les fonctions accueillant un nombre de paramètres aléatoires. Il est ainsi possible d’imaginer une fonction nécessitant un paramètre obligatoire ainsi que d’autres facultatifs :

function alerte ( pMessage:String, pX:int=0, pY:int=0 ):void

{

 trace( pMessage );  trace( pX, pY );

} /* affiche :

Erreur de connexion !

0 0

*/ alerte ("Erreur de connexion !");

Si nous passons des valeurs spécifi ques, les paramètres par défaut sont alors écrasés :

/* affiche :

Erreur de connexion !

150 150

*/ alerte ("Erreur de connexion !", 150, 150);

L’ordre des paramètres est alors important : il est interdit de défi nir un paramètre comme obligatoire après un paramètre facultatif. Si nous tentons de compiler la fonction suivante :

function alerte ( pX:int=0, pY:int=0, pMessage:String ):void

{

 trace( pMessage );

}

Le message d’erreur suivant est affi ché à la compilation :

1138: Les paramètres obligatoires sont interdits après les paramètres facultatifs.

Nous allons à présent voir les nouveautés liées au contexte d’exécution en ActionScript 3.

Contexte d’exécution

Afi n que vous ne soyez pas surpris, il convient de s’attarder quelques instants sur le nouveau comportement des fonctions passées en référence. Souvenez-vous, en ActionScript 1 et 2, nous pouvions passer en référence une fonction, celle-ci perdait alors son contexte d’origine et épousait le nouvel objet comme contexte :

var personnage:Object = { age : 25, nom : "Bobby" };

// la fonction parler est passée en référence personnage.parler = parler;

function parler ( )

{

 trace("bonjour, je m’appelle " + + ", j’ai " + + " ans"); }

// appel de la méthode

// affiche : bonjour, je m’appelle Bobby, j’ai 25 ans personnage.parler();

En ActionScript 3, la fonction parler conserve son contexte d’origine et ne s’exécute donc plus dans le contexte de l’objet personnage :

var personnage:Object = { age : 25, nom : "Bobby" };

// la fonction parler est passée en référence personnage.parler = parler;

function parler ( )

{

 trace("bonjour, je m’appelle " + + ", j’ai " + + " ans"); }

// appel de la méthode

// affiche : bonjour, je m’appelle undefined, j’ai undefined ans personnage.parler();

De nombreux développeurs ActionScript se basaient sur ce changement de contexte afi n de réutiliser des fonctions. Nous devrons donc garder à l’esprit ce nouveau comportement apporté par ActionScript 3 durant l’ensemble de l’ouvrage.

Boucles

ActionScript 3 introduit une nouvelle boucle permettant d’itérer au sein des propriétés d’un objet et d’accéder directement au contenu de chacune d’entre elles. Dans le code suivant, nous affi chons les propriétés de l’objet personnage à l’aide d’une boucle for in  :

var personnage:Object = { prenom : "Bobby", age : 50 };

for (var p:String in personnage) {

 /* affiche :  age  prenom

 */  trace( p ); }

Attention, l’ordre d’énumération des propriétés au sein d’un tableau associatif peut changer selon les machines. Il est donc essentiel de ne pas se baser sur l’ordre d’énumération.

NOTEINFO

Notons que la boucle for in utilisée sur un tableau en ActionScript 3 ne boucle plus de la dernière entrée à la première comme c’était le cas en ActionScript 1 et 2, mais de la première à la dernière.

Nous pouvons donc désormais utiliser la boucle for in afi n d’itérer au sein d’un tableau, sans se soucier du fait que la boucle démarre de la fi n du tableau :

var tableauDonnees:Array = [ 5654, 95, 54, 687968, 97851];

for ( var p:String in tableauDonnees ) {

 /* affiche :

 5654

 95

 54

 687968

 97851  */

 trace( tableauDonnees[p] );

}

La boucle for each accède, elle, directement au contenu de chaque propriété :

var personnage:Object = { prenom : "Bobby", age : 50 };

for each ( var valeur:* in personnage )

{

 /* affiche :

 50

 Bobby  */

 trace( valeur );

}

Nous pouvons donc plus simplement itérer au sein du tableau à l’aide de la nouvelle boucle for each :

var tableauDonnees:Array = [ 5654, 95, 54, 687968, 97851 ];

for each ( var valeur:int in tableauDonnees )

{

 /* affiche :

 5654

 95

 54

 687968

 97851  */

 trace( valeur );

}

Nous reviendrons, à la section Autres subtilités, sur le type * que nous venons d’utiliser. Nous allons nous intéresser maintenant aux nouvelles méthodes de la classe Array.

Nouveautés de la classe Array

En ActionScript 3, la classe Array  bénéfi cie de nouvelles méthodes facilitant la manipulation de données. La méthode forEach permet d’itérer simplement au sein du tableau :

// Array.forEach procède à une navigation simple

// sur chaque élément à l’aide d’une fonction spécifique var prenoms:Array = [ "bobby", "willy", "ritchie" ];

function navigue ( element:*, index:int, tableau:Array ):void

{

 trace ( element + “ : “ + index + “ : “ + tableau); }

/* affiche : bobby : 0 : bobby,willy,ritchie willy : 1 : bobby,willy,ritchie ritchie : 2 : bobby,willy,ritchie

*/ prenoms.forEach( navigue );

Ces nouvelles méthodes fonctionnent sur le même principe. Une fonction de navigation est passée en paramètre afi n d’itérer et de traiter les données au sein du tableau. La méthode every exécute la fonction de navigation jusqu’à ce que celle-ci ou l’élément parcouru renvoient false. Il est donc très simple de déterminer si un tableau contient des valeurs attendues. Dans le code suivant, nous testons si le tableau donnees est uniquement composé de nombres :

var donnees:Array = [ 12, "bobby", "willy", 58, "ritchie" ];

function navigue ( element:*, index:int, tableau:Array ):Boolean

{

 return ( element is Number ); } var tableauNombres:Boolean = donnees.every ( navigue );

// affiche : false trace( tableauNombres );

Néanmoins, la méthode map permet de créer un tableau relatif au retour de la fonction de navigation. Dans le code suivant, nous appliquons un formatage aux données du tableau prenoms. Un nouveau tableau de prénoms formatés est généré :

var prenoms:Array = ["bobby", "willy", "ritchie"];

function navigue ( element:*, index:int, tableau:Array ):String

{

 return element.charAt(0).toUpperCase()+element.substr(1).toLowerCase(); }

// on créé un tableau à partir du retour de la fonction navigue

var prenomsFormates:Array = ( navigue );

// affiche : Bobby,Willy,Ritchie trace( prenomsFormates );

La méthode map ne permet pas de fi ltrer les données. Toutes les données du tableau source sont ainsi placées au sein du tableau généré. Si nous souhaitons fi ltrer les données, nous pouvons appeler la méthode fi lter. Dans le code suivant, nous fi ltrons les utilisateurs mineurs et obtenons un tableau d’utilisateurs majeurs :

var utilisateurs:Array = [ { prenom : "Bobby", age : 18 },

                                                                          { prenom : "Willy", age : 20 },

                                           { prenom : "Ritchie", age : 16 },                                                   { prenom : "Stevie", age : 15 } ];

function navigue ( element:*, index:int, tableau:Array ):Boolean

{

 return ( >= 18 ); } var utilisateursMajeurs:Array = utilisateurs.filter ( navigue );

function parcourir ( element:*, index:int, tableau:Array ):void

{

 trace ( element.prenom, ); }

/* affiche :

Bobby 18

Willy 20

*/ utilisateursMajeurs.forEach( parcourir );

La méthode some permet de savoir si un élément existe au moins une fois au sein du tableau. La fonction de navigation est exécutée jusqu’à ce que celle-ci ou un élément du tableau renvoient true :

var utilisateurs:Array = [ { prenom : "Bobby", age : 18, sexe : "H" },

                                                                      { prenom : "Linda", age : 18, sexe : "F" },

                                                                       { prenom : "Ritchie", age : 16, sexe : "H"},

                                                                                    { prenom : "Stevie", age : 15, sexe : "H"} ]

function navigue ( element:*, index:int, tableau:Array ):Boolean

{

 return ( == "F" ); }

// y a t-il une femme au sein du tableau d’utilisateurs ? var resultat:Boolean = ( navigue );

// affiche : true trace( resultat );

Les méthodes indexOf et lastIndexOf font, elles aussi, leur apparition au sein de la classe Array. Elles permettent de rechercher si un élément existe et d’obtenir sa position :

var utilisateurs:Array = [ "Bobby", "Linda", "Ritchie", "Stevie", "Linda" ]; var position:int = utilisateurs.indexOf ("Linda");

var positionFin:int = utilisateurs.lastIndexOf ("Linda");

// affiche : 1 trace( position );

// affiche : 4 trace( positionFin );

La puissance des méthodes indexOf et lastIndexOf réside dans la possibilité de rechercher dans un tableau un élément de type primitif, comme de type composite. Nous pouvons ainsi rechercher la présence de références au sein d’un tableau :

var monClip:DisplayObject = new MovieClip(); var monAutreClip:DisplayObject = new MovieClip();

// une référence au clip monClip est placée au sein du tableau var tableauReferences:Array = [ monClip ]; var position:int = tableauReferences.indexOf (monClip); var autrePosition:int = tableauReferences.lastIndexOf (monAutreClip);

// affiche : 0 trace( position );

// affiche : -1 trace( autrePosition );

Nous reviendrons sur certaines de ces méthodes au sein de l’ouvrage.

?

Pensez à utiliser les nouvelles méthodes de la classe Array afi n de traiter plus facilement les données au sein d’un tableau.

La classe Vector

Le lecteur Flash 10 intègre une nouvelle classe Vector  introduite par la spécifi cation ECMAScript 4. Bien que son nom fasse penser à la notion de vecteurs utilisés en géométrie, la classe Vector n’est autre qu’un tableau accueillant des objets de type spécifi que. Voici la signature du constructeur de cette classe :

public function Vector(length:uint = 0, fixed:Boolean = false)

Nous remarquons que les deux paramètres sont facultatifs. Ainsi, pour créer un vecteur ne contenant que des chaînes de caractères, nous pouvons écrire :

var vecteurPrenoms:Vector.<String> = new Vector.<String>();

En utilisant le premier paramètre length, nous pouvons initialiser la longueur du vecteur de la même manière que pour la classe Array :

// création d’un vecteur de type String

var vecteurPrenoms:Vector.<String> = new Vector.<String>(3);

// affiche : 3 trace( vecteurPrenoms.length );

Lors de l’initialisation de la taille d’un vecteur, chaque index contient alors la valeur null :

// création d’un vecteur de type String

var vecteurPrenoms:Vector.<String> = new Vector.<String>(3);

// affiche : 3

trace( vecteurPrenoms.length );

// affiche : null null null trace( vecteurPrenoms[0], vecteurPrenoms[1], vecteurPrenoms[2] );

Si nous souhaitons créer un vecteur de taille fi xe, nous le spécifi ons à l’aide du paramètre fi xed :

// création d’un vecteur de taille fixe limité à 3 éléments var vecteurPrenoms:Vector.<String> = new Vector.<String>(3, true);

Nous pouvons aussi préciser cela plus tard à l’aide de la propriété du même nom :

// création d’un vecteur de type String

var vecteurPrenoms:Vector.<String> = new Vector.<String>(3);

// bloque la taille du vecteur vecteurPrenoms.fixed = true;

En bloquant la taille du vecteur, il ne peut contenir plus d’éléments que le nombre spécifi é lors de l’initialisation :

// création d’un vecteur d’une longueur de 3

var vecteurPrenoms:Vector.<String> = new Vector.<String>(3);

// bloque la taille du vecteur vecteurPrenoms.fixed = true;

// ajouts de prénoms ( “Bobby” ); ( “Stevie” ); ( “Ritchie” );

La classe Vector possède toutes les capacités de la classe Array, mais n’hérite pas de celle-ci. Dans le code précédent, nous utilisions la méthode push afi n d’ajouter de nouveaux prénoms.

 

En testant le code précédent, l’erreur d’exécution est levée :

RangeError: Error #1126: Impossible de modifier la longueur d’un vecteur fixe.

En réalité, dès lors que la taille d’un vecteur est fi xe, l’appel des différentes méthodes push, pop ou autres pouvant modifi er sa taille est interdite et lève une erreur à l’exécution. Ainsi, lors de l’utilisation d’un vecteur de taille fi xe, le seul moyen d’ajouter des données est la syntaxe crochet :

// création d’un vecteur de type String

var vecteurPrenoms:Vector.<String> = new Vector.<String>(3);

// bloque la taille du vecteur

vecteurPrenoms.fixed = true;

// ajouts de prénoms vecteurPrenoms[0] = “Bobby”; vecteurPrenoms[1] = “Stevie”; vecteurPrenoms[2] = “Ritchie”;

Si nous tentons de stocker un élément à un index supérieur à la limite fi xée, une erreur d’exécution est levée. Dans le code suivant, nous tentons d’ajouter un dernier prénom à l’index 3 :

// ajouts de prénoms vecteurPrenoms[0] = "Bobby"; vecteurPrenoms[1] = "Stevie"; vecteurPrenoms[2] = "Ritchie"; vecteurPrenoms[3] = “Billy”;

L’erreur d’exécution suivante est levée :

RangeError: Error #1125: L’index 3 est en dehors des limites 3.

À l’inverse de la classe Array, si nous tentons d’accéder à l’aide de la syntaxe crochet à un index inexistant, la même erreur à l’exécution est levée :



// ajouts de prénoms vecteurPrenoms[0] = "Bobby"; vecteurPrenoms[1] = "Stevie"; vecteurPrenoms[2] = "Ritchie";

// lève une erreur à l’exécution trace( vecteurPrenoms[3] );

Lors de l’utilisation de la classe Array, le code précédent ne lève aucune erreur d’exécution et renvoie simplement undefi ned :

// création d’un tableau

var tableauPrenoms:Array = new Array();

// ajouts de prénoms tableauPrenoms[0] = "Bobby"; tableauPrenoms[1] = "Stevie"; tableauPrenoms[2] = "Ritchie";

// affiche : undefined trace(tableauPrenoms[3] );

La classe Vector n’échappe pas à ce principe de conversion des types de données à l’exécution. En créant un vecteur ne devant contenir que des objets de type MovieClip, si nous tentons de stocker un objet d’un autre type, une exception est levée. Nous ajoutons ici un nombre entier au vecteur de type String :

// création d’un vecteur de type String

var vecteurPrenoms:Vector.<String> = new Vector.<String>();

// tentative d’ajout d’un nombre entier ( 150 );

// affiche : true

// l’entier est automatiquement converti en une chaîne de caractères trace(vecteurPrenoms[0] is String );

Comme nous l’avons abordé en début de chapitre, si la conversion implicite échoue, une erreur d’exécution est levée. Dans le code qui suit, nous tentons d’ajouter une chaîne de caractères à un vecteur de type MovieClip :

// création d’un vecteur de type MovieClip var vecteurPrenoms:Vector.<MovieClip> = new Vector.<MovieClip>();

// tentative d’ajout d’une chaîne de caractères ( “150” );

L’erreur d’exécution suivante est levée :

TypeError: Error #1034: Echec de la contrainte de type : conversion de "150" en flash.display.MovieClip impossible.

Attention, la fonction globale Vector permet, elle, de transformer un tableau traditionnel de type Array en un vecteur. Voici sa signature :

public function Vector(sourceArray:Object):Vector.<T>

Dans le code suivant, nous transformons un tableau de MovieClip en un vecteur :

var monClip1:MovieClip = new MovieClip(); var monClip2:MovieClip = new MovieClip(); var tableauClips:Array = new Array ( monClip1, monClip2 );

// création d’un vecteur à partir d’un tableau existant

var vecteurClips:Vector.<MovieClip> = Vector.<MovieClip>( tableauClips );

// affiche : 2

trace( vecteurClips.length );

// affiche : [object MovieClip] [object MovieClip] trace( vecteurClips[0], vecteurClips[1] );

Si le tableau source contient un élément ne correspondant pas au type du vecteur, celui-ci est converti automatiquement au risque de lever une exception en cas d’échec. Si le tableau source s’avère vide, le vecteur créé possède une longueur initiale de 0 :

var tableauClips:Array = new Array ();

// création d’un vecteur à partir d’un tableau existant

var vecteurClips:Vector.<MovieClip> = Vector.<MovieClip>( tableauClips );

// affiche : 0 trace( vecteurClips.length );

En tant que développeur découvrant la classe Vector, nous sommes en droit de nous poser la question suivante : outre le fait d’être standard par rapport à la spécifi cation ECMAScript 4, quel est l’intérêt de cette classe ?

Le premier intérêt réside dans les performances. Un vecteur est plus dense et plus léger en mémoire que la classe Array. Le fait de gérer une taille fi xe et un seul et unique type s’avère plus facile pour la machine virtuelle 2. Prenons un exemple simple. Nous allons créer un vecteur de longueur étendue, puis y placer un entier au sein d’une boucle :

var vecteurDonnees:Vector.<int> = new Vector.<int>(1500000, true); var depart:Number = getTimer();

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

{

 vecteurDonnees[i] = 0;

}

// affiche : 22 trace( getTimer() - depart );

La boucle a besoin d’environ 22 ms pour s’exécuter. Notons que si nous n’initialisons pas la taille du vecteur et que nous rendons sa taille variable, les performances chutent remarquablement :

var vecteurDonnees:Vector.<int> = new Vector.<int>(); var depart:Number = getTimer();

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

{

 vecteurDonnees[i] = 0; }

// affiche : 54 trace( getTimer() - depart );

La boucle prend désormais environ 54 ms pour s’exécuter. À présent, si nous utilisons la classe Array, nous obtenons un temps d’exécution environ 2 fois plus lent qu’un vecteur non optimisé et 4 fois plus lent qu’un vecteur optimisé :

var vecteurDonnees:Array = new Array(); var depart:Number = getTimer();

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

{

 vecteurDonnees[i] = 0;

}

// affiche : 95 trace( getTimer() - depart );

Notons qu’il est aussi possible de créer un vecteur accueillant différents types d’objets à l’aide de l’opérateur * :

var vecteur:Vector.<*> = new Vector.<*>()

En termes de performances, cela s’avère également plus intéressant que d’employer la classe Array.

Le second intérêt de la classe Vector tient à la souplesse de développement. Avec un tableau typé, nous bénéfi cions enfi n d’une vérifi cation du code à la compilation. Dans le code suivant, nous créons un vecteur qui contient un entier ayant pour valeur 150 :

var vecteurDonnees:Vector.<int> = new Vector.<int>(); ( 50 );

// tentative d’utilisation d’une méthode de la classe String trace( vecteurDonnees[0].charAt(0) );

Nous essayons d’utiliser la méthode charAt, défi nie par la classe String, sur le premier élément du vecteur.

S’agissant forcément d’un entier, le compilateur nous affi che l’erreur suivante à la compilation :

1061: Appel à la méthode charAt peut-être non définie, via la référence de type static int.

Si nous suivons la même logique à l’aide de la classe Array, nous nous rendons compte qu’aucun contrôle n’est effectué à la compilation :

var tableauDonnees:Array = new Array(); ( 50 );

// tentative d’utilisation d’une méthode de la classe String trace( tableauDonnees[0].charAt(0) );

L’erreur d’exécution suivante est levée :

TypeError: Error #1006: value n’est pas une fonction.

Nous allons nous intéresser dans la prochaine partie au concept de ramasse-miettes qui s’avère extrêmement important en ActionScript 3.

?

Pensez à utiliser la classe Vector afi n d’optimiser les performances de votre application.

?

À la différence d’un simple tableau, un vecteur peut avoir une taille fi xe.

?

La classe Vector possède les mêmes méthodes que la classe Array, mais s’avère plus rapide à l’exécution.

?

La classe Vector offre un contrôle des types à la compilation.

Ramasse-miettes

Tout au long de l’ouvrage nous reviendrons sur le concept de ramasse-miettes . Bien que le terme puisse paraître fantaisiste, ce mécanisme va s’avérer extrêmement important durant nos développements en Action Script 3.

Pendant la durée de vie d’un programme, certains objets peuvent devenir inaccessibles. Afi n de ne pas saturer la mémoire, un mécanisme de suppression des objets inutilisés est intégré au sein du lecteur Flash. Ce mécanisme est appelé ramasse-miettes (ou plus couramment Garbage collector en anglais). Afi n de bien comprendre ce mécanisme, nous défi nissons un simple objet référencé par une variable personnage :

var personnage:Object = { prenom : "Bobby", age : 50 };

Afi n de rendre cet objet inaccessible et donc éligible à la suppression par le ramasse-miettes, nous pourrions être tenté d’utiliser le mot-clé delete :

var personnage:Object = { prenom : "Bobby", age : 50 };

// génère une erreur à la compilation delete personnage;

Le code précédent génère l’erreur de compilation suivante :

1189: Tentative de suppression de la propriété fixe personnage. 

Seules les propriétés définies dynamiquement peuvent être supprimées.

Cette erreur traduit une modifi cation du comportement du mot-clé delete en ActionScript 3, qui ne peut être employé que sur des propriétés dynamiques d’objets dynamiques. Ainsi, le mot-clé delete pourrait servir à supprimer la propriété prenom au sein de l’objet personnage :

var personnage:Object = { prenom : "Bobby", age : 50 };

// affiche : Bobby trace( personnage.prenom );

// supprime la propriété prenom delete ( personnage.prenom );

// affiche : undefined trace( personnage.prenom );

Afi n de supprimer correctement une référence, nous devons affecter la valeur null à celle-ci :

 var personnage:Object = { prenom : "Bobby", age : 50 };

// supprime la référence vers l’objet personnage personnage = null;

Lorsque l’objet ne possède plus aucune référence, nous pouvons estimer que l’objet est éligible à la suppression. Nous devrons donc toujours veiller à ce qu’aucune référence ne subsiste vers notre objet, au risque de le voir conservé en mémoire.

 

L’affectation de la valeur null à une référence ne déclenche en aucun cas le passage du ramasse-miettes. Nous rendons simplement l’objet éligible à la suppression. Il est important de garder à l’esprit que le passage du ramasse-miettes reste potentiel. L’algorithme de nettoyage effectué par ce dernier étant relativement gourmand en termes de ressources, son déclenchement reste limité au cas où le lecteur utiliserait trop de mémoire.

 

Dans le code suivant, nous supprimons seulement l’une des deux références :

var personnage:Object = { prenom : "Bobby", age : 50 };

// copie d’une référence au sein du tableau var tableauPersonnages:Array = [ personnage ];

// suppression d’une seule référence personnage = null;

Une autre référence vers l’objet personnage subsiste au sein du tableau, l’objet ne sera donc jamais supprimé par le ramasse-miettes :

var personnage:Object = { prenom : "Bobby", age : 50 };

// copie d’une référence au sein du tableau var tableauPersonnages:Array = [ personnage ]; // supprime une des deux références seulement personnage = null;

var personnageOrigine:Object = tableauPersonnages[0];

// affiche : Bobby

trace( personnageOrigine.prenom );

// affiche : 50 trace( );

Nous devons donc aussi supprimer la référence présente dans le tableau afi n de rendre l’objet personnage éligible à la suppression :

var personnage:Object = { prenom : "Bobby", age : 50 };

// copie d’une référence au sein du tableau var tableauPersonnages:Array = [ personnage ];

// supprime la première référence personnage = null;

// supprime la seconde référence tableauPersonnages[0] = null;

Si la situation nous le permet, un moyen plus radical consiste à écraser le tableau contenant la référence :

var personnage:Object = { prenom : "Bobby", age : 50 };

// copie d’une référence au sein du tableau var tableauPersonnages:Array = [ personnage ];

// supprime la première référence personnage = null;

// écrase le tableau stockant la référence tableauPersonnages = new Array();

Depuis la version 9.0.115 du lecteur Flash 9, il est possible de déclencher le ramasse-miettes manuellement à l’aide de la méthode gc de la classe System. Notons que cette fonctionnalité n’est accessible qu’au sein du lecteur de débogage. Nous reviendrons sur cette méthode au cours du prochain chapitre intitulé Le modèle événementiel.

?

Afi n qu’un objet soit éligible à la suppression par le ramasse-miettes, nous devons passer toutes ses références à null.

?

Le ramasse-miettes intervient lorsque la machine virtuelle le juge nécessaire.

?

Il est possible de déclencher manuellement le ramasse-miettes au sein du lecteur de débogage 9.0.115.

Bonnes pratiques

Dans cet ouvrage, nous ferons usage de certaines bonnes pratiques, dont voici le détail.

Nous typerons systématiquement les variables afi n d’optimiser les performances de nos applications et garantir une meilleure gestion des erreurs à la compilation et à l’exécution.

Lors de la défi nition de boucles, nous utiliserons toujours une variable de référence afi n d’éviter que la machine virtuelle ne réévalue la longueur du tableau à chaque itération. Nous préférerons donc le code suivant :

var tableauDonnees:Vector.<int> = Vector.<int>([ 5654, 95, 54, 687968, 97851]);

// stockage de la longueur du tableau var lng:int = tableauDonnees.length;

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

{

}

à cette écriture non optimisée :

var tableauDonnees:Vector.<int> = Vector.<int>([ 5654, 95, 54, 687968, 97851]);

for ( var i:int = 0; i< tableauDonnees.length; i++ )

{

}

De la même manière, nous éviterons de redéfi nir nos variables au sein de boucles. Nous préférerons l’écriture suivante :

var tableauDonnees:Vector.<int> = Vector.<int>([ 5654, 95, 54, 687968, 97851]); var lng:int = tableauDonnees.length;

// déclaration de la variable elementEnCours une seule et unique fois var elementEnCours:int;

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

{

 elementEnCours = tableauDonnees[i]; }

à l’écriture suivante non optimisée :

var tableauDonnees:Vector.<int> = Vector.<int>([ 5654, 95, 54, 687968, 97851]); var lng:int = tableauDonnees.length;

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

{

 // déclaration de la variable elementEnCours à chaque itération  var elementEnCours:int = tableauDonnees[i]; }

Certaines conditions seront écrites de manière compacte. Ainsi, une simple condition traditionnellement écrite de la manière suivante :

if ( condition )

{

 expression; }

sera plutôt écrite :

if ( condition )  expression;

Découvrons à présent quelques dernières subtilités du langage ActionScript 3.

Autres subtilités

Le type Void, existant en ActionScript 2 et utilisé au sein des signatures de fonctions, prend désormais un v minuscule en ActionScript 3 :

function initilisation ( ):void

{

}

ActionScript 3 intègre un nouveau type de données permettant d’indiquer qu’une variable peut accueillir n’importe quel type de données. En ActionScript 2, nous nous contentions de ne pas défi nir de type. En ActionScript 3, nous utilisons le type * :

var condition:* = true; var total:* = 5; var couleur:* = 0x990000; var resultat:* = 45.4; var personnage:* = new Object(); var prenom:* = "Bobby";

Lorsque le type de chaque élément itéré est variable, nous emploierons systématiquement le type * au sein d’une boucle for each, car la variable p doit pouvoir accueillir n’importe quel type de données :

var personnage:Object = { prenom : "Bobby", age : 50 }; for each ( var valeur:* in personnage ) {

 /* affiche :

 50

 Bobby  */

 trace( valeur ); }

En recourant à un type spécifi que pour la variable d’itération p, nous risquons de convertir implicitement les données itérées. Dans le code suivant, nous utilisons le type Boolean pour la variable p :

var personnage:Object = { prenom : "Bobby", age : 50 }; for each ( var valeur:Boolean in personnage )

{

 /* affiche :

 true  true  */

 trace( valeur ); }

Le contenu des propriétés est automatiquement converti en booléen. Au cas où une donnée ne pourrait être convertie en booléen, le code précédent pourrait lever une erreur à l’exécution. Dans le cas d’une itération au sein d’un vecteur, nous pouvons utiliser en toute quiétude le type spécifi que du vecteur :

// création d’un vecteur de type String

var vecteurPrenoms:Vector.<String> = new Vector.<String>();

// ajouts de prénoms ( "Bobby" ); ( "Stevie" ); ( "Ritchie" );

for each ( var valeur:String in vecteurPrenoms ) {

 /* affiche :

 Bobby

 Stevie

 Ritchie  */

 trace( valeur );

}

Intéressons-nous à présent aux différentes optimisations introduites par les lecteurs Flash 9 et 10.

Optimisations du lecteur Flash

En introduisant le lecteur F lash 9, Adobe s’était beaucoup investi dans l’amélioration des performances du lecteur. Le premier point à avoir été optimisé fut la vitesse d’exécution du code. Ceci fut majoritairement dû à l’introduction de la machine virtuelle 2 et du principe de traduction dynamique (Just-In-Time Compiler). Par la suite, Adobe a également souhaité améliorer les performances du moteur de rendu du lecteur. À cette fi n, la version 9.0.115 introduit un support des processeurs multi-cœurs en intégrant un procédé de rendu vectoriel multi-processus léger (multi-thread). Grâce à cette amélioration, le lecteur Flash alloue à chaque processeur une partie du rendu.

Dans le cas d’un processeur double cœurs, le premier processeur se charge de rendre la partie supérieure du lecteur, le second s’occupe de la partie inférieure (voir Figure 2.6).

Figure 2.6

Division des zones de rendu par processeur.

Plus le nombre de processeur est élevé, plus le nombre de zones découpées est important.

 

En termes de rendu, on observe une amélioration d’environ 20 à 30 % entre un processeur simple cœur et un processeur double cœurs. Lors de l’utilisation de fi ltres et d’un processeur double cœurs, on peut remarquer une augmentation des performances d’environ 50 %, et de 90 % sur un processeur quadri-cœurs.

 

Parmi les autres améliorations apportées par le lecteur Flash 9, nous retiendrons en particulier l’intégration du codec H.264, la gestion du plein écran et le décodage audio AAC. L’intégration du format H.264 sera abordée au Chapitre 20, Son et Vidéo. Intéressons nous à présent à la notion d’accélération matérielle, souvent mal considérée.

Accélération matérielle

Avant d’aller plus loin, il convient de faire un point sur le concept d’accélération matérielle. Lorsque de lourds calculs occupent votre processeur, celui-ci est en mesure d’allouer une partie du traitement à un autre processeur présent sur la machine. La carte graphique s’avère être la cible idéale pour soulager le processeur. C’est pour cette raison que nous employons souvent le terme d’accélération GPU (Graphics Processing Unit).

Le support de l’accélération matérielle fut introduit pour la première fois au sein du lecteur Flash 9.0.115. Peut-être ne le saviez-vous pas, mais la version 9 du lecteur Flash intégrait déjà une accélération matérielle "partielle". La carte graphique n’était en réalité sollicitée que lors du passage d’une zone spécifi que du lecteur en plein écran par l’utilisation de la propriété fullScreenSourceRect. Rassurez-vous, nous reviendrons sur cette propriété au Chapitre 20.

Le lecteur Flash 10 étend cette fonctionnalité en bénéfi ciant de l’accélération matérielle pour d’autres opérations complexes, comme le rendu des données vectorielles, le décodage de fl ux vidéos, la déformation d’images bitmap ou encore l’affi chage des pixels. Deux types d’accélération matérielle sont confi gurables dans fl ash CS4, depuis l’onglet Flash du menu Paramètres de publication (voir Figure 2.7).

Figure 2.7

Paramètres d’accélération matérielle.

Voici en détail la description de chacun d’entre eux :

?Niveau 1 – Direct. En mode direct, le lecteur Flash fait appel à la carte graphique pour dessiner les pixels le plus rapidement possible, sans passer par l’intermédiaire du navigateur.

?Niveau 2 – GPU. En mode GPU, le lecteur Flash utilise la puissance de la carte graphique afi n de réaliser des traitements vidéos complexes, comme la conversion YUV, la correction colorimétrique, le redimensionnement ou la rotation de vidéos. L’accélération GPU est aussi employée lors de l’affi chage de bitmap en allouant le processus de "blitting" des surfaces bitmap à la carte graphique. Attention, ce mode peut offrir un rendu différent selon les confi gurations.

Pour activer l’accélération matérielle, Flash CS4 passe à l’attribut HTML wmode la chaîne direct ou gpu, lors de la publication. Cet attribut n’est pas une nouveauté du lecteur Flash 10, les précédentes versions permettaient déjà l’utilisation des valeurs suivantes :

?window. Cette option rend l’arrière-plan du contenu opaque et utilise la couleur d’arrière-plan de la page HTML. Le code HTML ne peut pas être affi ché au-dessus ou en dessous du contenu Flash.

?opaque. Cette option défi nit l’arrière-plan du contenu Flash opaque, obscurcissant tout ce qui se trouve sous ce dernier. Cette option permet d’affi cher le contenu HTML

?transparent. Cette option rend l’arrière-plan du contenu Flash transparent. Ceci permet d’affi cher le contenu HTML au-dessus et en dessous du contenu.

Dans le code HTML suivant, le lecteur Flash 10 utilise l’accélération matérielle en mode GPU :

 AC_FL_RunContent(

  ‘codebase’, ‘                   #version=10,0,0,0’,

                                      ‘width’, ‘720’,

                                      ‘height’, ‘576’,

                                      ‘src’, ‘rendu1’,

                                       ‘quality’, ‘high’,

                                                   ‘pluginspage’, ‘’,

                                       ‘align’, ‘middle’,

                                      ‘play’, ‘true’,

                                      ‘loop’, ‘true’,

                                       ‘scale’, ‘showall’,

                                    ‘wmode’, ‘gpu’,

                                         ‘devicefont’, ‘false’,

                                      ‘id’, ‘rendu1’,

                                         ‘bgcolor’, ‘#ffffff’,

                                      ‘name’, ‘rendu1’,

                                      ‘menu’, ‘true’,

                                          ‘allowFullScreen’, ‘false’,

                                         ‘allowScriptAccess’,’sameDomain’,

                                      ‘movie’, ‘rendu1’,

                                     ‘salign’, ‘’

                                     ); //end AC code

Il est donc possible de préciser le type d’accélération sans recompiler le SWF. Si un projet doit soudainement tirer parti de l’accélération matérielle, il suffi t de changer manuellement l’attribut wmode dans la page HTML. Pour la lecture de SWF avec le lecteur autonome, l’environnement auteur de Flash CS4 place dans l’en-tête du SWF un indicateur permettant de préciser le type d’accélération à employer.

NOTEINFO

En termes de rendu, on peut observer une amélioration d’environ 50 % lors de la lecture de vidéos ou manipulation de bitmaps en utilisant l’accélération matérielle en mode GPU.

Les Figures 2.8 et 2.9 illustrent la différence de rendu entre deux SWF. le premier est non accéléré, le second l’est. Nous remarquons une différence de rendu des pixels. Le mode GPU produit une image moins crénelée et des couleurs moins vives. Cette différence potentielle de rendu doit être prise en considération. Notez que l’accélération matérielle en mode direct offre un rendu similaire au mode non accéléré (voir Figure 2.7).

Figure 2.8

Rendu d’une vidéo lue sans accélération matérielle.

Figure 2.9

Rendu d’une vidéo

lue avec l’accélération matérielle en mode GPU.

 

Afi n de travailler avec la carte graphique, les lecteurs Flash 9 et 10 font appel aux bibliothèques DirectX 9 et Pixel Shader 2.0 sur l’environnement Windows et OpenGL sur Mac OS et Linux. Au cas où la carte graphique ne serait pas suffi samment récente ou incompatible, aucune accélération matérielle ne peut opérer, les calculs sont alors entièrement gérés par le processeur. Gardez à l’esprit que le lecteur Flash décide selon des tests bien précis si l’accélération matérielle demandée par le développeur peut opérer.

Sous Windows, le lecteur Flash 10 requiert la même confi guration que lors de l’activation du mode Aero. Ainsi, si ce mode ne fonctionne pas correctement sur votre machine, il y a des fortes chances pour que l’accélération matérielle ne tourne pas de manière optimisée avec le lecteur Flash 10.

 

Sachez qu’une carte graphique est fortement liée aux pilotes l’accompagnant. Ces derniers peuvent ne pas être à jour ni optimisés pour votre confi guration actuelle. Combien de fois avons-nous installé des pilotes qui ne s’avéraient pas optimisés ou défaillants ?

En faisant appel à une accélération matérielle par le mode GPU, le lecteur Flash 10 n’affi chera pas forcément les mêmes couleurs, le rendu pourra alors différer selon chaque confi guration. Dans ces conditions, l’internaute peut décider de désactiver volontairement l’accélération par l’intermédiaire de l’onglet approprié au sein des paramètres du lecteur Flash (voir Figure 2.10).

Figure 2.10

Activation et désactivation de l’accélération matérielle.

Nous pouvons alors nous demander quel est le type d’applications ciblé pour ces deux modes d’accélération ?

De manière générale, ces deux modes doivent être utilisés sur du contenu en mouvement perpétuel occupant une large surface de l’écran. La lecture de vidéos en plein écran ou la forte manipulation d’images bitmap au sein d’un jeu s’avèrent être des cas propice à ce type d’accélération. Au cours de l’ouvrage, nous n’aurons quasiment jamais recours à ces deux modes.

 

?

Le lecteur Flash 9 intégrait une accélération matérielle partielle.

?

Celle-ci opérait uniquement lors du passage d’une zone spécifi que du lecteur en plein écran par l’intermédiaire de la propriété fullScreenSourceRect.

?

Le lecteur Flash 10 supporte une accélération matérielle complète. Pour activer l’accélération, nous utilisons l’attribut wmode de la page HTML.

?

Contrairement au mode GPU, le mode direct n’offre pas de différence de rendu.

?

L’accélération matérielle doit être considérée dans des conditions spécifi ques établies.

?

De manière globale, l’accélération matérielle peut être désactivée dans les paramètres des lecteurs Flash 9 et 10.

?

Un seul et unique SWF au sein du navigateur doit bénéfi cier de l’accélération matérielle par mode GPU ou direct.

Au cas où l’accélération matérielle serait retenue pour votre projet, sachez qu’un seul et unique SWF au sein du navigateur doit bénéfi cier de l’accélération matérielle en mode GPU ou direct. Si plusieurs SWF en bénéfi cient, l’occupation mémoire du navigateur risque de devenir trop importante. Cela provoquerait inévitablement un plantage du navigateur.

Passons à présent aux nouveautés liées à l’interface de programmation du lecteur Flash. Les deux grandes nouveautés apportées par le lecteur Flash 9 concernent la gestion de l’affi chage ainsi que le modèle événementiel. Au cours du prochain chapitre, Le modèle événementiel, nous allons nous intéresser à ce nouveau modèle à travers différents exercices d’applications. Nous apprendrons à le maîtriser et découvrirons comment en tirer profi t tout au long de l’ouvrage.

Puis, au Chapitre 4, nous nous intéresserons au nouveau mécanisme de gestion de l’affi chage, appelé liste d’affi chage. Nous verrons qu’il offre beaucoup plus de souplesse en termes de manipulation des objets graphiques et d’optimisation de l’affi chage.

Vous êtes prêt pour la grande aventure ActionScript 3 ?



262