ActionScript 3.0 Particle Systems #2: Snow Effect

More ActionScript, much like the previous one in execution…

Source code and flash files after the jump for those who want ’em.

Flash File (ActionScript 3.0) Code:

import flash.events.KeyboardEvent;
import Snowflake;
 
// Function to return us a random number which is within a specified range
function randRange(low:Number, high:Number):Number {
	var randNum:Number = (Math.random() * (high - low)) + low;
	return randNum;
} 
 
// Define our vector (just a dynamic array with a specied type in AS3!)
var snowflakeVect:Vector.<Snowflake> = new Vector.<Snowflake>;
 
// Define our number of Snowflakes to display on the screen and a start/stop animation flag
var numberOfSnowflakes:uint = 200;
var toggleAnimation = false;
 
// Create our controls message, center it and add it to the screen
var msg:ControlsMessage = new ControlsMessage();
msg.x = stage.stageWidth / 2;
msg.y = stage.stageHeight / 2;
addChild(msg);
 
// Create a flag to only show our controls message once
var showMsg:Boolean = true;
 
function addSnowflakes():void
{
	// Create variables to store our x & y speeds, which get passed to the Snowflake constructor
	var flakeXSpeed:Number;
	var flakeYSpeed:Number;
 
	// Create however many Snowflakes we've entered into our numberOfSnowflakes variable
	for (var loop:uint = 0; loop < numberOfSnowflakes; loop++) {
 
		// Generate random x and y speeds for our snowflake instance
		flakeXSpeed = randRange(-1, 1);
	    flakeYSpeed = randRange(3, 7);
 
		// Create a new instance of Snowflake (passing x & y speed parameters)
		// and add it to our Vector of Snowflakes
		snowflakeVect.push(new Snowflake(flakeXSpeed, flakeYSpeed));
 
		// Randomise the x (horizontal) and y (vertical) locations on stage 
		snowflakeVect[loop].x = Math.random() * stage.stageWidth;
		snowflakeVect[loop].y = Math.random() * stage.stageHeight;
 
		// Set a random flake alpha within the given range
		snowflakeVect[loop].alpha = randRange(0.3, 1);
 
		// Set a random flake scale within the given range
		var flakeScale:Number = randRange(0.3, 0.9);	
		snowflakeVect[loop].scaleX = flakeScale;
		snowflakeVect[loop].scaleY = flakeScale;	
 
		// Add the Snowflake to the stage
		addChild(snowflakeVect[loop]);
 
	} // End of for loop
 
} // End of addSnowflakes function
 
function removeSnowflakes():void
{
	// Remove however many Snowflakes we're working with from the stage
	for (var loop:uint = 0; loop < numberOfSnowflakes; loop++) {
 
		// Call our custom destructor to unbind any Snowflake eventListeners
		snowflakeVect[loop].SnowflakeDestructor();
 
		// Remove the Snowflake from the stage
		removeChild(snowflakeVect[loop]);		
 
	}
 
	// Remove all snowflakes from the vector.
	// We can't just use "snowflakeVect = null;" or we'll lose our global instance of the vector!
	while(snowflakeVect.length > 0) {
		snowflakeVect.pop();
	}
 
} // End of removeSnowflakes function
 
function snowflakeController(e:KeyboardEvent):void
{
	// If the animation is stopped, add the Snowflakes and flip the flag
	if (toggleAnimation == false) 
	{
		addSnowflakes();
		toggleAnimation = true;
 
		// Only remove message after first display, as it'll only be on stage once
		if (showMsg == true) 
		{
			showMsg = false;
			removeChild(msg);
		}
	}
	else {
		// Otherwise animation must be running and we want it to stop, so remove the
		// Snowflakes and flip the flag
		removeSnowflakes();
		toggleAnimation = false;
	}
 
} // End of SnowflakeController function
 
// With all our functions in place, bind the SnowflakeController function to a keypress
stage.addEventListener(KeyboardEvent.KEY_DOWN, snowflakeController);

ActionScript 3.0 Snowflake Class Code:

package
{
	// Import the MovieClip and Event classes
	import flash.display.MovieClip;
	import flash.events.Event;
 
	public class Snowflake extends MovieClip
	{
		// Define our SnowFlake's properties
		var ySpeed:Number;
		var xSpeed:Number;
 
		// Snowflake Constructor
		function Snowflake(theXSpeed:Number, theYSpeed:Number):void
		{
			// Add an eventlistener for the flake instance that calls the updateSnowflake
			// function every time we draw a new frame
			this.addEventListener(Event.ENTER_FRAME, updateSnowflake);
 
			// Set our flake's x and y speeds as per the constructor's passed parameters
			this.xSpeed = theXSpeed;
			this.ySpeed = theYSpeed;
 
		} // End of constructor
 
		// Destructor to unbind the Snowflake's ENTER_FRAME event listener when we destroy it
		public function SnowflakeDestructor():void
		{
			this.removeEventListener(Event.ENTER_FRAME, updateSnowflake);
		} 
 
		// Function to update the snowflake
		// Remember that we ARE being passed an event by the EventListener - the ENTER_FRAME event!
		function updateSnowflake(e:Event):void
		{
			this.x += this.xSpeed;
			this.y += this.ySpeed;
 
			// If our snowflake has gone off the bottom of the stage, reset the height back to
			// above the stage and re-randomise the x and y speeds
			if (this.y > (stage.stageHeight + this.height))
			{				
				// Reset y position to above the stage. I know we don't need to use "0 - blah"
				// but if we want to do anything with reset offsets later it's already here.
				this.y = 0 - (this.height / 2);
 
				// Re-randomise the speeds
				this.xSpeed = (Math.random() * 2) - 1; // Range: -1 to +1
				this.ySpeed = (Math.random() * 4) + 3; // Range: +3 to +7
 
			} // End of if the flake is off the bottom of the stage
 
		} // End of updateSnowflake function
 
	} // End of Snowflake class
 
} // End of package

Adobe Flash CS4 files can be found: here

8 thoughts on “ActionScript 3.0 Particle Systems #2: Snow Effect”

  1. That is quite impressive stuff you’ve learned there, keep it up!

    And this one is quite apt too, since it is snowing here (again!) right now.

      1. I like the snow effect, question I have what’s the difference in the flash file at the top and the action script one. also if I wanted to accumulate snow ontop of the cabin or the mountains along with it snowing , how can I do that and combine the classes into the one package.

        thanks

        Jason

        1. Hi Jason,

          The difference between the flash file and the class is that the flash file code is placed on a keyframe of the timeline in the main .FLA file, while the class is a standalone file that describes the properties and functions related to a single snowflake, which you can then use to create as many snowflakes as you’d like. I think you can place the snowflake code inside the .fla code (above it), but it’s best to keep classes in separate files to cut down on the code getting bulky (and as such difficult to work with) and so you can re-use the code in other projects with minimum hassle.

          You’d need to make significant changes to the code for the snow to accumulate on top of anything depicted in the background image – if you really want to do it, start with just getting the snow to accumulate at the bottom of the stage by checking if it’s moved off the bottom of the stage or collided with another “locked” snowflake, at which point you just move the colliding snowflake back one frames worth of movement and lock it in place, or just lock it in place where it collided depending on how you want it to work…

          Collision detection is pretty easy in AS3 as you get the AS3 hitTestObject function to use (example: http://www.foundation-flash.com/tutorials/as3hittesting/) as well as the hitTest function for per-pixel collision detection (which I’ve covered in other flash articles such as this: variable-size-particle-collisions ) when you get more confident with AS3.

          With no offense meant, from your question it’s possible that you might be biting off a little bit more than you can chew with snowflake accumulation, so if you find you’re struggling with it, just try and concentrate on getting each aspect required individually until you feel you’re able to put it all together. i.e.:
          – Get comfortable adding and manipulating properties of classes
          – Make sure you can add a property to a class which will lock the object in place when you set it,
          – Make sure you can detect a collision between two objects
          – Make sure you can lock two objects in place once they collide
          – Make sure you can detect a collision, take one step back, and then lock objects in place once they collide etc.

          Hope this helps,
          r3dux

  2. Thank a lot!

    I modified some variables in “ActionScript 3.0 Snowflake Class Code” in order to create an upping bubbles effect.

    Enjoy it!!!

    	package {
    		// Import the MovieClip and Event classes
    		import flash.display.MovieClip;
    		import flash.events.Event;
     
    		public class Snowflake extends MovieClip {
    			// Define our SnowFlake's properties
    			var ySpeed:Number;
    			var xSpeed:Number;
     
    			// Snowflake Constructor
    			function Snowflake(theXSpeed:Number, theYSpeed:Number):void {
    				// Add an eventlistener for the flake instance that calls the updateSnowflake
    				// function every time we draw a new frame
    				this.addEventListener(Event.ENTER_FRAME, updateSnowflake);
     
    				// Set our flake's x and y speeds as per the constructor's passed parameters
    				this.xSpeed=theXSpeed;
    				this.ySpeed=theYSpeed;
     
    			}// End of constructor
     
    			// Destructor to unbind the Snowflake's ENTER_FRAME event listener when we destroy it
    			public function SnowflakeDestructor():void {
    				this.removeEventListener(Event.ENTER_FRAME, updateSnowflake);
    			}
     
    			// Function to update the snowflake
    			// Remember that we ARE being passed an event by the EventListener - the ENTER_FRAME event!
    			function updateSnowflake(e:Event):void {
    				this.x+=this.xSpeed;
    				this.y-=this.ySpeed;
    				trace (this.y );
     
    				// If our snowflake has gone off the bottom of the stage, reset the height back to
    				// above the stage and re-randomise the x and y speeds
    				if (this.y < 0){//(stage.stageHeight + this.height)) {
    					// Reset y position to above the stage. I know we don&#039;t need to use &quot;0 - blah&quot;
    					// but if we want to do anything with reset offsets later it&#039;s already here.
    					trace ("entro");
    					this.y = stage.stageHeight - (this.height);
     
    					// Re-randomise the speeds
    					this.xSpeed = (Math.random() * 2) - 1;// Range: -1 to +1
    					this.ySpeed = (Math.random() * 4) + 3;// Range: +3 to +7
     
    				}// End of if the flake is off the bottom of the stage
     
    			}// End of updateSnowflake function
     
    		}// End of Snowflake class
     
    	}// End of package
  3. i dont know how to get rid of the control message: press any key..etc

    // Create our controls message, center it and add it to the screen
    var msg:ControlsMessage = new ControlsMessage();
    msg.x = stage.stageWidth / 2;
    msg.y = stage.stageHeight / 2;
    addChild(msg);

    1. Try this: Snow-CtrlMsg+Banner.zip

      Obviously change the banner =P

      If you want the snow to be in front of the banner then just delete the Banner symbol and post-it-note.png from the library, then delete the below code from the bottom of the actions layer:

      var b:Banner = new Banner;
      b.x = stage.stageWidth  / 2;
      b.y = stage.stageHeight / 2;
      stage.addChild(b);

      Finally, just pick File | Import | Import to Stage… and point it at your banner of choice.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.