// Phlashers 2010 AS3 Contest // http://www.phlashers.com package { import flash.display.Sprite; import flash.display.Bitmap; import flash.display.Shape; import flash.display.BitmapData; import flash.display.BitmapDataChannel; import flash.display.GradientType; import flash.display.SpreadMethod; import flash.events.Event; import flash.events.MouseEvent; import flash.filters.DisplacementMapFilterMode; import flash.geom.Matrix; import flash.geom.Point; import flash.filters.BlurFilter; import flash.filters.DisplacementMapFilter; public class Smoke extends Sprite { //Perlin noise settings private var perlinNoiseBitmapData:BitmapData; private var offsets:Array = [ new Point(), new Point() ]; private const BASE_X:Number = 100; private const BASE_Y:Number = 100; private const OCTAVES:Number = 3; private const SEED:Number = 50; private const STITCH:Boolean = false; private const FRACTAL:Boolean = false; private const CHANNEL_OPTIONS:Number = 10; private const GREYSCALE:Boolean = true; //constant used to convert from degrees to radioans private const TO_RADIANS:Number = Math.PI/180; //Displacement map settings private var displacementMapBitmapData:BitmapData; private var dMap:DisplacementMapFilter; //bitmap to display final output private var bmp:Bitmap; private var blurFilter:BlurFilter = new BlurFilter( 2, 2, 1) ; private var s:Shape; //container to draw from private var container:Sprite = new Sprite(); //Type of Gradient we will be using private var fType:String = GradientType.LINEAR; //Colors of our gradient in the form of an array private var colors:Array = [ 0xffffff, 0xC40076 ]; //Store the Alpha Values in the form of an array private var alphas:Array = [ 1, 1 ]; //The value defines percentage of the width where the color is sampled at 100% private var ratios:Array = [ 0, 200 ]; //radius of circle private var r:Number = 30; //Create a Matrix instance and assign the Gradient Box private var matr:Matrix; //SpreadMethod will define how the gradient is spread. Note!!! Flash uses CONSTANTS to represent String literals private const SPREAD_METHOD:String = SpreadMethod.PAD; public function Smoke() { init(); } private function init():void{ matr = GradientMatrix.getGradientBox( r, r, 45*TO_RADIANS, -r * .5, -r * .5 ); perlinNoiseBitmapData = new BitmapData( 450, 450, false, 0x00 ); displacementMapBitmapData = perlinNoiseBitmapData.clone(); //create the container that we will draw into our bitmapdata object and add the circle in tehre container = addChild( new Sprite() ) as Sprite; //create the shape container where we'll draw our circle s = container.addChild( new Shape() ) as Shape; s.x = s.y = 450 * .5; //apply the displacement map dMap = new DisplacementMapFilter( perlinNoiseBitmapData, new Point(), 4, 4, 40, 40, "clamp" ); bmp = addChild( new Bitmap( displacementMapBitmapData ) ) as Bitmap; bmp.filters = [ dMap ]; addEventListener(Event.ENTER_FRAME, updateNoise ); } private function updateNoise( e:Event ):void{ //apply noise operations ++offsets[0].x; ++offsets[1].y; perlinNoiseBitmapData.perlinNoise( BASE_X, BASE_Y, OCTAVES, SEED, STITCH, FRACTAL, CHANNEL_OPTIONS, GREYSCALE, offsets ) //draw a circle with a random size s.graphics.clear(); s.graphics.beginGradientFill( fType, colors, alphas, ratios, matr, SPREAD_METHOD ); s.graphics.drawCircle( -r*.5, -r*.5, Math.random()*10 - 5 + r ); //move the x position of the shape towards the mouse, with an ease s.x -= ( s.x - mouseX ) * .33; s.y -= ( s.y - mouseY ) * .33; //draw container displacementMapBitmapData.draw( container, null, null, "hardlight" ); //apply a filter displacementMapBitmapData.applyFilter( displacementMapBitmapData, displacementMapBitmapData.rect, new Point(), blurFilter ); } } } // GradientMatrix // // Fixes the native implementation of Flash's matrix.createGradientBox() // which does not work as intended with rotated gradients // // released under MIT License (X11) // http://www.opensource.org/licenses/mit-license.php // // Author: Mario Klingemann // http://www.quasimondo.com import flash.geom.Matrix; class GradientMatrix{ public static function getGradientBox( width:Number, height:Number, rotation:Number, tx:Number, ty:Number ):Matrix{ var m:Matrix = new Matrix(); m.createGradientBox( 100, 100 ); m.translate( -50, -50 ); m.scale( width / 100, height / 100 ); m.rotate( rotation ); m.translate( tx, ty ); return m; } } flash on 2010-5-26