Ultrashock Forums > Flash > ActionScript
ActionScript Tips Thread

You are currently viewing our website as a guest which gives you limited access to forums, files and other resources.

Click here to join now for free, and start interacting with our members, download files and much more!

Click here if you are looking for our Flash files and other professional assets.
 
Closed thread | View first unread | Rate Thread Search this Thread | Thread Tools | Display Modes
1|2|> Page 1 of 2

#1
Bookmark and Share!
ActionScript Tips Thread
Old 2006-11-04 Last edited by Nutrox : 2006-11-05 at 08:04.

 
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!
postbit arrow 45 comments | 11009 views postbit arrow Reply:   
Coffee Monster
Nutrox is offline Super Moderator
seperator
Posts: 12,086
2004-04-25
Age: 32
Nutrox lives in United Kingdom
17
Nutrox's Avatar
seperator

Ultrashock Member Comments:
Nutrox's Avatar Nutrox Nutrox is offline Super Moderator Nutrox lives in United Kingdom 17 Creative Assets 2006-11-04 #2 Old  
001 - Delete all Movie Clips on a Timeline
 
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.

ActionScript Code:
  1. function removeChildren(parent:MovieClip):Void {
  2.     var i:String;
  3.     for (i in parent) {
  4.         if (parent[i].removeMovieClip) {
  5.             parent[i].removeMovieClip();
  6.         }
  7.     }
  8. }
  9.  
  10. // Delete all of the movie clips in myMovieClip.
  11. removeChildren(myMovieClip);
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.
 
Nutrox's Avatar Nutrox Nutrox is offline Super Moderator Nutrox lives in United Kingdom 17 Creative Assets 2006-11-04 #3 Old  
002 - Aligning Movie Clips
 
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.

ActionScript Code:
  1. function alignClips(clips:Array, alignment:String, spacing:Number):Void {
  2.     if (spacing == null) {
  3.         spacing = 0;
  4.     }
  5.     var hori:Boolean  = alignment == "horizontal";
  6.     var propA:String  = hori ? "_x" : "_y";
  7.     var propB:String  = hori ? "_y" : "_x";
  8.     var length:String = hori ? "_width" : "_height";
  9.     var value:Number  = clips[0][propA];
  10.     var i:Number      = 0;
  11.     var n:Number      = clips.length;
  12.    
  13.     while (i < n) {
  14.         clips[i][propA] = value;
  15.         if (i) {
  16.             clips[i][propB] = clips[i-1][propB];
  17.         }
  18.         value += clips[i++][length] + spacing;
  19.     }
  20. }
  21.  
  22. // Create an array and populate it with the movie clips
  23. // that we want to align.
  24. var myClips:Array = [mc1, mc2, mc3, mc4];
  25.  
  26. // Align the movie clips horizontally with 10px spacing.
  27. alignClips(myClips, "horizontal", 10);
  28.  
  29. // or.. Align the movie clips vertically with 2px spacing.
  30. // alignClips(myClips, "vertical", 5);
  31.  
 
Nutrox's Avatar Nutrox Nutrox is offline Super Moderator Nutrox lives in United Kingdom 17 Creative Assets 2006-11-04 #4 Old  
003 - Add Classes to MovieClips at Runtime
&nbsp;
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&nbsp;runtime.

ActionScript Code:
  1. myMovieClip.__proto__ = new MyClass();
MyClass should extend MovieClip in the usual&nbsp;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&nbsp;clip.

ActionScript Code:
  1. class MyClass extends MovieClip {
  2.  
  3.     public function MyClass() {
  4.         this.onRollOver = rollOverHandler;
  5.         this.onRollOut  = rollOutHandler;
  6.  
  7.         this._x = 0;
  8.     }
  9.  
  10.     private function rollOverHandler():Void {
  11.         this._xscale *= 2;
  12.         this._yscale *= 2;
  13.     }
  14.  
  15.     private function rollOutHandler():Void {
  16.         this._xscale /= 2;
  17.         this._yscale /= 2;
  18.     }
  19.  
  20. }
 
Nutrox's Avatar Nutrox Nutrox is offline Super Moderator Nutrox lives in United Kingdom 17 Creative Assets 2006-11-04 #5 Old  
004 - Gathering FlashVars
&nbsp;
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&nbsp;arrays.

Here's the function:

ActionScript Code:
  1. function getFlashVars():Object {
  2.     var o:Object = {};
  3.     var n:String;
  4.     var i:Number;
  5.     var s:String;
  6.     for (s in _level0) {
  7.         if (s.substr(0,3) == "fv_") {
  8.             n = s.substr(3);
  9.             if (n.indexOf("_") > -1) {
  10.                 i = Number(n.split("_")[1]);
  11.                 n = n.split("_")[0];
  12.                 if (o[n] == null) {
  13.                     o[n] = [];
  14.                 }
  15.                 if (isNaN(_level0[s])) {
  16.                     o[n][i] = unescape(_level0[s]);
  17.                 }
  18.                 else {
  19.                     o[n][i] = Number(_level0[s]);
  20.                 }
  21.             }
  22.             else {
  23.                 if (isNaN(_level0[s])) {
  24.                     o[n] = unescape(_level0[s]);
  25.                 }
  26.                 else {
  27.                     o[n] = Number(_level0[s]);
  28.                 }
  29.             }
  30.         }
  31.     }
  32.     return o;
  33. }
Here are a few examples of use. Note that each flashVar name is prefixed with&nbsp;fv_

01 - Basic example

HTML
Code:
<param name="flashVars" value="fv_foo=hello&fv_bob=123" />
AS
ActionScript Code:
  1. var info:Object = getFlashVars();
  2.  
  3. trace( info.foo ); // output: hello
  4. trace( info.bob ); // output: 123
  5. trace( typeof info.bob ); // output: number
  6.  

02 - Sending Arrays

To send an array to Flash you simply add _0 _1 _2 etc to the end of your variable&nbsp;name.

HTML
Code:
<param name="flashVars" value="fv_items_0=apple&fv_items_1=banana" />
AS
ActionScript Code:
  1. var info:Object = getFlashVars();
  2.  
  3. trace( info.items[0] ); // output: apple
  4. trace( info.items[1] ); // output: banana
  5.  
 
Nutrox's Avatar Nutrox Nutrox is offline Super Moderator Nutrox lives in United Kingdom 17 Creative Assets 2006-11-05 #6 Old  
005 - Multiple onEnterFrame Functions
&nbsp;
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&nbsp;with.

ActionScript Code:
  1. var frameListeners:Array = [];
  2.  
  3. function addFrameListener(func:Function):Void {
  4.     removeFrameListener(func);
  5.     frameListeners.push(func);
  6.     if (!this.onEnterFrame) {
  7.         this.onEnterFrame = fireFrameListeners;
  8.     }
  9. }
  10.  
  11. function removeFrameListener(func:Function):Void {
  12.     var i:Number = frameListeners.length;
  13.     while (i--) {
  14.         if (frameListeners[i] == func) {
  15.             delete frameListeners.splice(i, 1);
  16.             break;
  17.         }
  18.     }
  19.     if (!frameListeners.length) {
  20.         this.onEnterFrame = null;
  21.     }
  22. }
  23.  
  24. function fireFrameListeners():Void {
  25.     var i:Number = 0;
  26.     var n:Number = frameListeners.length;
  27.     while (i < n) {
  28.         frameListeners[i++]();
  29.     }
  30. }
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&nbsp;them.

ActionScript Code:
  1. addFrameListener(functionOne);
  2. addFrameListener(functionTwo);
  3.  
  4. //
  5.  
  6. function functionOne():Void {
  7.    trace("function one");
  8. }
  9.  
  10. function functionTwo():Void {
  11.    trace("function two");
  12. }
That would result in the following trace on each frame:

-- function one
-- function two

Removing functions is done in the same way.

ActionScript Code:
  1. removeFrameListener(functionTwo);
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&nbsp;this:

ActionScript Code:
  1. addFrameListener(someFunction);
  2.  
  3. this.onEnterFrame = function():Void {
  4.    //
  5. }
 
Nutrox's Avatar Nutrox Nutrox is offline Super Moderator Nutrox lives in United Kingdom 17 Creative Assets 2006-11-05 #7 Old  
006 - Prototype Functions
Last edited by Codemonkey : 2006-11-11 at 03:00.
&nbsp;
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&nbsp;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&nbsp;this:

ActionScript Code:
  1. String.prototype.reverse = function() {
  2.         var a = this.split("");
  3.         a.reverse();
  4.         return a.join("");
  5. };
Now that the new function has been added you will be able to reverse any of your&nbsp;strings:

ActionScript Code:
  1. var myText = "Hello Ultrashock";
  2. trace(myText); // output: Hello Ultrashock
  3.  
  4. myText = myText.reverse();
  5. trace(myText);// output: kcohsartlU olleH
  6.  
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&nbsp;this:

ActionScript Code:
  1. Array.prototype.shuffle = function() {
  2.     var a = [].concat(this);
  3.     var i = a.length;
  4.     var n;
  5.     while (i--) {
  6.         n = Math.floor(Math.random() * a.length);
  7.         this[i] = a.splice(n, 1);
  8.     }      
  9. }
Now you can shuffle any array in your movie:

ActionScript Code:
  1. var myItems = ["apple", "banana", "cherry", "doughnut"];
  2. trace( myItems ); // output: apple,banana,cherry,doughnut
  3.  
  4. myItems.shuffle();
  5. trace( myItems ); // output: doughnut,banana,apple,cherry
  6.  
You can add prototype functions to virtually any core class in Flash although it is better to create/use classes if you are able&nbsp;to.
 
Codemonkey's Avatar Codemonkey Codemonkey is offline Super Moderator Codemonkey lives in Netherlands 2006-11-05 #8 Old  
007 - Measuring frames per second
Last edited by Codemonkey : 2006-11-07 at 13:11.
&nbsp;
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:

ActionScript Code:
  1. import mx.utils.Delegate;
  2.  
  3. class util.FPS {
  4.     private static var instance:FPS;
  5.     private var time:Number;
  6.     private var counter:Number;
  7.     private var interval:Number;
  8.     private var dummy:MovieClip;
  9.    
  10.     public var onUpdate:Function;
  11.    
  12.     public function FPS(interval:Number) {
  13.         var d:Number = _root.getNextHighestDepth();
  14.         this.dummy = _root.createEmptyMovieClip("fpsmc" + d, d);
  15.         this.interval = interval;
  16.         this.start();
  17.     }
  18.  
  19.     // reset and start measuring
  20.     public function start() {
  21.         counter = 0;
  22.         time = getTimer();
  23.         dummy.onEnterFrame = Delegate.create(this, measure);
  24.     }
  25.  
  26.     public function stop() {
  27.         dummy.onEnterFrame = null;
  28.         delete dummy.onEnterFrame;
  29.     }
  30.  
  31.     // checks whether it should perform a measurement
  32.     private function measure() {
  33.         var now:Number = getTimer();
  34.         var lapsed:Number = now - time;
  35.         if (lapsed >= interval) {
  36.             onUpdate(counter * (1000 / lapsed));
  37.             time = now;
  38.             counter = 0;
  39.         } 
  40.         counter++;
  41.     }
  42. }

To use it:

ActionScript Code:
  1. import util.FPS;
  2.  
  3. // create FPS meter and update every 500ms
  4. var fps:FPS = new FPS(500);
  5. fps.onUpdate = function(fps:Number) {
  6.     trace(fps);
  7. }
Don't set the interval too low though (min. 250ms) or the measurements become unreliable.
 
Codemonkey's Avatar Codemonkey Codemonkey is offline Super Moderator Codemonkey lives in Netherlands 2006-11-05 #9 Old  
008 - Converting coordinates
&nbsp;
To quickly convert a coordination in one movieclip to another movieclip, you can use the following function:

ActionScript Code:
  1. import flash.geom.Point;
  2.  
  3. function transCoord(coord:Point, from:MovieClip, to:MovieClip):Void {
  4.         from.localToGlobal(coord);
  5.         to.globalToLocal(coord);
  6.     }
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.
 
Codemonkey's Avatar Codemonkey Codemonkey is offline Super Moderator Codemonkey lives in Netherlands 2006-11-05 #10 Old  
009 - Array item lookup/removal
&nbsp;
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:

ActionScript Code:
  1. // returns index of an item in array, -1 if it isn't in the array
  2.     function inArray(array:Array, item:Object):Number {
  3.         for (var i in array) {
  4.             if (array[i] == item) {
  5.                 return Number(i);
  6.             }
  7.         }
  8.         return -1;
  9.     }
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:

ActionScript Code:
  1. // tries to remove an item from array and returns whether it worked
  2.     function arrayRemove(array:Array, item:Object):Boolean {
  3.         var index:Number = inArray(array, item);
  4.         if (index != -1) {
  5.             array.splice(index, 1);
  6.         }
  7.         return index != -1;
  8.     }
Usage:

ActionScript Code:
  1. var names:Array = new Array("Bob", "Shirley", "Pete");
  2. trace(arrayRemove(array, "Bob")); // traces "true"
  3. trace(arrayRemove(array, "Bill")); // traces "false"
  4.  
---
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
 
Codemonkey's Avatar Codemonkey Codemonkey is offline Super Moderator Codemonkey lives in Netherlands 2006-11-05 #11 Old  
010a - Creating a utility class
Last edited by Codemonkey : 2006-11-06 at 11:56.
&nbsp;
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:

ActionScript Code:
  1. class MyUtil {
  2. }
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.

ActionScript Code:
  1. class MyUtil {
  2. public static function MyUtilFunction(params_here):Number {
  3. // do stuff with params and return result
  4. }
  5. }
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:

ActionScript Code:
  1. class MyUtil {
  2. private function MyUtil() {}
  3. }
Here's an example of a complete util class:

ActionScript Code:
  1. class ArrayUtils {
  2. private function ArrayUtils() {}
  3.  
  4. // returns index of an item in array, -1 if it isn't in the array
  5. public static function inArray(array:Array, item:Object):Number {
  6.         [..]
  7. }
  8.  
  9. // tries to remove an item from array and returns whether it worked
  10. public static function arrayRemove(array:Array, item:Object):Boolean {
  11.         [..]
  12. }
  13. }
Usage:

ActionScript Code:
  1. var names:Array = new Array("Bob", "Shirley", "Pete");
  2. trace(ArrayUtils.arrayRemove(array, "Bob")); // traces "true"
  3. trace(ArrayUtils.arrayRemove(array, "Bill")); // traces "false"
  4.  
 
Codemonkey's Avatar Codemonkey Codemonkey is offline Super Moderator Codemonkey lives in Netherlands 2006-11-05 #12 Old  
010b - Making a utility class global
Last edited by Codemonkey : 2007-05-06 at 03:24.
&nbsp;
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".

screenshot global paths

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:

ActionScript Code:
  1. // in this example ArrayUtils is in the directory/package "utils"
  2. import utils.ArrayUtils;
 
Codemonkey's Avatar Codemonkey Codemonkey is offline Super Moderator Codemonkey lives in Netherlands 2006-11-05 #13 Old  
011 - Quick random number
&nbsp;
If you quickly need a random number in a certain range, then you can use this simple (util) function:

ActionScript Code:
  1. function randomNum(min, max):Number {
  2.         return min + Math.round(Math.random() * (max - min));
  3.     }
 
Codemonkey's Avatar Codemonkey Codemonkey is offline Super Moderator Codemonkey lives in Netherlands 2006-11-05 #14 Old  
012 - Clipping a number
Last edited by Codemonkey : 2006-11-05 at 09:35.
&nbsp;
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:

ActionScript Code:
  1. function clip(value:Number, min:Number, max:Number):Number {
  2.         return Math.min(Math.max(value, min), max);
  3.     }
 
Nutrox's Avatar Nutrox Nutrox is offline Super Moderator Nutrox lives in United Kingdom 17 Creative Assets 2006-11-05 #15 Old  
013 - Loading, Bytes Per Second and ETA
&nbsp;
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&nbsp;etc.

I will wrap this up in a class soon.

ActionScript Code:
  1. var loadTarget:MovieClip;
  2. var loadTimer:Number;
  3. var loadTotal:Number;
  4.  
  5. function loadClip(target:MovieClip, url:String):Void {
  6.     loadTarget = target;
  7.     loadTimer  = getTimer();
  8.     loadTotal  = 0;
  9.     target.loadMovie(url);
  10.     this.onEnterFrame = updateLoadProgress;
  11. }
  12.  
  13. function updateLoadProgress():Void {
  14.     var bLoaded:Number = loadTarget.getBytesLoaded();
  15.     var bTotal:Number  = loadTarget.getBytesTotal();
  16.     if (bLoaded && bTotal) {
  17.         if (bLoaded == bTotal) {
  18.             this.onEnterFrame = null;
  19.             onLoadComplete();
  20.         }
  21.         else if (getTimer() - loadTimer >= 250) {
  22.             var bSec:Number = Math.round(bLoaded / (loadTotal / 1000));
  23.             var tRemaining:Number = Math.round((bTotal - bLoaded) / bSec);
  24.             onLoadProgress(bLoaded, bTotal, bSec, loadTotal, tRemaining);
  25.             loadTimer = getTimer();
  26.             loadTotal += 250;
  27.         }
  28.     }
  29. }
  30.  
  31. function onLoadProgress(bLoaded:Number, bTotal:Number, bSec:Number,
  32.                         tTotal:Number, tRemaining:Number):Void {
  33.     trace("loaded progress: " + bLoaded + "/" + bTotal);
  34.     trace("bytes per second (approx): " + bSec);
  35.     trace("total time (approx): " + tTotal + " seconds");
  36.     trace("remaining time (approx): " + tRemaining + " seconds");
  37.     trace("");
  38. }
  39.  
  40. function onLoadComplete():Void {
  41.     trace("loaded!");
  42. }
  43.  
  44. //
  45.  
  46. var container:MovieClip = this.createEmptyMovieClip("container", 0);
  47. var url:String = "external.swf";
  48.  
  49. loadClip(container, url);
 
Codemonkey's Avatar Codemonkey Codemonkey is offline Super Moderator Codemonkey lives in Netherlands 2006-11-05 #16 Old  
014 - fading your mx.screens.Forms
Last edited by Codemonkey : 2007-05-06 at 03:25.
&nbsp;
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:

ActionScript Code:
  1. import mx.transitions.*;
  2. import mx.transitions.easing.*;
  3.  
  4. // use this class on your forms instead
  5. class codemonkey.util.BasicForm extends mx.screens.Form {
  6.     private var __visible:Boolean = false;
  7.    
  8.     public function BasicForm() {
  9.         this.addEventListener("allTransitionsInDone", this);
  10.         this.addEventListener("allTransitionsOutDone", this);
  11.         this.createEmptyMovieClip("bg", this.getNextHighestDepth());
  12.     }
  13.     // display form (show/hide)
  14.     public function show(flag:Boolean) {
  15.         if (flag != this.__visible) {
  16.             this.__visible = flag;
  17.             this.visible = (__visible) ? true : this.visible;
  18.             var fadetype:Number = (flag) ? Transition.IN : Transition.OUT;
  19.             TransitionManager.start(
  20. this, {type:Fade, direction:fadetype, duration:1, easing:None.easeNone}
  21. );
  22.         }
  23.     }
  24.     // called by Flash' transition manager
  25.     private function allTransitionsInDone(eventObj:Object) {
  26.         this.visible = this.__visible;
  27.     }
  28.     private function allTransitionsOutDone(eventObj:Object) {
  29.         this.visible = this.__visible;
  30.     }
  31. }
To use this class, do as you normally would, but extend from the BasicForm class instead:

ActionScript Code:
  1. class LoadingScreen extends BasicForm {}
screenshot of applying your form in Flash
 
Codemonkey's Avatar Codemonkey Codemonkey is offline Super Moderator Codemonkey lives in Netherlands 2006-11-05 #17 Old  
015a - Creating sounds
&nbsp;
To create new sound objects that you can individually control, use can use the following function:

ActionScript Code:
  1. function loadSound(sound:String, vol:Number):Object {
  2.     // create sound container
  3.     var d:Number = _root.getNextHighestDepth();
  4.     var emptyMC:MovieClip = _root.createEmptyMovieClip("empty" + d, d);
  5.     // create sound
  6.     var sound:Sound = new Sound(emptyMC);
  7.     sound.attachSound(sound);
  8.     sound.setVolume(vol);
  9.     return sound;
  10. }
Usage:

ActionScript Code:
  1. var gunshot:Sound = loadSound("gunshot", 100);
  2. var squeeky:Sound = loadSound("squeeky", 60);
 
Codemonkey's Avatar Codemonkey Codemonkey is offline Super Moderator Codemonkey lives in Netherlands 2006-11-05 #18 Old  
015b - Creating enhanced sounds
Last edited by Codemonkey : 2006-11-11 at 03:18.
&nbsp;
To make the sound objects more manageble, you can embed it in a container that 'adds' functionality to a sound object. For example, you can simplify playing, status checks, looping etc. by adding functions for that to the sound's container.

Here's an example:

ActionScript Code:
  1. function loadSound(sound:String, vol:Number, loop:Boolean):Object {
  2.     var d:Number = _root.getNextHighestDepth();
  3.     var emptyMC:MovieClip = _root.createEmptyMovieClip("empty" + d, d);
  4.  
  5. // multifunctional container
  6.     var SoundObj:Object = new Object();
  7.     SoundObj.sound = new Sound(emptyMC);
  8.     SoundObj.sound.attachSound(sound);
  9.     SoundObj.sound.setVolume(vol);
  10.     SoundObj.sound.onSoundComplete = function() {
  11.         SoundObj.isPlaying = false;
  12.     };
  13.  
  14.     SoundObj.isLoop = loop;
  15.     SoundObj.isPlaying = false;
  16.  
  17. // only start playing when sound is not already playing
  18. SoundObj.softStart = function(Play:Boolean) {
  19.     if (Play) {
  20.         if (!this.isPlaying) this.sound.start(0, this.isLoop ? 999 : 0);
  21.     } else {
  22.         if (this.isPlaying) this.sound.stop();
  23.     }
  24.  
  25.     this.isPlaying = Play;
  26. }
  27.  
  28. // restart playing no matter what
  29. SoundObj.hardStart = function(Play:Boolean) {
  30.     this.sound.stop();
  31.     this.isPlaying = false;
  32.     this.softStart(Play);
  33. }
  34.  
  35.     return SoundObj;
  36. }
Ofcourse, you can add only so much until it becomes more logical to create a SoundClass instead and hide the details away in there.
 
Nutrox's Avatar Nutrox Nutrox is offline Super Moderator Nutrox lives in United Kingdom 17 Creative Assets 2006-11-05 #19 Old  
016 - Realtime Clock (tick tock)
&nbsp;
Copy and paste the following code into a new Flash document for an instant&nbsp;clock. :)

ActionScript Code:
  1. var hourHand:MovieClip;
  2. var minuteHand:MovieClip;
  3. var secondHand:MovieClip;
  4. var clockInterval:Number;
  5.  
  6. createClips();
  7. updateClock();
  8. clockInterval = setInterval(this, "updateClock", 500);
  9.  
  10. //
  11.  
  12. function updateClock():Void {
  13.     var d:Date   = new Date();
  14.     var h:Number = d.getHours();
  15.     var m:Number = d.getMinutes();
  16.     var s:Number = d.getSeconds();
  17.    
  18.     if (h >= 12) {
  19.         // getHours returns a value between 0 and 23,
  20.         // so we need to keep it within a 12 hour range.
  21.         h -= 12;
  22.     }
  23.    
  24.     hourHand._rotation   = (360 / 12) * h;
  25.     minuteHand._rotation = (360 / 60) * m;
  26.     secondHand._rotation = (360 / 60) * s;
  27. }
  28.  
  29. function createClips():Void {
  30.     var depth:Number = this.getNextHighestDepth();
  31.     // Second
  32.     secondHand = this.createEmptyMovieClip("secondHand", depth++);
  33.     secondHand.lineStyle(2, 0xFF0000);
  34.     secondHand.moveTo(0, -80);
  35.     secondHand.lineTo(0, 0);
  36.     // Minute
  37.     minuteHand = this.createEmptyMovieClip("minuteHand", depth++);
  38.     minuteHand.lineStyle(3, 0x00FF00);
  39.     minuteHand.moveTo(0, -90);
  40.     minuteHand.lineTo(0, 0);
  41.     // Hour
  42.     hourHand = this.createEmptyMovieClip("hourHand", depth);
  43.     hourHand.lineStyle(5, 0x0000FF);
  44.     hourHand.moveTo(0, -100);
  45.     hourHand.lineTo(0, 0);
  46.    
  47.     // Position the movie clips.
  48.     // Just move them to the center of the Stage for now.
  49.     var x:Number  = Math.floor(Stage.width / 2);
  50.     var y:Number  = Math.floor(Stage.height / 2);
  51.     hourHand._x   = x;
  52.     hourHand._y   = y;
  53.     minuteHand._x = x;
  54.     minuteHand._y = y;
  55.     secondHand._x = x;
  56.     secondHand._y = y;
  57. }
 
Nutrox's Avatar Nutrox Nutrox is offline Super Moderator Nutrox lives in United Kingdom 17 Creative Assets 2006-11-05 #20 Old  
017 - Removing Non-dynamic Movie Clips
&nbsp;
Normally you can't use removeMovieClip() on movie clips that you place on the Stage while authoring the movie. However, swap the movie clip depth to a positive value and removeMovieClip() will work&nbsp;fine!

ActionScript Code:
  1. function deleteClip(target:MovieClip):Void {
  2.    var d:Number = target._parent.getNextHighestDepth();
  3.    target.swapDepths(d);
  4.    target.removeMovieClip();
  5. }
  6.  
  7. // myMovieClip is already on the Stage
  8. deleteClip(myMovieClip);
 
Codemonkey's Avatar Codemonkey Codemonkey is offline Super Moderator Codemonkey lives in Netherlands 2006-11-06 #21 Old  
018 - __resolve your properties and methods
Last edited by Codemonkey : 2006-11-11 at 03:20.
&nbsp;
A less known and even less used feature in actionscript is the __resolve method.

If you declare a method called __resolve on your class and someone tries to call a property or method of your class that doesn't exist, flash will look for a __resolve instead and call that one. You will get a parameter with the name of the unknown property/method that the user is trying to call. In addition, you can use the arguments variable inside __resolve to uncover any arguments the user passed.

You can call properties/methods that don't exist on an object when:
  1. Your class was declared dynamic
    ActionScript Code:
    1. dynamic class MyClass {
    2. function __resolve(name:String) {
    3. // do something
    4. }
    5. }
    6. var instance:MyClass = new MyClass();
    7. instance.unknownFunction()
  2. You use an Object directly
    ActionScript Code:
    1. var o:Object = new Object();
    2. o.__resolve = function (name) {
    3. // do something
    4. }
    5. o.unknownFunction()
  3. You typecast an instance of your non-dynamic class as Object (this won't work in AS3.0 though)
    ActionScript Code:
    1. class MyClass {
    2. function __resolve(name:String) {
    3. // do something
    4. }
    5. }
    6. var instance:MyClass = new MyClass();
    7. Object(instance).unknownFunction()
__resolve can be useful in case you are creating dynamic classes for distribution and you want people to know when they called a non-existent function - which the compiler would've done if your class wasn't declared with the keyword dynamic. Or you could use __resolve to forward method calls to a server or act as an adaptor to other objects. In doing so you can also log all methods being called through __resolve in a single place. Another use is when you have a 'decorator' and you need to forward dynamic methods 1-on-1 to the 'decoratee'.

Be cautious though, __resolve doesn't *always* work as you would expect and you should have a very specific reason where you think __resolve is the solution.
 
Codemonkey's Avatar Codemonkey Codemonkey is offline Super Moderator Codemonkey lives in Netherlands 2006-11-06 #22 Old  
019 - InspectableList metatag
Last edited by Codemonkey : 2006-11-07 at 08:50.
&nbsp;
If you are creating your own components and you are extending an existing component class to do that, it may happen that you want to hide inherited public properties from the Component Inspector in Flash.

The answer is a Flash meta tag for components called InspectableList. While the component inspector knows what properties to list from each separate property that has Inspectable before it, you can override this list by using the InspectableList meta tag.

For example, when you know a component works with public x and y Numbers, but you want to work with a setPos() method and hide the x and y properties, you need a way to do this clean and simple (at least to users in the component inspector):

ActionScript Code:
  1. class ComponentA {
  2.         [Inspectable(defaultValue=0)]
  3.         public var x:Number;
  4.  
  5.         [Inspectable(defaultValue=0)]
  6.         public var y:Number;
  7.  
  8.         [Inspectable(defaultValue=100)]
  9.         public var size:Number;
  10. }
ActionScript Code:
  1. [InspectableList("size")]
  2. class ComponentB extends ComponentA {
  3. ...
  4. }
In component B, the x and y properties are not available in the component inspector, but the property size still is. Be cautious though, if you use this tag to exclude variables, you have to add all the others by hand to this meta tag.
 
Codemonkey's Avatar Codemonkey Codemonkey is offline Super Moderator Codemonkey lives in Netherlands 2006-11-06 #23 Old  
020 - Tip 20
&nbsp;
There is no Tip 20.
 
Codemonkey's Avatar Codemonkey Codemonkey is offline Super Moderator Codemonkey lives in Netherlands 2006-11-07 #24 Old  
021 - Bits as Flags
Last edited by Codemonkey : 2006-11-12 at 01:38.
&nbsp;
If you want a clean and efficient way of testing against flags, you can use bit-wise operators.

Define your flags as numbers like 2, 4, 8, 16 (double for each new flag constant):

ActionScript Code:
  1. var FUNNY = 2;
  2. var NOISY = 4;
  3. var HANDSOME = 8;
  4. var COOL = 16;
  5. var NERDY = 32;
  6. var SUPERMANLIKE = 64;
Then, you can combine these flags - and lateron check against individual flags - using the bitwise operator 'or':

ActionScript Code:
  1. var splat:Number = COOL | NERDY; // 'or' the bits!
  2. var codemonkey:Number = FUNNY | HANDSOME | COOL | SUPERMANLIKE;
To check if Splat is cool, use the bitwise operator 'and' to check the combined flags against the COOL flag:

ActionScript Code:
  1. if (splat & COOL) {
  2. trace("Splat is cool!");
  3. }

The key to this mechanism is being able to use many different flags together in one number variable. Take the Array class for example. If you want to sort an Array with the method Array.sort(), you can use constants from the Array class to indicate how the sort should happen. Those constants are flag numbers you bitwise combine to quickly, cleanly and efficiently let the sort method know your needs.

---
You can store an entire chessboard in one variable, because there are 64 spaces in a chess board and you can have 64 different single bits in a Number (and each bit is represented by 2, 4, 8, etc...). Even better, you can do cool stuff like:

if (blackHorse & whitePieces) {
&nbsp;&nbsp;&nbsp;// make black horse take whatever piece is occupying the same space
}


This principle is also known as bitboards, or boards of bits. It's one of the optimizations to make chess AI ultrafast.
---
 
Codemonkey's Avatar Codemonkey Codemonkey is offline Super Moderator Codemonkey lives in Netherlands 2006-11-07 #25 Old  
022 - Removing a single bitflag
Last edited by Codemonkey : 2006-11-12 at 02:08.
&nbsp
As you now know, you can combine flags to a combined flag, which means you join the ones '1' into a single number. Then you can check that number against a single flag whether it occurs.

To remove a single flag from such a combined number, you simply AND it with the opposite of the single bit flag. Huh? Take a look:

ActionScript Code:
  1. // combine flags:
  2. var combinedFlag = ONE | TWO;
  3.  
  4. // remove single flag TWO:
  5. combinedFlag = combinedFlag & ~TWO;
It's very simple to code out, but understanding why it works needs a bit of digging.

---
With the '~' operator you can flip all zeros and ones so that the bit representation is exactly the opposite (ie. 11001 becomes 00110). AND'ing that to the combined flag means: keep everything of the original number, but throw away what's behind the AND. This works because that number has zeros '0' where the ones '1' were and AND'ing with zeroes won't work.

In math, there's actually a special operator for this kind of thing. instead of AND'ing with the opposite of a flag, you can NAND a flag. NAND stands for Not And, which is exactly the same.
---


Here's another example with a rabbit that drinks blood when it is full moon:

ActionScript Code:
  1. var HUNGRY = 2;
  2. var THIRSTY = 4;
  3.  
  4. var WANT_CARROT = 8;
  5. var WANT_CABBAGE = 16;
  6. var WANT_WATER = 32;
  7. var WANT_BLOOD = 64;
  8.  
  9. var rabbit:Number = HUNGRY | WANT_CARROT;
  10.  
  11. if (fullMoon) {
  12.     // rabbit doesn't want to eat anymore
  13.     rabbit = rabbit & ~HUNGRY;
  14.     // rabbit is thirsty for blood now
  15.     rabbit = rabbit | THIRSTY | WANT_BLOOD;
  16. }
 
Codemonkey's Avatar Codemonkey Codemonkey is offline Super Moderator Codemonkey lives in Netherlands 2006-11-07 #26 Old  
023 - List all flags in a combined variable
Last edited by Codemonkey : 2006-11-12 at 02:45.
&nbsp
Sometimes it is useful to list all the single flags in a combined flag number. For example for debugging, logging or some other operation. You can do this by AND'ing all single flags by hand like this:

ActionScript Code:
  1. var FLAGONE = 1;
  2. var FLAGTWO = 2;
  3. var FLAGTHREE = 4;
  4.  
  5. var combinedFlag = FLAGONE | FLAGTHREE;
  6.  
  7. trace("FLAGONE: " + (combinedFlag & FLAGONE)); // traces "1"
  8. trace("FLAGTWO: " + (combinedFlag & FLAGTWO)); // traces "0"
  9. trace("FLAGTHREE: " + (combinedFlag & FLAGTHREE)); // traces "4"
  10.  
Everything that doesn't result in 0 means the flag is in it. Remember for example 16 only means the flag with the bit 5 (from the right) set. This can become cumbersome though when you have a lot of flags or when you add or remove flags. You want a dynamic way that lists all the flags in a combined flag. Here is one way:

ActionScript Code:
  1. // create the flags and put them in an array we'll
  2. // use to run through for tracing separate flags
  3. var flags:Array = new Array();
  4. var FLAGONE = 1; flags.push(FLAGONE);
  5. var FLAGTWO = 2; flags.push(FLAGTWO);
  6. var FLAGTHREE = 4; flags.push(FLAGTHREE);
  7.  
  8. // return a list of flags that are in the combined flag
  9. function listFlags(combinedFlag:Number): Array {
  10.         var result:Array = new Array();
  11.         for (var flag in flags) {
  12.                 // check if flag is in the combined flag
  13.                 if (combinedFlag & flags[flag]) {
  14.                         result.push(flags[flag]);
  15.                 }
  16.         }
  17.         return result;
  18. }
  19.  
  20. var combinedFlag = FLAGONE | FLAGTHREE;
  21. trace(listFlags(combinedFlag)); // traces "4, 1"
  22.  
There's one problem though. This method returns only the values of those individual flags, not their names. If you want their names as well (or some other description), create the constants another way:

ActionScript Code:
  1. // create the flags and put them in an array including descriptions
  2. // we'll use to run through for tracing separate flags
  3. var flags:Array = new Array();
  4. var FLAGONE = 1; flags[FLAGONE] = [FLAGONE, "Flag 1 for some purpose"];
  5. var FLAGTWO = 2; flags[FLAGTWO] = [FLAGTWO, "Flag 2"];
  6. var FLAGTHREE = 4; flags[FLAGTHREE] = [FLAGTHREE, "Flag 3 yay"];
  7.  
  8. // return a list of flags that are in the combined flag
  9. function listFlags(combinedFlag:Number): Array {
  10.         var result:Array = new Array();
  11.         for (var flag in flags) {
  12.                 // check if flag is in the combined flag
  13.                 if (combinedFlag & flags[flag][0]) {
  14.                     // add the flag's description
  15.                     result.push(flags[flag][1]);
  16.                 }
  17.         }
  18.         return result;
  19. }
  20.  
  21. var combinedFlag = FLAGONE | FLAGTHREE;
  22. trace(listFlags(combinedFlag));
  23. // traces:
  24. // "Flag 1 for some purpose"
  25. // "Flag 3 yay"
  26.  
 
Codemonkey's Avatar Codemonkey Codemonkey is offline Super Moderator Codemonkey lives in Netherlands 2006-11-12 #27 Old  
024 - Bitflags by bitshifting
Last edited by Codemonkey : 2006-11-28 at 02:10.
&nbsp
When you add new flags, move them around or change them a lot, it can be an annoyance to have to update all the flag values each time, making sure they are unique and doubled each time.

To make things a little bit easier, you can use the bitshift operator. The bitshift operator 'knows' you want to store a value as a bit representation, like all the flags we've been defining. Here's an example:

ActionScript Code:
  1. var OLD_ONE = 1;
  2. var OLD_TWO = 2;
  3. var OLD_THREE = 4;
  4. var OLD_FOUR = 8;
  5.  
  6. var NEW_ONE     = 1 << 0; // shift bit 0 left
  7. var NEW_TWO     = 1 << 1; // shift bit 1 left
  8. var NEW_THREE   = 1 << 2; // shift bit 2 left
  9. var NEW_FOUR    = 1 << 3; // shift bit 3 left
  10.  
  11. trace(OLD_ONE == NEW_ONE); // "true"
  12. trace(OLD_TWO == NEW_TWO); // "true"
  13. trace(OLD_THREE == NEW_THREE); // "true"
  14. trace(OLD_FOUR == NEW_FOUR); // "true"
  15.  
Here's a more practical way:

ActionScript Code:
  1. var shifts:Number = 0;
  2.  
  3. var NEW_ONE     = 1 << shifts++; // 1
  4. var NEW_TWO     = 1 << shifts++; // 2
  5. var NEW_THREE   = 1 << shifts++; // 4
  6. var NEW_FOUR    = 1 << shifts++; // 8
  7.  
Now you can move the flags around without having to worry about their values.
 
Nutrox's Avatar Nutrox Nutrox is offline Super Moderator Nutrox lives in United Kingdom 17 Creative Assets 2006-11-13 #28 Old  
025 - Shared Library, go away! (AS3)
&nbsp;
Shared Libraries can be summed up in four words: pain in the ass. They can still be used with AS3 but why bother with them when there is an easier way to pull library assets from SWF&nbsp;files!

Let's say that you have a SWF and in that SWF file's library is a sound file linked to the first frame of the movie with the class name "MySound". The following code demonstrates how to load that SWF file into another SWF file, grab the sound from the library, and then play the sound.&nbsp;Woohoo!

ActionScript Code:
  1. import flash.events.Event;
  2. import flash.net.URLRequest;
  3. import flash.display.Loader;
  4. import flash.media.Sound;
  5.  
  6. var req:URLRequest = new URLRequest("library.swf");
  7. var loader:Loader = new Loader();
  8. loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLibraryLoaded);
  9. loader.load(req);
  10.  
  11. var mySound:Sound;
  12.  
  13. function onLibraryLoaded(e:Event):void
  14. {
  15.     var cls:Class = Class(loader.contentLoaderInfo.applicationDomain.getDefinition("MySound"));
  16.     mySound = new cls();
  17.     mySound.play();
  18. }
This method can probably be used for most of the library assets you can store in a SWF file. I think you might even be able to use this with fonts but I haven't tried that&nbsp;yet.

Have fun!
 
Codemonkey's Avatar Codemonkey Codemonkey is offline Super Moderator Codemonkey lives in Netherlands 2006-11-15 #29 Old  
026 - Listening in on the listeners
&nbsp;
If you use the EventDispatcher to allow listeners to listen for events on your object, your object gets a list for these listeners and a bunch of functions like dispatchEvent etc. To access this array of listeners, use the property "__q_" on your object. This is the name of the array the EventDispatcher adds to your object:

Setting up the event dispatching object and a listener:

ActionScript Code:
  1. import mx.events.EventDispatcher;
  2. var eventsource:Object = new Object();
  3. EventDispatcher.initialize(eventsource);
  4.  
  5. var listener = new Object();
  6. listener.foo = function (eventObj:Object) {
  7.         trace(eventObj.message); // "I like apple pie!"
  8. }
  9.  
  10. eventsource.addEventListener("foo", listener);
  11. eventsource.dispatchEvent({type:"foo", target:this, message:"I like apple pie!"});
Get access to the array of listeners:

ActionScript Code:
  1. trace(eventsource["__q_" + "foo"] instanceof Array); // traces "true"
  2. trace(eventsource["__q_" + "foo"].length); // traces "1"
  3.  
 
Codemonkey's Avatar Codemonkey Codemonkey is offline Super Moderator Codemonkey lives in Netherlands 2006-11-15 #30 Old  
027 - Fixing scope with Delegates (as2)
Last edited by Codemonkey : 2006-11-28 at 02:11.
&nbsp;
If for some reason you think "Why is this or that tracing undefined??" or "Why isn't my function executing omg!". Then for the love of God, think of Delegates!! Search Ultrashock on the word "scope" and "Delegate" and don't ask us again please

Classic example:

ActionScript Code:
  1. class MyXMLParser {
  2.     var books:Array = new Array();
  3.  
  4.     function doIt() {
  5.         var xml:XML = new XML();
  6.         xml.onLoad = parseXML;
  7.         xml.load("books.xml");
  8.     }
  9.  
  10.     function parseXML(success:Boolean) {
  11.         // parse xml stuff
  12.         books.push(book_from_xml); // BUZZ, can't find books!
  13.     }
  14. }
Books couldn't be found, because when the xml object calls parseXML, the scope is in the xml object, not MyXMLParser. And so you can't access books because it isn't in the xml object.

Fix this with a Delegate:

ActionScript Code:
  1. import mx.utils.Delegate;
  2.  
  3. class MyXMLParser {
  4.     var books:Array = new Array();
  5.  
  6.     function doIt() {
  7.         var xml:XML = new XML();
  8.         xml.onLoad = Delegate.create(this, parseXML);
  9.         xml.load("books.xml");
  10.     }
  11.  
  12.     function parseXML(success:Boolean) {
  13.         // parse xml stuff
  14.         books.push(book_from_xml); // DING, can find books!
  15.     }
  16. }
 
Nutrox's Avatar Nutrox Nutrox is offline Super Moderator Nutrox lives in United Kingdom 17 Creative Assets 2006-11-15 #31 Old  
028 - Delegate Alternative
Last edited by Nutrox : 2006-11-22 at 05:23.
&nbsp;
Following on from Codemonkey's look at the Delegate class, I actually use my own delegate-like class for fixing scope. This version allows you to pass custom arguments to the target method without overwriting any arguments that Flash might spit out, the standard Delegate class will overwrite those arguments.

Here is the AS2 class:

ActionScript Code:
  1. class cs.utils.Scope
  2. {
  3.     public static function rewire(scope:Object, func:Function):Function
  4.     {
  5.         var args:Array = [];
  6.  
  7.         if (arguments.length > 2)
  8.         {
  9.             args = arguments.splice(2, arguments.length - 2);
  10.         }
  11.         return function()
  12.         {
  13.             return func.apply(scope, args.concat(arguments));
  14.         }
  15.     }
  16. }
A good example of how to use the class would be with the XML.onLoad event:

ActionScript Code:
  1. import cs.utils.Scope;
  2.  
  3. var xml:XML = new XML();
  4. xml.ignoreWhite = true;
  5. xml.onLoad = Scope.rewire(this, xmlLoadHandler, "Hello!", xml);
  6.  
  7. xml.load("file.xml");
  8.  
  9. function xmlLoadHandler(word:String, xmlFile:XML, success:Boolean):Void
  10. {
  11.     if (!success)
  12.     {
  13.         // D'oh!
  14.     }
  15.     else
  16.     {
  17.         trace(this);           // _level0
  18.         trace(word);           // output: Hello!
  19.         trace(xmlFile == xml); // output: true
  20.         trace(this == xml);    // output: false
  21.     }
  22. }
As you can see the scope of the xmlLoadHandler will be _level0 instead of the XML object. Your custom arguments will be passed to method before any of the default ones that Flash might send (i.e. success).

 
Nutrox's Avatar Nutrox Nutrox is offline Super Moderator Nutrox lives in United Kingdom 17 Creative Assets 2006-11-19 #32 Old  
029 - Math.floor Alternative
&nbsp;
You can use the bitwise right-shift operator to floor a number instead of using Math.floor(). Normally Math.floor() is absolutely fine to use, but if you are concerned about CPU cycles then this alternative will come in handy because it is a lot quicker than&nbsp;Math.floor().

Here is an example using Math.floor()...

ActionScript Code:
  1. var num:Number = 123.456;
  2. num = Math.floor(num);
  3.  
  4. trace( num ); // output: 123
  5.  
...and here is the same thing, but this time the bitwise right-shift operator is used...

ActionScript Code:
  1. var num:Number = 123.456;
  2. num >>= 0; // num >>= zero
  3.  
  4. trace( num ); // output: 123
  5.  
 
Nutrox's Avatar Nutrox Nutrox is offline Super Moderator Nutrox lives in United Kingdom 17 Creative Assets 2006-11-19 #33 Old  
030 - Rounding Numbers
&nbsp;
Here is a little utility function that you can use to round numbers to a certain decimal&nbsp;point.

It is very easy to use so I'll just drop some example code&nbsp;here...

ActionScript Code:
  1. function roundTo(value:Number, points:Number):Number
  2. {
  3.     if (points == null || points < 1)
  4.     {
  5.         return value >> 0;
  6.     }
  7.     var delta:Number = Math.pow(10, points);
  8.    
  9.     return (value * delta >> 0) / delta;
  10. }
  11.  
  12. //
  13.  
  14. var num:Number = 100.24680;
  15.  
  16. trace( roundTo(num) );    // output: 100
  17. trace( roundTo(num, 0) ); // output: 100
  18. trace( roundTo(num, 1) ); // output: 100.2
  19. trace( roundTo(num, 2) ); // output: 100.24
  20. trace( roundTo(num, 3) ); // output: 100.246
  21. trace( roundTo(num, 4) ); // output: 100.2468
  22. trace( roundTo(num, 5) ); // output: 100.23680
  23.  
 
Nutrox's Avatar Nutrox Nutrox is offline Super Moderator Nutrox lives in United Kingdom 17 Creative Assets 2006-11-22 #34 Old  
031 - Array Mapping
Last edited by Nutrox : 2006-11-22 at 05:29.
&nbsp;
Array mapping can come in very useful sometimes. What array mapping basically does is pass each array value to a function, and that function can then either alter the array value or return a result based on the array value.

I have included a prototype function and a standard function here just in case you prefer a particular flava.

You setup the Array prototype method like this:

ActionScript Code:
  1. Array.prototype.map = function(callback)
  2. {
  3.     var a = [];
  4.     var n = this.length;
  5.     while (n--)
  6.     {
  7.         a[n] = callback(this, n, this[n]);
  8.     }
  9.     return a;
  10. }

Prototype Example 1
This example checks to see which values in the myNumbers array are greater than 3. The results (in this example true or false) will be returned in an array.

ActionScript Code:
  1. var myNumbers = [1, 2, 3, 4, 5, 6];
  2. var results   = myNumbers.map(checkNumbers);
  3.  
  4. trace( results ); // false, false, false, true, true, true
  5.  
  6. //
  7.  
  8. function checkNumbers(array, index, value)
  9. {
  10.     // Check if the value is greater than 3.
  11.     return value > 3;
  12. }
Prototype Example 2
This example will prefix each value in the myNames array with "Name: ".

ActionScript Code:
  1. var myNames = ["Andy", "Bob", "Charlie", "Dood"];
  2. var newNames = myNames.map(changeNames);
  3.  
  4. trace( newNames ); // Name: Andy, Name: Bob, Name: Charlie, Name: Dood
  5.  
  6. //
  7.  
  8. function changeNames(array, index, value)
  9. {
  10.     return "Name: " + value;
  11. }
Better Example 1
We have left the world of prototypes now. This is the same example as Prototype Example 1 but instead of using a prototype a standalone function is used for the array mapping.

ActionScript Code:
  1. function mapArray(array:Array, callback:Function):Array
  2. {
  3.     var a:Array = [];
  4.     var n:Number = array.length;
  5.     while (n--)
  6.     {
  7.         a[n] = callback(array, n, array[n]);
  8.     }
  9.     return a;
  10. }
  11.  
  12. //
  13.  
  14. var myNumbers:Array = [1, 2, 3, 4, 5, 6];
  15. var results:Array   = mapArray(myNumbers, checkNumbers);
  16.  
  17. trace( results ); // false, false, false, true, true, true
  18.  
  19. //
  20.  
  21. function checkNumbers(array:Array, index:Number, value):Array
  22. {
  23.     return value > 3;
  24. }


PS: Array mapping is built-in to the AS3 Array class, so these examples are only useful for AS1 / AS2.
 
Codemonkey's Avatar Codemonkey Codemonkey is offline Super Moderator Codemonkey lives in Netherlands 2006-11-25 #35 Old  
032 - Calling methods with eval()
&nbsp;
You can't dynamically call functions with eval() like in Javascript or PHP unless you create your own parser for it, as well as for assignments etc. Flash can only locate identifiers for you with eval and that isn't necessary anymore these days.

If you want a quick way to call certain functions using a string, here's one way to do that (in AS2 at least):

ActionScript Code:
  1. // some values and a user function we'll call
  2. var monkeys:String = "monkeys!";
  3. var apes:String = "apes!";
  4.  
  5. function myFunc(str1:String, str2:String) {
  6.     trace(str1 + " and " + str2);
  7. }
  8.  
  9. // locate a function and apply the arguments to it
  10. function parseFunction(s:String) {
  11.     var fname:String = s.split("(")[0];
  12.     var parameters:String = s.split(")")[0].substr(fname.length + 1);
  13.     var paramlist:Array = parameters.split(", ");
  14.    
  15.     // get the results of each argument
  16.     for (i in paramlist) {
  17.         paramlist[i] = eval(paramlist[i]);
  18.     }
  19.     // call the function with the specified arguments
  20.     var func:Function = eval(fname);
  21.     func.apply(this, paramlist);
  22. }
  23.  
  24. // try to call user function, and a system function
  25. parseFunction("myFunc(monkeys, apes);");
  26. monkeys = "three little monkeys";
  27. parseFunction("trace(monkeys);");
You could expand it to parse expressions as well and execute several commands by splitting the string with ';'.
 
Nutrox's Avatar Nutrox Nutrox is offline Super Moderator Nutrox lives in United Kingdom 17 Creative Assets 2006-11-25 #36 Old  
033 - Array Rotation
Last edited by Nutrox : 2006-11-25 at 07:52.
&nbsp;
In a nutshell: Array rotation simply means shifting the array values to new positions while keeping their relative order.

Here is a quick example followed by the prototype version:

ActionScript Code:
  1. function rotateArray(arr:Array, amount:Number):Void
  2. {
  3.     var delta:Number = amount * -1;
  4.     if (amount < 0)
  5.     {
  6.         arr.splice(amount, null, arr.splice(0, delta));
  7.     }
  8.     else if (amount > 0)
  9.     {
  10.         arr.splice(0, null, arr.splice(delta, amount));
  11.     }
  12. }
  13.  
  14. //
  15.  
  16. var numbers:Array = [1,2,3,4,5];
  17.  
  18. rotateArray(numbers, -1);
  19. trace( numbers ); // 2,3,4,5,1
  20.  
  21. rotateArray(numbers, 1);
  22. trace( numbers ); // 1,2,3,4,5
  23.  
  24. rotateArray(numbers, 3);
  25. trace( numbers ); // 3,4,5,1,2
  26.  

ActionScript Code:
  1. Array.prototype.rotate = function(amount)
  2. {
  3.     var delta = amount * -1;
  4.     if (amount < 0)
  5.     {
  6.         this.splice(amount, null, this.splice(0, delta));
  7.     }
  8.     else if (amount > 0)
  9.     {
  10.         this.splice(0, null, this.splice(delta, amount));
  11.     }
  12. }
  13.  
  14. //
  15.  
  16. var numbers = [1,2,3,4,5];
  17.  
  18. numbers.rotate(-1);
  19. trace( numbers ); // 2,3,4,5,1
  20.  
  21. numbers.rotate(1);
  22. trace( numbers ); // 1,2,3,4,5
  23.  
  24. numbers.rotate(3);
  25. trace( numbers ); // 3,4,5,1,2
  26.  
 
Nutrox's Avatar Nutrox Nutrox is offline Super Moderator Nutrox lives in United Kingdom 17 Creative Assets 2006-11-27 #37 Old  
034 - Colour Manipulation
Last edited by Nutrox : 2007-11-15 at 00:54.
&nbsp;
Using the bit-shifting techniques that Codemonkey has covered allows you to quickly and easily manipulate colour values.

This first example demostrates how you can get the individual colour values from a RGB colour value:

ActionScript Code:
  1. var colour:Number = 0xFA802A;
  2.  
  3. var red:Number   = colour >> 16 & 255;
  4. var green:Number = colour >> 8 & 255;
  5. var blue:Number  = colour & 255;
  6.  
  7. trace( red   ); // 250
  8. trace( green ); // 128
  9. trace( blue  ); // 42
  10.  
  11. trace( red.toString(16)   ); // fa
  12. trace( green.toString(16) ); // 80
  13. trace( blue.toString(16)  ); // 2a
  14.  
If you want to construct a RGB colour value from red, green, and blue values then you can do this:

ActionScript Code:
  1. var red:Number   = 0x80;
  2. var green:Number = 0xFF;
  3. var blue:Number  = 0xCA;
  4.  
  5. var colour:Number = 0;
  6.  
  7. colour |= red   << 16;