Category Archives: Tutorials

Flash Optimization – Object Pooling

Flash optimization is becoming increasing important & with alternative development tools that developers can use. We all have a responsibility to build Flash elements that are efficient as much as they are groundbreaking. As someone who feels responsible for the future of this great application, I am creating a Flash Optimization series that will help educate the Flash development community on how to keep their Flash elements as lean as possible.

Another important optimization is called object pooling, which involves reusing objects over time.

You create a defined number of objects during the initialization of your application and store them inside a pool, such as an Array or Vector object. Once you are done with an object, you deactivate it so that it does not consume CPU resources, and
you remove all mutual references
.

However, you DO NOT set the references to null, which would make it eligible for garbage collection. You just put the object back into the pool, and retrieve it when you need a new object. Reusing objects reduces the need to instantiate objects, which can be expensive. It also reduces the chances of the garbage collector running, which can slow down your application. The following code illustrates the object pooling technique:


package
 {
 import flash.display.Sprite;

public final class SpritePool
 {
 private static var MAX_VALUE:uint;
 private static var GROWTH_VALUE:uint;
 private static var counter:uint;
 private static var pool:Vector.<Sprite>;
 private static var currentSprite:Sprite;

public static function initialize( maxPoolSize:uint, growthValue:uint ):void
 {
 MAX_VALUE = maxPoolSize;
 GROWTH_VALUE = growthValue;
 counter = maxPoolSize;

var i:uint = maxPoolSize;

pool = new Vector.<Sprite>(MAX_VALUE);
 while( –i > -1 )
 pool[i] = new Sprite();
 }

public static function getSprite():Sprite
 {
 if ( counter > 0 )
 return currentSprite = pool[--counter];

var i:uint = GROWTH_VALUE;
 while( –i > -1 )

pool.unshift ( new Sprite() );
 counter = GROWTH_VALUE;
 return getSprite();
 }

public static function disposeSprite(disposedSprite:Sprite):void
 {
 pool[counter++] = disposedSprite;
 }
 }
 }

The SpritePool class creates a pool of new objects at the initialization of the application.
The getSprite() method returns instances of these objects, and the disposeSprite() method releases them. The code allows the pool to grow when it has been consumed completely. It’s also possible to create a fixed-size pool where new objects would not be allocated when the pool is exhausted. Try to avoid creating new objects in loops, if possible.

The following code uses the SpritePool class to retrieve new instances:


const MAX_SPRITES:uint = 100;
 const GROWTH_VALUE:uint = MAX_SPRITES >> 1;
 const MAX_NUM:uint = 10;

SpritePool.initialize ( MAX_SPRITES,  GROWTH_VALUE );

var currentSprite:Sprite;
 var container:Sprite = SpritePool.getSprite();

addChild ( container );

for ( var i:int = 0; i< MAX_NUM; i++ )
 {
 for ( var j:int = 0; j< MAX_NUM; j++ )
 {
 currentSprite = SpritePool.getSprite();
 currentSprite.graphics.beginFill ( 0×990000 );
 currentSprite.graphics.drawCircle ( 10, 10, 10 );
 currentSprite.x = j * (currentSprite.width + 5);
 currentSprite.y = i * (currentSprite.width + 5);
 container.addChild ( currentSprite );
 }
 }

The following code removes all the display objects from the display list when the mouse is clicked, and reuses them
later for another task:


stage.addEventListener ( MouseEvent.CLICK, removeDots );

function removeDots ( e:MouseEvent ):void
 {
 while (container.numChildren > 0 )
 SpritePool.disposeSprite (container.removeChildAt(0) as Sprite );
 }

Note: The pool vector always references the Sprite objects. If you want to remove the object from memory completely, you
would need a dispose() method on the SpritePool class, which would remove all remaining references.

RSS Reader for FlashBannerOnline Blog!

Total primary goal , to create a tool with a different environment of the software available for more enjoyable to follow site information is complete and current version of growth and achieve sufficient as a tool for the complete facility Find and follow RSS feeds will , give your loved ones will be .

The current version of the program , the following features will provide you :
1 – View headlines last this blog content ( in future versions of supplemental feed Add the desired user can be created )
2 – Find a brief description in relation to content
3 – Settings related to the time information from server Refresh
4 – Settings related to the pause interval between each display
5 – Save the Last Data Feed and performance if being offline
And …

Images of the Environment Program :

Download :

Must install Adobe AIR is installed on your system.

Adobe Air format

ِDownload FlashBannerOnline RSS Reader (air format)

Adobe Air EXE format

ِDownload FlashBannerOnline RSS Reader (exe format)

Note :
To run on Windows 7 is better , right click on the program and click Run as administrator option to run the program .

Changes made in new versions

Version 1.1
Stop rotating display at the content display mouse button and box description , was added .

Version 1.0
First version created .
Bug :
If the problem or error in the program can be seen in the same comment more bug fixes and improvements to my program tell (with this post comment :D )

the Persian Language of this software update Here.

برای نصب می بایست Adobe AIR بر روی سیستم شما نصب باشد،

Flash Optimization – Reusing Objects

Flash optimization is becoming increasing important & with alternative development tools that developers can use. We all have a responsibility to build Flash elements that are efficient as much as they are groundbreaking. As someone who feels responsible for the future of this great application, I am creating a Flash Optimization series that will help educate the Flash development community on how to keep their Flash elements as lean as possible.

Another simple way to optimize memory is to reuse objects and avoid recreating them whenever possible.
For example, in a loop, do not use the following code:


const MAX_NUM:int = 18;
 const COLOR:uint = 0xCCCCCC;

var area:Rectangle;

for (var:int = 0; i < MAX_NUM; i++)
 {
 // Do not use the following code
 area = new Rectangle(i,0,1,10);
 myBitmapData.fillRect(area,COLOR);
 }

Recreating the Rectangle object in each loop iteration uses more memory and is slower because a new object is created
in each iteration
. Use the following approach:


const MAX_NUM:int = 18;
 const COLOR:uint = 0xCCCCCC;

// Create the rectangle outside the loop
 var area:Rectangle = new Rectangle(0,0,1,10);

for (var:int = 0; i < MAX_NUM; i++)
 {
 area.x = i;
 myBitmapData.fillRect(area,COLOR);
 }

The previous example used an object with a relatively small memory impact. The next example demonstrates larger
memory savings by reusing a BitmapData object. The following code to create a tiling effect wastes memory:


var myImage:BitmapData;
 var myContainer:Bitmap;
 const MAX_NUM:int = 300;

for (var i:int = 0; i< MAX_NUM; i++)
 {

// Create a 20 x 20 pixel bitmap, non-transparent
 myImage = new BitmapData(20,20,false,0xF0D062);

// Create a container for each BitmapData instance
 myContainer = new Bitmap(myImage);

// Add it to the display list
 addChild(myContainer);

// Place each container
 myContainer.x = (myContainer.width + 8 ) * Math.round(i % 20);
myContainer.y = (myContainer.height + 8 ) * int(i / 20);
 }

An optimized version creates a single BitmapData instance referenced by multiple Bitmap instances and produces the same result:


// Create a single 20 x 20 pixel bitmap, non-transparent
 var myImage:BitmapData = new BitmapData(20,20,false,0xF0D062);
 var myContainer:Bitmap;
 const MAX_NUM:int = 300;

for (var i:int = 0; i< MAX_NUM; i++)
 {
 // Create a container referencing the BitmapData instance
 myContainer = new Bitmap(myImage);

// Add it to the display list
 addChild(myContainer);

// Place each container
 myContainer.x = (myContainer.width + 8 ) * Math.round(i % 20);
myContainer.y = (myContainer.height + 8 ) * int(i / 20);
 }

This approach saves about 700 KB in memory, which is a significant savings on a traditional mobile device.

Flash Optimization – Display Objects

Flash optimization is becoming increasing important & with alternative development tools that developers can use. We all have a responsibility to build Flash elements that are efficient as much as they are groundbreaking. As someone who feels responsible for the future of this great application, I am creating a Flash Optimization series that will help educate the Flash development community on how to keep their Flash elements as lean as possible.

Continue reading

Understanding ActionScript3 Manages Depths

This tutorial will explain you how to manage AS3 sprites and depths, and what’s changed from AS2 to AS3.

In every Actionscript version, when two movieclips (or objects, shapes, texts…) overlap, the one with the greater depth stands in front of the other. You can think about depth as a Z coordinate.

The first difference between AS2 and AS3 is that AS2 allows you to leave “holes” in depths.

For example, you can declare the first object with a depth of 2 and the second one with a depth of 200… no matter if there isn’t any object with a depth between 3 and 199. In AS3, this is no longer possible.

To add an object to the stage, you must use addChild(object_name).
addChild() assigns the first free depth available, just like AS2 MovieClip.getNextHighestDepth()

So let’s add some objects to a movie:

package {
import flash.display.Shape;
import flash.display.Sprite;
public class depths extends Sprite {
public function depths() {
var blue_box:Shape = new Shape();
var red_box:Shape = new Shape();
blue_box.graphics.lineStyle(1);
blue_box.graphics.beginFill(0x0000FF, 1);
blue_box.graphics.drawRect(200,150,100,100);
red_box.graphics.lineStyle(1);
red_box.graphics.beginFill(0xFF0000, 1);
red_box.graphics.drawRect(220,170,100,100);
addChild(blue_box);
addChild(red_box);
}
}
}

This is the result: the red box is in front of the blue box because the red one was the last placed on the screen.

If you switch line 14 with line 15, the blue one will be the one on the top:

Sno now we know that the first child added with addChild() is placed at depth 0, the second one is placed at depth 1, and so on.
To know the depth value of an object, you can use getChildIndex(object_name);. So if you add this line:
trace(getChildIndex(red_box));
You will get a 1 in your output window.
To add an object at a specific depth position, you can use addChildAt(object_name, depth)

So let’s try this code:

package {
import flash.display.Shape;
import flash.display.Sprite;
public class depths extends Sprite {
public function depths() {
var blue_box:Shape = new Shape();
var red_box:Shape = new Shape();
blue_box.graphics.lineStyle(1);
blue_box.graphics.beginFill(0x0000FF, 1);
blue_box.graphics.drawRect(200,150,100,100);
red_box.graphics.lineStyle(1);
red_box.graphics.beginFill(0xFF0000, 1);
red_box.graphics.drawRect(220,170,100,100);
addChild(blue_box);
addChildAt(red_box,0);
}
}
}

Even if the red box was added after the blue box, it’s the blue one to stay on top because the red one was placed at depth zero.

That’s because if the specified depth is already taken by an existing object, then the new object is placed behind the existing one, whose depth is increased by one. So at the end of the script, the red box has depth zero, while the blue one has depth 1
You may ask: what if I change line 14 with addChildAt(blue_box,1);
You can’t… you will get an error because as I said at the beginning of this post, you can’t leave “holes” in depth. So you can’t place an object at depth 1 if there isn’t an object at depth 0.Using getChildIndex in a real life example, you can change line 15 with addChildAt(red_box,getChildIndex(blue_box));And you will get the same result.

Now, let’s see how to change depths dynamically.

package {
import flash.display.Shape;
import flash.display.Sprite;
public class depths extends Sprite {
public function depths() {
var blue_box:Shape = new Shape();
var red_box:Shape = new Shape();
blue_box.graphics.lineStyle(1);
blue_box.graphics.beginFill(0x0000FF, 1);
blue_box.graphics.drawRect(200,150,100,100);
red_box.graphics.lineStyle(1);
red_box.graphics.beginFill(0xFF0000, 1);
red_box.graphics.drawRect(220,170,100,100);
addChild(blue_box);
addChildAt(red_box,getChildIndex(blue_box));
swapChildren(red_box,blue_box);
}
}
}

At line 16 the swapChildren method swaps red box’s depth with the blue box one. So we’ll have the red box in front again

Another way to change depths dynamically is changing line 16 with:

setChildIndex(blue_box,0);

Putting the blue box to depth zero again and make the red one stay on the top of the screen.

This tutorial will explain you how to manage AS3 sprites and depths, and what’s changed from AS2 to AS3.

In every Actionscript version, when two movieclips (or objects, shapes, texts…) overlap, the one with the greater depth stands in front of the other. You can think about depth as a Z coordinate.

The first difference between AS2 and AS3 is that AS2 allows you to leave “holes” in depths.

For example, you can declare the first object with a depth of 2 and the second one with a depth of 200… no matter if there isn’t any object with a depth between 3 and 199. In AS3, this is no longer possible.

To add an object to the stage, you must use addChild(object_name).
addChild() assigns the first free depth available, just like AS2 MovieClip.getNextHighestDepth()

So let’s add some objects to a movie:

with() Statement in Actionscript 3

Often times, you will find yourself assigning many properties to one particular movie clip. Let’s say you have a movie clip instance called data_txt. Adding properties to it could look like this:

data_txt.text = "flashbanneronline.com!";
data_txt.x = 256;
data_txt.y = 145;
data_txt.alpha = 0.3;

Notice how you are repeating the word theContent. A better, cleaner method for referencing one particular object would be to use the with() statement.

The with() statement calls an object once and allows you to access all of the object’s properties and methods with only one reference. For example, using the with() statement, the above lines of code can be written as the following:

with(data_txt)
{

text = "flashbanneronline.com!";
x =256;
y =145;
alpha = 0.3;

}

I refer to data_txt only once! The with() statement may not be versatile enough to carry event handlers, but it does the work of referencing almost any class or object for you.

The following is an example of it working with the top level class Mouse:

with(Mouse)
{

hide();

}

In the above code snippet, I used a top level class and called its hide method.

You can also call nested objects inside the original object. Here is a diagram to better help you visualize what I am referring to:

The code for calling the secondObject object using with() would be:


with(firstObject)
{

secondObject.x = 110;

}


Here, I used a direct path to gain access to the properties of the nested secondObject object.

getting past IE popup blocker ActionScript3

can use this fix to bypass popups in IE…


/*

use this snippet in the as file to work with this class
 function  discoverBtnHandler(e:MouseEvent){

var popup:PassPopup = new PassPopup();
 // Open the popup window.
 popup.ChangePage( “http://blog.flashbanneronline.com/” );
 }

*/

package com {
 import flash.external.ExternalInterface;
 import flash.net.*;

public class PassPopup {
 public function ChangePage(url:*, window:String = “_blank”):void {
 var req:URLRequest = url is String ? new URLRequest(url) : url;
 if (!ExternalInterface.available) {
 navigateToURL(req, window);
 } else {
 var strUserAgent:String =  String(ExternalInterface.call(”function() {return  navigator.userAgent;}”)).toLowerCase();
 if (strUserAgent.indexOf(”firefox”) != -1 ||  (strUserAgent.indexOf(”msie”) != -1 &&  uint(strUserAgent.substr(strUserAgent.indexOf(”msie”) + 5, 3)) >= 7))  {
 ExternalInterface.call(”window.open”, req.url, window);
 } else {
 navigateToURL(req, window);
 }
 }
 }

}

}

and to use :


import com.neondust.external.PopupWindow;
 import com.neondust.external.PopupWindowDefaults;

var popup:PopupWindow = new PopupWindow();
 popup.width = WIDTH OF POPUP;
 popup.height = HEIGHT OF POPUP;
 popup.menuBar = false;
 popup.toolBar = false;
 popup.open( “YOUR HTML PAGE PATH” );

PopupWindow.as

//------------------------------------------------------------------------------
//
// COPYRIGHT © 2008 NEONDUST STUDIOS. ALL RIGHTS RESERVED.
//
//------------------------------------------------------------------------------
package com.neondust.external
{
	import flash.external.ExternalInterface;
	import flash.net.URLRequest;
	import flash.net.navigateToURL;

	/**
	 */
	public class PopupWindow
	{
		//----------------------------------------------------------------------
		//
		// PUBLIC CONSTANTS
		//
		//----------------------------------------------------------------------

		/**
		 * The name of the JavaScript function that will be used to open
		 * the popup window. The function should have the following signature:
		 *
		 * openPopupWindow( uri, name, opts )
		 */
		public static const OPEN_WINDOW_FUNCTION:String = "openPopupWindow";

		//----------------------------------------------------------------------
		//
		// PUBLIC PROPERTIES
		//
		//----------------------------------------------------------------------

		/**
		 * The x position of the popup window, in pixels. If this value is
		 * less than 0 the x position of the popup is set by the browser.
		 *
		 * @default -1
		 */
		public var x:int = PopupWindowDefaults.x;

		/**
		 * The y position of the popup window, in pixels. If this value is
		 * less than 0 the y position of the popup is set by the browser.
		 *
		 * @default -1
		 */
		public var y:int = PopupWindowDefaults.y;

		/**
		 * The width of the popup window, in pixels. If this value is
		 * less than 0 the width of the popup is set by the browser.
		 *
		 * @default -1
		 */
		public var width:int = PopupWindowDefaults.width;

		/**
		 * The height of the popup window, in pixels. If this value is
		 * less than 0 the height of the popup is set by the browser.
		 *
		 * @default -1
		 */
		public var height:int = PopupWindowDefaults.height;

		/**
		 * Indicates if the popup window menu bar should be displayed.
		 *
		 * @default false
		 */
		public var menuBar:Boolean = PopupWindowDefaults.menuBar;

		/**
		 * Indicates if the popup window tool bar should be displayed.
		 *
		 * @default false
		 */
		public var toolBar:Boolean = PopupWindowDefaults.toolBar;

		/**
		 * Indicates if the popup window location bar should be displayed.
		 *
		 * @default false
		 */
		public var locationBar:Boolean = PopupWindowDefaults.locationBar;

		/**
		 * Indicates if the popup window status bar should be displayed.
		 *
		 * @default false
		 */
		public var statusBar:Boolean = PopupWindowDefaults.statusBar;

		/**
		 * Indicates if the popup window scroll bars should be displayed.
		 *
		 * @default false
		 */
		public var scrollBars:Boolean = PopupWindowDefaults.scrollBars;

		/**
		 * Indicates if the popup window should be resizable.
		 *
		 * @default false
		 */
		public var resizable:Boolean = PopupWindowDefaults.resizable;

		//----------------------------------------------------------------------
		//
		// PRIVATE PROPERTIES
		//
		//----------------------------------------------------------------------

		/**
		 * @private
		 */
		private static var nextID:uint = 0;

		/**
		 * @private
		 */
		private var _uri:String = "";

		/**
		 * @private
		 */
		private var _name:String = "";

		//----------------------------------------------------------------------
		//
		// CONSTRUCTOR
		//
		//----------------------------------------------------------------------

		/**
		 */
		public function PopupWindow()
		{
			_name = "popupwindow_" + ( nextID ++ );
		}

		//----------------------------------------------------------------------
		//
		// PUBLIC METHODS
		//
		//----------------------------------------------------------------------

		/**
		 * Attempts to open a new popup window.
		 *
		 * @param uri
		 *        The URI of the page or file to load into the popup window.
		 */
		public function open( uri:String ):void
		{
			_uri = uri;

			var result:Boolean = false;

			if( ExternalInterface.available )
			{
				var func:String = OPEN_WINDOW_FUNCTION;
				var opts:String = optionsToString();

				result = ExternalInterface.call( func, uri, name, opts ) as Boolean;
			}

			if( result == false )
			{
				navigate();
			}
		}

		//----------------------------------------------------------------------
		//
		// PRIVATE METHODS
		//
		//----------------------------------------------------------------------

		/**
		 * @private
		 */
		private function navigate():void
		{
			var request:URLRequest = new URLRequest( uri );
			navigateToURL( request, "_blank" );
		}

		/**
		 * @private
		 */
		private function optionsToString():String
		{
			var opts:Array = [];

			if( x > -1 )
			{
				opts.push( "left=" + x );
			}

			if( y > -1 )
			{
				opts.push( "top=" + y );
			}

			if( width > -1 )
			{
				opts.push( "width=" + width );
				opts.push( "innerWidth=" + width );
			}

			if( height > -1 )
			{
				opts.push( "height=" + height );
				opts.push( "innerHeight=" + height );
			}

			opts.push( "menubar="    + ( menuBar     ? "yes" : "no" ) );
			opts.push( "toolbar="    + ( toolBar     ? "yes" : "no" ) );
			opts.push( "location="   + ( locationBar ? "yes" : "no" ) );
			opts.push( "status="     + ( statusBar   ? "yes" : "no" ) );
			opts.push( "scrollbars=" + ( scrollBars  ? "yes" : "no" ) );
			opts.push( "resizable="  + ( resizable   ? "yes" : "no" ) );

			return opts.join( "," );
		}

		//----------------------------------------------------------------------
		//
		// GETTERS/SETTERS
		//
		//----------------------------------------------------------------------

		/**
		 * The URI that was passed to the open() method. This value will be
		 * an empty string until the open() method is first invoked.
		 */
		public function get uri():String // read-only
		{
			return _uri;
		}

		/**
		 * The name of the popup window. This value is set internally by the
		 * PopupWindow class.
		 */
		public function get name():String // read-only
		{
			return _name;
		}

	}
}

PopupWindowDefaults.as

//------------------------------------------------------------------------------
//
// COPYRIGHT © 2008 NEONDUST STUDIOS. ALL RIGHTS RESERVED.
//
//------------------------------------------------------------------------------
package com.neondust.external
{
	/**
	 */
	public final class PopupWindowDefaults
	{
		//----------------------------------------------------------------------
		//
		// PUBLIC PROPERTIES
		//
		//----------------------------------------------------------------------

		/**
		 */
		public static var x:int = -1;

		/**
		 */
		public static var y:int = -1;

		/**
		 */
		public static var width:int = -1;

		/**
		 */
		public static var height:int = -1;

		/**
		 */
		public static var menuBar:Boolean = false;

		/**
		 */
		public static var toolBar:Boolean = false;

		/**
		 */
		public static var locationBar:Boolean = false;

		/**
		 */
		public static var statusBar:Boolean = false;

		/**
		 */
		public static var scrollBars:Boolean = false;

		/**
		 */
		public static var resizable:Boolean = false;

	}
}

//------------------------------------------------------------------------------
//
// COPYRIGHT © 2008 NEONDUST STUDIOS. ALL RIGHTS RESERVED.
//
//------------------------------------------------------------------------------
package com.neondust.external
{
	import flash.external.ExternalInterface;
	import flash.net.URLRequest;
	import flash.net.navigateToURL;

	/**
	 */
	public class PopupWindow
	{
		//----------------------------------------------------------------------
		//
		// PUBLIC CONSTANTS
		//
		//----------------------------------------------------------------------

		/**
		 * The name of the JavaScript function that will be used to open
		 * the popup window. The function should have the following signature:
		 *
		 * openPopupWindow( uri, name, opts )
		 */
		public static const OPEN_WINDOW_FUNCTION:String = "openPopupWindow";

		//----------------------------------------------------------------------
		//
		// PUBLIC PROPERTIES
		//
		//----------------------------------------------------------------------

		/**
		 * The x position of the popup window, in pixels. If this value is
		 * less than 0 the x position of the popup is set by the browser.
		 *
		 * @default -1
		 */
		public var x:int = PopupWindowDefaults.x;

		/**
		 * The y position of the popup window, in pixels. If this value is
		 * less than 0 the y position of the popup is set by the browser.
		 *
		 * @default -1
		 */
		public var y:int = PopupWindowDefaults.y;

		/**
		 * The width of the popup window, in pixels. If this value is
		 * less than 0 the width of the popup is set by the browser.
		 *
		 * @default -1
		 */
		public var width:int = PopupWindowDefaults.width;

		/**
		 * The height of the popup window, in pixels. If this value is
		 * less than 0 the height of the popup is set by the browser.
		 *
		 * @default -1
		 */
		public var height:int = PopupWindowDefaults.height;

		/**
		 * Indicates if the popup window menu bar should be displayed.
		 *
		 * @default false
		 */
		public var menuBar:Boolean = PopupWindowDefaults.menuBar;

		/**
		 * Indicates if the popup window tool bar should be displayed.
		 *
		 * @default false
		 */
		public var toolBar:Boolean = PopupWindowDefaults.toolBar;

		/**
		 * Indicates if the popup window location bar should be displayed.
		 *
		 * @default false
		 */
		public var locationBar:Boolean = PopupWindowDefaults.locationBar;

		/**
		 * Indicates if the popup window status bar should be displayed.
		 *
		 * @default false
		 */
		public var statusBar:Boolean = PopupWindowDefaults.statusBar;

		/**
		 * Indicates if the popup window scroll bars should be displayed.
		 *
		 * @default false
		 */
		public var scrollBars:Boolean = PopupWindowDefaults.scrollBars;

		/**
		 * Indicates if the popup window should be resizable.
		 *
		 * @default false
		 */
		public var resizable:Boolean = PopupWindowDefaults.resizable;

		//----------------------------------------------------------------------
		//
		// PRIVATE PROPERTIES
		//
		//----------------------------------------------------------------------

		/**
		 * @private
		 */
		private static var nextID:uint = 0;

		/**
		 * @private
		 */
		private var _uri:String = "";

		/**
		 * @private
		 */
		private var _name:String = "";

		//----------------------------------------------------------------------
		//
		// CONSTRUCTOR
		//
		//----------------------------------------------------------------------

		/**
		 */
		public function PopupWindow()
		{
			_name = "popupwindow_" + ( nextID ++ );
		}

		//----------------------------------------------------------------------
		//
		// PUBLIC METHODS
		//
		//----------------------------------------------------------------------

		/**
		 * Attempts to open a new popup window.
		 *
		 * @param uri
		 *        The URI of the page or file to load into the popup window.
		 */
		public function open( uri:String ):void
		{
			_uri = uri;

			var result:Boolean = false;

			if( ExternalInterface.available )
			{
				var func:String = OPEN_WINDOW_FUNCTION;
				var opts:String = optionsToString();

				result = ExternalInterface.call( func, uri, name, opts ) as Boolean;
			}

			if( result == false )
			{
				navigate();
			}
		}

		//----------------------------------------------------------------------
		//
		// PRIVATE METHODS
		//
		//----------------------------------------------------------------------

		/**
		 * @private
		 */
		private function navigate():void
		{
			var request:URLRequest = new URLRequest( uri );
			navigateToURL( request, "_blank" );
		}

		/**
		 * @private
		 */
		private function optionsToString():String
		{
			var opts:Array = [];

			if( x > -1 )
			{
				opts.push( "left=" + x );
			}

			if( y > -1 )
			{
				opts.push( "top=" + y );
			}

			if( width > -1 )
			{
				opts.push( "width=" + width );
				opts.push( "innerWidth=" + width );
			}

			if( height > -1 )
			{
				opts.push( "height=" + height );
				opts.push( "innerHeight=" + height );
			}

			opts.push( "menubar="    + ( menuBar     ? "yes" : "no" ) );
			opts.push( "toolbar="    + ( toolBar     ? "yes" : "no" ) );
			opts.push( "location="   + ( locationBar ? "yes" : "no" ) );
			opts.push( "status="     + ( statusBar   ? "yes" : "no" ) );
			opts.push( "scrollbars=" + ( scrollBars  ? "yes" : "no" ) );
			opts.push( "resizable="  + ( resizable   ? "yes" : "no" ) );

			return opts.join( "," );
		}

		//----------------------------------------------------------------------
		//
		// GETTERS/SETTERS
		//
		//----------------------------------------------------------------------

		/**
		 * The URI that was passed to the open() method. This value will be
		 * an empty string until the open() method is first invoked.
		 */
		public function get uri():String // read-only
		{
			return _uri;
		}

		/**
		 * The name of the popup window. This value is set internally by the
		 * PopupWindow class.
		 */
		public function get name():String // read-only
		{
			return _name;
		}

	}
}

Creating snow with Flint Particle Class AS3

Getting Started

Grab the source code, documentation and examples for the latest version of Flint. Either grab the current downloads of each or check out the latest code from the GitHub or Google Code repositories.

Introduction

This first tutorial will introduce the basics of Flint through a project to create a snow effect. Our effect will be snow flakes drifting down the screen. Each snow flake will be a particle in our particle system. If you want to see the final effect, scroll to the bottom of the page. This tutorial works with all versions of the Flint library since 2.0.0. This example creates a 2D particle effect. For 3D particle effects the principles are the same but you use a 3D emitter and 3D behaviours.

Because this is an introduction, I’ll work from the assumption that the user is writing frame scripts in Flash CS3. At the end I’ll summarize how to modify the script to use it within class based development in Flash CS3 or Flex.

Getting started

First create a new Flash file (Actionscript 3). Set the stage size to 500 pixels wide and 400 pixels high, set the frame rate to 30 fps and set the background color to black.

We’ll not need to add anything other than code to the flash movie but you do need to make sure that the flint library is in the classpath for the project. See the Flash help for info on how to do this.

Open the actions window to create a script in the first frame of the movie. Our script will need a lot of imports so I’ll just get them all out of the way at the beginning here. So place the following code at the start of the script so that Flash can find all the class files it needs from the Flint library.


import flash.geom.Point;
import org.flintparticles.common.counters.*;
import org.flintparticles.common.displayObjects.RadialDot;
import org.flintparticles.common.initializers.*;
import org.flintparticles.twoD.actions.*;
import org.flintparticles.twoD.emitters.Emitter2D;
import org.flintparticles.twoD.initializers.*;
import org.flintparticles.twoD.renderers.*;
import org.flintparticles.twoD.zones.*;

The Emitter

In Flint, particles are created by emitters. We don’t create the particles, we create the emitter and the emitter creates the particles. So lets create an emitter.


var emitter:Emitter2D = new Emitter2D();

This creates an emitter for creating 2D particle effects.

The Renderer

Our emitter needs a renderer. A renderer draws the particles on the screen. The different types of renderers use different techniques to draw the particles. In this tutorial we’ll use a DisplayObject renderer. The renderer is itself a DisplayObject so we can simply add it to the display list just like any other display object. So lets create our renderer and place it on the stage.


var renderer:DisplayObjectRenderer = new DisplayObjectRenderer();
addChild( renderer );

We add the emitter to the renderer so that the renderer will draw the emitter’s particles.


renderer.addEmitter( emitter );

You can add any number of emitters to one renderer to create complex particle effects, and you can also add an emitter to any number of renderers to create multiple views of the same particle effect.

The Counter

Our emitter needs to know how often to create a new particle. To do this we add a counter to the emitter. Flint has a number of counters, for creating a steady stream of particles, a single blast of particles, and various other types of activity. We want to keep creating new snowflakes so we’ll use a Steady counter to create a steady supply of snowflakes. We add the counter to the emitter using the counter property of the emitter, like this…


emitter.counter = new Steady( 100 );

The 100 indicates we want our emitter to create one hunderd particles every second.

Particle Initializers

We have to tell the emitter how to set up our particles. The sort of things we want to set up are the particle’s position, velocity, image and color. To set up the particles we add initializers to the emitter. Each initializer sets some property or properties of the particle.

The first thing we’ll do is tell the emitter what the particles should look like. We’re using a DisplayObjectEmitter so our emitter will create a new DisplayObject for each particle. We’ll use the ImageClass initializer to tell the emitter what type of DisplayObject to create for each particle.

If we had an image in our library that we want to use we would export the image for use in Actionscript and pass the Class it’s exported as to the ImageClass constructor like this (in Flex, we’d embed the image in the project and use the associated class in the same way).


var imgClass:ImageClass = new ImageClass( MyImageClass );

However, I’m going to use the RadialDot class that is in the Flint library. The RadialDot class is a simple circular image with a gradient fill. The constructor for the dot class takes an argument which is the radius of the dot, which we’ll set to 2 pixels, so we also have to pass this value to the ImageClass constructor like this…

var imgClass:ImageClass = new ImageClass( RadialDot, 2 );

We then add the ImageClass initializer to the emitter like this…

emitter.addInitializer( imgClass );

Alternatively, we could combine the previous two lines of code into one line like this…

emitter.addInitializer( new ImageClass( RadialDot, 2 ) );

Using Zones

Next we add a Position initializer to place the particle in the right position on screen. The Position initializer uses a Zone. A zone is a defined area of the particle system. Flint has classes to define various shapes of zone in the org.flintparticles.twoD.zones package. When you pass a zone to the Position initializer you are telling the initializer to place the particle at a random point within that zone.

We want all our particles to be placed just above the top of the stage so that they fall into the stage from above. To do this we use a LineZone placed just above the top of the stage so that the particles are placed anywhere along this line.

var zone:LineZone = new LineZone( new Point( -5, -5 ), new Point( 505, -5 ) );
var position:Position = new Position( zone );
emitter.addInitializer( position );

The LineZone is five pixels above the top of the stage and extends five pixels to either side of the stage (remember our stage is 500 pixels wide). The particles will start from a random position along this line. Once again, if we wish we can combine these three lines of code into one longer line like this…

emitter.addInitializer( new Position( new LineZone( new Point( -5, -5 ), new Point( 505, -5 ) ) ) );

Now our particles are placed properly, we need to make them move. For them to move they need to have a velocity and to do this we add a Velocity initializer to the emitter.

Perhaps surprisingly, the Velocity initializer also uses a zone to obtain its value. To see how this works, imagine a line zone as used above. Then imagine that the particle is at point 0,0 and that we have a random point within the zone. The particle will be given an initial velocity such that it will reach that point within one second. In other words the velocity vector is the vector from the origin to a random point inside the zone.

For now, we want all our particles to drop down the screen at exactly the same speed, so we use the simplest of zones – a PointZone. Because a PointZone only contains a single point, it will always set the velocity to the coordinates of that point. To fall down the screen, we want the x value in the velocity to be zero and the y value to be something bigger than zero.

So we set up the Velocity initializer like this…

var zone2:PointZone = new PointZone( new Point( 0, 65 ) );
var velocity:Velocity = new Velocity( zone2 );
emitter.addInitializer( velocity );

Or, in a single line, like this…

emitter.addInitializer( new Velocity( new PointZone( new Point( 0, 65 ) ) ) );

Using zones to define velocity may look complicated, but it enables us to create some great effects like the logo firework in the examples section.

Using Actions

If we ran the movie now, we’d still not see any particles. To round things off we need to add some actions to the emitter.

While Initializers modify the properties of a particle once, when it is created, Actions modify the properties of the particles continuously after they have been created.

To get started, we only need to add one action to our emitter. Although the particles have a position and a velocity, we have to add an action to update the particle’s position every frame, based on the value of its velocity. To do this we use the Move action.

We add the Move action like this…

var move:Move = new Move();
emitter.addAction( move );

Or, in a single line, like this…

emitter.addAction( new Move() );

Starting the emitter

Now that the emitter knows when to create particles, how to initialize them and what actions to perform on them while they’re there we’re only left with the job of starting the emitter.

emitter.start();

Your code should now look something like this…

import flash.geom.Point;
import org.flintparticles.common.counters.*;
import org.flintparticles.common.displayObjects.RadialDot;
import org.flintparticles.common.initializers.*;
import org.flintparticles.twoD.actions.*;
import org.flintparticles.twoD.emitters.Emitter2D;
import org.flintparticles.twoD.initializers.*;
import org.flintparticles.twoD.renderers.*;
import org.flintparticles.twoD.zones.*;

var emitter:Emitter2D = new Emitter2D();

var renderer:DisplayObjectRenderer = new DisplayObjectRenderer();
addChild( renderer );
renderer.addEmitter( emitter );

emitter.counter = new Steady( 100 );

emitter.addInitializer( new ImageClass( RadialDot, 2 ) );
emitter.addInitializer( new Position( new LineZone( new Point( -5, -5 ), new Point( 505, -5 ) ) ) );
emitter.addInitializer( new Velocity( new PointZone( new Point( 0, 65 ) ) ) );

emitter.addAction( new Move() );

emitter.start();

and when you test the flash movie you should see lots of white snowflakes falling down the screen.

Removing the particles

With the current code we never remove the particles. When they get to the bottom of the screen they just keep going. Eventually the flash movie will slow down and maybe even crash because it has too many particles to manage, so we need to remove the particles when they leave the screen. To do this we use the dramatically titled DeathZone action.

The DeathZone action checks whether particles are outside (or inside) a defined zone and destroys them if they are. We’ll use a rectangular zone slightly bigger than the stage and destroy all particles that are outside this zone. The code looks like this…

var dzone:RectangleZone = new RectangleZone( -10, -10, 520, 420 );
var deathZone:DeathZone = new DeathZone( dzone, true );
emitter.addAction( deathZone );

Or in one line of code

emitter.addInitializer( new ScaleImageInit( 0.75, 2 ) );

Finally, we’ll add some random drifting movement to the snow flakes. Because snow flakes are light they tend to drift about in the air currents. We can use the RandomDrift action to make the snow flakes drift around. The RandomDrift constructor takes two parameters; the maximum horizontal drift per second and the maximum vertical drift per second. We add it to the emitter like this…

var drift:RandomDrift = new RandomDrift( 15, 15 );
emitter.addAction( drift );

Or in one line of code

emitter.addAction( new RandomDrift( 15, 15 ) );

Running ahead

If you test the movie now it should look a lot more realistic. The only problem is, the screen really ought to be full of snowflakes when the movie starts. To make this happen, we tell the emitter to run on ahead a few seconds at the start, like this…

emitter.runAhead( 10 );

This causes the emitter to process ten seconds of movement immediately, so we start ten seconds in with a screen full of particles.

Finished

The complete code looks like this (I’ve rearranged the order a little for clarity)

import flash.geom.Point;
import org.flintparticles.common.counters.*;
import org.flintparticles.common.displayObjects.RadialDot;
import org.flintparticles.common.initializers.*;
import org.flintparticles.twoD.actions.*;
import org.flintparticles.twoD.emitters.Emitter2D;
import org.flintparticles.twoD.initializers.*;
import org.flintparticles.twoD.renderers.*;
import org.flintparticles.twoD.zones.*;

var emitter:Emitter2D = new Emitter2D();

emitter.counter = new Steady( 100 );

emitter.addInitializer( new ImageClass( RadialDot, 2 ) );
emitter.addInitializer( new Position( new LineZone( new Point( -5, -5 ), new Point( 505, -5 ) ) ) );
emitter.addInitializer( new Velocity( new PointZone( new Point( 0, 65 ) ) ) );
emitter.addInitializer( new ScaleImageInit( 0.75, 2 ) );

emitter.addAction( new Move() );
emitter.addAction( new DeathZone( new RectangleZone( -10, -10, 520, 420 ), true ) );
emitter.addAction( new RandomDrift( 15, 15 ) );

var renderer:DisplayObjectRenderer = new DisplayObjectRenderer();
addChild( renderer );
renderer.addEmitter( emitter );

emitter.start();
emitter.runAhead( 10 );

Using classes

If you want to program this with classes you have two options. The first is simply to place the above code in the constructor for you document class. The second is to create a custom emitter for the snow effect. Here’s what that custom emitter would look like…

package
{
  import flash.geom.Point;
  import org.flintparticles.common.counters.*;
  import org.flintparticles.common.displayObjects.RadialDot;
  import org.flintparticles.common.initializers.*;
  import org.flintparticles.twoD.actions.*;
  import org.flintparticles.twoD.emitters.Emitter2D;
  import org.flintparticles.twoD.initializers.*;
  import org.flintparticles.twoD.zones.*;

  public class Snowfall extends Emitter2D
  {
    public function Snowfall()
    {
      counter = new Steady( 100 );

      addInitializer( new ImageClass( RadialDot, 2 ) );
      addInitializer( new Position( new LineZone( new Point( -5, -5 ), new Point( 505, -5 ) ) ) );
      addInitializer( new Velocity( new PointZone( new Point( 0, 65 ) ) ) );
      addInitializer( new ScaleImageInit( 0.75, 2 ) );

      addAction( new Move() );
      addAction( new DeathZone( new RectangleZone( -10, -10, 520, 420 ), true ) );
      addAction( new RandomDrift( 15, 15 ) );
    }
  }
}

You then create an instance of this class, add it to a renderer and start it off like this…

import flash.geom.Point;
import org.flintparticles.twoD.renderers.*;

var emitter:Snowfall = new Snowfall();

var renderer:DisplayObjectRenderer = new DisplayObjectRenderer();
renderer.addEmitter( emitter );
addChild( renderer );

emitter.start();
emitter.runAhead( 10 );
import flash.geom.Point;
import org.flintparticles.common.counters.*;
import org.flintparticles.common.displayObjects.RadialDot;
import org.flintparticles.common.initializers.*;
import org.flintparticles.twoD.actions.*;
import org.flintparticles.twoD.emitters.Emitter2D;
import org.flintparticles.twoD.initializers.*;
import org.flintparticles.twoD.renderers.*;
import org.flintparticles.twoD.zones.*;