Generating Pseudo Realistic Clouds In Flash (AS3 + Perlin Noise)

I have recently been working on a web development project for one of my clients, and during the design portion of that process I came up with a visual element that required somewhat realistic looking clouds to be created in Flash. I had tried doing clouds in the past (you can see my more cartoon like attempts on my business' site www.seomaco.com) but to get the kind of look the client wanted I knew I would need to go another direction.



**************************** UPDATE ****************************

I recently updated this project and was able to achieve much better performance by revising my perlin noise generation routines. I will leave this post in tact in case anyone is already working with the code, however I strongly advise all new users to view this post first: Updated And Optimized AS3 Perlin Clouds Demo

******* We Now Return You To you Regularly Scheduled Program *******



To be honest at first I really was not sure where to start. I assumed that images were probably out, and I would need to used some sort of simple particle generation to get the effect I wanted. While searching around for solutions I came across two flash examples that helped me to figure out what perlin noise was, and more importantly provided some examples of the proper syntax needed to implement it. As I do like to credit and share sources I find useful the two projects I am referring to are:

OAXOA Blog's flash lavalamp
and
Flep's night time cloud scene

Flep's project was the closest thing I had to what I wanted, but it took a lot of manipulation to get the final desired effect I really wanted. Before I go any further I should point out that this is not totally finished right now. The movie file is incredibly small, which is great for load times, but with a image as large as this (800x600) it can seriously lag a system. Mario Klingemann has an optimized perlin noise routine that allows for fading that I would like to implement before I consider this project at its final stage. Until then this method is fine for smaller surface areas, and experimentation. (I hope to get a final version done this week, but no promises. If anyone has experience with using that perlin optimization routine, and has some code or advice to share, I would greatly appreciate hearing from you.)

So here is the look that we are going for:
The Plane Demo (this page may be slow on some older systems)

Pretty neat ehhh? (Well minus the system load of course, but I am working on that.)

What makes this effect even more interesting is the fact that it is really easy to script. (I tried to clean this up before I posted it, but if I left in any unnecessary stuff, please do let me know.)

package
{
	import flash.events.Event;
	import flash.display.Sprite;
	import flash.display.MovieClip;
	import flash.display.Bitmap;
	import flash.display.BitmapData;  
	import flash.display.BlendMode;
	import flash.geom.Rectangle;
	import flash.geom.Point;
    import flash.geom.Matrix;
    import flash.filters.ColorMatrixFilter;
	public class Main extends MovieClip
	{
		var h:Number= 525; //Height of area covered by clouds
		var w:Number= 797; // Width
		var dir:Array=[new Point(1,262), new Point(400,262)]; 
		var point:Point=new Point(0,0);
		var rect:Rectangle=new Rectangle(0,0,w,h); // replace the 0s to control how high or low your cloud box appears
		var cd:BitmapData;
		var bd:BitmapData;
		var bmp:Bitmap;
		public var sky:Sprite;
		public var cdF:ColorMatrixFilter;
        public var cdS:Sprite;
        public var cdMx:Matrix;
        public var cdMask:Sprite;
 
		public function Main()
		{
			initFilters(); // This just initializes any filters you want to use.  It is not required, but it makes it easier to separate things out for easy tweaking.
			initCloud(); // This starts our primary function
			return;
		}
 
		function initFilters():void {
			cdF = new ColorMatrixFilter([ // This will adjust the alpha and coloring of the clouds. If you are not used to matrixes, 3 = strength of each color, -200 the respective color's alpha
				3, 0, 0, 0, -300, // Red
				0, 3, 0, 0, -300, // Green
				0, 0, 3, 0, -300, // Blue
				0, 0, 0, 1, 0]); // Alpha
		}
 
		function initCloud():void {
    		cd=new BitmapData(w,h, false, 0 );
			bd=new BitmapData(w,h, false, 0 );
			cdS = new Sprite();
            cdS.addChild(new Bitmap(cd)); // Transfers our clouds to our newly created sprite
            cdS.blendMode = "screen"; // Using overlay will darken the background, but can be used to create an effect like clouds being reflected on glass
			sky.addChild(cdS); // My sky layer contains well a masked sky gradient, if you just want to have your clouds on top of a background you can remove the sky. before addchild.
			addEventListener(Event.ENTER_FRAME, renCloud); // Starts the function that generates cloud data
		}
 
		function renCloud(event:Event):void {
			dir[0].x-= 88.000000E-001; // This will give you control over cloud speed.  + = right to left
			dir[0].y-= 0.000000E-001;
			dir[1].x-= 88.000000E-0011;
			dir[1].y-= 0.000000E-001;
            cdMask = new Sprite();
            cdMx = new Matrix();
            cdMx.createGradientBox(w, h, Math.PI / 2, 0, 0); // This creats a gradient box that will work to give our clouds some depth to them
            cdMask.graphics.beginGradientFill("linear", [0, 0, 0], [0.5, 0.2, 1], [0, 96, 255], cdMx);  // These are the attributes for our gradient box, you can adjust these to scale where your gradient fades out your clouds
            cdMask.graphics.drawRect(0, 0, w, h); // Draws box to contain gradient
			cd.perlinNoise(w-300,h-400,5,Math.random() + 1 * h * 5,true,true,7,true,dir); // These are our actual clouds.  This line will let you change cloud size, octaves (layer depth basically), seed, continous or not, and direction
			cd.applyFilter(cd, cd.rect, new Point(0,0), cdF); // Applying our color matrix filter to fade out the clouds some with alpha, and to adjust the depth of color
			cd.draw(cdMask); // apllies our mask to the clouds
			bd.fillRect(rect, 0x00000000); // I tried not using this method and I got a really uneven motion, so I left it in.... there may be a better way to do this and I just don't know it.
			bd.threshold(cd, rect, point, ">", 0xFFFFFF, 0xFFCCCCCC, 0xFFFFFF, true); // sets the thresholds for the clouds
		}
 	}
 }

I tried to document everything I could think of throughout this file, but if something is not clear please do let me know. Feel free to download the zip file if you want the full working source of the above demo.


-Andrew N. Price



AttachmentSize
Cloud_Demo_2.zip24.37 KB
Cloud_Demo_2_CS3.fla40 KB

Comments

I'm not an IT person, but I really like the interface of your website. REALLy cool!!

Post new comment

The content of this field is kept private and will not be shown publicly.

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Enter the characters (without spaces) shown in the image.