Inspired by senocular’s impressive “ActionScript 3 Tip of the Day” thread over at the Kirupa forums, I thought I would start something similar here at Ultrashock.
I will try to add an ActionScript tip, code snippet, example, etc, at least once a day to this thread and a few classes might also make an appearance. The ActionScript will range from AS2 to AS3 and may even include some prototype related snippets (even though I’m not keen on them).
I would like to try and keep this thread as tidy as possible (unlike the Full Screen Flash thread
), so please post any comments or questions in the ActionScript Tips Discussion thread.
![]()
Update
Our very own Codemonkey is now joining in with the fun, so expect this thread to expand quite rapidly.
Go monkey go monkey go!
If you ever need to remove all of the movie clips on a timeline you could use the following function. Keep in mind that this will only remove movie clips that have been added using attachMovie, createEmptyMovieClip, or duplicateMovieClip.
[as]function removeChildren(parent:MovieClip):Void {
var i:String;
for (i in parent) {
if (parent.removeMovieClip) {
parent.removeMovieClip();
}
}
}
// Delete all of the movie clips in myMovieClip.
removeChildren(myMovieClip);[/as]
Instead of using typeof to check if the object is a movie clip I am simply checking if the removeMovieClip method is available in the object. This should be quicker than using typeof.
- 04 November 2006 06:50 PM
-
The following function will allow you to align movie clips horizontally or vertically. You can also set the amount of spacing between each movie clip.
[as]function alignClips(clips:Array, alignment:String, spacing:Number):Void {
if (spacing == null) {
spacing = 0;
}
var hori:Boolean = alignment == “horizontal”;
var propA:String = hori ? “_x” : “_y”;
var propB:String = hori ? “_y” : “_x”;
var length:String = hori ? “_width” : “_height”;
var value:Number = clips[0][propA];
var i:Number = 0;
var n:Number = clips.length;
while (i < n) {
clips[propA] = value;
if (i) {
clips[propB] = clips[i-1][propB];
}
value += clips[i++][length] + spacing;
}
}
// Create an array and populate it with the movie clips
// that we want to align.
var myClips:Array = [mc1, mc2, mc3, mc4];
// Align the movie clips horizontally with 10px spacing.
alignClips(myClips, “horizontal”, 10);
// or.. Align the movie clips vertically with 2px spacing.
// alignClips(myClips, “vertical”, 5);[/as]
- 04 November 2006 07:14 PM
-
Normally you would link a class to a library symbol if you wanted to add a class to a MovieClip. You can however take advantage of __proto__ if you want to add a class to a movie clip at runtime.
[as]myMovieClip.__proto__ = new MyClass();[/as]
MyClass should extend MovieClip in the usual way.
The only downside to this is that physical changes to the movie clip don’t seem possible from the class constructor. For example, this._x = 0 in the following class has no effect on the movie clip.
[as]class MyClass extends MovieClip {
public function MyClass() {
this.onRollOver = rollOverHandler;
this.onRollOut = rollOutHandler;
this._x = 0;
}
private function rollOverHandler():Void {
this._xscale *= 2;
this._yscale *= 2;
}
private function rollOutHandler():Void {
this._xscale /= 2;
this._yscale /= 2;
}
}[/as]
- 04 November 2006 08:13 PM
-
If you send variables to your Flash movie using flashVars the following function could be used to gather all of the variables up into an object. Number values are converted to true numbers, and you can also name your flashVars so they are recreated as arrays.
Here’s the function:
[as]function getFlashVars():Object {
var o:Object = {};
var n:String;
var i:Number;
var s:String;
for (s in _level0) {
if (s.substr(0,3) == “fv_”) {
n = s.substr(3);
if (n.indexOf(“_”) > -1) {
i = Number(n.split(“_”)[1]);
n = n.split(“_”)[0];
if (o[n] == null) {
o[n] = [];
}
if (isNaN(_level0[s])) {
o[n] = unescape(_level0[s]);
}
else {
o[n] = Number(_level0[s]);
}
}
else {
if (isNaN(_level0[s])) {
o[n] = unescape(_level0[s]);
}
else {
o[n] = Number(_level0[s]);
}
}
}
}
return o;
}[/as]
Here are a few examples of use. Note that each flashVar name is prefixed with fv_
01 - Basic example
HTML
<param name="flashVars" value="fv_foo=hello&fv_bob=123" />
AS
[as]var info:Object = getFlashVars();
trace( info.foo ); // output: hello
trace( info.bob ); // output: 123
trace( typeof info.bob ); // output: number[/as]
02 - Sending Arrays
To send an array to Flash you simply add _0 _1 _2 etc to the end of your variable name.
HTML
<param name="flashVars" value="fv_items_0=apple&fv_items_1=banana" />
AS
[as]var info:Object = getFlashVars();
trace( info.items[0] ); // output: apple
trace( info.items[1] ); // output: banana[/as]
- 04 November 2006 11:06 PM
-
If you want to be able to quickly and easily assign multiple functions to a movie clip’s onEnterFrame event then the following code should give you something to play with.
[as]var frameListeners:Array = [];
function addFrameListener(func:Function):Void {
removeFrameListener(func);
frameListeners.push(func);
if (!this.onEnterFrame) {
this.onEnterFrame = fireFrameListeners;
}
}
function removeFrameListener(func:Function):Void {
var i:Number = frameListeners.length;
while (i—) {
if (frameListeners == func) {
delete frameListeners.splice(i, 1);
break;
}
}
if (!frameListeners.length) {
this.onEnterFrame = null;
}
}
function fireFrameListeners():Void {
var i:Number = 0;
var n:Number = frameListeners.length;
while (i < n) {
frameListeners[i++]();
}
}[/as]
With those functions placed on the movie clip’s timeline you can now add (and remove) your functions. All of the assigned functions will be called on each frame in the order you add them.
[as]addFrameListener(functionOne);
addFrameListener(functionTwo);
//
function functionOne():Void {
trace(“function one”);
}
function functionTwo():Void {
trace(“function two”);
}[/as]
That would result in the following trace on each frame:
—function one
—function two
Removing functions is done in the same way.
[as]removeFrameListener(functionTwo);[/as]
Keep in mind that these functions will use the movie clip’s onEnterFrame event handler so if you manually assign a function to it then things will go pear shaped. For example, you shouldn’t do something like this:
[as]addFrameListener(someFunction);
this.onEnterFrame = function():Void {
//
}[/as]
- 05 November 2006 09:53 AM
-
Prototype functions can be used if you want to add functions to Flash’s core classes such as String, Array, Number, and so on. When you create a prototype function, all instances of the prototyped class will be able to access the new function.
For example, let’s say that you want to be able to reverse any of your strings at any time in your movie. To do that you would add a prototype function to the String class like this:
[as]String.prototype.reverse = function() {
var a = this.split(”“);
a.reverse();
return a.join(”“);
};[/as]
Now that the new function has been added you will be able to reverse any of your strings:
[as]var myText = “Hello Ultrashock”;
trace(myText); // output: Hello Ultrashock
myText = myText.reverse();
trace(myText);// output: kcohsartlU olleH[/as]
Maybe you would like to be able to shuffle any of your arrays? Easy enough, you add your function to the Array prototype object like this:
[as]Array.prototype.shuffle = function() {
var a = [].concat(this);
var i = a.length;
var n;
while (i—) {
n = Math.floor(Math.random() * a.length);
this = a.splice(n, 1);
}
}[/as]
Now you can shuffle any array in your movie:
[as]var myItems = [“apple”, “banana”, “cherry”, “doughnut”];
trace( myItems ); // output: apple,banana,cherry,doughnut
myItems.shuffle();
trace( myItems ); // output: doughnut,banana,apple,cherry[/as]
You can add prototype functions to virtually any core class in Flash although it is better to create/use classes if you are able to.
- 05 November 2006 11:16 AM
-
A lot of the time while debugging/profiling, you’ll be interested in how many FPS your movie is actually pulling to see if there’s something slowing it down.
Here’s a class that let’s you specify the update interval and invokes a method each time. You can drop this class in a util folder and use it in any of your projects:
[as]
import mx.utils.Delegate;
class util.FPS {
private static var instance:FPS;
private var time:Number;
private var counter:Number;
private var interval:Number;
private var dummy:MovieClip;
public var onUpdate:Function;
public function FPS(interval:Number) {
var d:Number = _root.getNextHighestDepth();
this.dummy = _root.createEmptyMovieClip(“fpsmc” + d, d);
this.interval = interval;
this.start();
}
// reset and start measuring
public function start() {
counter = 0;
time = getTimer();
dummy.onEnterFrame = Delegate.create(this, measure);
}
public function stop() {
dummy.onEnterFrame = null;
delete dummy.onEnterFrame;
}
// checks whether it should perform a measurement
private function measure() {
var now:Number = getTimer();
var lapsed:Number = now - time;
if (lapsed >= interval) {
onUpdate(counter * (1000 / lapsed));
time = now;
counter = 0;
}
counter++;
}
}
[/as]
To use it:
[as]
import util.FPS;
// create FPS meter and update every 500ms
var fps:FPS = new FPS(500);
fps.onUpdate = function(fps:Number) {
trace(fps);
}
[/as]
Don’t set the interval too low though (min. 250ms) or the measurements become unreliable.
- 05 November 2006 12:00 PM
-
To quickly convert a coordination in one movieclip to another movieclip, you can use the following function:
[as]
import flash.geom.Point;
function transCoord(coord:Point, from:MovieClip, to:MovieClip):Void {
from.localToGlobal(coord);
to.globalToLocal(coord);
}
[/as]
This can come in handy for example when you need to move a movieclip to another movieclip that is not in the same container mc.
- 05 November 2006 12:08 PM
-
If you have an indexed array (array with 1, 2, 3, 4, ... indexes) and you want to know the index of a certain object, you can use the following function:
[as]
// returns index of an item in array, -1 if it isn’t in the array
function inArray(array:Array, item:Object):Number {
for (var i in array) {
if (array == item) {
return Number(i);
}
}
return -1;
}
[/as]
If you want to remove a certain object from an array and want to know whether the object was found (and so removed) you can use the following method in conjunction with the previous one:
[as]
// tries to remove an item from array and returns whether it worked
function arrayRemove(array:Array, item:Object):Boolean {
var index:Number = inArray(array, item);
if (index != -1) {
array.splice(index, 1);
}
return index != -1;
}
[/as]
Usage:
[as]
var names:Array = new Array(“Bob”, “Shirley”, “Pete”);
trace(arrayRemove(array, “Bob”)); // traces “true”
trace(arrayRemove(array, “Bill”)); // traces “false”
[/as]
—-
You could also add these function to the Array class with prototyping as Nutrox explained in Tip 006. Or, you can add these methods to a global util class as explained in Tip 010
- 05 November 2006 12:19 PM
-
If you have some functions you might use anywhere and possibly in different projects, you might want to create util classes from them. A util class is a class available from a global path with static methods only. Flash’ Math class is a good example of this.
To create a util class start with an empty class like this:
[as]
class MyUtil {
}
[/as]
Then add your functions with the keywords public and static. Public so everyone can see them, static so everyone can access them through the classname without having to create an object first.
[as]
class MyUtil {
public static function MyUtilFunction(params_here):Number {
// do stuff with params and return result
}
}
[/as]
One benefit of having static methods only is that you acknowledge the functions do not depend on a state, which is the case a lot of the times with class instances (objects). This basically means you will only create one-shot functions that do a specific operation/calculation.
If you want to prohibit people from instantiating a utility class - which would also mean such a people didn’t ‘get’ your utility class - you can add a private constructor:
[as]
class MyUtil {
private function MyUtil() {}
}
[/as]
Here’s an example of a complete util class:
[as]
class ArrayUtils {
private function ArrayUtils() {}
// returns index of an item in array, -1 if it isn’t in the array
public static function inArray(array:Array, item:Object):Number {
[..]
}
// tries to remove an item from array and returns whether it worked
public static function arrayRemove(array:Array, item:Object):Boolean {
[..]
}
}
[/as]
Usage:
[as]
var names:Array = new Array(“Bob”, “Shirley”, “Pete”);
trace(ArrayUtils.arrayRemove(array, “Bob”)); // traces “true”
trace(ArrayUtils.arrayRemove(array, “Bill”)); // traces “false”
[/as]
- 05 November 2006 12:31 PM
-
To actually make your util class visible across your projects, you need to add it to your flash’ IDE. To do this, go to:
Edit->Preferences->ActionScript->ActionScript Settings button.
In there, click the button “Browse to Path” to select the folder your util class is in. For example, my global path is “D:\MyStuff\Flash\local”.
To use the global util class in your project, you can now just use a simple import statement without having to worry about whether it finds it:
[as]
// in this example ArrayUtils is in the directory/package “utils”
import utils.ArrayUtils;
[/as]
- 05 November 2006 12:44 PM
-
If you quickly need a random number in a certain range, then you can use this simple (util) function:
[as]
function randomNum(min, max):Number {
return min + Math.round(Math.random() * (max - min));
}
[/as]
- 05 November 2006 12:55 PM
-
If you want to make sure a number is within a certain range or clip it otherwise, here’s a simple way to do this:
[as]
function clip(value:Number, min:Number, max:Number):Number {
return Math.min(Math.max(value, min), max);
}
[/as]
- 05 November 2006 12:58 PM
-
The following code is an example of how you could calculate the value for “bytes per second” and “remaining time” when loading external movies or images etc.
I will wrap this up in a class soon.
[as]var loadTarget:MovieClip;
var loadTimer:Number;
var loadTotal:Number;
function loadClip(target:MovieClip, url:String):Void {
loadTarget = target;
loadTimer = getTimer();
loadTotal = 0;
target.loadMovie(url);
this.onEnterFrame = updateLoadProgress;
}
function updateLoadProgress():Void {
var bLoaded:Number = loadTarget.getBytesLoaded();
var bTotal:Number = loadTarget.getBytesTotal();
if (bLoaded && bTotal) {
if (bLoaded == bTotal) {
this.onEnterFrame = null;
onLoadComplete();
}
else if (getTimer() - loadTimer >= 250) {
var bSec:Number = Math.round(bLoaded / (loadTotal / 1000));
var tRemaining:Number = Math.round((bTotal - bLoaded) / bSec);
onLoadProgress(bLoaded, bTotal, bSec, loadTotal, tRemaining);
loadTimer = getTimer();
loadTotal += 250;
}
}
}
function onLoadProgress(bLoaded:Number, bTotal:Number, bSec:Number,
tTotal:Number, tRemaining:Number):Void {
trace(“loaded progress: ” + bLoaded + “/” + bTotal);
trace(“bytes per second (approx): ” + bSec);
trace(“total time (approx): ” + tTotal + ” seconds”);
trace(“remaining time (approx): ” + tRemaining + ” seconds”);
trace(”“);
}
function onLoadComplete():Void {
trace(“loaded!”);
}
//
var container:MovieClip = this.createEmptyMovieClip(“container”, 0);
var url:String = “external.swf”;
loadClip(container, url);[/as]
- 05 November 2006 01:10 PM
-
If you are working with Forms (mx.screens.Form), you can use this enhanced version to make your screens smoothly fade in/out when showing/hiding your form:
[as]
import mx.transitions.*;
import mx.transitions.easing.*;
// use this class on your forms instead
class codemonkey.util.BasicForm extends mx.screens.Form {
private var __visible:Boolean = false;
public function BasicForm() {
this.addEventListener(“allTransitionsInDone”, this);
this.addEventListener(“allTransitionsOutDone”, this);
this.createEmptyMovieClip(“bg”, this.getNextHighestDepth());
}
// display form (show/hide)
public function show(flag:Boolean) {
if (flag != this.__visible) {
this.__visible = flag;
this.visible = (__visible) ? true : this.visible;
var fadetype:Number = (flag) ? Transition.IN : Transition.OUT;
TransitionManager.start(
this, {type:Fade, direction:fadetype, duration:1, easing:None.easeNone}
);
}
}
// called by Flash’ transition manager
private function allTransitionsInDone(eventObj:Object) {
this.visible = this.__visible;
}
private function allTransitionsOutDone(eventObj:Object) {
this.visible = this.__visible;
}
}
[/as]
To use this class, do as you normally would, but extend from the BasicForm class instead:
[as]
class LoadingScreen extends BasicForm {}
[/as]
screenshot of applying your form in Flash
- 05 November 2006 01:33 PM
-
- Comments are closed.
- Log in or join for free to make a comment.


