<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Lon Hosford&#039;s Bitbox &#187; Flex</title>
	<atom:link href="http://www.lonhosford.com/lonblog/category/technologies/adobe/flex/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.lonhosford.com/lonblog</link>
	<description>Lon (Alonzo) Hosford&#039;s Professional Consulting Blog</description>
	<lastBuildDate>Fri, 03 Feb 2012 00:55:07 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Using ExternalInterface To Send Messages to Firebug Console</title>
		<link>http://www.lonhosford.com/lonblog/2011/01/29/using-externalinterface-to-send-messages-to-firebug-console/</link>
		<comments>http://www.lonhosford.com/lonblog/2011/01/29/using-externalinterface-to-send-messages-to-firebug-console/#comments</comments>
		<pubDate>Sat, 29 Jan 2011 20:41:23 +0000</pubDate>
		<dc:creator>Lon Hosford</dc:creator>
				<category><![CDATA[Actionscript 3]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[Actionscript]]></category>
		<category><![CDATA[ExternalInterface]]></category>

		<guid isPermaLink="false">http://www.lonhosford.com/lonblog/?p=1274</guid>
		<description><![CDATA[There are times that you do not have the debugger version of Flash Player running when testing in a web browser so you cannot use various extensions and plugins such as Flashbug that will display Actionscript tracing to the browser window. Flashbug is a Firefox Firebug extension. However you can use the Firebug console window [...]]]></description>
			<content:encoded><![CDATA[<p>There are times that you do not have the debugger version of Flash Player running when testing in a web browser so you cannot use various extensions and plugins such as <a href="https://addons.mozilla.org/en-US/firefox/addon/flashbug/" target = "_blank">Flashbug</a> that will display Actionscript tracing to the browser window. <img alt="" src="https://lh3.googleusercontent.com/_e5pwU0LJbN8/TUR6_4ErS3I/AAAAAAAAFyQ/KAIXHNv-3GM/s800/FirebugExternalInterface_published.png" class="alignleft" width="337" height="232" /> <a href="https://addons.mozilla.org/en-US/firefox/addon/flashbug/" target = "_blank">Flashbug</a> is a Firefox <a href="http://getfirebug.com/" target = "_blank">Firebug</a> extension.</p>
<p>However you can use the <a href="http://getfirebug.com/" target = "_blank">Firebug</a> console window directly from Actionscript using ExternalInterface. In fact you can use it for sending messages to any Javascript console you may have created or use. </p>
<p>ExternalInterface allows you to call Javascript function from within Actionscript. So we can apply it to calling the Firebug console.log method as well. </p>
<p>I have seen other examples of this code on the internet. Most have a few problems with handling errors. The most egregious is not testing if there is a Firebug console available. The problem is that it is easy to overlook removing Firebug console.log statements when you are working in Javascript. The result is errors when viewing the page in a browser like IE or any browser not having Firebug. The same applies to Actionscript calling Javascript functions. A test is needed to verify that the console.log method is available.</p>
<p>Second it the matter of fact inclusion of testing if ExternalInterface is available. ExternalInterface does not support all web browsers. You can check this out on the <a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/external/ExternalInterface.html?filter_flex=4.1&#038;filter_flashplayer=10.1&#038;filter_air=2"  target = "_blank">ExternalInterface documentation page</a>.</p>
<p>This example contains a method you can add to a class in your Flash or Flex classes and call. </p>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
<strong>Sending a Message To Firebug console.log Method</strong></p>
<p>This log method demonstrates code you might want to use. I gave it two purposes. One to trace to the standard Flash log you see on line 3. The second is to trace to the Firebug console. Putting all of this into one method makes it easy enough to turn off all tracing by commenting out the body of the method. Of course you may want to integrate this into a singleton class and use it throughout your code.</p>
<p>Line 4 insures the browser has ExternalInterface capability available.</p>
<p>Lines 7 to 9 compose a anonymous Javascript function that looks like this:<br />
<code>function(){if (window.console) console.log('Hello World');}</code></p>
<p>Then line 11 calls the function.</p>
<pre class="brush: as3; wrap-lines: false;">
		private function log(message:String):void
		{
			trace (message);
			if (ExternalInterface.available)
			{
				// Create Javascript function to call the Firebug console log method and append the message.
				message = &quot;function(){if (window.console) console.log('&quot; + message;
				// Close the Firebug console log method and the Javascript function.
				message +=  &quot;');}&quot;;
				// Request running the function.
				ExternalInterface.call(message);
			}
		}
</pre>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div></p>
<p>To use the function, simply call it with your tracing message and you will get the message both in the regular Flash trace consoles you are using and as well in the Firebug console.</p>
<pre class="brush: as3; wrap-lines: false;">
log(&quot;Hello Firebug Console From Actionscript&quot;);
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.lonhosford.com/lonblog/2011/01/29/using-externalinterface-to-send-messages-to-firebug-console/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Read Flash SWF Header in AIR with Parsley Framework</title>
		<link>http://www.lonhosford.com/lonblog/2011/01/17/read-flash-swf-header-in-air-with-parsley-framework/</link>
		<comments>http://www.lonhosford.com/lonblog/2011/01/17/read-flash-swf-header-in-air-with-parsley-framework/#comments</comments>
		<pubDate>Mon, 17 Jan 2011 18:34:47 +0000</pubDate>
		<dc:creator>Lon Hosford</dc:creator>
				<category><![CDATA[AIR (Adobe Integrated Runtime)]]></category>
		<category><![CDATA[Actionscript 3]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[Parsley]]></category>
		<category><![CDATA[Actionscript]]></category>
		<category><![CDATA[Air]]></category>
		<category><![CDATA[BorderContainer]]></category>
		<category><![CDATA[Flex 4]]></category>

		<guid isPermaLink="false">http://www.lonhosford.com/lonblog/?p=1204</guid>
		<description><![CDATA[I was asked to look for open source tools to read the basic information contained in a Flash swf file. Most of the items you find are for reverse engineering swf files. In the search process I found two sources to parse the swf file header. The first was a php script written by Carlos [...]]]></description>
			<content:encoded><![CDATA[<p>I was asked to look for open source tools to read the basic information contained in a Flash swf file. Most of the items you find are for reverse engineering swf files. In the search process I found two sources to parse the swf file header. <img alt="" src="http://lh6.ggpht.com/_e5pwU0LJbN8/TTSEk55KhzI/AAAAAAAAFxY/LhkeY0x2TOA/s800/adobe-swf_header_published.png" class="alignleft" width="400" height="235" /></p>
<p>The first was a <a href="http://www.fecj.org/extra/SWF-info-and-Frame-Rate-extraction.html"  target = "_blank">php script</a> written by Carlos Falo Hervá. You need to scroll down to the end of the post to find his work. This works just fine if you want to run off a server. </p>
<p>The second is <a href="http://simplistika.com/parsing-reading-swf-header/"  target = "_blank">written in Actionscript</a> for Flash CS5. Only the author&#8217;s handle, jared, and not the author&#8217;s name is not available at the site. The download works nice and you can run from the author&#8217;s web page. You need type or paste in a url for the swf file name. The code is all dropped in on the first frame.</p>
<p>This site also provided a nice link to the <a href="http://www.adobe.com/content/dam/Adobe/en/devnet/swf/pdf/swf_file_format_spec_v10.pdf"  target = "_blank">Adobe SWF file version 10 specifications</a> if you care to know. Page 25 has the key information on the SWF header. This is also repeated in the SWFHeaderParser parser class presented in this post.</p>
<p>I took the code for the second example and created a drag and drop version Adobe Air. First I separated the code into two Actionscript classes. One for parsing and one for loading swf file bytes. These classes are named respectively SWFHeaderParser and SWFHeaderLoader. I added a value object, SWFHeader_vo, to pass around the values. </p>
<p>I glued those items together in an Air project using the Parsley framework. This gave me a chance to use Parsley DynamicObject for the SWFHeaderLoader class that loads the SWF file for the parser.</p>
<p>The result is a fully decoupled version that serves as a super example of model-view-controller using Parsley for an Air app.</p>
<p>Download files:<br />
Here is the Flex project if you want to explore the code and the Air installer in case you just want the tool.</p>
<ul style = "padding-top:10px">
<li><a href="http://www.lonhosford.com/content/flex/swf/SWFHeader_Air.fxp"  onClick="javascript: pageTracker._trackPageview('/downloads/SWFHeader_Air.fxp'); ">Flex Builder 4 Flex Project</a></li>
<li><a href="http://www.lonhosford.com/content/flex/swf/SWFHeader.air"  onClick="javascript: pageTracker._trackPageview('/downloads/SWFHeader.air'); ">Adobe Air Installer</a></li>
</ul>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div></p>
<p><strong>SWF Parser &#8211; SWFHeaderParser.as</strong><br />
The parser class is first as that is what you might want to integrate into your code. Note it returns the SWFHeader_vo class. The comments are scant in this class since I did write the code and only converted it into a class, returned a value object and removed code not specific to parsing the bytes. The value object is created and populated on lines 85 &#8211; 95.</p>
<pre class="brush: as3; wrap-lines: false;">
package swf
{
	import flash.geom.Rectangle;
	import flash.utils.ByteArray;
	import flash.utils.Endian;
	import vo.SWFHeader_vo;
	/**
	 * SWF Header parsing. Code adapted from http://simplistika.com/parsing-reading-swf-header/.
	 * */
	public class SWFHeaderParser
	{
		private var xByte : uint;
		private var xNBits : int;
		private var xOffset : int;
		public function SWFHeaderParser()
		{
		}
		/**
		 * Get a SWFHeader_vo object from a ByteArray
		 * @param swfByteArray Any byte array, but expecting a SWF binary file or header from SWF file.
		 * @return Parsed values in SWFHeader_vo object.
		 * */
		public function parseBytes(swfByteArray : ByteArray) : SWFHeader_vo
		{
			return fParse(swfByteArray);
		}
		/**
		 * Original code from http://simplistika.com/parsing-reading-swf-header/ changed to
		 * return SWFHeader_vo object.
		 * */
		private function fParse(v : ByteArray) : SWFHeader_vo
		{
			/*
			Field		Type 	Comment
								Signature byte
			Signature	UI8		&quot;F&quot; indicates uncompressed
								&quot;C&quot; indicates compressed (SWF 6 and later only)
			Signature	UI8		Signature byte always &quot;W&quot;
			Signature	UI8		Signature byte always &quot;S&quot;

			Version		UI8		Single byte file version
			FileLength	UI32	Length of entire file in bytes
			FrameSize	RECT	Frame size in twips
			FrameRate	UI16	Frame delay in 8.8 fixed number of frames per second
			FrameCount	UI16	Total number of frames in file
			The header begins with a three-byte signature of either 0×46, 0×57, 0×53 (&quot;FWS&quot;); or 0×43, 0×57, 0×53 (“CWS”). An FWS signature indicates an uncompressed SWF file; CWS indicates that the entire file after the first 8 bytes (that is, after the FileLength field) was compressed by using the ZLIB open standard. The data format that the ZLIB library uses is described by Request for Comments (RFCs) documents 1950 to 1952. CWS file compression is permitted in SWF 6 or later only.

			A one-byte version number follows the signature.
			The version number is not an ASCII character,
			but an 8-bit number. For example, for SWF 4, the version byte is 0×04, not the
			ASCII character “4? (0×34). The FileLength field is the total length of the
			SWF file, including the header. If this is an uncompressed SWF file (FWS signature),
			the FileLength field should exactly match the file size. If this is a compressed SWF file
			(CWS signature), the FileLength field indicates the total length of the file after decompression,
			and thus generally does not match the file size. Having the uncompressed size available can make
			the decompression process more efficient. The FrameSize field defines the width and height
			of the on-screen display. This field is stored as a RECT structure, meaning that its size
			may vary according to the number of bits needed to encode the coordinates. The FrameSize
			RECT always has Xmin and Ymin value of 0; the Xmax and Ymax members define the width and
			height. The FrameRate is the desired playback rate in frames per second.

			Source: http://simplistika.com/parsing-reading-swf-header/

			*/
			var vFormat : String;
			var vSwfVersion : int;
			var vFileLength : int;
			var vFrameRate : int;
			var vTotalFrames : int;
			var vFrameSize : Rectangle;
			v.endian = Endian.LITTLE_ENDIAN;
			vFormat = v.readUTFBytes(3);
			vSwfVersion = v.readByte();
			vFileLength = v.readUnsignedInt();
			v.readBytes(v);
			v.length -= 8;
			if (vFormat == &quot;CWS&quot;)
				v.uncompress();
			v.position = 0;
			vFrameSize = new Rectangle();
			vFrameSize.left = xfReadNBits(v, true) / 20;
			vFrameSize.right = xfReadNBits(v) / 20;
			vFrameSize.top = xfReadNBits(v) / 20;
			vFrameSize.bottom = xfReadNBits(v) / 20;
			vFrameRate = v.readUnsignedByte() / 256 + v.readUnsignedByte();
			vTotalFrames = v.readUnsignedShort();
			var swfHeader_vo:SWFHeader_vo = new SWFHeader_vo();
			swfHeader_vo.format = vFormat;
			swfHeader_vo.swfVersion = vSwfVersion;
			swfHeader_vo.sizeUncompressed = vFileLength;
			swfHeader_vo.width = vFrameSize.width;
			swfHeader_vo.height =vFrameSize.height;
			swfHeader_vo.frameRate = vFrameRate;
			swfHeader_vo.totalFrames = vTotalFrames;
			return swfHeader_vo;
		}
		/**
		 * Original code from http://simplistika.com/parsing-reading-swf-header/.
		 * */
		private function xfReadNBits(v : ByteArray, vStart : Boolean = false) : uint
		{
			var n : uint;
			if (vStart)
			{
				xByte = v.readUnsignedByte();
				xNBits = xByte &gt;&gt; 3;
				xOffset = 3;
			}
			n = xByte &lt;&lt; (32 - xOffset) &gt;&gt; (32 - xNBits);
			xOffset -= xNBits;
			while (xOffset &lt; 0)
			{
				xByte = v.readUnsignedByte();
				n |= (xOffset &lt; -8) ? (xByte &lt;&lt; (-xOffset - 8)) : (xByte &gt;&gt; (-xOffset - 8));
				xOffset += 8;
			}
			return n;
		}
	}
}
</pre>
<p><strong>SWF Loader &#8211; SWFHeaderLoader.as</strong><br />
This is my class to load the SWF and it uses Parsley messaging. If you do not intend to use Parsley, you need to add your own messaging. </p>
<p>Most of this is standard URLLoader coding. </p>
<p>The SWFHeaderParser is called on line 62. On line 63, the actual bytes are not gotten from the SWFHeaderParser. So it can be a bit misleading that that is information found in the SWF header. The SWF header only contains the uncompressed file size.</p>
<pre class="brush: as3; wrap-lines: false;">
package swf
{
	import events.SWFHeaderLoaderCompleteEvent;
	import events.SWFHeaderLoaderErrorEvent;
	import events.SWFHeaderLoaderProgressEvent;
	import flash.events.Event;
	import flash.events.HTTPStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import models.SWFHeaderModel;
	import vo.SWFHeader_vo;
	/**
	 * Byte loader for a SWF file.
	 * */
	public class SWFHeaderLoader
	{
		/**
		 * Has a URLLoader
		 * */
		private var urlLoader:URLLoader;
		/**
		 * Model
		 * */
		[Inject]
		public var model:SWFHeaderModel;
		/**
		 * Receives Parsley messages.
		 * */
		[MessageDispatcher]
		public var dispatcher:Function;
		/**
		 * Load the bytes from a file.
		 * */
		public function load(url:String):void
		{
			urlLoader = new URLLoader();
			urlLoader.addEventListener(Event.COMPLETE, urlLoader_completeEventHandler);
			urlLoader.addEventListener(ProgressEvent.PROGRESS, urlLoader_progressHandler);
			urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, urlLoader_securityErrorHandler);
			urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, urlLoader_httpStatusHandler);
			urlLoader.addEventListener(IOErrorEvent.IO_ERROR, urlLoader_ioErrorHandler);
			urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
			urlLoader.load( new URLRequest(url) );
		}
		/**
		 * Handler for the urlLoader ProgressEvent.PROGRESS event.
		 * */
		private function urlLoader_progressHandler(event:ProgressEvent):void
		{
			dispatcher(new SWFHeaderLoaderProgressEvent(SWFHeaderLoaderProgressEvent.PROGRESS, event.bytesLoaded, event.bytesTotal));
		}
		/**
		 * Handler for the urlLoader Event.COMPLETE event.
		 * */
		private function urlLoader_completeEventHandler(event:Event):void
		{
			var swfHeader_vo:SWFHeader_vo = new SWFHeader_vo();
			swfHeader_vo  = new SWFHeaderParser().parseBytes(urlLoader.data);
			swfHeader_vo.sizeCompressed = urlLoader.bytesLoaded;
			dispatcher(new SWFHeaderLoaderCompleteEvent(SWFHeaderLoaderCompleteEvent.COMPLETE, swfHeader_vo));
		}
		/**
		 * Handler for the urlLoader SecurityErrorEvent.SECURITY_ERROR event.
		 * */
		private function urlLoader_securityErrorHandler(event:SecurityErrorEvent):void
		{
			dispatcher(new SWFHeaderLoaderErrorEvent(SWFHeaderLoaderErrorEvent.SECURITY_ERROR));
		}
		/**
		 * Handler for the urlLoader HTTPStatusEvent.HTTP_STATUS event.
		 * */
		private function urlLoader_httpStatusHandler(event:HTTPStatusEvent):void
		{
			if (event.status != 200 &amp;&amp; event.status != 0)
			{
				dispatcher(new SWFHeaderLoaderErrorEvent(SWFHeaderLoaderErrorEvent.HTTP_ERROR));
			}
		}
		/**
		 * Handler for the urlLoader IOErrorEvent.IO_ERROR event.
		 * */
		private function urlLoader_ioErrorHandler(event:IOErrorEvent):void
		{
			dispatcher(new SWFHeaderLoaderErrorEvent(SWFHeaderLoaderErrorEvent.IO_ERROR));
		}
	}
}
</pre>
<p><strong>SWF Header Value Object &#8211; SWFHeader_vo.as</strong><br />
The value object I use in the SWFHeaderLoader and SWFHeaderParser.</p>
<pre class="brush: as3; wrap-lines: false;">
package vo
{
	/**
	 * Defines the values in the SWF file header record needed for app
	 * */
	[Bindable]
	public class SWFHeader_vo
	{
		public var format:String;			//	3 characters.
											//  First character:
											//  	&quot;F&quot; indicates uncompressed.
											// 		&quot;C&quot; indicates compressed (SWF 6 and later only).
											//  Second character always &quot;W&quot;.
											//  Third character always &quot;S&quot;.
		public var swfVersion:Number;		//	The swf version.
		public var frameRate:Number;		//	Frame rate.
		public var totalFrames:Number;		//	Number of frames on main timeline.
		public var width:Number;			//	Stage width.
		public var height:Number;			//	Stage height.
		public var sizeUncompressed:Number;	//	File size before compression.
		public var sizeCompressed:Number;	//	Actual file size.
	}
}
</pre>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
The remainder code listings are the wiring into a Parsley Framework and published as an Adobe Air project.</p>
<p><strong>Application Class &#8211; SWFHeader.mxml</strong></p>
<p>This is the application mxml file. Gotta love how Parsley helps make these application  mxml files minimal.</p>
<pre class="brush: as3; wrap-lines: false;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;!---
Application container
--&gt;
&lt;s:WindowedApplication xmlns:fx=&quot;http://ns.adobe.com/mxml/2009&quot;
					   xmlns:s=&quot;library://ns.adobe.com/flex/spark&quot;
					   xmlns:mx=&quot;library://ns.adobe.com/flex/mx&quot;
					   xmlns:parsley=&quot;http://www.spicefactory.org/parsley&quot;
					   xmlns:views=&quot;views.*&quot;
					   height = &quot;450&quot;
					   backgroundAlpha=&quot;0&quot;
					   showStatusBar=&quot;false&quot; 					&gt;
	&lt;fx:Declarations&gt;
		&lt;!-- Place non-visual elements (e.g., services, value objects) here --&gt;
		&lt;parsley:ContextBuilder config=&quot;ParsleyConfiguration&quot;  /&gt;
		&lt;parsley:Configure/&gt;
	&lt;/fx:Declarations&gt;
	&lt;views:Main  /&gt;
&lt;/s:WindowedApplication&gt;
</pre>
<p><strong>Parsley Configuration File &#8211; ParsleyConfiguration.mxml</strong><br />
My first example that uses a Parsley DynamicObject. It is the SWFHeaderLoader class. I had a lot of silent failures before I could get this to stick. The result is that Parsley manages objects made from SWFHeaderLoader so we can have Parsley messaging and insertions. Only tried it with one object however.</p>
<pre class="brush: as3; wrap-lines: false;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;!---
Parsley framework configuration file
--&gt;
&lt;Objects
	xmlns:fx=&quot;http://ns.adobe.com/mxml/2009&quot;
	xmlns=&quot;http://www.spicefactory.org/parsley&quot;
	xmlns:spicefactory=&quot;http://www.spicefactory.org/parsley&quot;
	xmlns:models=&quot;models.*&quot;
	xmlns:controllers=&quot;controllers.*&quot;
	xmlns:s=&quot;library://ns.adobe.com/flex/spark&quot;
	&gt;
	&lt;fx:Script&gt;
		&lt;![CDATA[
			// Required for DynamicObject SWFHeaderLoader.
			import swf.*;
		]]&gt;
	&lt;/fx:Script&gt;
	&lt;fx:Declarations&gt;
		&lt;!--
		Parsley defined objects.
		--&gt;
		&lt;spicefactory:DynamicObject type = &quot;{SWFHeaderLoader}&quot; /&gt;
		&lt;models:ApplicationModel/&gt;
		&lt;models:SWFHeaderModel/&gt;
		&lt;controllers:ApplicationController/&gt;
	&lt;/fx:Declarations&gt;
&lt;/Objects&gt;
</pre>
<p><strong>Air Application Descriptor File &#8211; SWFHeader-app.xml</strong><br />
Key here is that this an Air 2.0 project indicated on line 2 and line 8.</p>
<pre class="brush: xml; wrap-lines: false;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; standalone=&quot;no&quot;?&gt;
&lt;application xmlns=&quot;http://ns.adobe.com/air/application/2.0&quot;&gt;

&lt;!-- Adobe AIR Application Descriptor File Template.

	Specifies parameters for identifying, installing, and launching AIR applications.

	xmlns - The Adobe AIR namespace: http://ns.adobe.com/air/application/2.0
			The last segment of the namespace specifies the version
			of the AIR runtime required for this application to run.

	minimumPatchLevel - The minimum patch level of the AIR runtime required to run
			the application. Optional.
--&gt;

	&lt;!-- The application identifier string, unique to this application. Required. --&gt;
	&lt;id&gt;SwfHeader&lt;/id&gt;

	&lt;!-- Used as the filename for the application. Required. --&gt;
	&lt;filename&gt;SWFHeaderInspector&lt;/filename&gt;

	&lt;!-- The name that is displayed in the AIR application installer.
	     May have multiple values for each language. See samples or xsd schema file. Optional. --&gt;
	&lt;name&gt;SWF Header Inspector&lt;/name&gt;

	&lt;!-- An application version designator (such as &quot;v1&quot;, &quot;2.5&quot;, or &quot;Alpha 1&quot;). Required. --&gt;
	&lt;version&gt;v0.01&lt;/version&gt;

	&lt;!-- Description, displayed in the AIR application installer.
	     May have multiple values for each language. See samples or xsd schema file. Optional. --&gt;
	&lt;!-- &lt;description&gt;&lt;/description&gt; --&gt;

	&lt;!-- Copyright information. Optional --&gt;
	&lt;!-- &lt;copyright&gt;&lt;/copyright&gt; --&gt;

	&lt;!-- Publisher ID. Used if you're updating an application created prior to 1.5.3 --&gt;
	&lt;!-- &lt;publisherID&gt;&lt;/publisherID&gt; --&gt;

	&lt;!-- Settings for the application's initial window. Required. --&gt;
	&lt;initialWindow&gt;
		&lt;!-- The main SWF or HTML file of the application. Required. --&gt;
		&lt;!-- Note: In Flash Builder, the SWF reference is set automatically. --&gt;
		&lt;content&gt;[This value will be overwritten by Flash Builder in the output app.xml]&lt;/content&gt;

		&lt;!-- The title of the main window. Optional. --&gt;
		&lt;!-- &lt;title&gt;&lt;/title&gt; --&gt;

		&lt;!-- The type of system chrome to use (either &quot;standard&quot; or &quot;none&quot;). Optional. Default standard. --&gt;
		&lt;systemChrome&gt;none&lt;/systemChrome&gt;

		&lt;!-- Whether the window is transparent. Only applicable when systemChrome is none. Optional. Default false. --&gt;
		&lt;transparent&gt;true&lt;/transparent&gt;

		&lt;!-- Whether the window is initially visible. Optional. Default false. --&gt;
		&lt;!-- &lt;visible&gt;&lt;/visible&gt; --&gt;

		&lt;!-- Whether the user can minimize the window. Optional. Default true. --&gt;
		&lt;!-- &lt;minimizable&gt;&lt;/minimizable&gt; --&gt;

		&lt;!-- Whether the user can maximize the window. Optional. Default true. --&gt;
		&lt;!-- &lt;maximizable&gt;&lt;/maximizable&gt; --&gt;

		&lt;!-- Whether the user can resize the window. Optional. Default true. --&gt;
		&lt;!-- &lt;resizable&gt;&lt;/resizable&gt; --&gt;

		&lt;!-- The window's initial width. Optional. --&gt;
		&lt;!-- &lt;width&gt;&lt;/width&gt; --&gt;

		&lt;!-- The window's initial height. Optional. --&gt;
		&lt;!-- &lt;height&gt;&lt;/height&gt; --&gt;

		&lt;!-- The window's initial x position. Optional. --&gt;
		&lt;!-- &lt;x&gt;&lt;/x&gt; --&gt;

		&lt;!-- The window's initial y position. Optional. --&gt;
		&lt;!-- &lt;y&gt;&lt;/y&gt; --&gt;

		&lt;!-- The window's minimum size, specified as a width/height pair, such as &quot;400 200&quot;. Optional. --&gt;
		&lt;!-- &lt;minSize&gt;&lt;/minSize&gt; --&gt;

		&lt;!-- The window's initial maximum size, specified as a width/height pair, such as &quot;1600 1200&quot;. Optional. --&gt;
		&lt;!-- &lt;maxSize&gt;&lt;/maxSize&gt; --&gt;
	&lt;/initialWindow&gt;

	&lt;!-- The subpath of the standard default installation location to use. Optional. --&gt;
	&lt;!-- &lt;installFolder&gt;&lt;/installFolder&gt; --&gt;

	&lt;!-- The subpath of the Programs menu to use. (Ignored on operating systems without a Programs menu.) Optional. --&gt;
	&lt;!-- &lt;programMenuFolder&gt;&lt;/programMenuFolder&gt; --&gt;

	&lt;!-- The icon the system uses for the application. For at least one resolution,
		 specify the path to a PNG file included in the AIR package. Optional. --&gt;
	&lt;!-- &lt;icon&gt;
		&lt;image16x16&gt;&lt;/image16x16&gt;
		&lt;image32x32&gt;&lt;/image32x32&gt;
		&lt;image48x48&gt;&lt;/image48x48&gt;
		&lt;image128x128&gt;&lt;/image128x128&gt;
	&lt;/icon&gt; --&gt;

	&lt;!-- Whether the application handles the update when a user double-clicks an update version
	of the AIR file (true), or the default AIR application installer handles the update (false).
	Optional. Default false. --&gt;
	&lt;!-- &lt;customUpdateUI&gt;&lt;/customUpdateUI&gt; --&gt;

	&lt;!-- Whether the application can be launched when the user clicks a link in a web browser.
	Optional. Default false. --&gt;
	&lt;!-- &lt;allowBrowserInvocation&gt;&lt;/allowBrowserInvocation&gt; --&gt;

	&lt;!-- Listing of file types for which the application can register. Optional. --&gt;
	&lt;!-- &lt;fileTypes&gt; --&gt;

		&lt;!-- Defines one file type. Optional. --&gt;
		&lt;!-- &lt;fileType&gt; --&gt;

			&lt;!-- The name that the system displays for the registered file type. Required. --&gt;
			&lt;!-- &lt;name&gt;&lt;/name&gt; --&gt;

			&lt;!-- The extension to register. Required. --&gt;
			&lt;!-- &lt;extension&gt;&lt;/extension&gt; --&gt;

			&lt;!-- The description of the file type. Optional. --&gt;
			&lt;!-- &lt;description&gt;&lt;/description&gt; --&gt;

			&lt;!-- The MIME content type. --&gt;
			&lt;!-- &lt;contentType&gt;&lt;/contentType&gt; --&gt;

			&lt;!-- The icon to display for the file type. Optional. --&gt;
			&lt;!-- &lt;icon&gt;
				&lt;image16x16&gt;&lt;/image16x16&gt;
				&lt;image32x32&gt;&lt;/image32x32&gt;
				&lt;image48x48&gt;&lt;/image48x48&gt;
				&lt;image128x128&gt;&lt;/image128x128&gt;
			&lt;/icon&gt; --&gt;

		&lt;!-- &lt;/fileType&gt; --&gt;
	&lt;!-- &lt;/fileTypes&gt; --&gt;

&lt;/xml&gt;
</pre>
<p><strong>Main.mxml</strong><br />
The layout is a header and a body. The header is set up to be the move area for the window. he header is the top_hg HGroup on line 60. The body is the SWFHeaderBasic component on line 62. Here you could swap another body view easily.</p>
<pre class="brush: as3; wrap-lines: false;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;!---
Main view
--&gt;
&lt;s:Group xmlns:fx=&quot;http://ns.adobe.com/mxml/2009&quot;
		 xmlns:s=&quot;library://ns.adobe.com/flex/spark&quot;
		 xmlns:mx=&quot;library://ns.adobe.com/flex/mx&quot;
		 xmlns:sf=&quot;http://www.spicefactory.org/parsley&quot;

		 width=&quot;100%&quot; height=&quot;100%&quot;
		 xmlns:views=&quot;views.*&quot;
		 xmlns:ui=&quot;ui.*&quot;
		 &gt;
	&lt;fx:Script&gt;
		&lt;![CDATA[
			import ui.ApplicationCloseButtonSkin;
			/**
			 * Called once Parsley framework has reflected.
			 * */
			[Init]
			public function parsleyInit():void
			{
				top_hg.addEventListener(MouseEvent.MOUSE_DOWN, top_hg_onMouseDown);
			}
			/**
			 * Handler for top_hg MouseEvent.MOUSE_DOWN. Handles OS window move.
			 * */
			private function top_hg_onMouseDown( evt:MouseEvent):void
			{
				stage.nativeWindow.startMove();
			}
		]]&gt;
	&lt;/fx:Script&gt;
	&lt;fx:Declarations&gt;
		&lt;sf:Configure/&gt;
	&lt;/fx:Declarations&gt;
	&lt;fx:Style&gt;
		#appName_lbl {
			font-weight:bold;
			color: #291F65;
			font-size:18px;
		}
		#version_lbl {
			font-weight:bold;
			color: #291F65;
			font-size:10px;
		}
	&lt;/fx:Style&gt;
	&lt;s:VGroup width=&quot;100%&quot; height=&quot;100%&quot;&gt;
	&lt;s:BorderContainer width=&quot;100%&quot; height=&quot;100%&quot;
					   cornerRadius=&quot;20&quot; borderWeight=&quot;3&quot;
					   borderColor=&quot;0x000000&quot; dropShadowVisible=&quot;true&quot;
					   backgroundColor=&quot;#858282&quot;&gt;
		&lt;s:VGroup  verticalAlign=&quot;middle&quot; width=&quot;100%&quot; height=&quot;100%&quot;
			paddingLeft=&quot;6&quot; paddingRight=&quot;6&quot; paddingBottom=&quot;12&quot;
				&gt;
			&lt;!---
			Appplication header and drag area.
			--&gt;
			&lt;s:HGroup id = &quot;top_hg&quot; width=&quot;100%&quot;  verticalAlign=&quot;middle&quot; paddingTop=&quot;12&quot;  &gt;
				&lt;s:HGroup  paddingLeft=&quot;5&quot; verticalAlign=&quot;middle&quot; horizontalAlign=&quot;left&quot; width=&quot;100%&quot;  gap=&quot;30&quot;&gt;
					&lt;mx:Image source=&quot;@Embed(source='../assets/Adobe-swf_icon_40x40_published.png')&quot; /&gt;
					&lt;s:Label id = &quot;appName_lbl&quot; text = &quot;SWF Header Inspection Tool&quot;/&gt;
				&lt;/s:HGroup&gt;
				&lt;s:HGroup  paddingRight=&quot;12&quot; verticalAlign=&quot;middle&quot; horizontalAlign=&quot;right&quot; width=&quot;100%&quot;  &gt;
					&lt;ui:ApplicationCloseButton
						click=&quot;NativeApplication.nativeApplication.exit()&quot; skinClass=&quot;ui.ApplicationCloseButtonSkin&quot;/&gt;

				&lt;/s:HGroup&gt;			

			&lt;/s:HGroup&gt;
			&lt;views:SWFHeaderBasic    width=&quot;100%&quot; height=&quot;100%&quot; /&gt;
			&lt;s:Label id = &quot;version_lbl&quot; text = &quot;Version 1.00&quot;/&gt;
		&lt;/s:VGroup&gt;

	&lt;/s:BorderContainer&gt;
	&lt;/s:VGroup&gt;
&lt;/s:Group&gt;
</pre>
<p><strong>SWFHeaderBasic.mxml</strong><br />
Body section for the application. You can easily plug in your own view to replace this one.</p>
<pre class="brush: as3; wrap-lines: false;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;!---
Basic view.
--&gt;
&lt;s:Group xmlns:fx=&quot;http://ns.adobe.com/mxml/2009&quot;
		 xmlns:s=&quot;library://ns.adobe.com/flex/spark&quot;
		 xmlns:sf=&quot;http://www.spicefactory.org/parsley&quot;
		 xmlns:mx=&quot;library://ns.adobe.com/flex/mx&quot;
		 &gt;
	&lt;fx:Script&gt;
		&lt;![CDATA[
			import events.LoadSwfUrlHeaderRequestEvent;
			import models.SWFHeaderModel;
			import mx.binding.utils.BindingUtils;
			import mx.binding.utils.ChangeWatcher;
			import mx.events.FlexEvent;
			/**
			 * File name extracted from url or path.
			 * */
			[Bindable]
			private var fileName:String = '';
			[Inject]
			[Bindable]
			public var model:SWFHeaderModel;

			[MessageDispatcher]
			public var dispatcher:Function;
			/**
			 * Called once Parsley framework has reflected.
			 * */
			[Init]
			public function parsleyInit():void
			{
				// Bind the model changes from bytesLoaded in order to call a method.
				ChangeWatcher.watch(model, &quot;bytesLoaded&quot;, updateProgressBar);
				addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER, onDragEnterHandler);
				addEventListener(NativeDragEvent.NATIVE_DRAG_DROP, onDragDropHandler);
			}
			/**
			 * Handler for the load_btn Mouse.Click event.
			 * */
			protected function load_btn_clickHandler(event:MouseEvent):void
			{
				fileName = url_ti.text.substr(   url_ti.text.lastIndexOf( '/' ) + 1);
				dispatcher(new LoadSwfUrlHeaderRequestEvent (LoadSwfUrlHeaderRequestEvent.LOAD, url_ti.text));
			}
			/**
			 * Handler for the load_btn Mouse.Click event.
			 * */
			private function updateProgressBar(bytesLoaded:Number):void
			{
				//trace (className + &quot;.updateProgressBar(...) - model.bytesLoaded: &quot; + model.bytesLoaded);
				//trace (className + &quot;.updateProgressBar(...) - model.bytesTotal: &quot; + model.bytesTotal);
				bar.setProgress(model.bytesLoaded,model.bytesTotal);
				var pct:Number = Math.round((model.bytesLoaded/model.bytesTotal) * 100);
				bar.label= &quot;Current Progress&quot; + &quot; &quot; + pct + &quot;%&quot;;
			}
			/**
			 * Handler for the NativeDragEvent.NATIVE_DRAG_ENTER event.
			 * */
			private function onDragEnterHandler(e:NativeDragEvent):void
			{
				//trace (className + &quot;.onDragEnterHandler(...)&quot;);
				if(e.clipboard.hasFormat(ClipboardFormats.FILE_LIST_FORMAT))
				{
					//Get the array of File objects
					var files:Array = e.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array;
					var file:File = File(files[0]);
					//Allow only one file as only supporting one in this application and soft check it is a swf file.
					if( files.length == 1 &amp;&amp; file.url.substr(file.url.length-4).toLowerCase() == &quot;.swf&quot; )
					{
						//Triggers NativeDragEvent.NATIVE_DRAG_DROP event.
						//This is when we see the drop icon.
						NativeDragManager.acceptDragDrop(this);
					}
				}
			}
			/**
			 * Handler for the NativeDragEvent.NATIVE_DRAG_DROP event.
			 * */
			private function onDragDropHandler(e:NativeDragEvent):void
			{
				//trace (className + &quot;.onDragDropHandler(...)&quot;);
				var files:Array = e.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array;
				var file:File = File(files[0]);
				//trace (className + &quot;.onDragDropHandler(...) - file.url:&quot; + file.url);
				url_ti.text = file.url;
				fileName = file.name;
				// Optional can initiate the load automatically.
				dispatcher(new LoadSwfUrlHeaderRequestEvent (LoadSwfUrlHeaderRequestEvent.LOAD, url_ti.text));
			}
		]]&gt;
	&lt;/fx:Script&gt;
	&lt;fx:Declarations&gt;
		&lt;sf:Configure/&gt;
		&lt;mx:NumberFormatter id=&quot;numberFormatter&quot; precision=&quot;0&quot;  useThousandsSeparator=&quot;true&quot; /&gt;
	&lt;/fx:Declarations&gt;
	&lt;!---
	Create NativeDrag target with BorderContainer
	--&gt;
	&lt;s:BorderContainer
				width=&quot;100%&quot; height=&quot;100%&quot;
					   borderAlpha=&quot;0&quot;
					   backgroundColor=&quot;0xffffff&quot;
					   &gt;
	&lt;s:VGroup verticalAlign=&quot;top&quot;  horizontalAlign=&quot;center&quot; width=&quot;100%&quot; height=&quot;100%&quot;
			   paddingTop=&quot;10&quot;
			   &gt;
		&lt;s:HGroup &gt;
			&lt;s:Label  text=&quot;SWF URL:&quot; paddingTop=&quot;6&quot; /&gt;
			&lt;s:VGroup &gt;
				&lt;s:HGroup  verticalAlign=&quot;middle&quot;&gt;
				&lt;s:TextInput id=&quot;url_ti&quot; text=&quot;Enter swf http url or drag from desktop&quot; width=&quot;294&quot; /&gt;
				&lt;s:Button  label=&quot;Load SWF&quot; id=&quot;load_btn&quot; click=&quot;load_btn_clickHandler(event)&quot;/&gt;
				&lt;/s:HGroup&gt;
				&lt;!---
				Progress bar for slow loads such as the internet.
				--&gt;
				&lt;mx:ProgressBar id=&quot;bar&quot;   labelPlacement=&quot;bottom&quot; minimum=&quot;0&quot; visible=&quot;true&quot; maximum=&quot;100&quot;
								color=&quot;0x323232&quot;
								label=&quot;Current Progress 0%&quot; direction=&quot;right&quot;
								mode=&quot;manual&quot; width=&quot;100%&quot;/&gt;
			&lt;/s:VGroup&gt;
		&lt;/s:HGroup&gt;
		&lt;!---
		The result values
		--&gt;
		&lt;mx:Form width=&quot;100%&quot; height=&quot;100%&quot;       &gt;
			&lt;mx:FormItem label=&quot;SWF File name: &quot;&gt;
				&lt;s:Label color=&quot;0x000000&quot; text=&quot;{fileName}&quot;/&gt;
			&lt;/mx:FormItem&gt;
			&lt;mx:FormItem label=&quot;Flash player version: &quot;&gt;
				&lt;s:Label color=&quot;0x000000&quot; text=&quot;{numberFormatter.format(model.swfHeader_vo.swfVersion)}&quot;/&gt;
			&lt;/mx:FormItem&gt;
			&lt;s:HGroup&gt;
				&lt;mx:FormItem label=&quot;Size uncompressed: &quot;&gt;
					&lt;s:Label color=&quot;0x000000&quot; text=&quot;{numberFormatter.format(model.swfHeader_vo.sizeUncompressed)}&quot;/&gt;
				&lt;/mx:FormItem&gt;
				&lt;mx:FormItem label=&quot;Compressed: &quot;&gt;
					&lt;s:Label color=&quot;0x000000&quot; text=&quot;{numberFormatter.format(model.swfHeader_vo.sizeCompressed)}&quot;/&gt;
				&lt;/mx:FormItem&gt;
			&lt;/s:HGroup&gt;
			&lt;mx:FormItem label=&quot;Frame rate: &quot;&gt;
				&lt;s:Label color=&quot;0x000000&quot; text=&quot;{numberFormatter.format(model.swfHeader_vo.frameRate)}&quot;/&gt;
			&lt;/mx:FormItem&gt;
			&lt;mx:FormItem label=&quot;Total frames: &quot;&gt;
				&lt;s:Label color=&quot;0x000000&quot; text=&quot;{numberFormatter.format(model.swfHeader_vo.totalFrames)}&quot;/&gt;
			&lt;/mx:FormItem&gt;
			&lt;mx:FormItem label=&quot;Width: &quot;&gt;
				&lt;s:Label  color=&quot;0x000000&quot; text=&quot;{numberFormatter.format(model.swfHeader_vo.width)}&quot;/&gt;
			&lt;/mx:FormItem&gt;
			&lt;mx:FormItem label=&quot;Height: &quot;&gt;
				&lt;s:Label color=&quot;0x000000&quot; text=&quot;{numberFormatter.format(model.swfHeader_vo.height)}&quot;/&gt;
			&lt;/mx:FormItem&gt;
		&lt;/mx:Form&gt;
	&lt;/s:VGroup&gt;
	&lt;/s:BorderContainer&gt;
&lt;/s:Group&gt;
</pre>
<p><strong>ApplicationCloseButton.as</strong><br />
Own version of the spark Button class.</p>
<pre class="brush: as3; wrap-lines: false;">
package ui
{
	import spark.components.Button;
	/**
	 * Button to close the application
	 * */
	public class ApplicationCloseButton extends Button
	{
		public function ApplicationCloseButton()
		{
			super();
		}
	}
}
</pre>
<p><strong>ApplicationCloseButtonSkin.mxml</strong><br />
Skin for the application close button class, ApplicationCloseButton. I had some trouble with the edges of the images causing a repeating state change on rollover. I solved this by making a transparent background on line 29 a few pixels larger than the bitmaps. The bitmaps then had their verticalCenter and  horizontalCenter properities set to zero to keep them in the middle. See lines 34 and 36.</p>
<pre class="brush: as3; wrap-lines: false;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;!---
Skin for ui.ApplicationCloseButton
--&gt;
&lt;s:SparkSkin xmlns:fx=&quot;http://ns.adobe.com/mxml/2009&quot;
			 xmlns:s=&quot;library://ns.adobe.com/flex/spark&quot;
			 xmlns:fb=&quot;http://ns.adobe.com/flashbuilder/2009&quot;

			 alpha.disabled=&quot;0.5&quot;&gt;

	&lt;!-- host component --&gt;
	&lt;fx:Metadata&gt;
		&lt;![CDATA[
		/* @copy spark.skins.spark.ApplicationSkin#hostComponent 	*/
		[HostComponent(&quot;ui.ApplicationCloseButton&quot;)]
		]]&gt;
	&lt;/fx:Metadata&gt;

	&lt;!-- states --&gt;
	&lt;s:states&gt;
		&lt;s:State name=&quot;up&quot; /&gt;
		&lt;s:State name=&quot;over&quot; /&gt;
		&lt;s:State name=&quot;down&quot; /&gt;
		&lt;s:State name=&quot;disabled&quot; /&gt;
	&lt;/s:states&gt;
	&lt;!---
	Hit area.
	--&gt;
	&lt;s:Rect  left=&quot;0&quot; right=&quot;0&quot; top=&quot;0&quot; bottom=&quot;0&quot;  width=&quot;34&quot; height=&quot;34&quot;&gt;
		&lt;s:fill&gt;
			&lt;s:SolidColor color=&quot;0xffffff&quot; alpha=&quot;0&quot; /&gt;
		&lt;/s:fill&gt;
	&lt;/s:Rect&gt;
	&lt;s:BitmapImage  verticalCenter=&quot;0&quot;  horizontalCenter=&quot;0&quot; source=&quot;@Embed('../assets/red_glossy_close_up_button_published.png')&quot;
				   includeIn=&quot;up, disabled, down &quot;/&gt;
	&lt;s:BitmapImage verticalCenter=&quot;0&quot;  horizontalCenter=&quot;0&quot;  source=&quot;@Embed('../assets/green_glossy_close_up_button_published.png')&quot;
				   includeIn=&quot;over&quot;/&gt;

&lt;/s:SparkSkin&gt;
</pre>
<p><strong>ApplicationModel.as</strong><br />
I could have merged the two models, but as a practice in Parsley frameworks, I create an ApplicationModel by default.</p>
<pre class="brush: as3; wrap-lines: false;">
package models
{
	/**
	 * Application model.
	 * */
	public class ApplicationModel
	{

	}
}
</pre>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
<strong>SWFHeaderModel.as</strong><br />
The model containing all the bound data. Flex binding is magnificent for creating model-view-controller solutions. </p>
<pre class="brush: as3; wrap-lines: false;">
package models
{
	import vo.SWFHeader_vo;
	/**
	 * Model for the SWF header information.
	 * */
	public class SWFHeaderModel
	{
		/**
		 * Swf header field values.
		 * */
		[Bindable]
		public var swfHeader_vo:SWFHeader_vo;
		/**
		 * Nest the ApplicationModel.
		 * */
		[Inject]
		[Bindable]
		public var applicationModel:ApplicationModel;
		/**
		 * Bytes loaded.
		 * */
		[Bindable]
		public var bytesLoaded:Number;
		/**
		 * Total bytes to load.
		 * */
		[Bindable]
		public var bytesTotal:Number;
		/**
		 * Initialize model values.
		 * */
		public function SWFHeaderModel()
		{
			swfHeader_vo = new SWFHeader_vo();
		}
	}
}
</pre>
<p><strong>ApplicationController.as</strong><br />
I could have created a controller just for the SWF header if I wanted a separate model-view-controller  for SWF header decoupled from the application. </p>
<pre class="brush: as3; wrap-lines: false;">
package controllers
{
	import events.LoadSwfUrlHeaderRequestEvent;
	import events.SWFHeaderLoaderCompleteEvent;
	import events.SWFHeaderLoaderErrorEvent;
	import events.SWFHeaderLoaderProgressEvent;
	import flash.net.URLRequest;
	import models.SWFHeaderModel;
	import mx.controls.Alert;
	import swf.SWFHeaderLoader;
	import vo.SWFHeader_vo;
	/**
	 * Application controller
	 * */
	public class ApplicationController
	{
		/**
		 * Toggle to indicate if an Alert error is being shown. All loading errors are
		 * routed to one method and so if there are more than one per SWFHeaderLoader.load
		 * request, this prevents multiple Alert popups.
		 * @see swfHeaderErroMessageHandler
		 * */
		private var showingSwfLoadError:Boolean = false;
		/**
		 * The SWFHeaderLoader
		 * */
		[Inject]
		public var swfHeaderLoader:SWFHeaderLoader;
		/**
		 * The model for MVC.
		 * */
		[Inject]
		[Bindable]
		public var model:SWFHeaderModel;
		/**
		 * Information Alert dialog title.
		 * */
		private var lang_info_alert_title:String = &quot;Attention&quot;;
		/**
		 * Message when file name does not contain a .swf extension.
		 * */
		private var lang_tool_requires_swf:String = &quot;Tool is designed for Flash Movie \&quot;.swf\&quot; files&quot;;
		/**
		 * Message when swf file could not be loaded for any reason.
		 * */
		private var lang_unable_to_load_swf:String = &quot;Sorry, unable to load the file.&quot;;
		/**
		 * Handler for LoadSwfUrlHeaderRequestEvent. Validate file extension. Load swf.
		 * */
		[MessageHandler]
		public function swfUrlLoadRequestMessageHandler( message : LoadSwfUrlHeaderRequestEvent ):void
		{
			model.swfHeader_vo = new SWFHeader_vo();
			// File url does not have a .swf at end.
			if ( message.swf_url.substr(message.swf_url.length-4).toLowerCase() != &quot;.swf&quot;  )
			{
				Alert.show(lang_tool_requires_swf ,lang_info_alert_title);
			}
			// File url has a .swf at end.
			else
			{
				showingSwfLoadError = false;
				swfHeaderLoader.load(message.swf_url);
			}
		}
		/**
		 * Handler for SWFHeaderLoaderProgressEvent.
		 * */
		[MessageHandler]
		public function swfHeaderProgressMessageHandler( message : SWFHeaderLoaderProgressEvent ):void
		{
			model.bytesTotal = message.bytesTotal;
			model.bytesLoaded = message.bytesLoaded;
		}
		/**
		 * Handler for SWFHeaderLoaderCompleteEvent.
		 * */
		[MessageHandler]
		public function swfHeaderLoadedMessageHandler( message : SWFHeaderLoaderCompleteEvent ):void
		{
			model.swfHeader_vo = message.swfHeader_vo;
		}
		/**
		 * Handler for SWFHeaderLoaderErrorEvent.
		 * */
		[MessageHandler]
		public function swfHeaderErroMessageHandler( message : SWFHeaderLoaderErrorEvent ):void
		{
			if (!showingSwfLoadError)
			{
				showingSwfLoadError = true;
				Alert.show(lang_unable_to_load_swf,lang_info_alert_title);
			}
		}
	}
}
</pre>
<p><strong>LoadSwfUrlHeaderRequestEvent.as</strong><br />
Event handler for requests to load a swf. Note how Parsley simplifies the event code.</p>
<pre class="brush: as3; wrap-lines: false;">
package events
{
	import flash.events.Event;
	/**
	 * Request the loading of a swf file.
	 * */
	public class LoadSwfUrlHeaderRequestEvent extends Event
	{
		public static const LOAD:String = &quot;event.load&quot;;
		public var swf_url:String;
		public function LoadSwfUrlHeaderRequestEvent(type:String, swf_url:String, bubbles:Boolean=false, cancelable:Boolean=false)
		{
			super(type, bubbles, cancelable);
			this.swf_url = swf_url;
		}
	}
}
</pre>
<p><strong>SWFHeaderLoaderProgressEvent.as</strong><br />
For monitoring the loading particularly when over the internet.</p>
<pre class="brush: as3; wrap-lines: false;">
package events
{
	import flash.events.Event;
	/**
	 * Progress of loading a swf file.
	 * */
	public class SWFHeaderLoaderProgressEvent extends Event
	{
		public static const PROGRESS:String = &quot;event_SWFHeaderLoaderEvent_progress&quot;;
		/**
		 * Bytes loaded.
		 * */
		public var bytesLoaded:Number;
		/**
		 * Total bytes to load.
		 * */
		public var bytesTotal:Number;
		public function SWFHeaderLoaderProgressEvent(type:String, bytesLoaded:Number, bytesTotal:Number, bubbles:Boolean=false, cancelable:Boolean=false)
		{
			super(type, bubbles, cancelable);
			this.bytesLoaded = bytesLoaded;
			this.bytesTotal = bytesTotal;

		}
	}
}
</pre>
<p><strong>SWFHeaderLoaderCompleteEvent.as</strong><br />
When an SWF is completely loaded. You may want to redesign to stop once the header is loaded. However I had thought it might be nice to show the SWF at one point or proceed to extract other information.</p>
<pre class="brush: as3; wrap-lines: false;">
package events
{
	import flash.events.Event;
	import vo.SWFHeader_vo;
	/**
	 * Completion of loading a swf file.
	 * */
	public class SWFHeaderLoaderCompleteEvent extends Event
	{
		public static const COMPLETE:String = &quot;event_SWFHeaderLoaderEvent_complete&quot;;
		/**
		 * Swf file header data.
		 * */
		public var swfHeader_vo:SWFHeader_vo;
		public function SWFHeaderLoaderCompleteEvent(type:String, swfHeader_vo:SWFHeader_vo, bubbles:Boolean=false, cancelable:Boolean=false)
		{
			super(type, bubbles, cancelable);
			this.swfHeader_vo = swfHeader_vo;
		}
	}
}
</pre>
<p><strong>SWFHeaderLoaderErrorEvent.as</strong><br />
Errors in loading the Swf file.</p>
<pre class="brush: as3; wrap-lines: false;">
package events
{
	import flash.events.Event;
	/**
	 * Errors from loading a swf file.
	 * */
	public class SWFHeaderLoaderErrorEvent extends Event
	{
		public static const SECURITY_ERROR:String = &quot;event_SWFHeaderLoaderEvent_security&quot;;
		public static const HTTP_ERROR:String = &quot;event_SWFHeaderLoaderEvent_HTTP&quot;;
		public static const IO_ERROR:String = &quot;event_SWFHeaderLoaderEvent_IO&quot;;
		public function SWFHeaderLoaderErrorEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
		{
			super(type, bubbles, cancelable);
		}
	}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.lonhosford.com/lonblog/2011/01/17/read-flash-swf-header-in-air-with-parsley-framework/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Vimeo Moogaloop Actionscript API In Flex 4</title>
		<link>http://www.lonhosford.com/lonblog/2010/12/27/vimeo-moogaloop-actionscript-api-in-flex-4/</link>
		<comments>http://www.lonhosford.com/lonblog/2010/12/27/vimeo-moogaloop-actionscript-api-in-flex-4/#comments</comments>
		<pubDate>Tue, 28 Dec 2010 01:55:35 +0000</pubDate>
		<dc:creator>Lon Hosford</dc:creator>
				<category><![CDATA[Actionscript 3]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[Actionscript]]></category>
		<category><![CDATA[Flex 4]]></category>
		<category><![CDATA[SpriteVisualElement]]></category>
		<category><![CDATA[Vimeo]]></category>

		<guid isPermaLink="false">http://www.lonhosford.com/lonblog/?p=1159</guid>
		<description><![CDATA[I wanted created a video switcher for Vimeo videos using Flex 4. I found my way to the Vimeo Moogaloop API page where there seemed to be a harmless Actionscript 3 class demonstrating a Flash application. Moogaloop is the name Vimeo uses for the embedded video player. The Moogaloop player is a Flash movie that [...]]]></description>
			<content:encoded><![CDATA[<p>I wanted created a video switcher for <a href = "http://www.vimeo.com"  target = "_blank">Vimeo</a> videos using Flex 4. I found my way to the <a href = "http://vimeo.com/api/docs/moogaloop" target = "_blank"> Vimeo Moogaloop API page </a>where there seemed to be a harmless Actionscript 3 class demonstrating a Flash application. Moogaloop is the name Vimeo uses for the embedded video player.</p>
<p> <img alt="" src="http://lh5.ggpht.com/_e5pwU0LJbN8/TRk-pcdm8JI/AAAAAAAAFwo/H292wh3NP2M/s800/Flex4Vimeo.jpg" class="alignleft" width="379" height="243" />The Moogaloop player is a Flash movie that must be loaded into your Flash movie. The example on the Moogaloop API page is an example of that process. The Moogaloop player contains the API you need to interface with the video player once it is loaded.</p>
<p>The example showed an interface, api_loadVideo(id),  to load a video into the Moogaloop player. The way the example worked is that loading of the Moogaloop player requires a video to load. Then the interface suggests this api_loadVideo is how you load a second. </p>
<p>I set up an Actionscript project in Flex Builder 4 and found the api_loadVideo(id) code was not loading videos. I posted my findings on the Vimeo api forum (see <a href="http://vimeo.com/forums/topic:32257" target = "_blank"> Does moogaloop.api_loadVideo( id); work in Flash example work?</a>) and fairly promptly got a reply to try it again where it now worked. So it appeared I hit a bug and it was fixed.</p>
<p>I found more issues with switching videos with Moogaloop. They all centered around the video controls not maintaining a consistent state. After extended two day effort of multiple trial and error sessions, I solved most of the issues. The one issue still hanging is that the auto hide state of the player controls stays on after the first video plays. So if you load a second video, the player controls will auto hide until mouse rolls over the player. The user interface expectation of a new video being keyed for a first play is to have the player controls visible until the video plays. I added this observation to the original <a href="http://vimeo.com/forums/topic:32257" target = "_blank">forum post</a> to see if we get some updates that make switching videos more seamless to the user.</p>
<p>At this point I just have a Flex project for downloads.</p>
<ul style = "padding-top:10px">
<li><a href="http://www.lonhosford.com/content/flex/vimeo/VimeoMoogaloopEx01_Flex.fxp"  onClick="javascript: pageTracker._trackPageview('/downloads/ParsleyFramework_HelloWorld.fxp'); ">Flex Builder 4 Flex Project</a></li>
</ul>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
<strong>Application Class &#8211; VimeoMoogaloopEx01_Flex.mxml</strong><br />
This is the main MXML file. Nothing special here other than using the new SpriteVisualElement component to contain the VimeoPlayer class. There are two buttons switching the videos. </p>
<p>Note you must get an <a href = "http://vimeo.com/api/applications/new" target = "_blank">Application id</a> from Vimeo and put that on line 21.</p>
<p>Also add Vimeo video ids on lines 25 and 29.</p>
<pre class="brush: as3; wrap-lines: false;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;!--
/**
* Demo of Vimeo Moogaloop video player switching between two videos.
* */
--&gt;
&lt;s:Application xmlns:fx=&quot;http://ns.adobe.com/mxml/2009&quot;
			   xmlns:s=&quot;library://ns.adobe.com/flex/spark&quot;
			   xmlns:mx=&quot;library://ns.adobe.com/flex/mx&quot;
			   creationComplete=&quot;creationCompleteHandler(event)&quot;
			   width=&quot;800&quot; height=&quot;400&quot;&gt;
	&lt;fx:Script&gt;
		&lt;![CDATA[
			import com.vimeo.moogaloop.VimeoPlayer;

			import mx.events.FlexEvent;

			/**
			 * Vimeo developer id.
			 * */
			private const VIMEO_ID:String = &quot;YOUR VIMEO APPLICATION ID GOES HERE&quot;;
			/**
			 * Vimeo video id for the first loaded video.
			 * */
			private const VIDEO_ID_1:int = PUT A VIMEO VIDEO ID HERE;
			/**
			 * Vimeo video id for the second video.
			 * */
			private const VIDEO_ID_2:int = PUT ANOTHER VIMEO VIDEO ID HERE;
			/**
			 * Properties for background
			 */
			private static const backgroundColor:Number = 0x333333;
			/**
			 * The Vimeo Moogaloop video player.
			 * */
			private var vimeoPlayer:VimeoPlayer;
			/**
			 * Event handler for creationComplete event.
			 * */
			protected function creationCompleteHandler(event:FlexEvent):void
			{
				// Create the Vimeo VideoPlayer class instance.
				vimeoPlayer = new VimeoPlayer(VIMEO_ID,VIDEO_ID_1,460,300);
				// Add to SpriteVisualElement
				vimeoVideoPlayer.addChild(vimeoPlayer);
				// Disable the first video switching button.
				video1.enabled = false;
			}
			/**
			 * Event handler for the first video button MouseEvent.CLICK event.
			 * */
			protected function video1_clickHandler(event:MouseEvent):void
			{
				// Load the video.
				loadVideo(VIDEO_ID_1);
				// Reset the video switching button states.
				video1.enabled = false;
				video2.enabled = true;
			}
			/**
			 * Event handler for the second video button MouseEvent.CLICK event.
			 * */
			protected function video2_clickHandler(event:MouseEvent):void
			{
				// Load the video.
				loadVideo(VIDEO_ID_2);
				// Reset the video switching button states.
				video1.enabled = true;
				video2.enabled = false;
			}
			/**
			 * Loads a new video into the Vimeo Moogaloop player.
			 * */
			private function loadVideo(videoId:int):void
			{
				vimeoPlayer.loadVideo(videoId);
			}
		]]&gt;
	&lt;/fx:Script&gt;
	&lt;!--
	UI
	--&gt;
	&lt;s:BorderContainer id = &quot;background_bc&quot;
					   width=&quot;{width}&quot; height = &quot;{height}&quot;
					   backgroundColor=&quot;{backgroundColor}&quot;&gt;
		&lt;s:layout&gt;
			&lt;s:VerticalLayout horizontalAlign=&quot;center&quot;/&gt;
		&lt;/s:layout&gt;
		&lt;s:SpriteVisualElement id = &quot;vimeoVideoPlayer&quot; width=&quot;460&quot; height=&quot;350&quot;/&gt;
		&lt;mx:HBox&gt;
			&lt;s:Button id = &quot;video1&quot; label=&quot;Video 1&quot; click=&quot;video1_clickHandler(event)&quot; /&gt;
			&lt;s:Button id = &quot;video2&quot; label=&quot;Video 2&quot; click=&quot;video2_clickHandler(event)&quot; /&gt;
		&lt;/mx:HBox&gt;
	&lt;/s:BorderContainer&gt;
&lt;/s:Application&gt;
</pre>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
<strong>VimeoPlayer Class</strong><br />
This is the class on the Vimeo Moogaloop API web site. It was modified to handle the mouse event override from the stage to the parent on line 108, removal of the player_mask Sprite and addition of seek and pause calls to the loadVideo method on lines 181 and 182. </p>
<p>Still not fully sure of the player_mask need for Flex. However upgrading the loader using Flex components is in order which I will explore if I stay with Vimeo for the project I have for a Vimeo user.</p>
<pre class="brush: as3; wrap-lines: false;">
package com.vimeo.moogaloop
{
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.geom.Point;
	import flash.net.URLRequest;
	import flash.system.Security;
	import flash.utils.Timer;
	/**
	 * Vimeo Moogaloop player class from the Vimeo web site: http://vimeo.com/api/docs/moogaloop.
	 * &lt;p&gt;Modified to handle issues with playing in Flex. Mask removed.
	 * See comments where other changes were made.&lt;/p&gt;
	 * */
	public class VimeoPlayer extends Sprite
	{
		/**
		 * Sprite container for the Moogaloop Flash movie.
		 * */
		private var container:Sprite = new Sprite();
		/**
		 * The Moogaloop player.
		 * */
		private var moogaloop:Object = false;
		/**
		 * Default width of the player.
		 * */
		private var player_width:int = 400;
		/**
		 * Default height of the player.
		 * */
		private var player_height:int = 300;
		/**
		 * Timer to delay until the Moogaloop Flash movies is loaded. Could be switched for a Flex component.
		 * */
		private var load_timer:Timer = new Timer(200);
		/**
		 * param oauth_key Vimeo developer key
		 * param clip_id Vimeo video id.
		 * param clip_id Vimeo video id.
		 * */
		public function VimeoPlayer(oauth_key:String,
										   clip_id:int,
										   w:int,
										   h:int,
										   fp_version:int = 10)
		{
			init(oauth_key, clip_id, w, h, fp_version);
		}
		/**
		 * Initialize and load Vimeo Moogaloop player.
		 * */
		private function init(oauth_key:String,
							  clip_id:int,
							  w:int,
							  h:int,
							  fp_version:int = 10):void
		{
			this.setDimensions(w, h);
			Security.allowDomain(&quot;*&quot;);
			Security.loadPolicyFile(&quot;http://vimeo.com/moogaloop/crossdomain.xml&quot;);
			var loader:Loader = new Loader();
			var request:URLRequest = new URLRequest(&quot;http://api.vimeo.com/moogaloop_api.swf?oauth_key=&quot; + oauth_key + &quot;&amp;clip_id=&quot; + clip_id + &quot;&amp;width=&quot; + w + &quot;&amp;height=&quot; + h + &quot;&amp;fullscreen=0&amp;fp_version=&quot; + fp_version);
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
			loader.load(request);
		}
		/**
		 * Store the dimensions.
		 */
		private function setDimensions(w:int, h:int):void
		{
			player_width  = w;
			player_height = h;
		}
		/**
		 * Handler for the URLRequest Event.COMPLETE event. Moogaloop Flash movie
		 * loading complete.
		 */
		private function onComplete(e:Event):void
		{
			// Add Moogaloop Flash movie to container Sprite.
			container.addChild(e.target.loader.content);
			// Provide reference to Moogaloop Flash movie API.
			moogaloop = e.target.loader.content;
			// Add the container to this.
			addChild(container);
			// Timer to wait for Moogaloop Flash movie to complete setup.
			load_timer.addEventListener(TimerEvent.TIMER, playerLoadedCheck);
			load_timer.start();
		}
		/**
		 * Handler for load_timer TimerEvent.Timer event.
		 * Check for Moogaloop to finish setting up.
		 */
		private function playerLoadedCheck(e:TimerEvent):void
		{
			// Moogaloop is finished configuring
			if (moogaloop.player_loaded)
			{
				load_timer.stop();
				load_timer.removeEventListener(TimerEvent.TIMER, playerLoadedCheck);
				// remove moogaloop's mouse listeners listener
				moogaloop.disableMouseMove();
				// Add MouseEvent.MOUSE_MOVE event listener to parent.
				// Original Vimeo code added to stage.
				parent.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
				// Broadcast COMPLETE event for Moogaloop loaded.
				dispatchEvent(new Event(Event.COMPLETE));
			}
		}
		/**
		 * Handler for parent MouseEvent.MOUSE_MOVE event.
		 * Fake the mouse move/out events for Moogaloop.
		 */
		private function mouseMove(e:MouseEvent):void
		{
			var pos:Point = this.parent.localToGlobal(new Point(this.x, this.y));
			// Mouse event occured in this rectangle representing the player.
			if (e.stageX &gt;= pos.x &amp;&amp; e.stageX &lt;= pos.x + this.player_width
				&amp;&amp;
				e.stageY &gt;= pos.y &amp;&amp; e.stageY &lt;= pos.y + this.player_height)
			{
				moogaloop.mouseMove(e); // Not documented. You have to have faith.
			}
			else
			{
				moogaloop.mouseOut(); // Not documented. You have to have faith.
			}
		}
		/**
		 * Play video in Moogaloop player.
		 */
		public function play():void
		{
			moogaloop.api_play();
		}
		/**
		 * Pause video in Moogaloop player.
		 */
		public function pause():void
		{
			moogaloop.api_pause();
		}
		/**
		 * returns duration of video in seconds
		 */
		public function getDuration():int
		{
			return moogaloop.api_getDuration();
		}
		/**
		 * Seek to specific loaded time in video (in seconds)
		 */
		public function seekTo(time:int):void
		{
			moogaloop.api_seekTo(time);
		}
		/**
		 * Change the primary color (i.e. 00ADEF)
		 */
		public function changeColor(hex:String):void
		{
			moogaloop.api_changeColor(hex);
		}
		/**
		 * Set dimensions of this instance and Moogaloop player.
		 */
		public function setSize(w:int, h:int):void
		{
			this.setDimensions(w, h);
			moogaloop.api_setSize(w, h);
		}
		/**
		 * Load in a different video.
		 */
		public function loadVideo(id:int):void
		{
			moogaloop.api_loadVideo(id);
			moogaloop.api_seekTo(0); 	// Added to code on Vimeo web site.
			moogaloop.api_pause(); 		// Added to code on Vimeo web site.

		}
	}
}
</pre>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonhosford.com/lonblog/2010/12/27/vimeo-moogaloop-actionscript-api-in-flex-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Box2D Flash Puggle Lite Game Version of Peggle Nights</title>
		<link>http://www.lonhosford.com/lonblog/2010/11/07/box2d-flash-puggle-lite-game-version-of-peggle-nights/</link>
		<comments>http://www.lonhosford.com/lonblog/2010/11/07/box2d-flash-puggle-lite-game-version-of-peggle-nights/#comments</comments>
		<pubDate>Sun, 07 Nov 2010 15:43:25 +0000</pubDate>
		<dc:creator>Lon Hosford</dc:creator>
				<category><![CDATA[Actionscript 3]]></category>
		<category><![CDATA[Animation]]></category>
		<category><![CDATA[Box2D]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[Gaming]]></category>
		<category><![CDATA[Actionscript]]></category>

		<guid isPermaLink="false">http://www.lonhosford.com/lonblog/?p=1084</guid>
		<description><![CDATA[This is an update of Todd Kerpelman&#8217;s video tutorial of Puggle a game based on Peggle Nights using Box2DFlash, a free 2D physics engine for Flash that works in both Flash and Flex Builder 4. This is example involves a great deal of interaction of game components. For a simpler example of Box2d version 2.1 [...]]]></description>
			<content:encoded><![CDATA[<div id="fb-root"></div>
<p><script src="http://connect.facebook.net/en_US/all.js#appId=105467682877384&amp;xfbml=1"></script><fb:like href="http://www.lonhosford.com/lonblog/2010/11/07/box2d-flash-puggle-lite-game-version-of-peggle-nights/" send="true" width="450" show_faces="true" font=""></fb:like><br />
<img class="alignleft" src="http://lh3.ggpht.com/_e5pwU0LJbN8/TNaZjUS70YI/AAAAAAAAFv0/5XhyOMoJdGw/s400/HelloWorldPuggle01_11-7-2010%207-18-47%20AM.png" alt="" width="400" height="373" />This is an update of Todd Kerpelman&#8217;s <a href="http://www.kerp.net/box2d/" target="_blank"> video tutorial of Puggle</a> a game based on <a href="http://en.wikipedia.org/wiki/Peggle_Nights"  target="_blank">Peggle Nights</a> using <a href="http://www.box2dflash.org/" target="_blank">Box2DFlash, a free 2D physics engine for Flash</a> that works in both Flash and Flex Builder 4. This is example involves a great deal of interaction of game components. For a simpler example of Box2d version 2.1 see <a href="http://www.lonhosford.com/lonblog/2010/10/27/box2d-flash-2-1-hello-world-falling-boxes/"> my falling boxes example</a>.</p>
<p>Todd&#8217;s Puggle game is really the example he uses to teach how to use Box2D. Todd&#8217;s version is based on Box2d 2.0 and I wanted to see how it applies to Box2D version 2.1. So I followed his tutorials and gleamed out the code and converted it. This was a painful process because the source code is not available and Todd spends a lot of time explaining concepts in his very helpful videos and went down some roads that he later changed perhaps to accentuate the right versus wrong way. </p>
<p>I did not reproduce all of the example Todd produced because I just ran out of time. However I got enough to put Puggle into working condition using Box2d 2.1 and also commented all the code extensively. </p>
<p><a href="http://www.amazon.com/gp/product/0763784516?ie=UTF8&#038;tag=hosfordusa&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=0763784516" target = "_blank"><img border="0" align="right" src="http://lh4.ggpht.com/_e5pwU0LJbN8/TMg4rcI62aI/AAAAAAAAFvI/HBJG_mAV_1M/s800/51kVfkmZ-WL._SL160_.jpg"></a></p>
<p>The Puggle Lite version composed from Todd&#8217;s work basically allows you to shoot balls from the gun at the top. You use the mouse to aim and fire. You can tune the code to determine the number of balls allowed in play at any one point in time. The source has this value set to 2. </p>
<p>A random selection of the pegs in the middle of the game are designated as goals. The remaining pegs are just that, pegs. They are colored to show goals as yellow and others as blue. They change color when hit and are removed once any ball in play leaves the game. </p>
<p>The moving chute at the bottom is a bonus if a ball falls into it. The game does not track points and perhaps something you may want to add. </p>
<p>You can build this with the free Flex SDK by using the code in the src folder and be sure to include a path to the Box2DFlash 2.1a library. For Flash CS3 and later versions, you need to create a Flash Document in the src folder and set the document class to <code>HelloWorldFallingBoxes01</code> and then add a library path to the  code or SWC if you created one. For your convenience the Flash CS4 example download is included with the needed SWC.</p>
<p>Also for Flash CS3 on up you will need some Flex library swc files because of the use of the Embed meta tag. Tareq AlJaber has <a href="http://www.adobe.com/devnet/flash/articles/embed_metadata.html" target = "_blank">good article on embedding meta data in Flash CS4</a>.</p>
<p><strong>Downloads</strong></p>
<ul style="padding-top: 10px;">
<li><a href="http://www.lonhosford.com/content/flex/2d/box2d/Box2D2.1aHelloWorldPuggle01_AS.zip" onClick="javascript: pageTracker._trackPageview('/downloads/Box2D2.1aHelloWorldPuggle01_AS.zip'); ">Flex Builder 4 Actionscript Project</a></li>
<li><a href="http://www.lonhosford.com/content/flex/2d/box2d/Box2D2.1aHelloWorldPuggle01_Flex.fxp" onClick="javascript: pageTracker._trackPageview('/downloads/Box2D2.1aHelloWorldPuggle01_Flex.fxp'); ">Flex Builder 4 Flex Project</a></li>
<li><a href="http://www.lonhosford.com/content/flex/2d/box2d/Box2D2.1aHelloWorldPuggle01_Flash_CS4.zip" onClick="javascript: pageTracker._trackPageview('/downloads/Box2D2.1aHelloWorldPuggle01_Flash_CS4.zip'); ">Flash CS4</a></li>
</ul>
<p>You can <a href="http://www.box2dflash.org/download" target="_blank">download Box2dFlash</a> to work with the source, get the API documentation and more examples. I included a SWC library for version 2.1a in the example downloads so you will know they work despite what happens at <a href="http://www.box2dflash.org" target="_blank">Box2dFlash.org</a>.</p>
<p>Another item used in this example is the <a href="http://www.greensock.com/""_blank">Greensock Tweening library TweenLite</a> for animations such as fade out. The SWC library is included in the downloads for your convenience.</p>
<p>This article shows the code for the Flex project. The main difference is how we stitch in the game sprites into the main class using the SpriteVisualElement.<br />
<div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
<strong>Application Class &#8211; HelloWorldPuggle01</strong><br />
There are a number of customization constants. I tried to extract all the data in buried in the code from Todd&#8217;s examples, but fell short for the side wall ramps. I prefer to have data either as members or other source and not buried in code.</p>
<p>The customization constants SHOW_BOX2D_DEBUG and SHOW_BOX2D_DEBUG_AS_OVERLAY on lines 127 and 134 respectively are useful in looking at the Box2D world visually. This helps in checking if the game assets, we call costumes, are synchronized with their physical representation in Box2D data.</p>
<p>The MAX_LAUNCED_BALLS_ALLOWED on line 57 is also helpful in testing. Run the number higher and more balls can be launched speeding up game action and shortening time to see coding changes.</p>
<p>Basically the Box2d world and the Shooter actor are created . The game is set up in the createLevel method we will visit in a later code block. </p>
<pre class="brush: as3; wrap-lines: false;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;!--
/**
* Demonstration of Box2D 2.1a converting Todd Kerpelman's Puggle Box2d 2.0 version
of Peggle Nights.
* */
--&gt;&lt;s:Application xmlns:fx=&quot;http://ns.adobe.com/mxml/2009&quot;
			   xmlns:s=&quot;library://ns.adobe.com/flex/spark&quot;
			   xmlns:mx=&quot;library://ns.adobe.com/flex/mx&quot;
			   applicationComplete=&quot;applicationCompleteHandler(event)&quot;
			   width = &quot;646&quot;
			   height = &quot;603&quot;
			   frameRate=&quot;30&quot;
			&gt;
	   &lt;fx:Script&gt;
		   &lt;![CDATA[
			   import Box2D.Collision.Shapes.b2CircleShape;
			   import Box2D.Common.Math.b2Vec2;
			   import Box2D.Dynamics.b2Body;
			   import Box2D.Dynamics.b2BodyDef;
			   import Box2D.Dynamics.b2DebugDraw;
			   import Box2D.Dynamics.b2FixtureDef;
			   import Box2D.Dynamics.b2World;
			   import mx.events.FlexEvent;
			   /**
				* Properties for background
				* @see background_bc
				*/
			   private static const backgroundColor:Number = 0x333333;
			   /**
				* Tracking of all actors to call their methods.
				* */
			   private var _actors:Array;
			   /**
				* Tracking of all actors that need to be removed after each update of the Box2dWorld.
				* */
			   private var _actorsTaggedForRemoval:Array;
			   /**
				* Tracking of all peg actors that have been hit.
				* */
			   private var _pegsLitUp:Array;
			   /**
				* Tracking of all peg actors that are considered goal targets.
				* */
			   private var _goalPegs:Array;
			   /**
				* Shooter actor.
				* */
			   private var _shooter:Shooter;
			   /**
				* Total balls launched.
				* */
			   private var _totalBallsLaunced:int = 0;
			   /**
				* Maximum balls that can be in play at a time.
				* */
			   private const MAX_LAUNCED_BALLS_ALLOWED:int = 2;
			   /**
				* Time to simulate world. Set Box2D world time step to movie frame rate.
				* Box2D manual recommends 1/60 seconds.
				* */
			   private const STEP_SIMULATION_TIME:Number = 1 / 30;
			   /**
				* Box2D interations for the velocity constraint solver
				* */
			   private const STEP_VELOCITY_ITERATIONS:int = 6;
			   /**
				* Box2D interations for the position constraint solver
				* */
			   private const POSITION_VELOCITY_ITERATIONS:int = 10;
			   /**
				* Horizontal spacing of PegActors.
				* */
			   private const PEG_H_SPACING:int = 36;
			   /**
				* Vertical spacing of PegActors.
				* */
			   private const PEG_V_SPACING:int = 36;
			   /**
				* Boundaries for the PegActors.
				* */
			   private const PEG_BOUNDARIES:Rectangle = new Rectangle(114, 226, 418, 255);
			   /**
				* Game side wall thickness.
				* */
			   private const SIDE_WALL_THICKNESS:Number = 10;
			   /**
				* Game side wall height.
				* */
			   private const SIDE_WALL_HEIGHT:Number = 603;
			   /**
				* Position of left wall.
				* */
			   private const LEFT_WALL_POSITION:Point = new Point(0,0);
			   /**
				* Position of right wall.
				* */
			   private const RIGHT_WALL_POSITION:Point = new Point(636,0);
			   /**
				* Left boundary of movable BonusChuteActor.
				* */
			   private const BONUS_CHUTE_LEFT_BOUNDS:int = 20;
			   /**
				* Right boundary of movable BonusChuteActor.
				* */
			   private const BONUS_CHUTE_RIGHT_BOUNDS:int = 433;
			   /**
				* Vertical position of the BonusChuteActor.
				* */
			   private const BONUS_CHUTE_VERTICAL_POSITION:int = 575;
			   /**
				* Position for the Shooter actor.
				* */
			   private const SHOOTER_POINT:Point = new Point(323,10);
			   /**
				* Velocity for the BallActors
				* */
			   private const LAUNCH_VELOCITY:Number = 90;
			   /**
				* Number of PegActors set as goal targets.
				* */
			   private const GOAL_PEG_NUM:int = 22;
			   /**
				* Developer testing for visualization of the Box2D elements using b2DebugDraw.
				* Determines if b2DebugDraw is added to stage and called.
				* */
			   private const SHOW_BOX2D_DEBUG:Boolean = false;
			   /**
				* Developer b2DebugDraw visual is shown on top of visual actors. False the
				* visual actors hide the b2DebugDraw visuals unless removed or are not occupying
				* the intended position of the actors the Box2d world represents. Can be useful
				* to see the removal process of actors and their Box2d counterparts when set to false.
				* */
			   private const SHOW_BOX2D_DEBUG_AS_OVERLAY:Boolean = true;
			   /**
				* Handler for applicationComplete event. Setup world and begin animation.
				* */
			   protected function applicationCompleteHandler(event:FlexEvent):void
			   {
				   trace(&quot;applicationCompleteHandler(...)&quot;);
				   // Initialize member variables.
				   _actors = new Array();
				   _actorsTaggedForRemoval = new Array();
				   _pegsLitUp = new Array();
				   _goalPegs = new Array();
				   _shooter = new Shooter();
				   // Add the Shooter actor
				   box2DContainer.addChild(_shooter);
				   _shooter.x = SHOOTER_POINT.x;
				   _shooter.y = SHOOTER_POINT.y;
				   // Create the Box2d world.
				   setupPhysicsWorld();
				   // Create the game elements other than the Shooter.
				   createLevel();
				   // The ENTER_FRAME event will drive the updates to the Box2d world.
				   addEventListener (Event.ENTER_FRAME, enterFrameHandler);
				   // Handle the mouse clicks to the stage.
				   stage.addEventListener(MouseEvent.CLICK, stageMouseClickHandler);

			   }
</pre>
<p>The setupPhysicsWorld method creates a Box2D 2.1 world and checks for the state to display the debug data to be shown under the game assets using the SHOW_BOX2D_DEBUG_AS_OVERLAY constant. In the createLevel method, there is the opposite case for the more likely need of showing the debug data over the assets.</p>
<p>Another debugging trick is to open Actor classes and set their "costume" visual visible property to false. Then you can see the Box2d world visual representation without the game visual representation.</p>
<p>Line 175 routes Box2d world body contact incidents to the PuggleContactListener class discussed in a later code block.</p>
<p>The addDebugDraw method determines if the debug data is shown at all.</p>
<pre class="brush: as3; first-line: 161; wrap-lines: false;">
			   /**
				* Creates the Box2dWorld
				* */
			   private function setupPhysicsWorld():void
			   {
				   // Create world. Gravity and let sleeping babies be.
				   PhysiVals.world = new b2World(new b2Vec2(0,9.8), true);

				   // Add b2DebugDraw under the visual actors.
				   if (!SHOW_BOX2D_DEBUG_AS_OVERLAY)
				   {
					   addDebugDraw();
				   }
				   // Set the class to handle Box2d objects contacting each other.
				   PhysiVals.world.SetContactListener(new PuggleContactListener());
			   }
			   /**
				* b2DebugDraw visualization for Box2d.
				* */
			   private function addDebugDraw():void
			   {
				   //Debugging visualization for Box2d. Will appear under the actors.
				   if (SHOW_BOX2D_DEBUG)
				   {
					   var debugSprite:Sprite = new Sprite();
					   box2DContainer.addChild(debugSprite);
					   var debugDraw:b2DebugDraw = new b2DebugDraw();
					   debugDraw.SetSprite(debugSprite);
					   debugDraw.SetDrawScale(PhysiVals.RATIO);
					   debugDraw.SetLineThickness( 1.0);
					   debugDraw.SetAlpha(1);
					   debugDraw.SetFillAlpha(0.4);
					   debugDraw.SetFlags(b2DebugDraw.e_shapeBit);
					   PhysiVals.world.SetDebugDraw(debugDraw);
				   }
			   }
</pre>
<p>The createLevel method adds the PegActors in staggered rows and randomizes some of the PegActors to be goals. It also creates the game walls and ramps. </p>
<p>A big distinction that Box2D 2.1 uses over previous versions is the b2Fixture for each body to determine collisions.</p>
<pre class="brush: as3; first-line: 197; wrap-lines: false;">
			   /**
				* The only game level. Creates the walls, pegs, the ramps and the bonus chute.
				* */
			   private function createLevel():void
			   {
				   // Horizontal spacing of PegActors
				   var hSpacing:int = PEG_H_SPACING;
				   // Vertical spacing of PegActors
				   var vSpacing:int = PEG_V_SPACING;
				   // Rectangle boundaries of PegActors
				   var pegBounds:Rectangle = PEG_BOUNDARIES;
				   // Is odd numbered row
				   var oddRow:Boolean = false;
				   // Array of all PegActors created
				   var allPegs:Array = new Array();
				   // Loop from the top to the bottom of the PegActor boundaries until filled vertically.
				   for (var pegY:int = pegBounds.top; pegY &lt; pegBounds.bottom; pegY += vSpacing)
				   {
					   // The starting x position of the PegActor is 0 or half of horizonal spacing
					   // depending upon even or odd row state.
					   var startX:int = pegBounds.left + ((oddRow) ? 0: (hSpacing / 2));
					   // Flip odd row state.
					   oddRow = ! oddRow;
					   // Loop from the left to the right of the PegActor boundaries until filled horizontally.
					   for (var pegX:int = startX; pegX &lt; pegBounds.right; pegX += hSpacing)
					   {
						   // Create new PegActor in PegActor.NORMAL state
						   var newPeg:PegActor = new PegActor(box2DContainer, new Point (pegX, pegY), PegActor.NORMAL);
						   // Add listener for PegEvent.PEG_LIT_UP.
						   newPeg.addEventListener(PegEvent.PEG_LIT_UP, pegEventHandler);
						   // Add listener for PegEvent.PEG_FADE_OUT_COMPLETE.
						   newPeg.addEventListener(PegEvent.PEG_FADE_OUT_COMPLETE, pegEventHandler);
						   // Add PegActor to actor tracking array.
						   _actors.push(newPeg);
						   // Add PegActor to local tracking array.
						   allPegs.push(newPeg);
					   }
				   }
				   // For the number of PegActors to set to PegActor.GOAL state.
				   for (var i:int = 0; i &lt; GOAL_PEG_NUM; i++)
				   {
					   // Select a PegActor randomly from local tracking array
					   var randomPegNum:int = Math.floor(Math.random() * allPegs.length);
					   // Set the PegActor to PegActor.GOAL state.
					   PegActor(allPegs[randomPegNum]).setType(PegActor.GOAL);
					   _goalPegs.push(allPegs[randomPegNum]);
					   // Remove PegActor from local tracking array.
					   allPegs.splice(randomPegNum, 1);
				   }
				   // Dimensions for the walls
				   var wallShapeCoords:Array = new Array();
				   wallShapeCoords.push(
					   new Array(
						   new Point(0,0),
						   new Point(SIDE_WALL_THICKNESS,0),
						   new Point(SIDE_WALL_THICKNESS,SIDE_WALL_HEIGHT),
						   new Point(0,SIDE_WALL_HEIGHT)
					   )
				   );
				   //Create the left wall.
				   var leftWall:ArbiStaticActor = new ArbiStaticActor(box2DContainer, LEFT_WALL_POSITION, wallShapeCoords);
				   _actors.push(leftWall);
				   //Create the right wall.
				   var rightWall:ArbiStaticActor = new ArbiStaticActor(box2DContainer, RIGHT_WALL_POSITION, wallShapeCoords);
				   _actors.push(rightWall);
				   // Dimensions for the left ramps.
				   var leftRampCoords:Array = new Array();
				   leftRampCoords.push(
					   new Array(
						   new Point(0,0),
						   new Point(79,27),
						   new Point(79,30),
						   new Point(0,3)
					   )
				   );
				   // Add left ramps
				   var leftRamp1:ArbiStaticActor = new ArbiStaticActor(box2DContainer, new Point(0,265), leftRampCoords);
				   _actors.push(leftRamp1);
				   var leftRamp2:ArbiStaticActor = new ArbiStaticActor(box2DContainer, new Point(0,336), leftRampCoords);
				   _actors.push(leftRamp2);
				   var leftRamp3:ArbiStaticActor = new ArbiStaticActor(box2DContainer, new Point(0,415), leftRampCoords);
				   _actors.push(leftRamp3);
				   // Dimensions for the right ramps
				   var rightRampCoords:Array = new Array();
				   rightRampCoords.push(
					   new Array(
						   new Point(0,0),
						   new Point(0, 3),
						   new Point(-85,32),
						   new Point(-85,29)
					   )
				   );
				   // Add the right ramps
				   var rightRamp1:ArbiStaticActor = new ArbiStaticActor(box2DContainer, new Point(646, 232), rightRampCoords);
				   _actors.push(rightRamp1);
				   var rightRamp2:ArbiStaticActor = new ArbiStaticActor(box2DContainer, new Point(646, 308), rightRampCoords);
				   _actors.push(rightRamp2);
				   var rightRamp3:ArbiStaticActor = new ArbiStaticActor(box2DContainer, new Point(646, 388), rightRampCoords);
				   _actors.push(rightRamp3);
				   // Create the bonus chute
				   var bonusChute:BonusChuteActor = new BonusChuteActor(box2DContainer,
					   BONUS_CHUTE_LEFT_BOUNDS,
					   BONUS_CHUTE_RIGHT_BOUNDS,
					   BONUS_CHUTE_VERTICAL_POSITION);
				   _actors.push(bonusChute);
				   // Add b2DebugDraw over the visual actors.
				   if (SHOW_BOX2D_DEBUG_AS_OVERLAY)
				   {
					   addDebugDraw();
				   }
			   }
</pre>
<p>Updating the world involves calling the Box2D world Step method. Then all the game Actor classes updateNow methods are called. Finally all the Actors tagged for removal are removed from the game. The tag and remove methodology is necessary to avoid instability in Box2D. </p>
<pre class="brush: as3; first-line: 308; wrap-lines: false;">
			   /**
				* Game ENTER_FRAME event handler.
				* */
			   private function enterFrameHandler(e:Event):void
			   {
				   updateWorld();
			   }
			   /**
				* .
				* */
			   private function updateWorld():void
			   {
				   // Step simulation time
				   var timeStep:Number = STEP_SIMULATION_TIME;
				   // Step velocity iterations
				   var velocityIterations:int = STEP_VELOCITY_ITERATIONS;
				   // Step position interactions
				   var positionIterations:int = POSITION_VELOCITY_ITERATIONS;
				   //Collision detection, integration, and constraint solutions performed.
				   PhysiVals.world.Step( timeStep, velocityIterations, positionIterations);
				   // As of version 2.1 we must clear the forces.
				   PhysiVals.world.ClearForces();
				   // You want to show debug visualizations.
				   if (SHOW_BOX2D_DEBUG)
				   {
					   PhysiVals.world.DrawDebugData();
				   }
				   // Update all the Actors.
				   for each (var actor:Actor in _actors)
				   {
					   actor.updateNow();
				   }
				   // Remove actors tagged for removal.
				   removeActors();
			   }
			   /**
				* Marks an actor for removal
				* */
			   public function markActorForRemoval(actor:Actor):void
			   {
				   if (_actorsTaggedForRemoval.indexOf(actor) &lt; 0 )
				   {
					   _actorsTaggedForRemoval.push(actor);
				   }
			   }
			   /**
				* Remove actors. Calls their destroy methods.
				* */
			   private function removeActors():void
			   {
				   // Each Actor tagged for removal.
				   for each (var actor:Actor in _actorsTaggedForRemoval)
				   {
					   // This is a BallActor.
					   if (actor is BallActor)
					   {
						   // Reduce counter for number of BallActors in play.
						   _totalBallsLaunced --;
					   }
					   // Destroy the actor using its destroy() method.
					   actor.destroy();
					   // Remove Actor from the actors tracking array.
					   var actorIndex:int = _actors.indexOf(actor);
					   if (actorIndex &gt; -1)
					   {
						   _actors.splice(actorIndex, 1);
					   }
				   }
				   // Reset the actors tagged for removal tracking array.
				   _actorsTaggedForRemoval = new Array();
			   }
</pre>
<p>This code handles the BallActor creation and launching. It also show handling the BallEvent.BALL_OFF_SCREEN and BALL_HIT_BONUS events.</p>
<pre class="brush: as3; first-line: 379; wrap-lines: false;">
                            /**
			     * Handler for stage MouseEvent.CLICK.
			     * */
			   private function stageMouseClickHandler(e:MouseEvent):void
			   {
				   launchBall();
			   }
			   /**
				* Launch a new ball.
				* */
			   private function launchBall():void
			   {

				   if (_totalBallsLaunced &lt; MAX_LAUNCED_BALLS_ALLOWED)
				   {
					   // Get the launch position from the Shooter.
					   var launchPoint:Point = _shooter.getLaunchPosition();
					   // Subtract the coordinates of launch point from the mouse point to get direction.
					   var direction:Point = new Point(mouseX,mouseY).subtract(launchPoint);
					   // Scale by the LAUNCH_VELOCITY.
					   direction.normalize(LAUNCH_VELOCITY);

					   // Create a BallActor
					   var ballActor:BallActor = new BallActor(box2DContainer, launchPoint, direction);
					   ballActor.addEventListener(BallEvent.BALL_OFF_SCREEN, ballOffScreenEventHandler);
					   ballActor.addEventListener(BallEvent.BALL_HIT_BONUS, ballHitBonusEventHandler);
					   _actors.push(ballActor);
					   _totalBallsLaunced++
				   }
			   }
			   /**
				* Handler for BallEvent.BALL_HIT_BONUS
				* */
			   private function ballHitBonusEventHandler(e:BallEvent):void
			   {
				   var ballActor:BallActor = BallActor(e.currentTarget);
				   markActorForRemoval(ballActor);
				   removePegActors();
				   ballActor.removeEventListener(BallEvent.BALL_HIT_BONUS,ballHitBonusEventHandler);
			   }
			   /**
				* Handler for BallEvent.BALL_OFF_SCREEN
				* */
			   private function ballOffScreenEventHandler(e:BallEvent):void
			   {
				   var ballActor:BallActor = BallActor(e.currentTarget);
				   markActorForRemoval(ballActor);
				   removePegActors();
				   ballActor.removeEventListener(BallEvent.BALL_OFF_SCREEN,ballOffScreenEventHandler);
			   }
</pre>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
Once a PegActor is hit, the process involves using <a href="http://www.greensock.com/" target = "_blank">Tweener</a>  to fade out the peg. The process starts in removePegActors method on line 433 and ends in the pegFadeOutState method on line 472 via the pegEventHandler method, on line 446, that handles the PegEvent.PEG_FADE_OUT_COMPLETE event .</p>
<p>The hit processing is handled in the pegEventHandler with PegEvent.PEG_LIT_UP event and adds the PegActor hit to the _pegsLitUp tracking array in the pegLitUpState method which you also see used in the removePegActors method to trigger the fade out process for PegActors in a lit up state.</p>
<pre class="brush: as3; first-line: 429; wrap-lines: false;">
			   /**
				* Fade out peg actors that have been hit (lit up). Removed from the array of lit up PegActors
				* and the fade out eventually leads to their removal.
				* */
			   private function removePegActors():void
			   {
				   var pegNumber:int = 0;
				   for each (var pegActor:PegActor in _pegsLitUp)
				   {
					   pegActor.fadeOut(pegNumber);
					   pegNumber++;
				   }
				   _pegsLitUp = new Array();
			   }
			   /**
				* Handler for the PegActor PegEvent.PEG_LIT_UP and PegEvent.PEG_FADE_OUT_COMPLETE events.
				* */
			   private function pegEventHandler(e:PegEvent):void
			   {
				   switch (e.type)
				   {
					   case PegEvent.PEG_LIT_UP:
						   pegLitUpState(PegActor(e.currentTarget));
						   break;
					   case PegEvent.PEG_FADE_OUT_COMPLETE:
						   pegFadeOutState(PegActor(e.currentTarget));
						   break;
				   }
			   }
			   /**
				* Add tracking for PegActors that are lit up.
				* */
			   private function pegLitUpState(pegActor:PegActor):void
			   {
				   pegActor.removeEventListener(PegEvent.PEG_LIT_UP,pegEventHandler);
				   if (_pegsLitUp.indexOf(pegActor) &lt; 0 )
				   {
					   _pegsLitUp.push(pegActor);
				   }
			   }
			   /**
				* Tag PegActors for removal if they have faded out.
				* */
			   private function pegFadeOutState(pegActor:PegActor):void
			   {
				   _actorsTaggedForRemoval.push(pegActor);
			   }
		   ]]&gt;
	   &lt;/fx:Script&gt;
</pre>
<p>SpriteVisualElement is a simple way to show Sprites in Flex.</p>
<pre class="brush: as3; first-line: 478; wrap-lines: false;">
	   &lt;!--
	   Background for app
	   --&gt;
	   &lt;s:BorderContainer id = &quot;background_bc&quot;
						  width=&quot;{width}&quot; height = &quot;{height}&quot;
						  backgroundColor=&quot;{backgroundColor}&quot;&gt;

		   &lt;!--
		   Container for the Box2D world
		   --&gt;
		   &lt;s:SpriteVisualElement id = &quot;box2DContainer&quot; /&gt;
	   &lt;/s:BorderContainer&gt;
&lt;/s:Application&gt;
</pre>
<p><strong>Shooter Class</strong><br />
The functionality for the shooter is basically to rotate to aim towards the mouse and providing the starting point for the BallActors to launch. These are handled in the alignToMouse, on line 46, and getLaunchPosition, on line 57, methods respectively. </p>
<p>The graphics source and published files are included in the downloads. Many measurements are based on the graphic and so you can open them for viewing to see where values like BALL_OFFSET are derived.</p>
<p>The Shooter is not added to the Box2D world to simplify coding as there is no expectation of the Box2D world&#8217;s bodies coming into contact with it. You might want to include it if you expect collisions.</p>
<pre class="brush: as3; wrap-lines: false;">
package
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Point;
	import mx.core.BitmapAsset;
	/**
	 * Defines the game shooter.
	 * */
	public class Shooter extends Sprite
	{
		/**
		 * Using an embedded graphic.
		 * */
		[Embed(source=&quot;assets/shooter_published.png&quot;)]
		private var ShooterGraphic:Class;
		/**
		 * Starting stage position of BallActor relative to this Shooter.
		 * */
		private const BALL_OFFSET:Point = new Point(70,0);
		/**
		 * Constructor.
		 * */
		public function Shooter()
		{
			// Create an instance for the graphic
			var shooterImg:BitmapAsset = new ShooterGraphic();
			// Center registration point.
			shooterImg.x -= shooterImg.width / 2;
			shooterImg.y -= shooterImg.height / 2;
			// Add the graphic
			addChild(shooterImg);
			// Listen for ENTER_FRAME events.
			this.addEventListener(Event.ENTER_FRAME, enterFrameEventHandler);
		}
		/**
		 * Handler for the ENTER_FRAME event.
		 * */
		private function enterFrameEventHandler(e:Event):void
		{
			alignToMouse();
		}
		/**
		 * Shooter aims at the mouse position.
		 * */
		private function alignToMouse():void
		{
			// Compute the angle to the mouse.
			var mouseAngle:Number = Math.atan2(
				this.stage.mouseY - this.y,
				this.stage.mouseX - this.x) * 180 / Math.PI;
			this.rotation = mouseAngle;
		}
		/**
		 * Provide the starting stage position for BallActors.
		 * */
		public function getLaunchPosition():Point
		{
			return (localToGlobal(BALL_OFFSET));
		}
	}
}
</pre>
<p><strong>Actor Class</strong><br />
This defines the basic structure of the game pieces. It keeps a reference to game piece&#8217;s b2Body and the visual component called _costume.</p>
<p>Most of the methods are overridden in subclasses. However the updating of the costume positions with the Box2D world is done here in the updateMyLook method on line 59. Line 46 contains the pubic interface for updating Actors which first calls updateMyLook and then allows subclasses to perform any child specific tasks.</p>
<p>Line 368 of the HelloWorldPuggle01 class removeActors method call the destroy method you see here on line 75. That method then calls cleanUpBeforeRemoving method, on line 82, that removes the costume and the b2Body for the Actor.</p>
<pre class="brush: as3; wrap-lines: false;">
package
{
	import Box2D.Dynamics.b2Body;
	import flash.display.DisplayObject;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	/**
	 * Defines requirements for all game actors and retains references to Box2d body and the actor's costume.
	 * */
	public class Actor extends EventDispatcher
	{
		protected var _body:b2Body;
		protected var _costume:DisplayObject;
		/**
		 * Constructor
		 * @param body Box2D body for Actor
		 * @param costume is the visual for the Actor.
		 * */
		public function Actor(body:b2Body, costume:DisplayObject)
		{
			_body = body;
			_costume = costume;
			// Store instance in the Box2D body for use as needed.
			_body.SetUserData(this);
			// Update the visual costume.
			updateMyLook();
		}
		/**
		 * Handle being hit by another actor.
		 * @param actor The actor hiting this actor.
		 * */
		public function hitByActor(actor:Actor):void
		{
			// OVERRIDE IN EXTENDED ACTOR CLASS.
		}
		/**
		 * Handle hitting the bonus chute.
		 * */
		public function hitBonusTarget():void
		{
			// OVERRIDE IN EXTENDED ACTOR CLASS.
		}
		/**
		 * Updates the actor.
		 * */
		public function updateNow():void
		{
			// This is a dynamic Actor needing its costume synchronized.
			if ( _body.GetType() == b2Body.b2_dynamicBody)
			{
				updateMyLook();
			}
			// Include any extended class updating specific to that class.
			childSpecificUpdating();
		}
		/**
		 * Updates the actor's costume position and angle.
		 * */
		private function updateMyLook():void
		{
			_costume.x = _body.GetPosition().x * PhysiVals.RATIO;
			_costume.y = _body.GetPosition().y * PhysiVals.RATIO;
			_costume.rotation = _body.GetAngle() * 180 / Math.PI;
		}
		/**
		 * Expected to be overridden by children
		 * */
		protected function childSpecificUpdating():void
		{
			// OVERRIDE IN EXTENDED ACTOR CLASS.
		}
		/**
		 * Handle permanent remove of Actor from game.
		 * */
		public function destroy():void
		{
			cleanUpBeforeRemoving();
		}
		/**
		 * Handles removal of Actor's costume and removal from the Box2D world.
		 * */
		protected function cleanUpBeforeRemoving():void
		{
			// Remove the costume.
			_costume.parent.removeChild(_costume);
			// Remove the Box2D representation.
			PhysiVals.world.DestroyBody(_body);
		}
	}
}
</pre>
<p><strong>BallShape Class</strong><br />
This is a simple graphic to depict a ball for the BallActor and PegActor. You could embellish it with bitmaps or more enhanced vector drawing.</p>
<pre class="brush: as3; wrap-lines: false;">
package
{
	import flash.display.Sprite;
	/**
	 * Draws a filled circle to represent a ball
	 * */
	public class BallShape extends Sprite
	{
		/**
		 * The circle radius.
		 * */
		private var _radius:Number;
		/**
		 * The circle color.
		 * */
		private var _color:uint;
		/**
		 * param radius Radius of ball in pixels.
		 * param color Color of ball.
		 * */
		public function BallShape(radius:Number = 30, color:uint=0xff0000)
		{
			// Consume the parameters into member variables.
			_radius = radius;
			_color = color;
			// Draw the circle.
			draw();
		}
		/**
		 * Draws the circle
		 * */
		private function draw():void
		{
			graphics.clear();
			graphics.beginFill(_color);
			graphics.drawCircle(0, 0, _radius);
			graphics.endFill();
		}
		/**
		 * Set the fill color.
		 * */
		public function set color(colorVal:uint):void
		{
			_color = colorVal;
			draw();
		}
	}
}
</pre>
<p><strong>BallActor Class</strong><br />
The class defines the Box2D representation of our ball bullets.</p>
<p>Two other functions are the  dispatches of the BallEvent.BALL_HIT_BONUS and BallEvent.BALL_OFF_SCREEN events on line 67 and 78 respectively.</p>
<p>The PuggleContactListener class calls the hitBonusTarget method on line 64 for collisions.</p>
<p>The BallEvent.BALL_OFF_SCREEN allows the BallActor to handled for removal in the HelloWorldPuggle01 class ballOffScreenEventHandler method.</p>
<p>The BallEvent.BALL_HIT_BONUS currently just results in the BallActor targeting for removal in the HelloWorldPuggle01 class ballHitBonusEventHandler method. However, you can consider adding scoring logic there if you like.</p>
<pre class="brush: as3; wrap-lines: false;">
package
{
	import Box2D.Collision.Shapes.b2CircleShape;
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.b2BodyDef;
	import Box2D.Dynamics.b2FixtureDef;
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.geom.Point;
	/**
	 * Defines ball game elements that user shoots.
	 * */
	public class BallActor extends Actor
	{
		/**
		 * The diameter for the ball
		 * */
		public static const BALL_DIAMETER:int = 12;
		/**
		 * Constructor
		 * @param parent Display container for the BallActor
		 * @param location Starting position in Box2dWorld
		 * @param initVel The starting velocity.
		 * */
		public function BallActor(parent:DisplayObjectContainer, location:Point, initVel:Point)
		{
			// Create the costume.
			var ballSprite:Sprite = new BallShape();
			ballSprite.scaleX = BALL_DIAMETER / ballSprite.width;
			ballSprite.scaleY = BALL_DIAMETER / ballSprite.height;
			// Add costume to display container.
			parent.addChild(ballSprite);

			// Create a b2BodyDef
			var bodyDef:b2BodyDef = new b2BodyDef();
			// This is a dynamic Box2D body.
			bodyDef.type = b2Body.b2_dynamicBody;
			// Position the BallActor body.
			bodyDef.position.Set(location.x / PhysiVals.RATIO,location.y / PhysiVals.RATIO);
			// Create the b2Body to represent the ballSprite
			var ballBody:b2Body= PhysiVals.world.CreateBody(bodyDef);
			// Body is to be treated for multiple collisions.
			ballBody.SetBullet(true);
			// Create b2CircleShape to represent this body.
			var dynamicCircle:b2CircleShape = new b2CircleShape();
			dynamicCircle.SetRadius(BALL_DIAMETER / 2 / PhysiVals.RATIO);
			// Define b2FixtureDef - the collision detection wrapper.
			var fixtureDef:b2FixtureDef = new b2FixtureDef();
			fixtureDef.shape = dynamicCircle;
			fixtureDef.density = 1.5;
			fixtureDef.friction = 0;
			fixtureDef.restitution = 0.45;
			// Create b2FixtureDef - the collision detection wrapper.
			ballBody.CreateFixture(fixtureDef);
			// Set velocity
			var velocityVector:b2Vec2 = new b2Vec2( initVel.x / PhysiVals.RATIO, initVel.y / PhysiVals.RATIO);
			ballBody.SetLinearVelocity(velocityVector);
			super(ballBody, ballSprite);
		}
		/**
		 * Bonus target hit by this BallActor.
		 * */
		override public function hitBonusTarget():void
		{
			// Broadcast the BallEvent.BALL_HIT_BONUS event.
			dispatchEvent(new BallEvent(BallEvent.BALL_HIT_BONUS));
		}
		/**
		 * Handle the specific items for updates.
		 * */
		override protected function childSpecificUpdating():void
		{
			// Off the stage.
			if (_costume.y &gt; PhysiVals.STAGE_HEIGHT )
			{
				// Broadcast the BallEvent.BALL_OFF_SCREEN event.
				dispatchEvent(new BallEvent(BallEvent.BALL_OFF_SCREEN));
			}
		}
	}
}
</pre>
<p><strong>BallEvent Class</strong><br />
Just a basic Actionscript event class for BallActor events.</p>
<pre class="brush: as3; wrap-lines: false;">
package
{
	import flash.events.Event;
	/**
	 * Defines events for BallActors
	 * */
	public class BallEvent extends Event
	{
		public static const BALL_OFF_SCREEN:String = &quot;ballOffScreen&quot;;
		public static const BALL_HIT_BONUS:String = &quot;ballHitBonus&quot;;
		public function BallEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
		{
			super(type, bubbles, cancelable);
		}
		public override function clone():Event
		{
			return new BallEvent(type,bubbles,cancelable);
		}
	}
}
</pre>
<p><strong>PegActor Class</strong><br />
The first main responsibility is to create both the costume and b2Body for the peg in the constructor.</p>
<p>The HelloWorldPuggle01 class removePegActors method calls the fadeOut method on line 101 where <a href="http://www.greensock.com/" target = "_blank">Tweener</a> does the fade out. </p>
<p>The completion of fade out then triggers the PegEvent.PEG_FADE_OUT_COMPLETE event in fadeOutCompleteHandler on line 110.</p>
<p>The hitByActor method on line 134 is called by the PuggleContactListener for collisions. Here the state is updated and the PegEvent.PEG_LIT_UP is fired for handling in the HelloWorldPuggle01 pegEventHandler and pegLitUpState methods.</p>
<p>The checkPegType method on line 124 is guarantees correct values in setting NORMAL or GOAL states.</p>
<p>The setPegState method on  line 149 sets the costume state of the PegActor. </p>
<pre class="brush: as3; wrap-lines: false;">
package
{
	import Box2D.Collision.Shapes.b2CircleShape;
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.b2BodyDef;
	import Box2D.Dynamics.b2FixtureDef;
	import com.greensock.TweenLite;
	import flash.display.DisplayObjectContainer;
	import flash.geom.Point;
	/**
	 * Defines circle peg actor.
	 * */
	public class PegActor extends Actor
	{
		/**
		 * Normal state for PegActor
		 * */
		public static const NORMAL:int = 1;
		/**
		 * Goal state for PegActor
		 * */
		public static const GOAL:int = 2;
		/**
		 * Color for NORMAL PegActor hit state.
		 * */
		private const NORMAL_HIT_COLOR:Number = 0xff0000;
		/**
		 * Color for NORMAL PegActor not hit state.
		 * */
		private const NORMAL_NOT_HIT_COLOR:Number = 0x0000ff;
		/**
		 * Color for GOAL PegActor hit state.
		 * */
		private const GOAL_HIT_COLOR:Number = 0x00ff00;
		/**
		 * Color for GOAL PegActor not hit state.
		 * */
		private const GOAL_NOT_HIT_COLOR:Number = 0xffff00;
		/**
		 * Diameter for PegActor
		 * */
		private static const PEG_DIAMETER:int = 19;
		/**
		 * Hit state.
		 * */
		private var _beenHit:Boolean = false;
		/**
		 * Type of NORMAL or GOAL.
		 * */
		private var _pegType:int;
		/**
		 * Costume as a BallShape.
		 * */
		private var _pegSprite:BallShape;
		/**
		 * Constructor
		 * @param parent Display container for the PegActor
		 * @param location Location of the PegActor.
		 * @param pegType Valid _pegType.
		 * */
		public function PegActor(parent:DisplayObjectContainer, location:Point, pegType:int)
		{
			// Consume parameters to member variables.
			_pegType = pegType;

			// Create the costume
			_pegSprite = new BallShape();
			_pegSprite.scaleX = PEG_DIAMETER / _pegSprite.width;
			_pegSprite.scaleY = PEG_DIAMETER / _pegSprite.height;
			// Add to display container.
			parent.addChild( _pegSprite );
			// Create the body definitions.
			var bodyDef:b2BodyDef = new b2BodyDef();
			// Set the body as static.
			bodyDef.type = b2Body.b2_staticBody;
			bodyDef.position.Set( location.x / PhysiVals.RATIO, location.y / PhysiVals.RATIO );
			// Create the b2Body to represent the pegSprite.
			var pegBody:b2Body= PhysiVals.world.CreateBody( bodyDef );
			// Create a b2CircleShape for the Box2D world.
			var b2_circleShape:b2CircleShape = new b2CircleShape();
			b2_circleShape.SetRadius( PEG_DIAMETER / 2 / PhysiVals.RATIO );
			// Define the collision detection fixture.
			var fixtureDef:b2FixtureDef = new b2FixtureDef();
			// Set the fixture shape to the circle.
			fixtureDef.shape = b2_circleShape;
			fixtureDef.density = 0;
			fixtureDef.friction = 0;
			fixtureDef.restitution = .45;
			// Add the fixture to the BonusChute b2Body.
			pegBody.CreateFixture(fixtureDef);
			// Call super before throw statements
			super(pegBody, _pegSprite);
			// Check the pegType value.
			checkPegType(pegType);
			// Update the state.
			setPegState();
		}
		/**
		 * Fade out the costume.
		 * */
		public function fadeOut(pegNumber:int):void
		{
			TweenLite.to(_costume, 0.3, {alpha:0, delay: .08 * pegNumber, onComplete: fadeOutCompleteHandler});
		}
		/**
		 * Handler for TweenLite onComplete event. Costume fade out complete.
		 * */
		private function fadeOutCompleteHandler():void
		{
			dispatchEvent(new PegEvent(PegEvent.PEG_FADE_OUT_COMPLETE));
		}
		/**
		 * Set the pegType.
		 * */
		public function setType(pegType:int):void
		{
			checkPegType(pegType);
			_pegType = pegType;
			setPegState();
		}
		/**
		 * Validator for pegType input.
		 * */
		private function checkPegType(pegType:int):void
		{
			if (pegType != NORMAL &amp;&amp; pegType != GOAL)
			{
				throw(new Error(&quot;PegActor setType should be PegActor.NORMAL || PegActor.GOAL&quot;));
			}
		}
		/**
		 * Process a collision with other Actors.
		 * */
		public override function hitByActor(actor:Actor):void
		{
			// Not in hit state.
			if (! _beenHit)
			{
				_beenHit = true;
				setPegState();
				// Broadcase the change to a hit state.
				dispatchEvent(new PegEvent(PegEvent.PEG_LIT_UP));
			}
		}
		/**
		 * Set the state of the peg based on hit state and peg type.
		 * Set the costume look to represent the state.
		 * */
		private function setPegState():void
		{
			if (_pegType == NORMAL)
			{
				if (_beenHit)
				{
					_pegSprite.color = NORMAL_HIT_COLOR;
				}
				else
				{
					_pegSprite.color = NORMAL_NOT_HIT_COLOR;
				}
			}
			else if (_pegType == GOAL)
			{
				if (_beenHit)
				{
					_pegSprite.color = GOAL_HIT_COLOR;
				}
				else
				{
					_pegSprite.color = GOAL_NOT_HIT_COLOR;
				}
			}
		}
	}
}
</pre>
<p><strong>PegEvent Class</strong><br />
Defines the events for PegActors.</p>
<pre class="brush: as3; wrap-lines: false;">
package
{
	import flash.events.Event;
	/**
	 * Defines events for PegActors
	 * */
	public class PegEvent extends Event
	{
		public static const PEG_LIT_UP:String = &quot;pegLitUp&quot;;
		public static const PEG_FADE_OUT_COMPLETE:String = &quot;pegFadeOutComplete&quot;;
		public function PegEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
		{
			super(type, bubbles, cancelable);
		}
		public override function clone():Event
		{
			return new PegEvent(type,bubbles,cancelable);
		}
	}
}
</pre>
<p><strong>BonusChuteActor Class</strong><br />
Most of the code is consumed by creating the b2Body. The b2Body creation on line 99. The b2Body is made of three parts. There are two ramps on the left and right side that BallActor will bounce off. The center marks the point the BallActor can pass into the BonusChute. I broke the creation of these parts into separate methods on lines 127, 170 and 213 respectively. </p>
<p>The work is done in the childSpecificUpdating method on line 263. This mainly positions and moves the BonusChute in the HelloWorldPuggle01 updateWorld method. It also keeps the BonusChute within the boundaries. </p>
<pre class="brush: as3; wrap-lines: false;">
package
{
	import Box2D.Collision.Shapes.b2PolygonShape;
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.b2BodyDef;
	import Box2D.Dynamics.b2FixtureDef;
	import flash.display.DisplayObjectContainer;
	import flash.geom.Point;
	import mx.core.BitmapAsset;
	/**
	 * Defines bonus chute element. This moves left and right automatically.
	 * */
	public class BonusChuteActor extends Actor
	{
		/**
		 * Using an embedded graphic.
		 * */
		[Embed(source=&quot;assets/bonus_chute_published.png&quot;)]
		private var BonusChute:Class;

		/**
		 * Container for the graphic.
		 * */
		private var _bonusChute:BitmapAsset
		/**
		 * Identifies this as a bonus target and is passed along in the b2FixtureDef as user data.
		 * */
		public static const BONUS_TARGET:String = &quot;BonusTarget&quot;;
		/**
		 * Moving left.
		 * */
		private static const LEFT:int = -1;
		/**
		 * Moving right.
		 * */
		private static const RIGHT:int = 1;
		/**
		 * Index in _bounds for the left boundary.
		 * */
		private static const LEFT_BOUND_INDEX:int = 0;
		/**
		 * Index in _bounds for the right boundary.
		 * */
		private static const RIGHT_BOUND_INDEX:int = 1;
		/**
		 * Speed in pixels.
		 * */
		private static const TRAVEL_SPEED:int = 2;
		/**
		 * The b2Body.
		 * */
		private var _chuteBody:b2Body
		/**
		 * Boundary data.
		 * */
		private var _bounds:Array;
		/**
		 * Vertical position.
		 * */
		private var _yPos:int;
		/**
		 * Current direction.
		 * */
		private var _direction:int;
		/**
		 * Display container
		 * */
		private var _displayContainer:DisplayObjectContainer;
		/**
		 * Constructor
		 * @param parent Display container for the BonusChuteActor
		 * @param leftBounds Left boundary.
		 * @param rightBounds Right boundary.
		 * @param yPos Verticle position.
		 * */
		public function BonusChuteActor(parent:DisplayObjectContainer, leftBounds:int, rightBounds:int, yPos:int)
		{
			// Consume arguments.
			_bounds = [leftBounds, rightBounds];
			_yPos = yPos;
			_direction = RIGHT;
			_displayContainer = parent;

			// Create the Box2D body.
			create_b2Body();
			// Add the left ramp b2Polygon.
			createLeftRamp();
			// Add the right ramp b2Polygon.
			createRightRamp();
			// Add the center hole b2Polygon.
			createCenterHole()

			super(_chuteBody, _bonusChute);
		}
		/**
		 * Create the Box2d body for BonusChute.
		 * */
		private function create_b2Body():void
		{
			var leftBounds:int = _bounds[0];
			var rightBounds:int = _bounds[1];
			// Costume
			_bonusChute = new BonusChute();
			// Add costume to display container.
			_displayContainer.addChild(_bonusChute);
			// Set center as registration point.
			_bonusChute.x -= _bonusChute.width / 2;
			_bonusChute.y -= _bonusChute.height / 2;
			//_bonusChute.visible = false;  // For testing just the b2Body
			// Create b2BodyDef.
			var chuteBodyDef:b2BodyDef = new b2BodyDef();
			// This is a dynamic b2Body.
			chuteBodyDef.type = b2Body.b2_dynamicBody;
			// Does not rotate.
			chuteBodyDef.fixedRotation = true;
			// Set position converted into the physical values.
			chuteBodyDef.position.Set(
				(leftBounds + rightBounds) / 2 / PhysiVals.RATIO,
				_yPos / PhysiVals.RATIO);
			// Create the b2Body.
			_chuteBody = PhysiVals.world.CreateBody(chuteBodyDef);
		}
		/**
		 * Create the left ramp to deflect BallActors that miss the chute opening
		 * */
		private function createLeftRamp():void
		{
			// Box2d polygon shape.
			var polyShape:b2PolygonShape;
			// Define b2FixtureDef - the collision detection wrapper.
			var fixtureDef:b2FixtureDef;
			// Polygon points.
			var listOfPointVectors:Array;
			// Each polygon point.
			var v1:b2Vec2;
			var v2:b2Vec2;
			var v3:b2Vec2;
			// Left ramp pixels converted into the b2World dimensions.
			// Need to explore the BonusChute graphic for pixel dimensions.
			listOfPointVectors = new Array();
			v1 = new b2Vec2();
			v1.x = 1 / PhysiVals.RATIO;
			v1.y = 25 / PhysiVals.RATIO;
			listOfPointVectors.push(v1);
			v2 = new b2Vec2();
			v2.x = 19 / PhysiVals.RATIO;
			v2.y = 10 / PhysiVals.RATIO;
			listOfPointVectors.push(v2);
			v3 = new b2Vec2();
			v3.x = 18 / PhysiVals.RATIO;
			v3.y = 25 / PhysiVals.RATIO;
			listOfPointVectors.push(v3);
			// Create the b2PolygonShape.
			polyShape = new b2PolygonShape();
			polyShape.SetAsArray( listOfPointVectors, listOfPointVectors.length);
			// Define the collision detection fixture.
			fixtureDef = new b2FixtureDef();
			// Assign the b2Polygon shape.
			fixtureDef.shape = polyShape;
			fixtureDef.density = 1;
			fixtureDef.friction = .1;
			fixtureDef.restitution = 0.6;
			// Add the fixture to the BonusChute b2Body.
			_chuteBody.CreateFixture(fixtureDef);
		}
		/**
		 * Create the right  ramp to deflect BallActors that miss the chute opening
		 * */
		private function createRightRamp():void
		{
			// Box2d polygon shape.
			var polyShape:b2PolygonShape;
			// Define b2FixtureDef - the collision detection wrapper.
			var fixtureDef:b2FixtureDef;
			// Polygon points.
			var listOfPointVectors:Array;
			// Each polygon point.
			var v1:b2Vec2;
			var v2:b2Vec2;
			var v3:b2Vec2;
			// Right ramp pixels converted into the b2World dimensions.
			// Need to explore the BonusChute graphic for pixel dimensions.
			listOfPointVectors = new Array();
			v1 = new b2Vec2();
			v1.x = 150 / PhysiVals.RATIO;
			v1.y = 25 / PhysiVals.RATIO;
			listOfPointVectors.push(v1);
			v2 = new b2Vec2();
			v2.x = 150 / PhysiVals.RATIO;
			v2.y = 10 / PhysiVals.RATIO;
			listOfPointVectors.push(v2);
			v3 = new b2Vec2();
			v3.x = 167 / PhysiVals.RATIO;
			v3.y = 25 / PhysiVals.RATIO;
			listOfPointVectors.push(v3);
			// Create the b2PolygonShape.
			polyShape = new b2PolygonShape();
			polyShape.SetAsArray( listOfPointVectors, listOfPointVectors.length);
			// Define the collision detection fixture.
			fixtureDef = new b2FixtureDef();
			// Assign the b2Polygon shape.
			fixtureDef.shape = polyShape;
			fixtureDef.density = 1;
			fixtureDef.friction = .1;
			fixtureDef.restitution = 0.6;
			// Add the fixture to the BonusChute b2Body
			_chuteBody.CreateFixture(fixtureDef);
		}
		/**
		 * Create the center chute opening
		 * */
		private function createCenterHole():void
		{
			// Box2d polygon shape.
			var polyShape:b2PolygonShape;
			// Define b2FixtureDef - the collision detection wrapper.
			var fixtureDef:b2FixtureDef;
			// Polygon points.
			var listOfPointVectors:Array;
			// Each polygon point.
			var v1:b2Vec2;
			var v2:b2Vec2;
			var v3:b2Vec2;
			var v4:b2Vec2;
			// Right ramp pixels converted into the b2World dimensions.
			// Need to explore the BonusChute graphic for pixel dimensions.
			listOfPointVectors = new Array();
			v1 = new b2Vec2();
			v1.x = 19 / PhysiVals.RATIO;
			v1.y = 10 / PhysiVals.RATIO;
			listOfPointVectors.push(v1);
			v2 = new b2Vec2();
			v2.x = 150 / PhysiVals.RATIO;
			v2.y = 10 / PhysiVals.RATIO;
			listOfPointVectors.push(v2);
			v3 = new b2Vec2();
			v3.x = 150 / PhysiVals.RATIO;
			v3.y = 25 / PhysiVals.RATIO;
			listOfPointVectors.push(v3);
			v4 = new b2Vec2();
			v4.x = 18 / PhysiVals.RATIO;
			v4.y = 25 / PhysiVals.RATIO;
			listOfPointVectors.push(v4);
			// Create the b2PolygonShape.
			polyShape = new b2PolygonShape();
			polyShape.SetAsArray( listOfPointVectors, listOfPointVectors.length );
			// Define the collision detection fixture.
			fixtureDef = new b2FixtureDef();
			// Assign the b2Polygon shape.
			fixtureDef.shape = polyShape;
			fixtureDef.density = 1;
			fixtureDef.friction = .1;
			fixtureDef.restitution = 0.6;
			fixtureDef.isSensor = true;
			fixtureDef.userData = BONUS_TARGET;
			// Add the fixture to the BonusChute b2Body
			_chuteBody.CreateFixture(fixtureDef);
		}
		/**
		 * Handle the specific items for updates.
		 * */
		override protected function childSpecificUpdating():void
		{
			// Hit right boundary.
			if (_costume.x &gt;= _bounds[RIGHT_BOUND_INDEX] )
			{
				_direction = LEFT;
			}
			// Hit left boundary.
			else if (_costume.x &lt;= _bounds[LEFT_BOUND_INDEX] )
			{
				_direction = RIGHT;
			}
			// New location in pixels.
			var idealLocation:b2Vec2 = new b2Vec2(
				_costume.x + ( _direction * TRAVEL_SPEED),
				_yPos);
			// Distance to travel in one frame in pixels.
			var directionToTravel:b2Vec2 = new b2Vec2(
				idealLocation.x - _costume.x,
				idealLocation.y - _costume.y);
			// Distance to travel in one frame in meters
			directionToTravel.Multiply( 1 / PhysiVals.RATIO );
			// The distance in one second in meters.
			directionToTravel.Multiply(PhysiVals.FRAME_RATE);
			// Set linear velocity of the center of mass.
			_chuteBody.SetLinearVelocity(directionToTravel);
			// Peform any generic child specific updating.
			super.childSpecificUpdating();
		}
	}
}
</pre>
<p><strong>ArbiStaticActor Class</strong><br />
 A generic class for creating static Actors like walls and ramps.</p>
<pre class="brush: as3; wrap-lines: false;">
package
{
	import Box2D.Collision.Shapes.b2PolygonShape;
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.b2BodyDef;
	import Box2D.Dynamics.b2FixtureDef;
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.geom.Point;
	/**
	 * Defines generic static actors such as walls and ramps.
	 * */
	public class ArbiStaticActor extends Actor
	{
		/**
		 * Constructor
		 * @param parent Display container for the ArbiStaticActor
		 * @param location Location of the ArbiStaticActor.
		 * @param coordinates Point coordinates for the ArbiStaticActor.
		 * */
		public function ArbiStaticActor(parent:DisplayObjectContainer, location:Point, coordinates:Array)
		{
			// Create the b2Body.
			var myBody:b2Body = createBodyFromCoordinates(coordinates, location);
			// Create the costume.
			var mySprite:Sprite = createSpriteFromCoordinates( coordinates, location, parent);
			super (myBody, mySprite);
		}
		/**
		 * Create the costume for the AribStaticActor.
		 * @param coordinates Point coordinates for the ArbiStaticActor.
		 * @param location Location of the ArbiStaticActor.
		 * @param parent Display container for the ArbiStaticActor
		 * */
		private function createSpriteFromCoordinates(coordinates:Array, location:Point, parent:DisplayObjectContainer):Sprite
		{
			// Create a Sprite to represent the ArbiStaticActor.
			var newSprite:Sprite = new Sprite();
			newSprite.graphics.lineStyle(2, 0x00bb00);
			// Each point array.
			for each ( var listOfPoints:Array in coordinates )
			{
				var firstPoint:Point = listOfPoints[0];
				newSprite.graphics.moveTo(firstPoint.x, firstPoint.y);
				newSprite.graphics.beginFill(0x00bb00);
				// Each point.
				for each (var newPoint:Point in listOfPoints)
				{
					newSprite.graphics.lineTo(newPoint.x,newPoint.y);
				}
				newSprite.graphics.lineTo(firstPoint.x, firstPoint.y);
				newSprite.graphics.endFill();
			}
			newSprite.x = location.x;
			newSprite.y = location.y;
			parent.addChild(newSprite);
			return newSprite;
		}
		/**
		 * Create the b2Body for the AribStaticActor.
		 * @param coordinates Point coordinates for the ArbiStaticActor.
		 * @param location Location of the ArbiStaticActor.
		 * @param parent Display container for the ArbiStaticActor
		 * */
		private function createBodyFromCoordinates(coordinates:Array, location:Point):b2Body
		{
			// Create the b2Body definitions.
			var bodyDef:b2BodyDef = new b2BodyDef();
			bodyDef.type = b2Body.b2_staticBody;
			bodyDef.position.Set(location.x / PhysiVals.RATIO, location.y / PhysiVals.RATIO);
			// Create the b2Body.
			var arbiBody:b2Body= PhysiVals.world.CreateBody(bodyDef);
			// Each point array.
			for each (var listOfPoints:Array in coordinates)
			{
				var listOfPointVectors:Array = new Array();
				// Each point.
				for (var i:int = 0; i &lt; listOfPoints.length; i++)
				{
					var v:b2Vec2 = new b2Vec2();
					var nextPoint:Point = listOfPoints[i];
					// Convert to b2World measurements.
					v.x = nextPoint.x / PhysiVals.RATIO;
					v.y = nextPoint.y / PhysiVals.RATIO;
					listOfPointVectors.push(v);
				}
				// Create polygon shape.
				var polyShape:b2PolygonShape = new b2PolygonShape();
				polyShape.SetAsArray( listOfPointVectors, listOfPointVectors.length);
				// Define the collision detection fixture.
				var fixtureDef:b2FixtureDef = new b2FixtureDef();
				// Assign the b2Polygon shape.
				fixtureDef.shape = polyShape;
				fixtureDef.density = 0;
				fixtureDef.friction = .2;
				fixtureDef.restitution = 0.3;
				// Add the fixture to the b2Body.
				arbiBody.CreateFixture(fixtureDef);
			}
			return arbiBody;
		}
	}
}
</pre>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
<strong>PuggleContactListener Class</strong><br />
On line 175 of the HelloWorldPuggle01 setupPhysicsWorld() method, this class is assigned as the b2worlds&#8217;s contact listener.</p>
<p>Collisions occurring during the Step method updating of the b2World fire contact events and they are received here. The BeginContact event handler on line 21 does the work we need. We are either calling the Actor&#8217;s hitByActor method as shown on lines 31 and 36 or the hitBonusTarget method on lines 43 and 50. </p>
<p>The BeginContact method provides GetFixtureA and GetFixtureB to represent the collision. From them we use data stored in b2Bodies or b2Fixturesto determine the Actors involved with collisions. </p>
<p>For example the BonusChute class createCenterHole method stores user data on line 256: fixtureDef.userData = BONUS_TARGET;. Here we see on line 40 and 47 testing for that value when user data is a String. </p>
<p>The other case is when the user data contains an Actor we can determine if the Actor is a PegActor or BallActor as on lines 29 and 34.</p>
<p>You can work out your own method of supplying and testing for user data depending on your own code.</p>
<pre class="brush: as3; wrap-lines: false;">
package
{
	import Box2D.Collision.b2Manifold;
	import Box2D.Dynamics.Contacts.b2Contact;
	import Box2D.Dynamics.b2ContactListener;
	/**
	 * Handler for collisions in b2World.
	 * */
	public class PuggleContactListener extends b2ContactListener
	{
		/**
		 * Constructor.
		 * */
		public function PuggleContactListener()
		{
			super();
		}
		/**
		 * Contact started. Notify actors involved.
		 * */
		override public function BeginContact(contact:b2Contact):void
		{
			// Extract user data from contacting Actors.
			var actorA:Actor = contact.GetFixtureA().GetBody().GetUserData();
			var actorB:Actor = contact.GetFixtureB().GetBody().GetUserData();
			var actorAFixtureUserData:* = contact.GetFixtureA().GetUserData();
			var actorBFixtureUserData:* = contact.GetFixtureB().GetUserData();
			// BallActor and PegActor contacted.
			if (actorA is PegActor &amp;&amp; actorB is BallActor)
			{
				actorA.hitByActor(actorB);
			}
			// BallActor and PegActor contacted.
			else if (actorB is PegActor &amp;&amp; actorA is BallActor)
			{
				actorB.hitByActor(actorA);
			}
			// BallActor contacted BonusChuteActor.BONUS_TARGET.
			else if (actorAFixtureUserData is String
				&amp;&amp; actorAFixtureUserData == BonusChuteActor.BONUS_TARGET
				&amp;&amp; actorB is BallActor)
			{
				actorB.hitBonusTarget()
			}
			// BallActor contacted BonusChuteActor.BONUS_TARGET.
			else if (actorBFixtureUserData is String
				&amp;&amp; actorBFixtureUserData == BonusChuteActor.BONUS_TARGET
				&amp;&amp; actorA is BallActor)
			{
				actorA.hitBonusTarget()
			}
			super.BeginContact(contact);
		}
		/**
		 * Contact ended.
		 * */
		override public function EndContact(contact:b2Contact):void
		{
			super.EndContact(contact);
		}
	}
}
</pre>
<p><strong>PhysiValsClass</strong></p>
<p>A place to store some of the values used across classes. The key value is the RATIO that converts the pixel world into the physics world&#8217;s meters. </p>
<pre class="brush: as3; wrap-lines: false;">
package
{
	import Box2D.Dynamics.b2World; 

	public class PhysiVals
	{
		public static const STAGE_HALF_WIDTH:int = 323;
		public static const STAGE_HEIGHT:int = 603;
		private static var _instance:PhysiVals;			// Singleton instance
		public static const RATIO:Number = 30;
		public static const FRAME_RATE:Number = 30;
		private static var _world:b2World;

		public function PhysiVals(pvt:PhysiValsPrivateClass)
		{
		}
		/**
		 * Singleton instantiation method
		 * */
		public static function getInstance():PhysiVals
		{
			if (PhysiVals._instance == null)
			{
				PhysiVals._instance = new PhysiVals( new PhysiValsPrivateClass() );

			}
			return PhysiVals._instance;
		}
		public static function get world():b2World
		{
			return _world
		}
		public static function set world(world:b2World):void
		{
			_world = world;
		}
	}
}

/**
 * Singleton enforcer class
 * */
class PhysiValsPrivateClass
{
	public function PhysiValsPrivateClass()
	{

	}
}
</pre>
<div id="fb-root"></div>
<p><script src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script><fb:comments href="http://www.lonhosford.com/lonblog/2010/11/07/box2d-flash-puggle-lite-game-version-of-peggle-nights/" num_posts="2" width="500"></fb:comments></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonhosford.com/lonblog/2010/11/07/box2d-flash-puggle-lite-game-version-of-peggle-nights/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Flixel Hello World Basic Shooter Game in Flash and Flex</title>
		<link>http://www.lonhosford.com/lonblog/2010/11/01/flixel-hello-world-basic-shooter-game-in-flash-and-flex/</link>
		<comments>http://www.lonhosford.com/lonblog/2010/11/01/flixel-hello-world-basic-shooter-game-in-flash-and-flex/#comments</comments>
		<pubDate>Mon, 01 Nov 2010 20:07:04 +0000</pubDate>
		<dc:creator>Lon Hosford</dc:creator>
				<category><![CDATA[Actionscript 3]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[Flixel]]></category>
		<category><![CDATA[Gaming]]></category>
		<category><![CDATA[Actionscript]]></category>

		<guid isPermaLink="false">http://www.lonhosford.com/lonblog/?p=1059</guid>
		<description><![CDATA[Decided to try an Actionscript 3 game engine and chose Flixel to start. I started late afternoon Halloween and when the devil (local neighbor in costume) showed up with treats and pizza, I was well on the way. The Flixel site lead me off to a &#8220;hello world&#8221; space ship shooter game laid out by [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" src="http://lh6.ggpht.com/_e5pwU0LJbN8/TM8hDqR80xI/AAAAAAAAFvk/_7NG6QL2hss/s800/FlixelBasicShooterGame01_AS_11-1-2010%202-14-58%20PM.png" alt="" width="372" height="169" />Decided to try an Actionscript 3 game engine and chose <a href="http://flixel.org/" target = "_blank">Flixel</a> to start. I started late afternoon Halloween and when the devil (local neighbor in costume) showed up with treats and pizza, I was well on the way.</p>
<p>The Flixel site lead me off to a &#8220;hello world&#8221; space ship shooter game laid out by <a href="http://se.linkedin.com/in/andreaszecher" target = "_blank">Andreas Zecher</a>. He has a nice <a href="http://www.creativeapplications.net/flash/flixel-2-tutorial-flash-tutorials-games/"  target = "_blank">incremental tutorial</a> that shows the changes if you follow it. I decided to create my own game pieces and also comment all the code so I understood on a line by line basis what was happening. I also made some changes to data moving it out of the code to at least the class member level. This post shows the results of the work.</p>
<p><a href="http://www.amazon.com/gp/product/0763784516?ie=UTF8&#038;tag=hosfordusa&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=0763784516" target = "_blank"><img border="0" align="right" src="http://lh4.ggpht.com/_e5pwU0LJbN8/TMg4rcI62aI/AAAAAAAAFvI/HBJG_mAV_1M/s800/51kVfkmZ-WL._SL160_.jpg"></a></p>
<p>I am using version <a href="http://flixel.org/" target = "_blank">Flixel version 2.35</a> because and included a swc in the download files so you do not need to download it.</p>
<p>You can build this with the free Flex SDK by using the code in the src folder and be sure to include a path to the Flixel library. For Flash CS3 and later versions, you need to create a Flash Document in the src folder and set the document class to <code>Main</code> and then add a library path to the Flixel  2.35 code or SWC if you created one. For your convenience the Flash CS4 example download is included with a Flixel 2.35 SWC.</p>
<p>Also for Flash CS3 on up you will need some Flex library swc files because of the use of the Embed meta tag. Tareq AlJaber has <a href="http://www.adobe.com/devnet/flash/articles/embed_metadata.html" target = "_blank">good article on embedding meta data in Flash CS4</a>.</p>
<ul style="padding-top: 10px;">
<li><a href="http://www.lonhosford.com/content/gaming/flixel/FlixelBasicShooterGame01_AS.zip" onClick="javascript: pageTracker._trackPageview('/downloads/FlixelBasicShooterGame01_AS.zip'); ">Flex Builder 4 Actionscript Project</a></li>
<li><a href="http://www.lonhosford.com/content/gaming/flixel/FlixelBasicShooterGame01_Flex.fxp" onClick="javascript: pageTracker._trackPageview('/downloads/FlixelBasicShooterGame01_Flex.fxp'); ">Flex Builder 4 Flex Project</a></li>
<li><a href="http://www.lonhosford.com/content/gaming/flixel/FlixelBasicShooterGame01_CS4.zip" onClick="javascript: pageTracker._trackPageview('/downloads/FlixelBasicShooterGame01_CS4.zip'); ">Flash CS4</a></li>
</ul>
<p>This article shows the code for the Flex project.</p>
<p><strong>Application Class &#8211; Main</strong><br />
The applicationCompleteHandler creates Flixel game instance variable named flxGame. It is easily added to the Flex SpriteVisualElement and we are off and playing.</p>
<pre class="brush: as3; wrap-lines: false;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;s:Application xmlns:fx=&quot;http://ns.adobe.com/mxml/2009&quot;
			   xmlns:s=&quot;library://ns.adobe.com/flex/spark&quot;
			   xmlns:mx=&quot;library://ns.adobe.com/flex/mx&quot;
			   applicationComplete=&quot;applicationCompleteHandler(event)&quot;
			   width = &quot;644&quot;
			   height = &quot;484&quot;
			   &gt;
	&lt;fx:Script&gt;
		&lt;![CDATA[
			import mx.events.FlexEvent;

			import org.flixel.FlxGame;
			/**
			 * Set the preloader.
			 * */
			[Frame(factoryClass=&quot;Preloader&quot;)]
			/**
			 * Properties for background
			 * @see background_bc
			 */
			private static const backgroundColor:Number = 0x333333;
			/**
			 * The Flixel game.
			 */
			private var flxGame:FlxGame;
			/**
			 * Handler for applicationComplete event. Setup world and begin animation.
			 * */
			protected function applicationCompleteHandler(event:FlexEvent):void
			{
				trace( className + &quot;.applicationCompleteHandler(...)&quot;);
				flxGame = new FlxGame(640, 480, PlayState, 1 );
				box2DContainer.addChild(flxGame);
				// Offset to show box2DContainer evenly.
				flxGame.x = 1;
				flxGame.y = 1;
			}
		]]&gt;
	&lt;/fx:Script&gt;
	&lt;!--
	Background for app
	--&gt;
	&lt;s:BorderContainer id = &quot;background_bc&quot;
					   width=&quot;{width}&quot; height = &quot;{height}&quot;

					   backgroundColor=&quot;{backgroundColor}&quot;&gt;

		&lt;!--
		Container for the FlxGame
		--&gt;
		&lt;s:SpriteVisualElement id = &quot;box2DContainer&quot; /&gt;
	&lt;/s:BorderContainer&gt;
&lt;/s:Application&gt;
</pre>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
<strong>PlayState Class</strong><br />
The PlayState class does the real game specific details. Flixel does the rest of the work.</p>
<p>Overall the plan is to have a player space ship pointing to the right only and that moves up, down, left and right with arrow keys. The spacebar is used for firing bullets. Enemy space ships appear of the right and travel left with a slight sine wave. Collisions of bullets with enemy ships terminates them in an explosion. Collision of the player ship with an enemy ship terminates both ships and ends the game.</p>
<p>Enemy ships are added in more frequently as the game progress. Bullets are unlimited and have no repetition governor.</p>
<p>The create method on line 88 sets the game up and starts the game. In 2.5 seconds the first enemy ship appears.</p>
<p>The update method on line 116 represents the testing for player input and collisions. Lines 119 and 121 detect collisions. </p>
<p>Lines 123 &#8211; 127 test for starting the game which is done by detecting if the player ship is inactive (&#8220;dead&#8221;) and the ENTER key is pressed. Game in play is based on the player ship being active.</p>
<p>Lines 128 &#8211; 133 set the flag to fire a bullet when the SPACE BAR is pressed.</p>
<p>Lines 135  &#8211; 144 simple detect if it is time to add another enemy ship and to call resetSpawnTimer() on line 173 that adjusts the timer to a smaller interval.</p>
<p>The handler for an enemy ship hit with a bullet is the overlapAlienBullet method on line 188. Basically the enemy ship and bullet are destroyed and broken into exploding pixels. That code I have not studied but is handled by the createEmitter() method  on line 228 and the FlxEmitter class. </p>
<p>The overlapAlienShip method on line 207 handles an enemy ship colliding with the play ship. The game is rendered inactive at this point, however enemy ships keep showing up in larger numbers: something I did not bother to fix. The game gets a shake using the FlxG.quake.start method on line 214.</p>
<pre class="brush: as3; wrap-lines: false;">
package
{
	import org.flixel.FlxEmitter;
	import org.flixel.FlxG;
	import org.flixel.FlxGroup;
	import org.flixel.FlxPoint;
	import org.flixel.FlxSprite;
	import org.flixel.FlxState;
	import org.flixel.FlxText;
	import org.flixel.FlxU;

	public class PlayState extends FlxState
	{
		/**
		 * Player ship.
		 * */
		private var _playerShip:PlayerShip;
		/**
		 * FlxGroup for EnemyShip objects.
		 * */
		private var _enemyShips:FlxGroup;
		/**
		 * FlxGroup for player ship bullets
		 * */
		private var _bullets:FlxGroup;
		private var _enemyShipSpawnTimer:Number;
		/**
		 * Starting number of seconds that new enemy ships are spawned.
		 * */
		private var _enemyShipSpawnInterval:Number = 2.5;
		/**
		 * Minimum seconds that new enemy ships are spawned.
		 * */
		private var _enemyShipSpawnIntervalMin:Number = .1;
		/**
		 * Reducing factor for seconds next enemy ship is spawned.
		 * */
		private var _enemyShipSpawnIntervalReductionFactor:Number = 0.95;
		/**
		 * Game text displaying number of enemy ships hit.
		 * */
		private var _scoreText:FlxText;
		/**
		 * Score text font size.
		 * */
		private var _scoreTextFontSize:Number = 32;
		/**
		 * Score text font color.
		 * */
		private var _scoreTextFontColor:Number = 0xFF597137;
		/**
		 * Score text horizontal alignment.
		 * */
		private var _scoreTextAlign:String = &quot;left&quot;;
		/**
		 * Game text displaying end of game message.
		 * */
		private var _gameOverText:FlxText;
		/**
		 * End of came message.
		 * */
		private var _lang_GameOverMessage:String = &quot;GAME OVER\nPRESS ENTER TO PLAY AGAIN&quot;;
		/**
		 * Sound for exploding game ship
		 * */
		[Embed(source=&quot;assets/ExplosionShip.mp3&quot;)]
		private var SoundExplosionShip:Class;
		/**
		 * Sound for exploding enemy ship
		 * */
		[Embed(source=&quot;assets/ExplosionAlien.mp3&quot;)]
		private var SoundExplosionEnemyShip:Class;
		/**
		 * Sound for ship bullet
		 * */
		[Embed(source=&quot;assets/Bullet.mp3&quot;)]
		private var SoundBullet:Class;
		/**
		 * The game play state constructor.
		 * */
		public function PlayState()
		{
			super();
		}
		/**
		 * Create game objects
		 */
		override public function create():void
		{
			// Set the FlxState bgColor. The default background color of the game.
			bgColor = 0xFFABCC7D;
			// Set the Flixel starting score value
			FlxG.score = 0;
			// Set the costume score value
			_scoreText = new FlxText(10, 8, 200, &quot;0&quot;);
			_scoreText.setFormat(null, _scoreTextFontSize, _scoreTextFontColor, _scoreTextAlign);
			add(_scoreText);
			// Add player ship.
			_playerShip = new PlayerShip();
			add(_playerShip);
			// Add a group for enemy ships
			_enemyShips = new FlxGroup();
			add(_enemyShips);
			// Add a group for player ship bullets
			_bullets = new FlxGroup();
			add(_bullets);
			// Reset the enemy ship spawning timer.
			resetSpawnTimer();
			// Flixel framework creating process.
			super.create();
		}
		/**
		 * Automatically calls update on everything added to the game loop.
		 * Handle custom input and perform collisions.
		 */
		override public function update():void
		{
			// Bullet hit an enemy ship
			FlxU.overlap(_enemyShips, _bullets, overlapAlienBullet);
			// Enemy ship hit player ship
			FlxU.overlap(_enemyShips, _playerShip, overlapAlienShip);
			// Ship dead and Enter key is pressed
			if(FlxG.keys.ENTER &amp;&amp; _playerShip.dead)
			{
				// Reset the game state to start.
				FlxG.state = new PlayState();
			}
			// Space key and ship is active
			if(FlxG.keys.justPressed(&quot;SPACE&quot;) &amp;&amp; _playerShip.dead == false)
			{
				// Fire a bullet
				spawnBullet(_playerShip.getBulletSpawnPosition());
			}
			// Reduce enemy ship spawning timer by seconds that passed since last frame
			_enemyShipSpawnTimer -= FlxG.elapsed;
			// Enemy ship spawning timer is negative
			if(_enemyShipSpawnTimer &lt; 0)
			{
				// Create enemy ship
				spawnEnemyShip();
				// Reset the enemy ship spawning timer.
				resetSpawnTimer();
			}
			// Update default game actions
			super.update();
		}
		/**
		 * Launch an enemy ship at random location.
		 * */
		private function spawnEnemyShip():void
		{
			// Enemy ship starts on right off screen
			var x: Number = FlxG.width;
			// Enemy ship random y position
			var y: Number = Math.random() * (FlxG.height - 100) + 50;
			_enemyShips.add(new EnemyShip(x, y));
		}
		/**
		 * Fire a bullet.
		 * */
		private function spawnBullet(p:FlxPoint):void
		{
			// Create a bullet.
			var bullet: PlayerShipBullet = new PlayerShipBullet(p.x, p.y);
			// Add bullet to this play state.
			_bullets.add(bullet);
			// Make bullet firing sound
			FlxG.play(SoundBullet);
		}
		/**
		 * Reset the bullet and enemy ship spawning timer
		 * */
		private function resetSpawnTimer():void
		{
			// Reset the count down timer
			_enemyShipSpawnTimer = _enemyShipSpawnInterval;
			// Shorten the countdown timer interval for next pass.
			_enemyShipSpawnInterval *= _enemyShipSpawnIntervalReductionFactor;
			// Below minimum interval
			if(_enemyShipSpawnInterval &lt; _enemyShipSpawnIntervalMin)
			{
				_enemyShipSpawnInterval = _enemyShipSpawnIntervalMin;
			}
		}
		/**
		 * Enemy ship hit by bullet.
		 * */
		private function overlapAlienBullet(enemyShip:EnemyShip, bullet:PlayerShipBullet):void
		{
			// Set the enemy ship as dead. See FlxObject.kill();
			enemyShip.kill();
			// Set the bullet as dead. See FlxObject.kill();
			bullet.kill();
			// Update score for Flixel.
			FlxG.score += 1;
			// Update score costume.
			_scoreText.text = FlxG.score.toString();
			// Explode the enemy ship.
			var emitter:FlxEmitter = createEmitter();
			emitter.at(enemyShip);
			// Play sound for enemy ship exploding.
			FlxG.play(SoundExplosionEnemyShip);
		}
		/**
		 * Play ship and enemy ship collide.
		 * */
		private function overlapAlienShip(enemyShip:EnemyShip, playerShip:PlayerShip):void
		{
			// Set the player ship as dead. See FlxObject.kill();
			playerShip.kill();
			// Set the enemy ship as dead. See FlxObject.kill();
			enemyShip.kill();
			// Shake game.
			FlxG.quake.start(0.02);
			// Explode player ship
			var emitter:FlxEmitter = createEmitter();
			emitter.at(playerShip);
			// Play player ship explosion sound.
			FlxG.play(SoundExplosionShip);
			// Update game text costume.
			_gameOverText = new FlxText(0, FlxG.height / 2, FlxG.width,_lang_GameOverMessage);
			_gameOverText.setFormat(null, 16, 0xFF597137, &quot;center&quot;);
			add(_gameOverText);
		}
		/**
		 * Ship explosion particle emitter animation.
		 * */
		private function createEmitter():FlxEmitter
		{
			var emitter:FlxEmitter = new FlxEmitter();
			emitter.delay = 1;
			emitter.gravity = 0;
			emitter.maxRotation = 0;
			emitter.setXSpeed(-500, 500);
			emitter.setYSpeed(-500, 500);
			var particles: int = 10;
			for(var i: int = 0; i &lt; particles; i++)
			{
				var particle:FlxSprite = new FlxSprite();
				particle.createGraphic(2, 2, 0xFF597137);
				particle.exists = false;
				emitter.add(particle);
			}
			emitter.start();
			add(emitter);
			return emitter;
		}
	}
}
</pre>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
<strong>PlayerShip Class</strong><br />
This class adds the graphic for the player ship. When the Flixel framework calls the update method, the player ship is repositioned and kept with boundaries.</p>
<p>When the PlayerState class requires a bullet the getBulletSpawnPosition() on line 104 provides the starting position based on the graphic design for the gun barrel.</p>
<pre class="brush: as3; wrap-lines: false;">
package
{
	import org.flixel.FlxG;
	import org.flixel.FlxPoint;
	import org.flixel.FlxSprite;

	/**
	 * Defines the player's ship.
	 * */
	public class PlayerShip extends FlxSprite
	{
		/**
		 * Starting game horizontal position.
		 * */
		private const SHIP_START_X:Number = 50;
		/**
		 * Starting game vertical position.
		 * */
		private const SHIP_START_Y:Number = 50;
		/**
		 * Ship movement velocity.
		 * */
		private const SHIP_MOVEMENT_VELOCITY:Number = 250;
		/**
		 * Padding for movement of ships.
		 * */
		private const SHIP_MOVEMENT_PADDING:Number = 16;
		/**
		 * Graphic for player ship.
		 * */
		[Embed(source=&quot;assets/ship_published.png&quot;)]
		private var ImgShip:Class;

		/**
		 * Player ship.
		 * */
		public function PlayerShip():void
		{
			super(SHIP_START_X, SHIP_START_Y, ImgShip);
		}
		/**
		 * Update ship.
		 * */
		override public function update():void
		{
			// Set horizontal velocity to stopped position.
			velocity.x = 0;
			// Set vertical velocity to stopped position.
			velocity.y = 0;

			// Left key.
			if(FlxG.keys.LEFT)
			{
				// Set horizontal velocity to left.
				velocity.x = -SHIP_MOVEMENT_VELOCITY;
			}
			// Right key.
			else if(FlxG.keys.RIGHT)
			{
				// Set horizontal velocity to right.
				velocity.x = SHIP_MOVEMENT_VELOCITY;
			}
			// Up key.
			if(FlxG.keys.UP)
			{
				// Set vertical velocity to up.
				velocity.y = -SHIP_MOVEMENT_VELOCITY;
			}
			// Down key.
			else if(FlxG.keys.DOWN)
			{
				// Set vertical velocity to down.
				velocity.y = SHIP_MOVEMENT_VELOCITY;
			}
			// Postion is near right side of screen.
			if(x &gt; FlxG.width - width - SHIP_MOVEMENT_PADDING)
			{
				// Hold the position.
				x = FlxG.width - width - SHIP_MOVEMENT_PADDING;
			}
			// Postion is near left side of screen.
			else if(x &lt; SHIP_MOVEMENT_PADDING)
			{
				// Hold the position.
				x = SHIP_MOVEMENT_PADDING;
			}
			// Postion is near bottom of screen.
			if(y &gt; FlxG.height - height - SHIP_MOVEMENT_PADDING)
			{
				// Hold the position.
				y = FlxG.height - height - SHIP_MOVEMENT_PADDING;
			}
			// Postion is near top of screen.
			else if(y &lt; SHIP_MOVEMENT_PADDING)
			{
				// Hold the position.
				y = SHIP_MOVEMENT_PADDING;
			}
			super.update();
		}
		/**
		 * Position bullet starting position at tip of gun barrel.
		 * */
		public function getBulletSpawnPosition():FlxPoint
		{
			// See ImgShip asset for placement offset metrics to end of gun barrel.
			var p: FlxPoint = new FlxPoint(x + 108, y + 27);
			return p;
		}
	}
}
</pre>
<p><strong>EnemyShip Class</strong><br />
This class adds the graphic for the enemy ship and the initial game position when created. The PlayState spawnEnemyShip method computes the vertical starting position using some random computations and the horizontal position always off the right side of the game screen..</p>
<p>It mainly provides the velocity for the enemy ships which include a left only horizontal direction and a sine wave for vertical direction.</p>
<pre class="brush: as3; wrap-lines: false;">
package
{
	import org.flixel.FlxSprite;
	/**
	 * Defines enemy ship.
	 * */
	public class EnemyShip extends FlxSprite
	{
		/**
		 * Horizontal velocity for enemy ship.
		 * */
		private const ENEMY_SHIP_HORIZONTAL_VELOCITY:Number = 200;
		/**
		 * Vertical velocity for enemy ship.
		 * */
		private const ENEMY_SHIP_VERTICAL_VELOCITY:Number = 50;
		/**
		 * Graphic for enemy ship.
		 * */
		[Embed(source=&quot;assets/enemy_ship_published.png&quot;)]
		private var ImgEnemy:Class;
		/**
		 * Enemy ship constructor.
		 * */
		public function EnemyShip(x: Number, y: Number):void
		{
			super(x, y, ImgEnemy);
			// Enemy ship moves left.
			velocity.x = -ENEMY_SHIP_HORIZONTAL_VELOCITY;
		}
		/**
		 * Update the enemy ship.
		 * */
		override public function update():void
		{
			// Sine wave for vertical velocity.
			velocity.y = Math.cos(x / ENEMY_SHIP_VERTICAL_VELOCITY) * ENEMY_SHIP_VERTICAL_VELOCITY;
			super.update();
		}

	}
}
</pre>
<p><div style = "text-align:center"><script type="text/javascript"><!--
google_ad_client = "pub-8926707286265620";
/* 300x250, created 7/29/10 */
google_ad_slot = "4548376258";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script></div><br />
<strong>PlayerShipBullet Class</strong><br />
Defines the player ship bullet using the FlxSprite createGraphic method which simply creates a rectangular image.</p>
<p>The player bullet x velocity is set to right. This matches the player ship always pointing right.</p>
<p>It could be interesting providing an alternative sine based vertical velocity.</p>
<pre class="brush: as3; wrap-lines: false;">
package
{
	import org.flixel.FlxSprite;

	public class PlayerShipBullet extends FlxSprite
	{
		/**
		 * Player ship bullet.
		 * */
		public function PlayerShipBullet(x: Number, y: Number):void
		{
			super(x, y);
			// Use simple flat colored square image for bullet.
			createGraphic(16, 3, 0xFF597137);
			velocity.x = 1000;
		}
	}
}
</pre>
<p><strong>Preloader Class</strong><br />
This is supposed to show a nice 8-bit style preloader bar according to Andreas Zecher. I noticed a comment on his<a href="http://www.creativeapplications.net/flash/flixel-2-tutorial-flash-tutorials-games/"  target = "_blank">tutorial</a> that it did not work. I ran this in the Flash CS4 bandwidth profiler and could not show the preloader. All the content is in the first frame, and for that matter in Main, for CS4 and thus all needs loading before any code would run to show a preloader. </p>
<p>I kept the coding in and the Preloader class simply needs to know what class it is to measure for the preloading animation to run.</p>
<pre class="brush: as3; wrap-lines: false;">
package
{
	import org.flixel.FlxPreloader;

	/**
	 * Flixel preloader.
	 * */
	public class Preloader extends FlxPreloader
	{
		/**
		 * Set Flixel preloader class name.
		 * */
		override public function Preloader()
		{
			className = &quot;Main&quot;;
			super();
		}
	}
}
</pre>
<p><strong>Default.css</strong><br />
This is blank and appears to be needed to remove the &#8220;Default css file not found&#8221; warning message in Flex Builder 4. You can see the solution for this in <a href="http://github.com/AdamAtomic/flixel/wiki/Hello,-World!-%28Flex-Builder-3.0,-OSX%29" target = "_blank"> APPENDIX C: That Annoying Default.css Warning</a> of an article on setting up a Flixel Actionscript project in Flex Builder.  </p>
<p>Basically you need a blank Default.css file and add the switch -defaults-css-url Default.css to the project Actionscript Compiler Additional compiler arguments found in the project properties.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonhosford.com/lonblog/2010/11/01/flixel-hello-world-basic-shooter-game-in-flash-and-flex/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

