This website uses cookies to improve user experience. By using our website you consent to all cookies in accordance with our Cookie Policy. X

Singletons in Flash [basic]

In today's post I will write a little about singletons, which are objects that exist in only one instance - what are they, how to make them in Flash and what are they useful for.
Singleton is a design pattern and like many of those it might appear to overcomplicate things that can be done it much simpler way, however the truth is in return we get much cleaner and more specialized code which is especially useful when working in bigger group or when we often go back to older projects that we have already forgotten, although even smaller, single handily crafted applications will benefit from this solution.
When creating a singleton class we want to have only one object for it in the whole system, in such way that we will always access the same properties independently of the calling location. In most well-known programming languages it can be done by simply writing:
private class Single {
	private static const instance:Single = new Single();
	private function Single():void { }
	public static function getInstance():Single {
		return instance;
	}
}
Unfortunately it won't be the case for Flash, since it doesn't support constructors in private space, which is why we have to work around this problem usually by introducing a parameter that third party won't be able to supply correctly:
public class Singleton {
	private static const instance:Singleton = new Singleton(getInstance);
	public var myVar:Number;
	public function Singleton(f:Function = null) {
		if(f != getInstance) throw new Error("You cannot instance Singleton! Use getInstance() instead.");
		myVar = 5;
	}
	public static function getInstance():Singleton {
		return instance;
	}
}
Well, that is pretty much it, however it is hard to point out any particular advantage for Singletons in this example, that is why we will for something a bit more complex, i.e. application's sound controlling class. Usually in case like this we want to hold all sounds in once place to easily read, play and pause them at the same time, which is a perfect reason to use the singleton pattern like this one (in very simplified form):
public class SoundControl {
	private static var instance:SoundControl;
	private var bIsLoading:Boolean;
	private var aQueue:Array;
	private var aSounds:Array;
	public function SoundControl(f:Function = null) {
	if(f != getInstance) throw new Error("You cannot instance SoundControl! Use getInstance() instead.");
		aSounds = new Array();
		aQueue = new Array();
	}
	public function play(name:String):void {
		if(bIsLoading) {
			aQueue.push(name);
		} else {
			aSounds.push( new Sound(name) );
			/* play sound */
		}
	}
	public function stopAll():void {
		for each(var snd:Sound in aSounds) {
			snd.stop();
		}
		aQueue = new Array();
	}
	private function loadAll():void {
		bIsLoading = true;
		/* load all sounds and call onLoaded when done */
	}
	private function onLoaded():void {
		bIsLoading = false;
		/* play all sounds stored in aQueue */
	}
	public static function getInstance():Singleton {
		if(instance == null) {
			instance = new SoundControl(getInstance);
			instance.loadAll();
		}
		return instance;
	}
}
SoundControl seems to do a lot, but an "outside" person will only see three functions: getInstance(), play() and stopAll(), which is enough to properly control all the sounds in the application, while leaving all the dirty work (volume control, channel assigning, resources managing etc.) to us, the class creators. Additionally we will always be certain that no one will create their own private SoundControl to play sounds that no one else would be able to access because they belong to a different SoundControl object than the one we all agreed to use...

Publishing for Flash Player 11 in Flash Professional CS5.5 [basic]

Recently Adobe released a new version of Flash Player, this time with a number 11 that features 3D acceleration (which I will write something about soon hopefully), support for bigger bitmaps, JSON etc. However those of you who wish to check out those new functions in Flash Professional are up for an unpleasant surprise - Adobe is yet to release an update that actually allows for publishing to the newer format. There is a workaround for this problem, however it is not quite perfect, but on the other hand the only other way is to switch from Flash Professional to a different programming environment (for example: Flashdevelop which is a perfect alternative for people that are seriously thinking about programming in ActionScript).

So anyway, how to add Flash Player 11 support to Flash Professional?

1. Before anything we will need the latest Flash libraries: http://www.adobe.com/support/flashplayer/downloads.html. At the very end of "ADOBE FLASH PLAYER 11" paragraph there is a link leading to a file called: "PlayerGlobal (.swc)" which will be needed in the next step.

2. Now open your Flash Professional installation folder (on XP by default it is: "C:\Program Files\Adobe\Adobe Flash CS5.5"), then move to "Common" -> "Configuration" -> "ActionScript 3.0". In here you already should see directories like "FP9" or "AIR2.5" - we will focus on Flash Player 11 for which we will create "FP11". To this "FP11" folder put previously downloaded "playerglobal11_0.swc" and rename it to: "playerglobal.swc". The final path to the file should look something like this: "C:\Program Files\Adobe\Adobe Flash CS5.5\Common\Configuration\ActionScript 3.0\FP11\playerglobal.swc".

3. Those libraries give us access to the latest functions available in ActionScript but we still need to tell Flash Professional to actually use them. To achieve this head onto the "Players" directory (which is located within "Configuration", just few steps above our previous location) and duplicate a "FlashPlayer" file (in case there are more files like this, duplicate the one with the highest number in the name) renaming it to "FlashPlayer11" in the mean time. Proceed to open it with a text editor of your choice (Notepad will do just fine) and at the very top find lines that look like this:

  <player id="FlashPlayer10" version="10" asversion="3">
   <name>Flash Player 10 & 10.1</name>
Ten replace them with this:
  <player id="FlashPlayer11" version="13" asversion="3">
   <name>Flash Player 11</name>
("version="13"" is not a spelling error)
Further more find a line that starts with: "playerglobal.swc" which we need to modify so it points to our "FP11" directory (created in the previous step).
Or you could just download the whole profile file from here: FlashPlayer11.zip

4. Theoretically that is all you need to export SWF files in their latest version. Unfortunately it is "theoretically", because in reality Flash Professional won't be able to open them, as it is using an older version of the player. Right now I have both good and bad news: that old player can be replaced... but only for the "debugger" (the usual move testing done by CTRL+ENTER won't work). That is why this is not a perfect workaround, but perhaps still better than nothing.
To replace the old Flash Player you will first need to download a latest debug projector: http://www.adobe.com/support/flashplayer/downloads.html ("Flash Player 11.0 Projector content debugger"). Then open the "Players" folder located in the Flash Profesional installation directory (for XP it will be: "C:\Program Files\Adobe\Adobe Flash CS5.5\Players"). There you will find "Debug" and within it "FlashPlayerDebugger.exe" which is a file you will need to replace with that projector gotten off Adobe site (while at the same time renaming it to " FlashPlayerDebugger.exe" most likely).

5. Now it is only a matter of starting Flash Professional and checking whether debugging actually works (CTRL+SHIFT+ENTER by default) while using the example from the documentation: flash.display3D.Context3D - ActionScript 3.0 Reference (at the very bottom; also read the comments under the example).

Putting objects of your own class on the Stage within Flash IDE [basic]

While programming interfaces (or similar stuff) in Flash I started asking myself "wouldn't it be cool if Flash had allowed custom objects of my own class on the Stage"? While the truth is it's entirely possibility even since AS2! But the problem is that you won't hear about it anywhere and Flash doesn't really tell if you the object you have put on the Stage is already that of your own class rather than the standard MovieClip.
To see what this feature is useful for I suggest a following test my Dear reader:

1. Download one of those classes: AS2Test.as (ActionScript2 version) or AS3Test.as (ActionScript3 version).

2. In the new Flash project (AS2 or AS3 depending on the downloaded class) create a MovieClip with at least three different animation frames.

3. If you haven't done so already put the downloaded class into your project's folder and then open the MovieClip's (one created in the previous step) properties.

4. Move to the advanced settings and check the "Export for ActionScript", followed by typing in the downloaded class' name ("AS3Test" for ActionScript3 example in the image below).

(For AS2 "Base Class" won't be available while AS3 will have this field empty).

5. Now simply drag and drop your MovieClip from the Library onto the Stage and then compile the animation (CTRL+Enter by default). If everything went smoothing the MovieClip in the animation should react to the mouses cursor movement and clicks.

This all might seem like a gimmick, but in practice this could save you a lot of time, especially in bigger project where lot of objects are being reused multiple times.

3D engine for beginners I [basic]

If anyone ever wanted to create their own 3D engine in Flash (and not only) not sure of what to expect, surely they met them self with a lot of mathematics and advanced programming routines during the search for information. It might be a little disheartening, but the truth is you don't need all that fancy stuff to create something basic, like for example: an application that displays a 3D cube.
That is why this post will be dedicated to people who are completely new to the topic of creating a 3D engine (which can display that 3D cube).

All of it will fit into one class - for best effect it should be the document's class. In case you are wondering the "Document Class" can be created on properties tab.

(Enter the class name and press the pencil icon).
After creating the new class we should prepare all the variables that we will need in our little engine. Lets start with the camera position:

var cx:Number = 0;
var cy:Number = 0;
var cz:Number = 0;
Nothing fancy here - camera position will determinate what we see on the screen. I think it is best if I take this moment to explain what effects will the movement have (since we don't have to stick to mathematics' rules and switch stuff like up and down around):
cx is the left(-) or the right(+) movement.
cy is the up(-) or down(+) movement.
cz is the backward/"away from the screen"(-) or forward/"to the screen"(+) movement.
OK, now we need a point where the perspective will focus too:
var vx:Number = stage.stageWidth/2;
var vy:Number = stage.stageHeight/2;
The vanishing point is usually in the middle of the screen and the easiest way to get is to divide the screen in half. Of course nothing stops us from defining a different point (but this will required some modifications to the transformation equation I will talk about later). By the way, the 0,0 point is located on the upper left corner of the screen and everything to the right or down from it consists of positive numbers only.
The last set of variables defines the 3D cube:
var bx:Array = [-50, 50, 50, -50, -50, 50, 50, -50];
var by:Array = [-50, -50, 50, 50, -50, -50, 50, 50];
var bz:Array = [200, 200, 200, 200, 300, 300, 300, 300];
Those three arrays hold points that describe our three-dimensional box. For example if we take bx[0],by[0],by[0] we get the upper left corner of the front facing wall.
Now that we have all the needed parameters we can proceed to create our 3D rendering function. To achieve the smoothest animation it's best to connect it with the ENTER_FRAME event - that is why we will write the following line within the constructor:
addEventListener(Event.ENTER_FRAME,render);
Don't forget to import flash.events.Event! As you can see I named my function "render" and for now it looks like this:
private function render(e:Event):void {
 graphics.clear();
}
Just a standard function definition. We will need the graphics.clear(); line because the process of rendering always looks the same - when entering a new animation frame we remove the old graphics and insert new ones (inserting will be explain in a moment). Anyway, it is time to move on onto the most important part of the application, which is the transformation from 3D into the 2D (because currently no monitor screen can handle anything else than 2D image):
var bx2:Array = new Array(bx.length);
var by2:Array = new Array(by.length);
var i:Number = 0;
while (i<bx.length) {
	bx2[i] = vx+(((cx-bx[i])/(cz-bz[i]))*vx);
	by2[i] = vy+(((cy-by[i])/(cz-bz[i]))*vy);
	++i;
}
So first things first:
var bx2:Array = new Array(bx.length);
var by2:Array = new Array(by.length);
Those arrays will hold all 2D points after the transformation.
Then, in the loop, we have:
bx2[i] = vx+(((cx-bx[i])/(cz-bz[i]))*vx);
by2[i] = vy+(((cy-by[i])/(cz-bz[i]))*vy);
Which is the code responsible for that transformation. Quite frankly you don't need to understand it to use it efficiently, so feel free to skip the following explanation and perhaps return to it later:
cx-bx[i] - we are subtracting a point's coordinate from the camera's position to retrieve the translation vector. It's a standard method when dealing with transformations, because we don't care where the point is, but rather how far it is from the camera - relative information like that is easier to carry between spaces.
cz-bz[i] - here we calculate the distance from the camera. We need this value to create the illusion of perspective.
(cx-bx[i])/(cz-bz[i]) - and here we create that illusion of perspective, so objects will seem to be getting smaller when moving further away.
*vx - after we are done with the perspective it is time to include the viewing angle. Only not in the scope we would expect it to be as bigger number stretch the image (make the angle smaller). Clearly it has nothing to do with the vanishing point's vx that we defined but it just so happens that the best value here is also the half of the screen.
vx+ - and finally our vanishing point.

Now that we have all our points in 2D, it is time to display them:

//drawing:
graphics.lineStyle(1, 0xffffff, 100);
//front face:
graphics.moveTo(bx2[0], by2[0]);
graphics.lineTo(bx2[1], by2[1]);
graphics.lineTo(bx2[2], by2[2]);
graphics.lineTo(bx2[3], by2[3]);
graphics.lineTo(bx2[0], by2[0]);
//back face:
graphics.moveTo(bx2[4], by2[4]);
graphics.lineTo(bx2[5], by2[5]);
graphics.lineTo(bx2[6], by2[6]);
graphics.lineTo(bx2[7], by2[7]);
graphics.lineTo(bx2[4], by2[4]);
//connecting lines:
graphics.moveTo(bx2[0], by2[0]);
graphics.lineTo(bx2[4], by2[4]);
graphics.moveTo(bx2[1], by2[1]);
graphics.lineTo(bx2[5], by2[5]);
graphics.moveTo(bx2[2], by2[2]);
graphics.lineTo(bx2[6], by2[6]);
graphics.moveTo(bx2[3], by2[3]);
graphics.lineTo(bx2[7], by2[7]);
The graphics.lineStyle(1, 0xffffff, 100); part describes the style of the drawing line. First value is the width (in pixels), second is the color, and the last one is transparency.
Next we have the drawing itself, starting from the front face:

Then we add the back face:

And connect them at the end:

(Of course in the application this will be done instantly).
If everything went smoothing an image of 3D cube should be visible on the screen (just like in the last picture).
In the next step we should implement some kind of camera movement but this will be explained later posts.

Whole source code is available here: box3d.zip

From AS2 to AS3: _global equivalent in AS3 [basic]

I once was asked is there a way to access variables that were set on _root or _global. The problem comes from how strict the ActionScript3 is - in AS2 you would just write _global.myVar = 5 and then access it from anywhere, but AS3 just doesn't tolerate dynamic variables (and also there is no _global keyword).
There are two ways to work around it:

1. Use syntax meant for dynamic variables.

root["myVar"] = 5;
It is almost the same thing as in AS2, but since you are using dynamic variables you might find yourself with an extremely slow application (when used excessively). If that is the case you should consider the second option.

2. Use static keyword.
This is probably the most proper way to do it, but requires some additional work. Before you do anything create a "Document Class", which you will find in the properties tab.

Type in any name you want for you class (e.g. "MyClass"), confirm it with enter key (at this point a warning should pop-up saying the class doesn't exist - ignore it) and then click the pencil icon on the side.
If done correctly, new class file should be created in a separate window looking something like this:

package  {
	import flash.display.MovieClip;
	
	public class MyClass extends MovieClip {
		
		public function MyClass() {
			// constructor code
		}
	}
	
}
Now just before the public function MyClass() line, type in:
public static var myVar:Number = 5;
That is pretty much it. From anywhere in your project you can now access this variable through class identifier, for example:
import MyClass;
trace(MyClass.myVar);
Also, since you document class is used as "root" object, you can now access it through root field of each MovieClip. It needs to be casted to your class beforehand though:
import MyClass;
trace((root as MyClass).myVar);


<<<Newer posts