Un feu en AS3

admin mai 7th, 2007

Un exemple de feu géré en AS3


Je me suis inspiré d’un exemple fait en Flash 8 que j’ai trouvé sur le site de betaruce : Flash 8 Tutorial: Fire effect.

Contrairement à l’exemple original, le dégradé est créé par code, ce n’est pas un symbole que l’on utilise.

package {
    import flash.display.Sprite;
    import flash.display.Shape;
    import flash.display.GradientType;
    import flash.display.SpreadMethod;
    import flash.display.InterpolationMethod;
    import flash.display.Loader;
    import flash.net.URLRequest;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.events.Event;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.BitmapDataChannel;
    import flash.filters.DisplacementMapFilter;
    import flash.filters.DisplacementMapFilterMode;

[SWF(frameRate='50',width='320',height='240',backgroundColor='0x869CA7')]

    public class fire extends Sprite
    {

        private var gradientX_data:BitmapData; // le bitmapData du dégradé

        private var perlin_data:BitmapData; // le bitmapData du bruit perlin

        private var fire_data:BitmapData; // le bitmapData du feu
        private var fireScreen:Bitmap;   //  l'image du feu

        private var a:Array; // le tableau pour les 2 octaves du bruit Perlin
        

        public function fire()
        {
            // on charge l'image du fond
            loadBackground();

            // la matrice pour la création du dégradé
            var matrix:Matrix = new Matrix();

            // transformation à appliquer au dégradé
            // par défaut, il s'agit d'une matrice 1x1, il faut la transformer
            // pour l'adapter à la taille du remplissage
            // largueur, hauteur, rotation, translationX, translationY)
            matrix.createGradientBox(100, 100, - Math.PI/2, 0, 0);

            // type de gradiant LINEAR ou RADIAL
            var type:String = GradientType.LINEAR;

            // liste des couleurs du dégradé
            var colors:Array = [0xFF6600, 0x000000];

            // liste de la transparence associée aux couleurs
            var alphas:Array = [1, 0.5];

            // liste des ratios des couleurs (là ou les couleurs sont pures)
            // en principe 0, 255
            var ratios:Array = [0, 210];

            // étalement du dégradé si la taille du dégradé est plus petite que le remplissage
            // PAD, REFLECT ou REPEAT
            var spreadMethod:String = SpreadMethod.PAD;

            // le type d'interpolation des couleurs RGB ou LINEAR_RGB
            var interp:String = InterpolationMethod.RGB;

            // uniquement pour le gradient RADIAL, vaut entre -1 et 1
            // déplace la focale du dégradé
            var focalPtRatio:Number = 0;

            // on définit une forme qui va contenir le dégradé
            var square:Shape = new Shape;

            // on affecte le remplisaage à cette forme
            square.graphics.beginGradientFill(type,
                            colors,
                            alphas,
                            ratios,
                            matrix,
                            spreadMethod,
                            interp,
                            focalPtRatio);

            // on réalise un rectangle de taille 100 x 100
            square.graphics.drawRect(0, 0, 100, 100);

            // on ferme le remplissage
            square.graphics.endFill();

            // maintenant que le dégradé vectoriel est créé
            // on va récupérer le bitmapData
            // on fabrique d'abord un bitmapData vide
            gradientX_data = new BitmapData(100, 100, true, 0x00000000);

            // on récupère le bitmap du vectoriel
            gradientX_data.draw(square);

            // on fait la création de l'image qui va contenir le feu
            fire_data = new BitmapData(100, 100, true, 0x00000000);
            fireScreen = new Bitmap(fire_data);
            // on l'étire à la taille 320x240
            fireScreen.scaleX = 3.2;
            fireScreen.scaleY = 2.4;
            fireScreen.smoothing = true;
            // on l'ajoute à la liste d'affichage
            addChild(fireScreen);

            // on fabrique le bitmapData qui va contenir le bruit Perlin
            // (largueur, hauteur, opaque ou non (alpha-channel), couleur de remplissage)
            perlin_data = new BitmapData(100, 100, true, 0x00000000);

            // nous n'utilisons que 2 octaves pour le bruit Perlin
            a = new Array();
            for(var i:int = 0; i<  2; i++){
                a.push(new Point());
            }

            // on définit maintenant un évènement qui réagit à chaque EnterFrame
            // On choisit le type d'évènement dans la classe Event
            // Le nom de la s/s routine peut être ce que l'on veut
            // onEnterFrame ou toto mais
            // par convention onEnterFrame, c'est mieux
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }

        public function onEnterFrame(event:Event):void {
            // à chaque EnterFrame, on fait bouger les flammes

            // le vecteur de déplacement des flammes (vers le haut)
            var vx:int = 0;
            var vy:int = 7;

            a[0].x += vx;
            a[0].y += vy;
            a[1].x += vx;
            a[1].y += vy;

            // on fabrique un bruit Perlin
            // perlinNoise(baseX, baseY, octaves, seed, stitch, fractal, channels, grayscale, offsets);
            perlin_data.perlinNoise(10, 150, 2, 123456, true, false, 2, false, a);

            // DisplacementMapFilter(BitmapData, mapPoint, componentX, componentY, scaleX, scaleY, mode, color, alpha)
            var d:DisplacementMapFilter = new DisplacementMapFilter(perlin_data,
                                                new Point(),
                                                BitmapDataChannel.RED,
                                                BitmapDataChannel.GREEN,
                                                50,
                                                50,
                                                DisplacementMapFilterMode.IGNORE);

            // j'applique le filtre à mon feu
            fire_data.applyFilter(gradientX_data, gradientX_data.rect, new Point(), d);
        }

        private function loadBackground():void
        {
            // on charge l'image de fond (fire) dans la display list
            var loaderFond:Loader = new Loader();
            loaderFond.load(new URLRequest(fullPath ("fire.jpg")));
            loaderFond.cacheAsBitmap = true;
            this.addChild(loaderFond);
        }

        private function fullPath(nomFichier:String) : String {
            // on fournit en entrée le nom d'un fichier image
            // qui se trouve au même niveau que le fichier Flash
            // on récupère le path complet du movie Flash, on enlève le nom du fichier Flash
            // et on ajoute le nom du fichier image pour avoir son chemin complet
            // uniquement pour corriger un problème dans WordPress
            return((root.loaderInfo.url.substring(0, (root.loaderInfo.url).lastIndexOf("/") + 1 ) ) + nomFichier );
        }
    }
}

Source disponible ici

2 Responses to “Un feu en AS3”

  1. jeromeon 28 août 2007 at 17:42

    salut, je suis graphiste et je me mets tout doucement à actionscript3. je ne comprend pas il n’y a rien pour bloquer une scene (le stop() ne marche plus) quelle démarche je pourrai avoir?

  2. pmantouton 30 août 2007 at 11:58

    il n’y a rien pour bloquer une scene (le stop() ne marche plus)

    Rasssures-toi le stop(); marche toujours (encore heureux :-) ).
    Je te conseille de lire la documentation en ligne, en français que tu trouveras ici : http://www.adobe.com/support/documentation/fr/flash/

    Commences par
    http://livedocs.adobe.com/flash/9.0_fr/UsingFlash/flash_cs3_help.pdf

    Bon courage