Erain 3D
-->

Author: makc
Date: May 20th 2008
version: 3.0.3

Snowflakes

Objective of the tutorial

In this tutorial we will see how to employ new StarField class to create snow effect.

Setting things up

This time we will start from code stub somewhat resembling our good old fog demo:

Click to download source files

This source will get us started with nice winter forest background asking for some snow.

Let it snow

First, make a movie clip and draw a snowflake in it. Set it to export to actionscript and type “Snoflake” as a class name:

Second, look at StarField starSprites property. It allows you to use your movie clips or bitmaps as an image for “stars”, and that's exactly what we need. In our code stub we already have StarField named snow; let's put it in good use now:

// TODO make snowflakes here
var snowflake:Snowflake = new Snowflake ();
 
for (var k:int = 0; k < 1000; k++)
{
	snow.stars [k] = new Vertex (
		/* .x = */ w * (k - 500) / 500,
		/* .y = */ 600 * (Math.random () - 0.5),
		/* .z = */ (1000 - scene.camera.z) * Math.random () + scene.camera.z
	);
	snow.starSprites [k] = snowflake;
}
 
// set snow depth to -1 to bring it on top of trees
snow.depth = -1; scene.root.addChild (snow);

Just like with trees, we need same code to scroll the snow in enterFrameHandler:

// move snowflakes
for (var k:int = 0; k < snow.stars.length; k++) {
	snow.stars [k].z -= 10; if (snow.stars [k].z < scene.camera.z) snow.stars [k].z = 1000;
}

Unlike trees, however, snow is supposed to fall down, so we have to add another line to our loop:

// additionally, move them down
snow.stars [k].y -= 5; if (snow.stars [k].y < -300) snow.stars [k].y = 300;

Finally, to make it a bit more interesting, we will make snowflakes to swing from side to side a little:

// additionally, move them side to side
snow.stars [k].x = w * (k - 500) / 500 + 10 * Math.sin (snow.stars [k].y * 3e-2);

The result

If you actually followed the tutorial, you should have ended up with the code like this:

package {
	import flash.display.*;
	import flash.events.*
	import sandy.core.*;
	import sandy.core.data.*;
	import sandy.core.scenegraph.*;
	import sandy.primitive.*;
	import sandy.materials.*;
	import sandy.materials.attributes.*;

	public class Snowflakes extends Sprite {
		// screen size
		private var w = 400;
		private var h = 300;
		// sandy scene
		private var scene:Scene3D;
		// snowflakes starfield
		private var snow:StarField;
		// trees array
		private var trees:Array = [];


		public function Snowflakes () {
			// set up scene
			scene = new Scene3D ("", this, new Camera3D (w, h), new Group (""));
			scene.camera.near = 0;
			// set up snow
			snow = new StarField ();

			// TODO make snowflakes here
			var snowflake:Snowflake = new Snowflake ();

			for (var k:int = 0; k < 1000; k++)
			{
				snow.stars [k] = new Vertex (
					/* .x = */ w * (k - 500) / 500,
					/* .y = */ 600 * (Math.random () - 0.5),
					/* .z = */ (1000 - scene.camera.z) * Math.random () + scene.camera.z
				);
				snow.starSprites [k] = snowflake;
			}

			snow.depth = -1; scene.root.addChild (snow);

			// set up trees in the background
			var tree_bmp:BitmapData = new TreePng (1, 1);
			var darkness:Material = new Material (
				new MaterialAttributes (new MediumAttributes (0xFF000000,
					new Vector (0, 0, 300), new Vector (0, 0, 1000))));
			for (var i:int = 0; i < 16; i++)
			{
				trees [i] = new Sprite2D ("tree" + i, new Bitmap (tree_bmp),
					0.5 * (1 + Math.random ()));
				trees [i].autoCenter = false;
				trees [i].floorCenter = true;
				trees [i].x = w * (i - 8) / 8;
				trees [i].y = -tree_bmp.height;
				trees [i].z = (1000 - scene.camera.z) * Math.random () + scene.camera.z;
				trees [i].material = darkness;
 
				scene.root.addChild (trees [i]);
			}

			// subscribe to Event.ENTER_FRAME
			addEventListener (Event.ENTER_FRAME, enterFrameHandler);
		}


		private function enterFrameHandler (event:Event):void {
			// move trees
			for (var i:int = 0; i < trees.length; i++) {
				trees [i].z -= 10; if (trees [i].z < scene.camera.z) trees [i].z = 1000;
			}
			
			// move snowflakes
			for (var k:int = 0; k < snow.stars.length; k++) {
				snow.stars [k].z -= 10; if (snow.stars [k].z < scene.camera.z) snow.stars [k].z = 1000;
				// additionally, move them down
				snow.stars [k].y -= 5; if (snow.stars [k].y < -300) snow.stars [k].y = 300;
				// additionally, move them side to side
				snow.stars [k].x = w * (k - 500) / 500 + 10 * Math.sin (snow.stars [k].y * 3e-2);
			}

			// render the scene
			scene.render ();
		}
	}
}