What goes (onKey)Up comes (onKey)Down

Monday, December 14th, 2009

While adding a keyboard event listener to the stage I innocently (or ignorantly) named the event handler onKeyUp… Flash threw a migration issue compiler error saying that’s discontinued since AS3!

It did not mess with the swf running but it’s worthwhile to notice that it’s still like a reserved keyword despite it not being applicable to AS3. I renamed the function nevertheless so that I don’t get the annoying compiler error ;)

Accessing the document class from inside a movie clip

Sunday, May 24th, 2009

If you want to access a function in the document class from the frame of a movie clip, the you do so like this

Lets say there is a document class called Main.as which is associated with your fla and it has a function called foo(). On the timeline of the fla you have a movie clip and you want to call the foo() function from one of the frames in this movie clip then you can write on that frame

Object(this).parent.foo();

Make sure that foo() was a public function :)

AS3 – Singleton (ready to mingleton)

Tuesday, February 3rd, 2009

Creating a Singleton class in AS3 is quite straight forward. You can use a static property coupled with a static method and an enforcer class to do so. Static methods/properties are those which can be accessed even before an instance of the class exists (evaluates at compile time as opposed to run time).  For example the Math class. You do not need to initialize the Math class to get round(), ceil() or a floor() of a floating point number.

The score of a game is a great example for a Singleton class. Create a as file called Score.as and paste the following in it:

package
{
public class Score
{

private static var _instance:Score = null;

public function Score(enf:Enforcer)
{

}

public static function get_instance():Score    //static method-> accessed directly without any instance
{
if(_instance == null)
{
_instance = new Score(new Enforcer);    //new Enforcer makes sense only in this line
}

return _instance;                                        //returns the same Score object no matter what
}

}

}

class Enforcer
{
//empty class -> useable from this file only
}

The Enforcer class is outside the package and hence can be accessed by this .AS file only. Our Score class needs this class as an argument and it cannot create one by

var obj:Score = new Score();                            //no argument – will throw an error

var obj:Score = new Score(new Enforcer());      //doesnt recognize Enforcer out of context

Only the public static method get_instance() returns the single Score class by directly checking the static property _instance.

To make this class a little more useful we ll add a actual score property and getter & setter methods to use the actual score.

Add the colored items to the Score class

package
{
public class Score
{

private static var _instance:Score = null;
private var _the_score:Number = 0;

public function Score(enf:Enforcer)
{

}

public static function get_instance():Score
{
if(_instance == null)
{
_instance = new Score(new Enforcer);
}

return _instance;
}

public function get score()
{
return _the_score;
}

public function set score(num:Number):void
{
_the_score = num;
}

}

}

class Enforcer
{

}

Now create a new Flash file(AS3) and save it in the same place as the Score.as file and paste the following in the first frame

var obj = Score.get_instance();
trace(obj.score);           //returns 0

var obj2 = Score.get_instance();
trace(obj2.score);       //returns 0
obj2.score=20;           //changing the score from the second Score object
trace(obj.score);           //accessing the first obj’s score, returns 20

Overlapping movie clips not allowing mouse events of underlying movieclips

Friday, December 19th, 2008

Like many others I ve been struggling with mouse events of overlapping movie clips crapping all over the mouse events of movie clips under them. So here is the solution finally. For movie clips that may get placed over some movie clips with actions, disable the mouseEnabled and mouseChildren property of the overlapping element like this

overlapping_mc.mouseEnabled = overlapping_mc.mouseChildren = false;

If the overlaying item is a textfield then you will need to set its mouseEnabled to false as well. There is no mouseChildren to a textfield.

Also, if you are confused between ROLL_OVER and MOUSE_OVER not targetting evt.target.parent correctly, then use ROLL_OVER for movie clips that are not made up of more than one object inside. Coz if you use MOUSE_OVER for such a movie clip then any of its inner items are qualified for recieving an event if their mouseEnabled is not disabled. So you can either switch to ROLL_OVER or use

evt.target.parent.parent;      //extra ‘.parent’ added

You can also use

evt.currentTarget;

Selecting library items dynamically in Flash

Friday, November 28th, 2008

If you have a bunch of items in the library with a common prefix and you must choose one dynamically then you can use the getDefinitionByName method to get its name. For example, in the current project I am working on, I have 7 maps out of which one will be used randomly. This will be coupled by a dynamically updated XML file that stores the location and size of each of the rects in the maps. So whenever an id is provided, I must get hold of the right map. If the maps are named map1, map2, map3 etc. and their class names are Map1, Map2, Map3 etc., then I must pull Map2 if the id is 2.

To do this, I must first import the utility that will do this

import flash.utils.getDefinitionByName;

Then I must create a class reference object and assign the randomly generated ‘id’ to it and add it to the stage or whichever container.

var class_ref:Class = getDefinitionByName(“Map” + id) as Class; //dynamically decides th name of the class
var _map = new class_ref();
addChild(_map);

Thats it.

Using SWFObject 2.0

Monday, November 17th, 2008

SWFObject is a minimal & clean way to embed your flash content across any browser. Most flash sites use it and soon Adobe is going to use it as the de-facto standard for embedding flash content!

Download the object from here.

Take the swfobject.js from the downloaded folder and paste it in the folder where you store your index file which will use it along with your swf file. Copy the ‘expressinstall.swf’ file to this location as well.

Create a <div> element in the <body> part of the HTML page and call it ‘my_swf’ or whatever you want. This will hold the swf file. Presently just put in some content in there like what the page is about or a link to downloading Adobe Flash player coz the initial content will be seen only if the user’s computer does not have the Flash player installed. I think you should not only put the link to the player but also some stuff about your site. As it is Google is not going to be able to read what is inside the swf, it can definitely read the contents of this <div>.

Now call the swfobject.js file from the html page that holds your swf in the <head> section:

<script type=”text/javascript” src=”swfobject.js”></script>

The js file can be placed inside a folder called ‘js’ and called as well. So in that case, the src attribute of the <script> would look like this: src=”js/swfobject.js”

Now embed your swf directly like this (still in the <head> section)

<script type=”text/javascript”>

swfobject.embedSWF(“index.swf”, “my_swf”, “800″, “600″, “9.0.0″, “expressInstall.swf”);

</script>

Thats It!

As you can see, it took 6 arguments.

  1. Name of the swf
  2. Id of the <div> element
  3. Width of the swf
  4. Height of the swf
  5. Flash Player version required
  6. Name of the expressinstall file (used for getting the player)

Now if you want to make a 100% flash site that occupies the available space and also loads some FlashVars then add some CSS to the HTML + some parameters to the Javascript

In the <script> tag, where you embedded the swf, create an object for the FlashVars

var flashvars = {};

Now add properties to this using the object.property syntax

flashvars.the_flash_var = “Hello from HTML”;

To add some parameters that you’d generally set from the Settings button in the Flash CS3 IDE, create another object and add properties to it

var params = {};
params.menu = “false”;
params.scale = “noscale”;

Now add these to the embedSWF function of the swfobject

swfobject.embedSWF(“index.swf”, “gmi_swf”, “100%”, “100%”, “9.0.0″, “expressInstall.swf”, flashvars, params);

Thats all!

Inside flash, you can access the value of the_flash_var by typing

root.loaderInfo.parameters.the_flash_var;

Here is the code from the <head> tag all together

<script type=”text/javascript” src=”swfobject.js”></script>
<script type=”text/javascript”>

var flashvars = {};
flashvars.the_flash_var = “Hello from HTML”;

var params = {};
params.menu = “false”;
params.scale = “noscale”;

swfobject.embedSWF(”index.swf”, “gmi_swf”, “100%”, “100%”, “9.0.0?, “expressInstall.swf”, flashvars, params);

</script>

Stretching the background image of a Flash site to 100%

Monday, November 17th, 2008

There are many sites around now (including the new Grandmother site) which have a 100% background image on a site completely in Flash. Here is a small tutorial to do exactly that.

If you are using the SWF Object then you must set the width and height to 100% in the embedSWF() method and add a paramater to allow NOSCALE so that only the background stretches and the rest of the site does not. Here is a tutorial to do this on this site itself.

If you are using the inbuilt mechanism of Flash to publish the site, then you must specify 100% as the dimensions of the swf in the HTML tab of the Settings page and select No Scale in the Scale dropdown and then publish the swf.

The background image should stretch

  1. When the image loads for the first time
  2. Whenever the stage is resized (by clicking the Restore button or manually dragging the corners of the browser window)

So to start with, decide the dimensions of the image you want to use. There is a misconception that the jpeg must be at least the size of the stage, but that is not necessary. It can be smaller as well(maybe 50 to 75% of the stage). You can enable smoothing on it to make sure that it is aliases or pixeleted. Of course you can use the stage size and maybe even bigger if you please to make sure that the clarity is not compromised on smoothing.

Once you have decided the dimensions. bring the image inside(either as a library item inside a movie clip or by using the Loader object). Create 2 functions that will resize the image. One to decide the percentage and one to do the actual resizing. Both these functions can be clubbed together as well.

I am calling the background image movie clip : _bg_image_mc.

var _init_w:Number = 720;      //the width of the image

function resize_image():void
{

var _percent = get_percent_width();
_bg_image_mc.scaleX = _percent;
_bg_image_mc.scaleY = _percent;

}

function get_percent_width():Number
{

var _percent:Number;
if (stage.stageWidth > _init_w) {

//get the percent
_diff = stage.stageWidth – _init_w;
_percent = _diff / _init_w * 100;
_percent /= 100;                     //scale in AS 3 is 0 to 1
_percent += 1;                        //we have to add the percent change to 1

}else {
_percent = 1;
}

return _percent;
}

The second function simply checks the difference between the initial width of the image and the width of the stage and converts into a percent. This percent value is then applied to the scaleX and scaleY value of the bg image mc.

Now apply the function resize_image() once when the image was loaded and then in an event listener on the stage object

stage.addEventListener(Event.RESIZE, on_resize);

If you customize this and use it in a class and are facing issues due to the stage.stageWidth, then please note that you cannot use stage.stageWidth before adding the object to the stage.