New name for FlexBuilder

29 05 2009

Interesting news!! FlexBuilder is being rebranded to a new name – FlashBuilder. I feel this is more intuitive than earlier. Basically FlexBuilder is a tool for creating flash applications only. Whether you use Flex SDK or just plain actionscript, that’s upto you.

Check this article by Lee Brimelow.


Advertisements




Handle XML with namespaces

29 01 2009

Yesterday, I faced an issue while working with an xml file in Flash. I was unable to parse the xml data using the normal E4X syntax such as xml.node1.node2. It would give an error. The only thing different about this particular xml is that it has a lot of namespaces declared in it. After going through the documentation I found out a way to handle this issue. Check the following code:

var xml:XML = <Workbook xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:x2="http://schemas.microsoft.com/office/excel/2003/xml" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:x="urn:schemas-microsoft-com:office:excel">
	<ss:Worksheet ss:Name="Sheet1">
	<Table ss:StyleID="ta1">
		<Row ss:AutoFitHeight="0" ss:Height="13.4064">
			<Cell>
				<Data ss:Type="String">Preview</Data>
			</Cell>
			<Cell>
				<Data ss:Type="String">unicode</Data>
			</Cell>
			<Cell>
				<Data ss:Type="String">htmlcode</Data>
			</Cell>
			<Cell>
				<Data ss:Type="String">htmlalt</Data>
			</Cell>
			<Cell>
				<Data ss:Type="String">utfcode</Data>
			</Cell>
			<Cell>
				<Data ss:Type="String">utfalt</Data>
			</Cell>
		</Row>
	</Table>
	</ss:Worksheet>
</Workbook>

namespace ns1 = "urn:schemas-microsoft-com:office:spreadsheet";
use namespace ns1;

trace(xml..*::Table.Row[0].Cell[0].Data); //Preview

Here, I just declared the default namespace for the above xml. Try this code without the namespace statement and you will get an error. The namespace declared without a prefix is the default namespace for the xml. For this xml the default namespace is xmlns=”urn:schemas-microsoft-com:office:spreadsheet”.

In this case what I’ve done is declared the default namespace in actionscript. And to reference a deeply nested node I’ve used “..*::” instead of a simple ” ..”

Also, in case you want to remove all the namespaces mentioned in the xml, you can try doing something like this:

var arNS:Array = xml.inScopeNamespaces();
for each (var item:Namespace in arNS)
{
	xml.removeNamespace(item);
}

However, do note that this will not remove the default namespace.





Collision Detection

4 12 2008

Whether it’s a shooting game, a car racing, a pin ball, or a pac man game, collision detection is one of the most important aspects in building games. Without proper colision detection none of these games can exist in Flash. I want to share a very basic collision detection using a ball bounce example. Below, see how the ball bounces back when it hits any of the side walls or the moving wall in the center.

BallBounce.swf

BallBounce in Flash AS3 using hitTestObject()

BallBounce in Flash AS3 using hitTestObject()

Here, collision is detected using two AS3.0 techniques:

1. movieclip1.hitTestObject(movieClip2)
2. checking the overlapping of x and y coordinates of the two movieclips

I have also used a custom event (BounceEvent) that helps in announcing when the ball hits a wall and specifically which wall(or which side.)

There are 5 classes being used in this example:

1. Ball: A ball that will move and bounce around.
2. MovingWall: A movieclip in the center that is constantly moving to create obstruction for the ball.
3. Splat: A movieclip object to show the collision effect.
4. BounceEvent: A custom event to announce that a ball has hit the wall.
5. main: This is the document class. Initiates all the objects and controls the collision detection.

Ball.as

package
{
	import flash.display.MovieClip;
	public class Ball extends MovieClip
	{
		public function Ball(xPos:Number, yPos:Number)
		{

			var b:MovieClip = new MovieClip();
			b.graphics.beginFill(0xFF9933);
			b.graphics.drawCircle(0, 0, 10);
			x = xPos;
			y = yPos;
			addChild(b);
		}
	}
}

Splat.as

package
{
	import flash.display.MovieClip;
	import fl.transitions.Tween;
	import fl.transitions.easing.*;
	public class Splat extends MovieClip
	{
		public function Splat()
		{
			alpha = 0;
		}

		public function explode(xPos:Number, yPos:Number):void
		{
			x = xPos;
			y = yPos;

			new Tween(this, "alpha", Strong.easeOut, 30, 0, 0.2, true);
		}
	}
}

MovingWall.as

package
{
	import flash.display.MovieClip;
	import flash.events.Event;
	public class MovingWall extends MovieClip
	{
		private var wallVelocityY:Number = 3;
		public function MovingWall(xPos:Number, yPos:Number)
		{
			x = 130;
			y = 40;
			setMotion();
		}
		private function setMotion():void
		{
			addEventListener(Event.ENTER_FRAME, moveWall);
		}
		private function moveWall(event:Event):void
		{
			y += wallVelocityY;
			if (y <= 40)
			{
				wallVelocityY = Math.abs(wallVelocityY);
			}
			else if (y >= 120)
			{
				wallVelocityY = -Math.abs(wallVelocityY);
			}
		}
	}
}

BounceEvent.as

package
{
	import flash.events.Event;
	public class BounceEvent extends Event
	{
		public static const BOUNCE:String = "Bounce";
		private var _side:String = "none";

		public function get side():String
		{
			return _side;
		}

		public function BounceEvent(type:String, side:String)
		{
			super(type, true);
			_side = side;
		}

		public override function clone():Event
		{
			return new BounceEvent(type, _side);
		}
	}
}

main.as

This is where the real action happens. First we instantiate the ball, movingWall, and the splat objects. Then we set the ball in motion. And then, using hitTestObject() we check when the ball hits the side walls. Using the custom BounceEvent we make an announcement when the ball hits a wall. The event also lets us know which wall has been hit. For the moving wall after checking with hitTestObject() we also need to find out which side of the wall has been hit. For that we check the overlapping of x and y coordinates of the ball and the moving wall.

package
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.display.MovieClip;

	public class main extends Sprite
	{
		private var ballVelocityX:Number = 2;
		private var ballVelocityY:Number = 3;
		private var ball:MovieClip;
		private var movingWall:MovingWall;
		private var splat:Splat;
		public function main()
		{
			stage.frameRate = 36;
			setGraphicObjects();
			startBallMotion();
		}
		private function setGraphicObjects():void
		{
			ball = new Ball(100, 100);
			addChild(ball);
			movingWall = new MovingWall(130, 40);
			addChild(movingWall);
			splat = new Splat();
			addChild(splat);
		}
		private function startBallMotion():void
		{
			ball.addEventListener(Event.ENTER_FRAME, moveball)
			addEventListener(BounceEvent.BOUNCE, bounceHandler);
		}
		private function moveball(event:Event):void
		{
			event.target.x += ballVelocityX;
			event.target.y += ballVelocityY;
			sideWallCollision();
			movingWallCollision();
		}
		private function sideWallCollision():void
		{
			if (ball.hitTestObject(wallLeft))
			{
				ballVelocityX = Math.abs(ballVelocityX);
				ball.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "left"));
			}
			else if (ball.hitTestObject(wallRight))
			{
				ballVelocityX = -Math.abs(ballVelocityX);
				ball.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "right"));
			}
			if (ball.hitTestObject(wallTop))
			{
				ballVelocityY = Math.abs(ballVelocityY);
				ball.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "top"));
			}
			else if (ball.hitTestObject(wallBottom))
			{
				ballVelocityY = -Math.abs(ballVelocityY);
				ball.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "bottom"));
			}
		}
		private function movingWallCollision():void
		{
			if (ball.hitTestObject(movingWall))
			{
				var movingWallLeft:Number = movingWall.x;
				var movingWallRight:Number = movingWall.x + movingWall.width;
				var movingWallTop:Number = movingWall.y;
				var movingWallBottom:Number = movingWall.y + movingWall.height;
				if (ball.x >= movingWallLeft)
				{
					ballVelocityX = -Math.abs(ballVelocityX);
					ball.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "center left"));
				}
				else if (ball.x <= movingWallRight)
				{
					ballVelocityX = Math.abs(ballVelocityX);
					ball.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "center right"));
				}
				if (ball.y >= movingWallTop)
				{
					ballVelocityX = -Math.abs(ballVelocityY);
					ball.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "center top"));
				}
				else if (ball.y <= movingWallBottom)
				{
					ballVelocityX = Math.abs(ballVelocityY);
					ball.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "center bottom"));
				}
			}
		}
		private function bounceHandler(event:BounceEvent):void
		{
			trace("Bounce on " + event.side + " side");
			splat.explode(event.target.x, event.target.y);
		}
	}
}

You can download all the files here:

BallBounce.zip





Keeping your code clean

17 11 2008

Quite often we are in a situation where we have to work on a code that was written a few months (or years) back by self or someone else. Sounds a little scary? To ensure that reworking on a code is not as difficult as mining a coal mine I always try and keep my code clean. Now, what is clean? There can be a lot of ways to keep your code clean, but two thumb rules that I follow are:

1. One responsibility per class: For example, I’m working on building a media player in Flash that will run audio and video files. I’ve kept the code for playing the video and audio in separate classes that are sub-classes of one common MediaPlayer class. VideoPlayer class carries the responsibility of playing the video, and AudioPlayer class encapsulates properties and methods for playing audio only. Then, I also have a separate class called VideoUI for laying out the user interface for the video player and a AudioUI class for building the audio player UI.

2. One task per method: In the above example of VideoPlayer class, there’s a separate method for each of the tasks that it needs to perform – playVideo(), pauseVideo(), stopVideo(), and so on. In some cases, it means that you make a separate method for even a one line code. 

Following the above two principles really help in keeping my code clean, readable,  scalable, and reusable.





Reading Flash Vars in AS3.0

13 11 2008

Very often your flash app is required to read variables from the wrapper html page. We define the variables as a name-value pairs string in “FlashVars” param tag. Then, read the variable values in Flash using the LoaderInfo object. See the details below:

The HTML looks like this:

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0" width="550" height="400" title="ReadingFlashVars">
	<param name="movie" value="ReadingFlashVars.swf" />
	<param name="quality" value="high" />
	<param name="FlashVars" value="day=Thursday&month=November&year=2008" />
	<embed src="ReadingFlashVars.swf" width="550" height="400" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" FlashVars="day=Thursday&month=November&year=2008"></embed>
</object>

Notice, the param tag with name as FlashVars. It is passing 3 variables to the SWF file – day, month, and year with values as Thursday, November, and 2008 respectively.

Now, the actionscript part goes something like this – you take the params property of the root loaderInfo object and store it in an object reference. Then, using a for in loop, run through each of the name-value pairs.

var displayData:TextField = new TextField();
displayData.width = 300;
displayData.border = true;
addChild(displayData);
displayData.text = " < Display Flash Vars > ";
var objParam:Object = LoaderInfo(this.root.loaderInfo).parameters;
for (var key:String in objParam)
{
	displayData.appendText("\n " + key + " :: " + objParam[key]);
}

Following result should get displayed when the HTML page is loaded in browser:

Read FlashVars in AS3.0

Read FlashVars in AS3.0





Flex AMF3

30 10 2008

Here’s a very interesting app made by James Ward for comparing the performances of different web technologies for building RIAs – Flex & AMF3, AJAX & XML, AJAX & JSON, and so on. You select a technology pair and click Execute. The command will fetch 5000 rows from a database and show the proformance results in terms of server execution time, transfer time, and so on.

http://www.jamesward.com/wordpress/2007/04/30/ajax-and-flex-data-loading-benchmarks/

Of all the technology pairs listed in this app, I’ve used Flex XML AS, Flex XML E4X, and Flex AMF3. Out of these I’ve found Flex AMF3 very easy to use, fast, and responsive. To get started with this technology I’d recommend chapter 7 of the following book by Friends Of Ed…

http://www.friendsofed.com/book.html?isbn=1430209933