• 12 heures
  • {0} Facile|{1} Moyenne|{2} Difficile

Ce cours est visible gratuitement en ligne.

Ce cours existe en livre papier.

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

Mis à jour le 30/04/2014

Les masques

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Pour le dernier chapitre théorique de cette partie sur l'affichage, je vous propose de découvrir les masques ! Ce concept qui permet de cacher certaines zones d'un objet affichage, est spécifique à l'Actionscript et à la technologie Flash. Pour ceux qui utilisent des logiciels de graphisme comme Gimp ou Photoshop, vous devriez vite cerner la chose. En revanche, pour les autres, suivez attentivement ce que va être dit ici car cette technique est vraiment très pratique et très utilisée.

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'isoler une certaine partie de l'objet d'affichage en question. C'est pourquoi vous aurez besoin de séparer la zone visible de la zone à cacher. Pour cela, nous utilisons ce qu'on appelle des masques !

Qu'est-ce qu'un masque ?

Un masque est un élément graphique comme un autre. On retrouve alors des masques de type Shape, Sprite ou encore Bitmap. Celui-ci sert alors à délimiter la zone visible d'un autre objet d'affichage, définie par l'opacité du masque.

Pour bien comprendre cette notion, je vous propose à la figure suivante un petit schéma.

Principe d'utilisation des masques
Principe d'utilisation des masques

Comme vous pouvez le voir, nous avons donc défini un masque circulaire qui laisse apparaître la photo uniquement à l'intérieur de celui-ci. Bien évidemment, un masque peut être extrêmement complexe et composé de différentes formes. Par exemple, nous aurions pu suivre les courbes du serpent pour pouvoir l'isoler du reste de l'image.

Les masques en Flash

Définition du masque

Avant d'appliquer un masque à un objet visuel quelconque, il est nécessaire de définir ces 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 formes basiques.

Voici donc nos deux éléments monObjet et masque contenant respectivement un rectangle orange et un cercle vert :

var monObjet:Shape = new Shape();
var masque:Shape = new Shape();
this.addChild(monObjet);
this.addChild(masque);

monObjet.graphics.beginFill(0xFF8800);
monObjet.graphics.drawRect(0, 0, 100, 100);
monObjet.graphics.endFill();

masque.graphics.beginFill(0x00FF00);
masque.graphics.drawCircle(50, 50, 50);
masque.graphics.endFill();

Nous avons ici placé l'objet masque au premier plan, ce qui donne la figure suivante.

L'objet et son masque
L'objet et son masque

L'objectif consiste donc maintenant à définir l'objet de couleur verte comme masque pour 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 de la classe DisplayObject ou plutôt d'une de ses sous-classes.
Nous avons déjà vu qu'une classe peut posséder un attribut d'elle-même ; la classe DisplayObject est justement l'une d'elles. En effet, celle-ci possède une propriété nommée mask de type DisplayObject !

Ainsi, avec les objets de type Shape déclarés précédemment, il est possible de faire ceci :

monObjet.mask = masque;

Dans cette instruction, nous passons bien l'objet masque à la propriété mask de l'élément monObjet. Si vous relancez alors l'exécution du projet, vous verrez la magie s'opérer (voir figure suivante).

Effet du masque sur l'objet
Effet du masque sur l'objet

Pour finir, veuillez noter qu'il est possible de supprimer le masque d'un objet simplement 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 masque pour isoler certaines zones d'un objet d'affichage. Toutefois, il est également possible de définir la transparence de celui-ci en gérant l'opacité du masque. Rien ne nous empêche alors d'utiliser des niveaux de transparence multiples.
Pour illustrer cela, je vous propose à la figure suivante un exemple de masque à plusieurs niveaux de transparence.

Principe des niveaux de transparence multiples
Principe des niveaux de transparence multiples

Comme le montre l'illustration précédente, l'objet d'affichage adapte donc sa transparence à l'opacité du masque qui lui est associé. Nous verrons alors qu'il est possible 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 » avec l'opacité des remplissages.
Je suggère alors que nous réalisions un masque composé de trois disques qui se superposent partiellement. Voici le code que je vous propose pour faire cela :

// Objet à masquer
monObjet.graphics.beginFill(0xFF00FF);
monObjet.graphics.drawRect(0, 0, 160, 150);
monObjet.graphics.endFill();
// Masque
masque.graphics.beginFill(0x00FF00,0.5);
masque.graphics.drawCircle(80, 50, 50);
masque.graphics.endFill();
masque.graphics.beginFill(0x00FF00,0.5);
masque.graphics.drawCircle(50, 100, 50);
masque.graphics.endFill();
masque.graphics.beginFill(0x00FF00,0.5);
masque.graphics.drawCircle(110, 100, 50);
masque.graphics.endFill();

Nous avons donc ici réalisé un masque composé de trois niveaux de transparence différents comme vous pouvez le voir à la figure suivante.

Un masque à plusieurs niveaux de transparence
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 :

monObjet.mask = masque;

Vous serez alors surpris de découvrir que ce masque ne fonctionne pas comme nous l'avions prévu, mais réagit comme si nous avions laissé une opacité maximale pour nos remplissages. Regardez plutôt la figure suivante.

Mauvaise application d'un masque à plusieur niveaux de transparence
Mauvaise application d'un masque à plusieur niveaux de transparence
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éfinissant tout simplement à true. Habituellement, les objets d'affichage sont manipulés par le lecteur Flash comme s'il s'agissait d'objets vectoriels, ce qui donne de bonnes performances la plupart du temps, mais implique quelques limitations, comme celle que nous venons de rencontrer. Lorsqu'un objet d'affichage est mis en cache sous forme de bitmap, il est d'abord rendu sous forme d'image contenant des pixels, puis manipulé par le lecteur Flash. Cela nous permet donc d'effectuer des opérations plus complexes (comme les masques à plusieurs niveaux de transparence). Ainsi, il nous faut activer ce cache sur le masque, mais également sur l'objet auquel il est appliqué.
Voici comment procéder pour appliquer le masque à l'objet :

monObjet.cacheAsBitmap = true; 
masque.cacheAsBitmap = true; 
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 suivante.

Application correcte d'un masque à plusieurs niveaux de tranparence
Application correcte d'un masque à plusieurs niveaux de tranparence

Exercice : une lampe torche

Pour terminer ce chapitre, nous allons réaliser un petit exercice ensemble.
Nous allons créer une lampe torche à partir de deux images et d'un masque. Cet exercice ne comporte aucune difficulté, contentez-vous uniquement de suivre ces différentes étapes avec moi.

Préparation des images

Rue de nuit

Pour commencer, je vous invite à créer un dossier nommé images où nous placerons nos deux images.
Dans un premier temps, nous aurons besoin de l'image d'une rue sombre qui servira de fond pour notre projet. Voici à la figure suivante l'image que j'ai nommée « RueSombre.png ».

RueSombre.png
RueSombre.png

Cette image sera ainsi notre rue lorsqu'elle n'est pas éclairée par la lampe torche. Nous viendrons donc ajouter une partie lumineuse par dessus pour simuler l'effet d'une lampe torche.

Rue éclairée par la lampe

Lorsque notre lampe torche passera sur une zone, celle-ci sera éclairée presque comme en plein jour. Nous aurons alors besoin d'une seconde image de cette même rue, mais cette fois beaucoup plus lumineuse. Voici donc notre seconde image « RueEclairee.png » (figure suivante).

RueEclairee.png
RueEclairee.png

La lampe torche n'agissant que sur une certaine partie de la rue, c'est cette image qui subira 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. Pour cela, nous créerons deux variables de type Class que nous appellerons RueSombre et RueEclairee comme vous avez appris à le faire.
Voici toutefois le code correspondant pour ceux qui auraient déjà oublié :

// Chargement des images
[Embed(source = 'images/RueSombre.png')]
private var RueSombre:Class;
[Embed(source = 'images/RueEclairee.png')]
private var RueEclairee:Class;
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 RueEclaireepar dessus celle de la classe RueSombre. Sinon, vous ne verrez absolument rien dans le rendu final de l'animation.
Voici ce que je vous propose de faire :

// Mise en place des images
var maRueSombre:Bitmap = new RueSombre();
var maRueEclairee:Bitmap = new RueEclairee();
this.addChild(maRueSombre);
this.addChild(maRueEclairee);

Mise en place du masque

À présent, nous allons nous occuper du masque que nous appliquerons à l'image de la rue éclairée. Cela devrait donc donner au final un effet de lampe torche, que vous pourrez 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é :

// Préparation du dégradé
var couleurs:Array = [0x00FF00, 0x00FF00];
var alphas:Array = [1, 0];
var ratios:Array = [192, 255];
var matrix:Matrix = new Matrix();
matrix.createGradientBox(200, 200, 0, -100, -100);

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 avons augmenté 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 pour représenter la forme du faisceau de lumière sortant de la lampe.
Voici comment réaliser ceci :

// Création de la lampe
var lampe:Sprite = new Sprite();
lampe.graphics.beginGradientFill(GradientType.RADIAL, couleurs, alphas, ratios, matrix);
lampe.graphics.drawCircle(0, 0, 100);
lampe.graphics.endFill();
this.addChild(lampe);

La figure suivante vous montre à quoi ressemble le masque nous allons utiliser.

Aperçu du masque
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ée uniquement dans la zone où la lampe pointe.
Pour faire cela, nous allons définir l'instance lampe comme masque pour l'objet maRueEclairee. Nous allons donc procéder comme nous avons appris à le faire :

// Mise en place du masque
maRueEclairee.cacheAsBitmap = true;
lampe.cacheAsBitmap = true;
maRueEclairee.mask = lampe;

Nous avons à présent réalisé l'effet souhaité. Pour donner un peu plus d'intérêt à ce projet, nous allons animer celui-ci.

Animation de la lampe

Pour animer le masque, nous allons utiliser la méthode startDrag() de la classe Sprite. En indiquant son paramètre à true, on impose à l'objet en question de « coller » à la position de la souris. Ainsi, notre lampe va suivre les mouvements de la souris, pour imiter les gestes du poignet.
Voici donc comment procéder :

// Animation de la lampe
lampe.startDrag(true);

Projet final

Le rendu

Nous avons maintenant terminé cet exercice sur les masques. Je vous propose à la figure suivante un aperçu de l'animation finale.

Rendu final de l'exercice
Rendu final de l'exercice
Le code complet

Enfin, pour vous aider à avoir une vision d'ensemble de ce que nous venons de réaliser ensemble, voici ci-dessous l'intégralité du code de ce projet :

package 
{
    import flash.display.Sprite;
    import flash.display.Shape;
    import flash.display.Bitmap;
    import flash.events.Event;
    import flash.geom.Matrix;
    import flash.display.GradientType;
    
    /**
     * ...
     * @author Guillaume
     */
    public class Main extends Sprite 
    {
        // Chargement des images
        [Embed(source = 'images/RueSombre.png')]
        private var RueSombre:Class;
        [Embed(source = 'images/RueEclairee.png')]
        private var RueEclairee:Class;
        
        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            
            // Mise en place des images
            var maRueSombre:Bitmap = new RueSombre();
            var maRueEclairee:Bitmap = new RueEclairee();
            this.addChild(maRueSombre);
            this.addChild(maRueEclairee);
            
            // Préparation du dégradé
            var couleurs:Array = [0x00FF00, 0x00FF00];
            var alphas:Array = [1, 0];
            var ratios:Array = [192, 255];
            var matrix:Matrix = new Matrix();
            matrix.createGradientBox(200, 200, 0, -100, -100);

            // Création de la lampe
            var lampe:Sprite = new Sprite();
            lampe.graphics.beginGradientFill(GradientType.RADIAL, couleurs, alphas, ratios, matrix);
            lampe.graphics.drawCircle(0, 0, 100);
            lampe.graphics.endFill();
            this.addChild(lampe);
            
            // Mise en place du masque
            maRueEclairee.cacheAsBitmap = true;
            lampe.cacheAsBitmap = true;
            maRueEclairee.mask = lampe;
            
            // Animation de la lampe
            lampe.startDrag(true);
        }
        
    }
    
}
En résumé
  • Un masque est un objet d'affichage qui sert à délimiter une zone visible d'un autre objet.

  • Lorsqu'on utilise la classe Graphics, seuls les remplissages sont pris en compte dans les 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 à la valeur null.

Exemple de certificat de réussite
Exemple de certificat de réussite